Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(300)

Side by Side Diff: third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp

Issue 2629463002: Refactor valuesForFrameRangeImpl (Closed)
Patch Set: Make AutomationState const and add documentation Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved. 2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 789 matching lines...) Expand 10 before | Expand all | Expand 10 after
800 double sampleRate, 800 double sampleRate,
801 double controlRate) { 801 double controlRate) {
802 DCHECK(values); 802 DCHECK(values);
803 DCHECK_GE(numberOfValues, 1u); 803 DCHECK_GE(numberOfValues, 1u);
804 if (!values || !(numberOfValues >= 1)) 804 if (!values || !(numberOfValues >= 1))
805 return defaultValue; 805 return defaultValue;
806 806
807 // Return default value if there are no events matching the desired time 807 // Return default value if there are no events matching the desired time
808 // range. 808 // range.
809 if (!m_events.size() || (endFrame / sampleRate <= m_events[0]->time())) { 809 if (!m_events.size() || (endFrame / sampleRate <= m_events[0]->time())) {
810 for (unsigned i = 0; i < numberOfValues; ++i) 810 fillWithDefault(values, defaultValue, numberOfValues, 0);
811 values[i] = defaultValue; 811
812 return defaultValue; 812 return defaultValue;
813 } 813 }
814 814
815 int numberOfEvents = m_events.size(); 815 int numberOfEvents = m_events.size();
816 816
817 if (numberOfEvents > 0) { 817 if (numberOfEvents > 0) {
818 bool clampedSomeEventTime = false;
819 double currentTime = startFrame / sampleRate; 818 double currentTime = startFrame / sampleRate;
819 clampToCurrentTime(numberOfEvents, startFrame, sampleRate);
820 820
821 // Look at all the events in the timeline and check to see if any needs 821 if (handleAllEventsInThePast(currentTime, sampleRate, defaultValue,
822 // to clamp the start time to the current time. 822 numberOfValues, values))
823 for (int k = 0; k < numberOfEvents; ++k) {
824 ParamEvent* event = m_events[k].get();
825
826 // We're examining the event for the first time and the event time is
827 // in the past so clamp the event time to the current time (start of
828 // the rendering quantum).
829 if (event->needsTimeClampCheck()) {
830 if (event->time() < currentTime) {
831 event->setTime(currentTime);
832 clampedSomeEventTime = true;
833 }
834
835 // In all cases, we can clear the flag because the event is either
836 // in the future, or we've already checked it (just now).
837 event->clearTimeClampCheck();
838 }
839 }
840
841 if (clampedSomeEventTime) {
842 // If we clamped some event time to current time, we need to
843 // sort the event list in time order again, but it must be
844 // stable!
845 std::stable_sort(m_events.begin(), m_events.end(),
846 ParamEvent::eventPreceeds);
847 }
848
849 // Optimize the case where the last event is in the past.
850 ParamEvent* lastEvent = m_events[m_events.size() - 1].get();
851 ParamEvent::Type lastEventType = lastEvent->getType();
852 double lastEventTime = lastEvent->time();
853
854 // If the last event is in the past and the event has ended, then we can
855 // just propagate the same value. Except for SetTarget which lasts
856 // "forever". SetValueCurve also has an explicit SetValue at the end of
857 // the curve, so we don't need to worry that SetValueCurve time is a
858 // start time, not an end time.
859 //
860 // Allow at least one render quantum to go by before handling this
861 // to allow k-rate parameters to finish processing the event. See
862 // crbug.com/672857. Due to possible roundoff, arbirtrarily wait
863 // for 1.5 render quanta instead of 1.
864 if (lastEventTime +
865 1.5 * AudioUtilities::kRenderQuantumFrames / sampleRate <
866 currentTime &&
867 lastEventType != ParamEvent::SetTarget) {
868 // The event has finished, so just copy the default value out.
869 // Since all events are now also in the past, we can just remove all
870 // timeline events too because |defaultValue| has the expected
871 // value.
872 for (unsigned i = 0; i < numberOfValues; ++i)
873 values[i] = defaultValue;
874 m_smoothedValue = defaultValue;
875 m_events.clear();
876 return defaultValue; 823 return defaultValue;
877 }
878 } 824 }
879 825
880 // Maintain a running time (frame) and index for writing the values buffer. 826 // Maintain a running time (frame) and index for writing the values buffer.
881 size_t currentFrame = startFrame; 827 size_t currentFrame = startFrame;
882 unsigned writeIndex = 0; 828 unsigned writeIndex = 0;
883 829
884 // If first event is after startFrame then fill initial part of values buffer 830 // If first event is after startFrame then fill initial part of values buffer
885 // with defaultValue until we reach the first event time. 831 // with defaultValue until we reach the first event time.
886 double firstEventTime = m_events[0]->time(); 832 std::tie(currentFrame, writeIndex) =
887 if (firstEventTime > startFrame / sampleRate) { 833 handleFirstEvent(values, defaultValue, numberOfValues, startFrame,
888 // |fillToFrame| is an exclusive upper bound, so use ceil() to compute the 834 endFrame, sampleRate, currentFrame, writeIndex);
889 // bound from the firstEventTime.
890 size_t fillToFrame = endFrame;
891 double firstEventFrame = ceil(firstEventTime * sampleRate);
892 if (endFrame > firstEventFrame)
893 fillToFrame = static_cast<size_t>(firstEventFrame);
894 DCHECK_GE(fillToFrame, startFrame);
895
896 fillToFrame -= startFrame;
897 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues));
898 for (; writeIndex < fillToFrame; ++writeIndex)
899 values[writeIndex] = defaultValue;
900
901 currentFrame += fillToFrame;
902 }
903 835
904 float value = defaultValue; 836 float value = defaultValue;
905 837
906 // Go through each event and render the value buffer where the times overlap, 838 // Go through each event and render the value buffer where the times overlap,
907 // stopping when we've rendered all the requested values. 839 // stopping when we've rendered all the requested values.
908 int lastSkippedEventIndex = 0; 840 int lastSkippedEventIndex = 0;
909 for (int i = 0; i < numberOfEvents && writeIndex < numberOfValues; ++i) { 841 for (int i = 0; i < numberOfEvents && writeIndex < numberOfValues; ++i) {
910 ParamEvent* event = m_events[i].get(); 842 ParamEvent* event = m_events[i].get();
911 ParamEvent* nextEvent = i < numberOfEvents - 1 ? m_events[i + 1].get() : 0; 843 ParamEvent* nextEvent = i < numberOfEvents - 1 ? m_events[i + 1].get() : 0;
912 844
913 // Wait until we get a more recent event. 845 // Wait until we get a more recent event.
914 // 846 if (!isEventCurrent(event, nextEvent, currentFrame, sampleRate)) {
915 // WARNING: due to round-off it might happen that nextEvent->time() is 847 // This is not the special SetValue event case, and nextEvent is
916 // just larger than currentFrame/sampleRate. This means that we will end 848 // in the past. We can skip processing of this event since it's
917 // up running the |event| again. The code below had better be prepared 849 // in past. We keep track of this event in lastSkippedEventIndex
918 // for this case! What should happen is the fillToFrame should be 0 so 850 // to note what events we've skipped.
919 // that while the event is actually run again, nothing actually gets 851 lastSkippedEventIndex = i;
920 // computed, and we move on to the next event. 852 continue;
921 //
922 // An example of this case is setValueCurveAtTime. The time at which
923 // setValueCurveAtTime ends (and the setValueAtTime begins) might be
924 // just past currentTime/sampleRate. Then setValueCurveAtTime will be
925 // processed again before advancing to setValueAtTime. The number of
926 // frames to be processed should be zero in this case.
927 if (nextEvent && nextEvent->time() < currentFrame / sampleRate) {
928 // But if the current event is a SetValue event and the event time is
929 // between currentFrame - 1 and curentFrame (in time). we don't want to
930 // skip it. If we do skip it, the SetValue event is completely skipped
931 // and not applied, which is wrong. Other events don't have this problem.
932 // (Because currentFrame is unsigned, we do the time check in this funny,
933 // but equivalent way.)
934 double eventFrame = event->time() * sampleRate;
935
936 // Condition is currentFrame - 1 < eventFrame <= currentFrame, but
937 // currentFrame is unsigned and could be 0, so use
938 // currentFrame < eventFrame + 1 instead.
939 if (!((event->getType() == ParamEvent::SetValue &&
940 (eventFrame <= currentFrame) &&
941 (currentFrame < eventFrame + 1)))) {
942 // This is not the special SetValue event case, and nextEvent is
943 // in the past. We can skip processing of this event since it's
944 // in past. We keep track of this event in lastSkippedEventIndex
945 // to note what events we've skipped.
946 lastSkippedEventIndex = i;
947 continue;
948 }
949 } 853 }
950 854
951 // If there's no next event, set nextEventType to LastType to indicate that. 855 // If there's no next event, set nextEventType to LastType to indicate that.
952 ParamEvent::Type nextEventType = 856 ParamEvent::Type nextEventType =
953 nextEvent ? static_cast<ParamEvent::Type>(nextEvent->getType()) 857 nextEvent ? static_cast<ParamEvent::Type>(nextEvent->getType())
954 : ParamEvent::LastType; 858 : ParamEvent::LastType;
955 859
956 // If the current event is SetTarget and the next event is a 860 processSetTargetFollowedByRamp(i, event, nextEventType, currentFrame,
957 // LinearRampToValue or ExponentialRampToValue, special handling is needed. 861 sampleRate, controlRate, value);
958 // In this case, the linear and exponential ramp should start at wherever
959 // the SetTarget processing has reached.
960 if (event->getType() == ParamEvent::SetTarget &&
961 (nextEventType == ParamEvent::LinearRampToValue ||
962 nextEventType == ParamEvent::ExponentialRampToValue)) {
963 // Replace the SetTarget with a SetValue to set the starting time and
964 // value for the ramp using the current frame. We need to update |value|
965 // appropriately depending on whether the ramp has started or not.
966 //
967 // If SetTarget starts somewhere between currentFrame - 1 and
968 // currentFrame, we directly compute the value it would have at
969 // currentFrame. If not, we update the value from the value from
970 // currentFrame - 1.
971 //
972 // Can't use the condition currentFrame - 1 <= t0 * sampleRate <=
973 // currentFrame because currentFrame is unsigned and could be 0. Instead,
974 // compute the condition this way,
975 // where f = currentFrame and Fs = sampleRate:
976 //
977 // f - 1 <= t0 * Fs <= f
978 // 2 * f - 2 <= 2 * Fs * t0 <= 2 * f
979 // -2 <= 2 * Fs * t0 - 2 * f <= 0
980 // -1 <= 2 * Fs * t0 - 2 * f + 1 <= 1
981 // abs(2 * Fs * t0 - 2 * f + 1) <= 1
982 if (fabs(2 * sampleRate * event->time() - 2 * currentFrame + 1) <= 1) {
983 // SetTarget is starting somewhere between currentFrame - 1 and
984 // currentFrame. Compute the value the SetTarget would have at the
985 // currentFrame.
986 value = event->value() +
987 (value - event->value()) *
988 exp(-(currentFrame / sampleRate - event->time()) /
989 event->timeConstant());
990 } else {
991 // SetTarget has already started. Update |value| one frame because it's
992 // the value from the previous frame.
993 float discreteTimeConstant = static_cast<float>(
994 AudioUtilities::discreteTimeConstantForSampleRate(
995 event->timeConstant(), controlRate));
996 value += (event->value() - value) * discreteTimeConstant;
997 }
998
999 // Insert a SetValueEvent to mark the starting value and time.
1000 // Clear the clamp check because this doesn't need it.
1001 m_events[i] =
1002 ParamEvent::createSetValueEvent(value, currentFrame / sampleRate);
1003 m_events[i]->clearTimeClampCheck();
1004
1005 // Update our pointer to the current event because we just changed it.
1006 event = m_events[i].get();
1007 }
1008 862
1009 float value1 = event->value(); 863 float value1 = event->value();
1010 double time1 = event->time(); 864 double time1 = event->time();
1011 865
1012 float value2 = nextEvent ? nextEvent->value() : value1; 866 float value2 = nextEvent ? nextEvent->value() : value1;
1013 double time2 = nextEvent ? nextEvent->time() : endFrame / sampleRate + 1; 867 double time2 = nextEvent ? nextEvent->time() : endFrame / sampleRate + 1;
1014 868
1015 // Check to see if an event was cancelled. 869 // Check to see if an event was cancelled.
1016 if (nextEventType == ParamEvent::CancelValues) { 870 std::tie(value2, time2, nextEventType) =
1017 switch (event->getType()) { 871 handleCancelValues(event, nextEvent, value2, time2);
1018 case ParamEvent::LinearRampToValue:
1019 case ParamEvent::ExponentialRampToValue:
1020 case ParamEvent::SetValue: {
1021 // These three events potentially establish a starting value for
1022 // the following event, so we need to examine the cancelled
1023 // event to see what to do.
1024 const ParamEvent* savedEvent = nextEvent->savedEvent();
1025
1026 // Update the end time and type to pretend that we're running
1027 // this saved event type.
1028 time2 = nextEvent->time();
1029 nextEventType = savedEvent->getType();
1030
1031 if (nextEvent->hasDefaultCancelledValue()) {
1032 // We've already established a value for the cancelled
1033 // event, so just return it.
1034 value2 = nextEvent->value();
1035 } else {
1036 // If the next event would have been a LinearRamp or
1037 // ExponentialRamp, we need to compute a new end value for
1038 // the event so that the curve works continues as if it were
1039 // not cancelled.
1040 switch (savedEvent->getType()) {
1041 case ParamEvent::LinearRampToValue:
1042 value2 =
1043 linearRampAtTime(nextEvent->time(), value1, time1,
1044 savedEvent->value(), savedEvent->time());
1045 break;
1046 case ParamEvent::ExponentialRampToValue:
1047 value2 = exponentialRampAtTime(nextEvent->time(), value1, time1,
1048 savedEvent->value(),
1049 savedEvent->time());
1050 break;
1051 case ParamEvent::SetValueCurve:
1052 case ParamEvent::SetValue:
1053 case ParamEvent::SetTarget:
1054 case ParamEvent::CancelValues:
1055 // These cannot be possible types for the saved event
1056 // because they can't be created.
1057 // createCancelValuesEvent doesn't allow them (SetValue,
1058 // SetTarget, CancelValues) or cancelScheduledValues()
1059 // doesn't create such an event (SetValueCurve).
1060 NOTREACHED();
1061 break;
1062 case ParamEvent::LastType:
1063 // Illegal event type.
1064 NOTREACHED();
1065 break;
1066 }
1067
1068 // Cache the new value so we don't keep computing it over and over.
1069 nextEvent->setCancelledValue(value2);
1070 }
1071 } break;
1072 case ParamEvent::SetValueCurve:
1073 // Everything needed for this was handled when cancelling was
1074 // done.
1075 break;
1076 case ParamEvent::SetTarget:
1077 case ParamEvent::CancelValues:
1078 // Nothing special needs to be done for SetTarget or
1079 // CancelValues followed by CancelValues.
1080 break;
1081 case ParamEvent::LastType:
1082 NOTREACHED();
1083 break;
1084 }
1085 }
1086 872
1087 DCHECK_GE(time2, time1); 873 DCHECK_GE(time2, time1);
1088 double deltaTime = time2 - time1; 874 // double deltaTime = time2 - time1;
1089 float k = deltaTime > 0 ? 1 / deltaTime : 0; 875 // float k = deltaTime > 0 ? 1 / deltaTime : 0;
hongchan 2017/02/10 23:37:29 These are commented out.
Raymond Toy 2017/02/14 19:55:52 Done.
1090 876
1091 // |fillToEndFrame| is the exclusive upper bound of the last frame to be 877 // |fillToEndFrame| is the exclusive upper bound of the last frame to be
1092 // computed for this event. It's either the last desired frame (|endFrame|) 878 // computed for this event. It's either the last desired frame (|endFrame|)
1093 // or derived from the end time of the next event (time2). We compute 879 // or derived from the end time of the next event (time2). We compute
1094 // ceil(time2*sampleRate) because fillToEndFrame is the exclusive upper 880 // ceil(time2*sampleRate) because fillToEndFrame is the exclusive upper
1095 // bound. Consider the case where |startFrame| = 128 and time2 = 128.1 881 // bound. Consider the case where |startFrame| = 128 and time2 = 128.1
1096 // (assuming sampleRate = 1). Since time2 is greater than 128, we want to 882 // (assuming sampleRate = 1). Since time2 is greater than 128, we want to
1097 // output a value for frame 128. This requires that fillToEndFrame be at 883 // output a value for frame 128. This requires that fillToEndFrame be at
1098 // least 129. This is achieved by ceil(time2). 884 // least 129. This is achieved by ceil(time2).
1099 // 885 //
1100 // However, time2 can be very large, so compute this carefully in the case 886 // However, time2 can be very large, so compute this carefully in the case
1101 // where time2 exceeds the size of a size_t. 887 // where time2 exceeds the size of a size_t.
1102 888
1103 size_t fillToEndFrame = endFrame; 889 size_t fillToEndFrame = endFrame;
1104 if (endFrame > time2 * sampleRate) 890 if (endFrame > time2 * sampleRate)
1105 fillToEndFrame = static_cast<size_t>(ceil(time2 * sampleRate)); 891 fillToEndFrame = static_cast<size_t>(ceil(time2 * sampleRate));
1106 892
1107 DCHECK_GE(fillToEndFrame, startFrame); 893 DCHECK_GE(fillToEndFrame, startFrame);
1108 size_t fillToFrame = fillToEndFrame - startFrame; 894 size_t fillToFrame = fillToEndFrame - startFrame;
1109 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues)); 895 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues));
1110 896
897 const AutomationState currentState = {
898 numberOfValues, startFrame, endFrame, sampleRate, controlRate,
899 fillToFrame, fillToEndFrame, value1, time1, value2,
900 time2, event, i,
901 };
902
1111 // First handle linear and exponential ramps which require looking ahead to 903 // First handle linear and exponential ramps which require looking ahead to
1112 // the next event. 904 // the next event.
1113 if (nextEventType == ParamEvent::LinearRampToValue) { 905 if (nextEventType == ParamEvent::LinearRampToValue) {
1114 const float valueDelta = value2 - value1; 906 std::tie(currentFrame, value, writeIndex) = processLinearRamp(
1115 #if CPU(X86) || CPU(X86_64) 907 currentState, values, currentFrame, value, writeIndex);
1116 if (fillToFrame > writeIndex) {
1117 // Minimize in-loop operations. Calculate starting value and increment.
1118 // Next step: value += inc.
1119 // value = value1 +
1120 // (currentFrame/sampleRate - time1) * k * (value2 - value1);
1121 // inc = 4 / sampleRate * k * (value2 - value1);
1122 // Resolve recursion by expanding constants to achieve a 4-step loop
1123 // unrolling.
1124 // value = value1 +
1125 // ((currentFrame/sampleRate - time1) + i * sampleFrameTimeIncr) * k
1126 // * (value2 -value1), i in 0..3
1127 __m128 vValue =
1128 _mm_mul_ps(_mm_set_ps1(1 / sampleRate), _mm_set_ps(3, 2, 1, 0));
1129 vValue =
1130 _mm_add_ps(vValue, _mm_set_ps1(currentFrame / sampleRate - time1));
1131 vValue = _mm_mul_ps(vValue, _mm_set_ps1(k * valueDelta));
1132 vValue = _mm_add_ps(vValue, _mm_set_ps1(value1));
1133 __m128 vInc = _mm_set_ps1(4 / sampleRate * k * valueDelta);
1134
1135 // Truncate loop steps to multiple of 4.
1136 unsigned fillToFrameTrunc =
1137 writeIndex + ((fillToFrame - writeIndex) / 4) * 4;
1138 // Compute final time.
1139 DCHECK_LE(fillToFrameTrunc, numberOfValues);
1140 currentFrame += fillToFrameTrunc - writeIndex;
1141
1142 // Process 4 loop steps.
1143 for (; writeIndex < fillToFrameTrunc; writeIndex += 4) {
1144 _mm_storeu_ps(values + writeIndex, vValue);
1145 vValue = _mm_add_ps(vValue, vInc);
1146 }
1147 }
1148 // Update |value| with the last value computed so that the
1149 // .value attribute of the AudioParam gets the correct linear
1150 // ramp value, in case the following loop doesn't execute.
1151 if (writeIndex >= 1)
1152 value = values[writeIndex - 1];
1153 #endif
1154 // Serially process remaining values.
1155 for (; writeIndex < fillToFrame; ++writeIndex) {
1156 float x = (currentFrame / sampleRate - time1) * k;
1157 // value = (1 - x) * value1 + x * value2;
1158 value = value1 + x * valueDelta;
1159 values[writeIndex] = value;
1160 ++currentFrame;
1161 }
1162 } else if (nextEventType == ParamEvent::ExponentialRampToValue) { 908 } else if (nextEventType == ParamEvent::ExponentialRampToValue) {
1163 if (value1 * value2 <= 0) { 909 std::tie(currentFrame, value, writeIndex) = processExponentialRamp(
1164 // It's an error if value1 and value2 have opposite signs or if one of 910 currentState, values, currentFrame, value, writeIndex);
1165 // them is zero. Handle this by propagating the previous value, and
1166 // making it the default.
1167 value = value1;
1168
1169 for (; writeIndex < fillToFrame; ++writeIndex)
1170 values[writeIndex] = value;
1171 } else {
1172 double numSampleFrames = deltaTime * sampleRate;
1173 // The value goes exponentially from value1 to value2 in a duration of
1174 // deltaTime seconds according to
1175 //
1176 // v(t) = v1*(v2/v1)^((t-t1)/(t2-t1))
1177 //
1178 // Let c be currentFrame and F be the sampleRate. Then we want to
1179 // sample v(t) at times t = (c + k)/F for k = 0, 1, ...:
1180 //
1181 // v((c+k)/F) = v1*(v2/v1)^(((c/F+k/F)-t1)/(t2-t1))
1182 // = v1*(v2/v1)^((c/F-t1)/(t2-t1))
1183 // *(v2/v1)^((k/F)/(t2-t1))
1184 // = v1*(v2/v1)^((c/F-t1)/(t2-t1))
1185 // *[(v2/v1)^(1/(F*(t2-t1)))]^k
1186 //
1187 // Thus, this can be written as
1188 //
1189 // v((c+k)/F) = V*m^k
1190 //
1191 // where
1192 // V = v1*(v2/v1)^((c/F-t1)/(t2-t1))
1193 // m = (v2/v1)^(1/(F*(t2-t1)))
1194
1195 // Compute the per-sample multiplier.
1196 float multiplier = powf(value2 / value1, 1 / numSampleFrames);
1197 // Set the starting value of the exponential ramp.
1198 value = value1 * powf(value2 / value1,
1199 (currentFrame / sampleRate - time1) / deltaTime);
1200
1201 for (; writeIndex < fillToFrame; ++writeIndex) {
1202 values[writeIndex] = value;
1203 value *= multiplier;
1204 ++currentFrame;
1205 }
1206 // |value| got updated one extra time in the above loop. Restore it to
1207 // the last computed value.
1208 if (writeIndex >= 1)
1209 value /= multiplier;
1210
1211 // Due to roundoff it's possible that value exceeds value2. Clip value
1212 // to value2 if we are within 1/2 frame of time2.
1213 if (currentFrame > time2 * sampleRate - 0.5)
1214 value = value2;
1215 }
1216 } else { 911 } else {
1217 // Handle event types not requiring looking ahead to the next event. 912 // Handle event types not requiring looking ahead to the next event.
1218 switch (event->getType()) { 913 switch (event->getType()) {
1219 case ParamEvent::SetValue: 914 case ParamEvent::SetValue:
1220 case ParamEvent::LinearRampToValue: { 915 case ParamEvent::LinearRampToValue: {
1221 currentFrame = fillToEndFrame; 916 currentFrame = fillToEndFrame;
1222 917
1223 // Simply stay at a constant value. 918 // Simply stay at a constant value.
1224 value = event->value(); 919 value = event->value();
1225 920 writeIndex = fillWithDefault(values, value, fillToFrame, writeIndex);
1226 for (; writeIndex < fillToFrame; ++writeIndex)
1227 values[writeIndex] = value;
1228 921
1229 break; 922 break;
1230 } 923 }
1231 924
1232 case ParamEvent::CancelValues: { 925 case ParamEvent::CancelValues: {
1233 // If the previous event was a SetTarget or ExponentialRamp 926 std::tie(currentFrame, value, writeIndex) = processCancelValues(
1234 // event, the current value is one sample behind. Update 927 currentState, values, currentFrame, value, writeIndex);
1235 // the sample value by one sample, but only at the start of
1236 // this CancelValues event.
1237 if (event->hasDefaultCancelledValue()) {
1238 value = event->value();
1239 } else {
1240 double cancelFrame = time1 * sampleRate;
1241 if (i >= 1 && cancelFrame <= currentFrame &&
1242 currentFrame < cancelFrame + 1) {
1243 ParamEvent::Type lastEventType = m_events[i - 1]->getType();
1244 if (lastEventType == ParamEvent::SetTarget) {
1245 float target = m_events[i - 1]->value();
1246 float timeConstant = m_events[i - 1]->timeConstant();
1247 float discreteTimeConstant = static_cast<float>(
1248 AudioUtilities::discreteTimeConstantForSampleRate(
1249 timeConstant, controlRate));
1250 value += (target - value) * discreteTimeConstant;
1251 }
1252 }
1253 }
1254
1255 // Simply stay at the current value.
1256 for (; writeIndex < fillToFrame; ++writeIndex)
1257 values[writeIndex] = value;
1258
1259 currentFrame = fillToEndFrame;
1260 break; 928 break;
1261 } 929 }
1262 930
1263 case ParamEvent::ExponentialRampToValue: { 931 case ParamEvent::ExponentialRampToValue: {
1264 currentFrame = fillToEndFrame; 932 currentFrame = fillToEndFrame;
1265 933
1266 // If we're here, we've reached the end of the ramp. If we can 934 // If we're here, we've reached the end of the ramp. If we can
1267 // (because the start and end values have the same sign, and neither 935 // (because the start and end values have the same sign, and neither
1268 // is 0), use the actual end value. If not, we have to propagate 936 // is 0), use the actual end value. If not, we have to propagate
1269 // whatever we have. 937 // whatever we have.
1270 if (i >= 1 && ((m_events[i - 1]->value() * event->value()) > 0)) 938 if (i >= 1 && ((m_events[i - 1]->value() * event->value()) > 0))
1271 value = event->value(); 939 value = event->value();
1272 940
1273 // Simply stay at a constant value from the last time. We don't want 941 // Simply stay at a constant value from the last time. We don't want
1274 // to use the value of the event in case value1 * value2 < 0. In this 942 // to use the value of the event in case value1 * value2 < 0. In this
1275 // case we should propagate the previous value, which is in |value|. 943 // case we should propagate the previous value, which is in |value|.
1276 for (; writeIndex < fillToFrame; ++writeIndex) 944 writeIndex = fillWithDefault(values, value, fillToFrame, writeIndex);
1277 values[writeIndex] = value;
1278 945
1279 break; 946 break;
1280 } 947 }
1281 948
1282 case ParamEvent::SetTarget: { 949 case ParamEvent::SetTarget: {
1283 // Exponential approach to target value with given time constant. 950 std::tie(currentFrame, value, writeIndex) = processSetTarget(
1284 // 951 currentState, values, currentFrame, value, writeIndex);
1285 // v(t) = v2 + (v1 - v2)*exp(-(t-t1/tau))
1286 //
1287
1288 float target = event->value();
1289 float timeConstant = event->timeConstant();
1290 float discreteTimeConstant = static_cast<float>(
1291 AudioUtilities::discreteTimeConstantForSampleRate(timeConstant,
1292 controlRate));
1293
1294 // Set the starting value correctly. This is only needed when the
1295 // current time is "equal" to the start time of this event. This is
1296 // to get the sampling correct if the start time of this automation
1297 // isn't on a frame boundary. Otherwise, we can just continue from
1298 // where we left off from the previous rendering quantum.
1299 {
1300 double rampStartFrame = time1 * sampleRate;
1301 // Condition is c - 1 < r <= c where c = currentFrame and r =
1302 // rampStartFrame. Compute it this way because currentFrame is
1303 // unsigned and could be 0.
1304 if (rampStartFrame <= currentFrame &&
1305 currentFrame < rampStartFrame + 1) {
1306 value =
1307 target +
1308 (value - target) *
1309 exp(-(currentFrame / sampleRate - time1) / timeConstant);
1310 } else {
1311 // Otherwise, need to compute a new value bacause |value| is the
1312 // last computed value of SetTarget. Time has progressed by one
1313 // frame, so we need to update the value for the new frame.
1314 value += (target - value) * discreteTimeConstant;
1315 }
1316 }
1317
1318 // If the value is close enough to the target, just fill in the data
1319 // with the target value.
1320 if (fabs(value - target) < kSetTargetThreshold * fabs(target) ||
1321 (!target && fabs(value) < kSetTargetZeroThreshold)) {
1322 for (; writeIndex < fillToFrame; ++writeIndex)
1323 values[writeIndex] = target;
1324 } else {
1325 #if CPU(X86) || CPU(X86_64)
1326 if (fillToFrame > writeIndex) {
1327 // Resolve recursion by expanding constants to achieve a 4-step
1328 // loop unrolling.
1329 //
1330 // v1 = v0 + (t - v0) * c
1331 // v2 = v1 + (t - v1) * c
1332 // v2 = v0 + (t - v0) * c + (t - (v0 + (t - v0) * c)) * c
1333 // v2 = v0 + (t - v0) * c + (t - v0) * c - (t - v0) * c * c
1334 // v2 = v0 + (t - v0) * c * (2 - c)
1335 // Thus c0 = c, c1 = c*(2-c). The same logic applies to c2 and c3.
1336 const float c0 = discreteTimeConstant;
1337 const float c1 = c0 * (2 - c0);
1338 const float c2 = c0 * ((c0 - 3) * c0 + 3);
1339 const float c3 = c0 * (c0 * ((4 - c0) * c0 - 6) + 4);
1340
1341 float delta;
1342 __m128 vC = _mm_set_ps(c2, c1, c0, 0);
1343 __m128 vDelta, vValue, vResult;
1344
1345 // Process 4 loop steps.
1346 unsigned fillToFrameTrunc =
1347 writeIndex + ((fillToFrame - writeIndex) / 4) * 4;
1348 DCHECK_LE(fillToFrameTrunc, numberOfValues);
1349
1350 for (; writeIndex < fillToFrameTrunc; writeIndex += 4) {
1351 delta = target - value;
1352 vDelta = _mm_set_ps1(delta);
1353 vValue = _mm_set_ps1(value);
1354
1355 vResult = _mm_add_ps(vValue, _mm_mul_ps(vDelta, vC));
1356 _mm_storeu_ps(values + writeIndex, vResult);
1357
1358 // Update value for next iteration.
1359 value += delta * c3;
1360 }
1361 }
1362 #endif
1363 // Serially process remaining values
1364 for (; writeIndex < fillToFrame; ++writeIndex) {
1365 values[writeIndex] = value;
1366 value += (target - value) * discreteTimeConstant;
1367 }
1368 // The previous loops may have updated |value| one extra time.
1369 // Reset it to the last computed value.
1370 if (writeIndex >= 1)
1371 value = values[writeIndex - 1];
1372 currentFrame = fillToEndFrame;
1373 }
1374 break; 952 break;
1375 } 953 }
1376 954
1377 case ParamEvent::SetValueCurve: { 955 case ParamEvent::SetValueCurve: {
1378 Vector<float> curve = event->curve(); 956 std::tie(currentFrame, value, writeIndex) = processSetValueCurve(
1379 float* curveData = curve.data(); 957 currentState, values, currentFrame, value, writeIndex);
1380 unsigned numberOfCurvePoints = curve.size();
1381
1382 float curveEndValue = event->curveEndValue();
1383
1384 // Curve events have duration, so don't just use next event time.
1385 double duration = event->duration();
1386 // How much to step the curve index for each frame. This is basically
1387 // the term (N - 1)/Td in the specification.
1388 double curvePointsPerFrame =
1389 event->curvePointsPerSecond() / sampleRate;
1390
1391 if (!numberOfCurvePoints || duration <= 0 || sampleRate <= 0) {
1392 // Error condition - simply propagate previous value.
1393 currentFrame = fillToEndFrame;
1394 for (; writeIndex < fillToFrame; ++writeIndex)
1395 values[writeIndex] = value;
1396 break;
1397 }
1398
1399 // Save old values and recalculate information based on the curve's
1400 // duration instead of the next event time.
1401 size_t nextEventFillToFrame = fillToFrame;
1402
1403 // fillToEndFrame = min(endFrame,
1404 // ceil(sampleRate * (time1 + duration))),
1405 // but compute this carefully in case sampleRate*(time1 + duration) is
1406 // huge. fillToEndFrame is an exclusive upper bound of the last frame
1407 // to be computed, so ceil is used.
1408 {
1409 double curveEndFrame = ceil(sampleRate * (time1 + duration));
1410 if (endFrame > curveEndFrame)
1411 fillToEndFrame = static_cast<size_t>(curveEndFrame);
1412 else
1413 fillToEndFrame = endFrame;
1414 }
1415
1416 // |fillToFrame| can be less than |startFrame| when the end of the
1417 // setValueCurve automation has been reached, but the next automation
1418 // has not yet started. In this case, |fillToFrame| is clipped to
1419 // |time1|+|duration| above, but |startFrame| will keep increasing
1420 // (because the current time is increasing).
1421 fillToFrame =
1422 (fillToEndFrame < startFrame) ? 0 : fillToEndFrame - startFrame;
1423 fillToFrame =
1424 std::min(fillToFrame, static_cast<size_t>(numberOfValues));
1425
1426 // Index into the curve data using a floating-point value.
1427 // We're scaling the number of curve points by the duration (see
1428 // curvePointsPerFrame).
1429 double curveVirtualIndex = 0;
1430 if (time1 < currentFrame / sampleRate) {
1431 // Index somewhere in the middle of the curve data.
1432 // Don't use timeToSampleFrame() since we want the exact
1433 // floating-point frame.
1434 double frameOffset = currentFrame - time1 * sampleRate;
1435 curveVirtualIndex = curvePointsPerFrame * frameOffset;
1436 }
1437
1438 // Set the default value in case fillToFrame is 0.
1439 value = curveEndValue;
1440
1441 // Render the stretched curve data using linear interpolation.
1442 // Oversampled curve data can be provided if sharp discontinuities are
1443 // desired.
1444 unsigned k = 0;
1445 #if CPU(X86) || CPU(X86_64)
1446 if (fillToFrame > writeIndex) {
1447 const __m128 vCurveVirtualIndex = _mm_set_ps1(curveVirtualIndex);
1448 const __m128 vCurvePointsPerFrame =
1449 _mm_set_ps1(curvePointsPerFrame);
1450 const __m128 vNumberOfCurvePointsM1 =
1451 _mm_set_ps1(numberOfCurvePoints - 1);
1452 const __m128 vN1 = _mm_set_ps1(1.0f);
1453 const __m128 vN4 = _mm_set_ps1(4.0f);
1454
1455 __m128 vK = _mm_set_ps(3, 2, 1, 0);
1456 int aCurveIndex0[4];
1457 int aCurveIndex1[4];
1458
1459 // Truncate loop steps to multiple of 4
1460 unsigned truncatedSteps = ((fillToFrame - writeIndex) / 4) * 4;
1461 unsigned fillToFrameTrunc = writeIndex + truncatedSteps;
1462 DCHECK_LE(fillToFrameTrunc, numberOfValues);
1463
1464 for (; writeIndex < fillToFrameTrunc; writeIndex += 4) {
1465 // Compute current index this way to minimize round-off that would
1466 // have occurred by incrementing the index by curvePointsPerFrame.
1467 __m128 vCurrentVirtualIndex = _mm_add_ps(
1468 vCurveVirtualIndex, _mm_mul_ps(vK, vCurvePointsPerFrame));
1469 vK = _mm_add_ps(vK, vN4);
1470
1471 // Clamp index to the last element of the array.
1472 __m128i vCurveIndex0 = _mm_cvttps_epi32(
1473 _mm_min_ps(vCurrentVirtualIndex, vNumberOfCurvePointsM1));
1474 __m128i vCurveIndex1 = _mm_cvttps_epi32(
1475 _mm_min_ps(_mm_add_ps(vCurrentVirtualIndex, vN1),
1476 vNumberOfCurvePointsM1));
1477
1478 // Linearly interpolate between the two nearest curve points.
1479 // |delta| is clamped to 1 because currentVirtualIndex can exceed
1480 // curveIndex0 by more than one. This can happen when we reached
1481 // the end of the curve but still need values to fill out the
1482 // current rendering quantum.
1483 _mm_storeu_si128((__m128i*)aCurveIndex0, vCurveIndex0);
1484 _mm_storeu_si128((__m128i*)aCurveIndex1, vCurveIndex1);
1485 __m128 vC0 = _mm_set_ps(
1486 curveData[aCurveIndex0[3]], curveData[aCurveIndex0[2]],
1487 curveData[aCurveIndex0[1]], curveData[aCurveIndex0[0]]);
1488 __m128 vC1 = _mm_set_ps(
1489 curveData[aCurveIndex1[3]], curveData[aCurveIndex1[2]],
1490 curveData[aCurveIndex1[1]], curveData[aCurveIndex1[0]]);
1491 __m128 vDelta =
1492 _mm_min_ps(_mm_sub_ps(vCurrentVirtualIndex,
1493 _mm_cvtepi32_ps(vCurveIndex0)),
1494 vN1);
1495
1496 __m128 vValue =
1497 _mm_add_ps(vC0, _mm_mul_ps(_mm_sub_ps(vC1, vC0), vDelta));
1498
1499 _mm_storeu_ps(values + writeIndex, vValue);
1500 }
1501 // Pass along k to the serial loop.
1502 k = truncatedSteps;
1503 }
1504 if (writeIndex >= 1)
1505 value = values[writeIndex - 1];
1506 #endif
1507 for (; writeIndex < fillToFrame; ++writeIndex, ++k) {
1508 // Compute current index this way to minimize round-off that would
1509 // have occurred by incrementing the index by curvePointsPerFrame.
1510 double currentVirtualIndex =
1511 curveVirtualIndex + k * curvePointsPerFrame;
1512 unsigned curveIndex0;
1513
1514 // Clamp index to the last element of the array.
1515 if (currentVirtualIndex < numberOfCurvePoints) {
1516 curveIndex0 = static_cast<unsigned>(currentVirtualIndex);
1517 } else {
1518 curveIndex0 = numberOfCurvePoints - 1;
1519 }
1520
1521 unsigned curveIndex1 =
1522 std::min(curveIndex0 + 1, numberOfCurvePoints - 1);
1523
1524 // Linearly interpolate between the two nearest curve points.
1525 // |delta| is clamped to 1 because currentVirtualIndex can exceed
1526 // curveIndex0 by more than one. This can happen when we reached
1527 // the end of the curve but still need values to fill out the
1528 // current rendering quantum.
1529 DCHECK_LT(curveIndex0, numberOfCurvePoints);
1530 DCHECK_LT(curveIndex1, numberOfCurvePoints);
1531 float c0 = curveData[curveIndex0];
1532 float c1 = curveData[curveIndex1];
1533 double delta = std::min(currentVirtualIndex - curveIndex0, 1.0);
1534
1535 value = c0 + (c1 - c0) * delta;
1536
1537 values[writeIndex] = value;
1538 }
1539
1540 // If there's any time left after the duration of this event and the
1541 // start of the next, then just propagate the last value of the
1542 // curveData. Don't modify |value| unless there is time left.
1543 if (writeIndex < nextEventFillToFrame) {
1544 value = curveEndValue;
1545 for (; writeIndex < nextEventFillToFrame; ++writeIndex)
1546 values[writeIndex] = value;
1547 }
1548
1549 // Re-adjust current time
1550 currentFrame += nextEventFillToFrame;
1551
1552 break; 958 break;
1553 } 959 }
1554 case ParamEvent::LastType: 960 case ParamEvent::LastType:
1555 ASSERT_NOT_REACHED(); 961 ASSERT_NOT_REACHED();
1556 break; 962 break;
1557 } 963 }
1558 } 964 }
1559 } 965 }
1560 966
1561 // If we skipped over any events (because they are in the past), we can 967 // If we skipped over any events (because they are in the past), we can
1562 // remove them so we don't have to check them ever again. (This MUST be 968 // remove them so we don't have to check them ever again. (This MUST be
1563 // running with the m_events lock so we can safely modify the m_events 969 // running with the m_events lock so we can safely modify the m_events
1564 // array.) 970 // array.)
1565 if (lastSkippedEventIndex > 0) 971 if (lastSkippedEventIndex > 0)
1566 m_events.remove(0, lastSkippedEventIndex - 1); 972 m_events.remove(0, lastSkippedEventIndex - 1);
1567 973
1568 // If there's any time left after processing the last event then just 974 // If there's any time left after processing the last event then just
1569 // propagate the last value to the end of the values buffer. 975 // propagate the last value to the end of the values buffer.
1570 for (; writeIndex < numberOfValues; ++writeIndex) 976 writeIndex = fillWithDefault(values, value, numberOfValues, writeIndex);
1571 values[writeIndex] = value;
1572 977
1573 // This value is used to set the .value attribute of the AudioParam. it 978 // This value is used to set the .value attribute of the AudioParam. it
1574 // should be the last computed value. 979 // should be the last computed value.
1575 return values[numberOfValues - 1]; 980 return values[numberOfValues - 1];
1576 } 981 }
1577 982
983 std::tuple<size_t, unsigned> AudioParamTimeline::handleFirstEvent(
hongchan 2017/02/10 23:37:29 From this to the end, you just copied/pasted and s
Raymond Toy 2017/02/14 19:55:52 Yes, I basically copied and pasted the bodies from
984 float* values,
985 float defaultValue,
986 unsigned numberOfValues,
987 size_t startFrame,
988 size_t endFrame,
989 double sampleRate,
990 size_t currentFrame,
991 unsigned writeIndex) {
992 double firstEventTime = m_events[0]->time();
993 if (firstEventTime > startFrame / sampleRate) {
994 // |fillToFrame| is an exclusive upper bound, so use ceil() to compute the
995 // bound from the firstEventTime.
996 size_t fillToFrame = endFrame;
997 double firstEventFrame = ceil(firstEventTime * sampleRate);
998 if (endFrame > firstEventFrame)
999 fillToFrame = static_cast<size_t>(firstEventFrame);
1000 DCHECK_GE(fillToFrame, startFrame);
1001
1002 fillToFrame -= startFrame;
1003 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues));
1004 writeIndex = fillWithDefault(values, defaultValue, fillToFrame, writeIndex);
1005
1006 currentFrame += fillToFrame;
1007 }
1008
1009 return std::make_tuple(currentFrame, writeIndex);
1010 }
1011
1012 bool AudioParamTimeline::isEventCurrent(const ParamEvent* event,
1013 const ParamEvent* nextEvent,
1014 size_t currentFrame,
1015 double sampleRate) {
1016 //
hongchan 2017/02/10 23:37:29 Remove this line.
Raymond Toy 2017/02/14 19:55:52 Done.
1017 // WARNING: due to round-off it might happen that nextEvent->time() is
1018 // just larger than currentFrame/sampleRate. This means that we will end
1019 // up running the |event| again. The code below had better be prepared
1020 // for this case! What should happen is the fillToFrame should be 0 so
1021 // that while the event is actually run again, nothing actually gets
1022 // computed, and we move on to the next event.
1023 //
1024 // An example of this case is setValueCurveAtTime. The time at which
1025 // setValueCurveAtTime ends (and the setValueAtTime begins) might be
1026 // just past currentTime/sampleRate. Then setValueCurveAtTime will be
1027 // processed again before advancing to setValueAtTime. The number of
1028 // frames to be processed should be zero in this case.
1029 if (nextEvent && nextEvent->time() < currentFrame / sampleRate) {
1030 // But if the current event is a SetValue event and the event time is
1031 // between currentFrame - 1 and curentFrame (in time). we don't want to
1032 // skip it. If we do skip it, the SetValue event is completely skipped
1033 // and not applied, which is wrong. Other events don't have this problem.
1034 // (Because currentFrame is unsigned, we do the time check in this funny,
1035 // but equivalent way.)
1036 double eventFrame = event->time() * sampleRate;
1037
1038 // Condition is currentFrame - 1 < eventFrame <= currentFrame, but
1039 // currentFrame is unsigned and could be 0, so use
1040 // currentFrame < eventFrame + 1 instead.
1041 if (!((event->getType() == ParamEvent::SetValue &&
1042 (eventFrame <= currentFrame) && (currentFrame < eventFrame + 1)))) {
1043 // This is not the special SetValue event case, and nextEvent is
1044 // in the past. We can skip processing of this event since it's
1045 // in past.
1046 return false;
1047 }
1048 }
1049 return true;
1050 }
1051
1052 void AudioParamTimeline::clampToCurrentTime(int numberOfEvents,
1053 size_t startFrame,
1054 double sampleRate) {
1055 if (numberOfEvents > 0) {
1056 bool clampedSomeEventTime = false;
1057 double currentTime = startFrame / sampleRate;
1058
1059 // Look at all the events in the timeline and check to see if any needs
1060 // to clamp the start time to the current time.
1061 for (int k = 0; k < numberOfEvents; ++k) {
1062 ParamEvent* event = m_events[k].get();
1063
1064 // We're examining the event for the first time and the event time is
1065 // in the past so clamp the event time to the current time (start of
1066 // the rendering quantum).
1067 if (event->needsTimeClampCheck()) {
1068 if (event->time() < currentTime) {
1069 event->setTime(currentTime);
1070 clampedSomeEventTime = true;
1071 }
1072
1073 // In all cases, we can clear the flag because the event is either
1074 // in the future, or we've already checked it (just now).
1075 event->clearTimeClampCheck();
1076 }
1077 }
1078
1079 if (clampedSomeEventTime) {
1080 // If we clamped some event time to current time, we need to
1081 // sort the event list in time order again, but it must be
1082 // stable!
1083 std::stable_sort(m_events.begin(), m_events.end(),
1084 ParamEvent::eventPreceeds);
1085 }
1086 }
1087 }
1088
1089 bool AudioParamTimeline::handleAllEventsInThePast(double currentTime,
1090 double sampleRate,
1091 float defaultValue,
1092 unsigned numberOfValues,
1093 float* values) {
1094 // Optimize the case where the last event is in the past.
1095 ParamEvent* lastEvent = m_events[m_events.size() - 1].get();
1096 ParamEvent::Type lastEventType = lastEvent->getType();
1097 double lastEventTime = lastEvent->time();
1098
1099 // If the last event is in the past and the event has ended, then we can
1100 // just propagate the same value. Except for SetTarget which lasts
1101 // "forever". SetValueCurve also has an explicit SetValue at the end of
1102 // the curve, so we don't need to worry that SetValueCurve time is a
1103 // start time, not an end time.
1104 if (lastEventTime + 1.5 * AudioUtilities::kRenderQuantumFrames / sampleRate <
1105 currentTime &&
1106 lastEventType != ParamEvent::SetTarget) {
1107 // The event has finished, so just copy the default value out.
1108 // Since all events are now also in the past, we can just remove all
1109 // timeline events too because |defaultValue| has the expected
1110 // value.
1111 fillWithDefault(values, defaultValue, numberOfValues, 0);
1112 m_smoothedValue = defaultValue;
1113 m_events.clear();
1114 return true;
1115 }
1116
1117 return false;
1118 }
1119
1120 void AudioParamTimeline::processSetTargetFollowedByRamp(
1121 int eventIndex,
1122 ParamEvent*& event,
1123 ParamEvent::Type nextEventType,
1124 size_t currentFrame,
1125 double sampleRate,
1126 double controlRate,
1127 float& value) {
1128 // If the current event is SetTarget and the next event is a
1129 // LinearRampToValue or ExponentialRampToValue, special handling is needed.
1130 // In this case, the linear and exponential ramp should start at wherever
1131 // the SetTarget processing has reached.
1132 if (event->getType() == ParamEvent::SetTarget &&
1133 (nextEventType == ParamEvent::LinearRampToValue ||
1134 nextEventType == ParamEvent::ExponentialRampToValue)) {
1135 // Replace the SetTarget with a SetValue to set the starting time and
1136 // value for the ramp using the current frame. We need to update |value|
1137 // appropriately depending on whether the ramp has started or not.
1138 //
1139 // If SetTarget starts somewhere between currentFrame - 1 and
1140 // currentFrame, we directly compute the value it would have at
1141 // currentFrame. If not, we update the value from the value from
1142 // currentFrame - 1.
1143 //
1144 // Can't use the condition currentFrame - 1 <= t0 * sampleRate <=
1145 // currentFrame because currentFrame is unsigned and could be 0. Instead,
1146 // compute the condition this way,
1147 // where f = currentFrame and Fs = sampleRate:
1148 //
1149 // f - 1 <= t0 * Fs <= f
1150 // 2 * f - 2 <= 2 * Fs * t0 <= 2 * f
1151 // -2 <= 2 * Fs * t0 - 2 * f <= 0
1152 // -1 <= 2 * Fs * t0 - 2 * f + 1 <= 1
1153 // abs(2 * Fs * t0 - 2 * f + 1) <= 1
1154 if (fabs(2 * sampleRate * event->time() - 2 * currentFrame + 1) <= 1) {
1155 // SetTarget is starting somewhere between currentFrame - 1 and
1156 // currentFrame. Compute the value the SetTarget would have at the
1157 // currentFrame.
1158 value = event->value() +
1159 (value - event->value()) *
1160 exp(-(currentFrame / sampleRate - event->time()) /
1161 event->timeConstant());
1162 } else {
1163 // SetTarget has already started. Update |value| one frame because it's
1164 // the value from the previous frame.
1165 float discreteTimeConstant =
1166 static_cast<float>(AudioUtilities::discreteTimeConstantForSampleRate(
1167 event->timeConstant(), controlRate));
1168 value += (event->value() - value) * discreteTimeConstant;
1169 }
1170
1171 // Insert a SetValueEvent to mark the starting value and time.
1172 // Clear the clamp check because this doesn't need it.
1173 m_events[eventIndex] =
1174 ParamEvent::createSetValueEvent(value, currentFrame / sampleRate);
1175 m_events[eventIndex]->clearTimeClampCheck();
1176
1177 // Update our pointer to the current event because we just changed it.
1178 event = m_events[eventIndex].get();
1179 }
1180 }
1181
1182 std::tuple<float, double, AudioParamTimeline::ParamEvent::Type>
1183 AudioParamTimeline::handleCancelValues(const ParamEvent* currentEvent,
1184 ParamEvent* nextEvent,
1185 float value2,
1186 double time2) {
1187 DCHECK(currentEvent);
1188
1189 ParamEvent::Type nextEventType =
1190 nextEvent ? nextEvent->getType() : ParamEvent::LastType;
1191
1192 if (nextEvent && nextEvent->getType() == ParamEvent::CancelValues) {
1193 float value1 = currentEvent->value();
1194 double time1 = currentEvent->time();
1195
1196 switch (currentEvent->getType()) {
1197 case ParamEvent::LinearRampToValue:
1198 case ParamEvent::ExponentialRampToValue:
1199 case ParamEvent::SetValue: {
1200 // These three events potentially establish a starting value for
1201 // the following event, so we need to examine the cancelled
1202 // event to see what to do.
1203 const ParamEvent* savedEvent = nextEvent->savedEvent();
1204
1205 // Update the end time and type to pretend that we're running
1206 // this saved event type.
1207 time2 = nextEvent->time();
1208 nextEventType = savedEvent->getType();
1209
1210 if (nextEvent->hasDefaultCancelledValue()) {
1211 // We've already established a value for the cancelled
1212 // event, so just return it.
1213 value2 = nextEvent->value();
1214 } else {
1215 // If the next event would have been a LinearRamp or
1216 // ExponentialRamp, we need to compute a new end value for
1217 // the event so that the curve works continues as if it were
1218 // not cancelled.
1219 switch (savedEvent->getType()) {
1220 case ParamEvent::LinearRampToValue:
1221 value2 =
1222 linearRampAtTime(nextEvent->time(), value1, time1,
1223 savedEvent->value(), savedEvent->time());
1224 break;
1225 case ParamEvent::ExponentialRampToValue:
1226 value2 = exponentialRampAtTime(nextEvent->time(), value1, time1,
1227 savedEvent->value(),
1228 savedEvent->time());
1229 break;
1230 case ParamEvent::SetValueCurve:
1231 case ParamEvent::SetValue:
1232 case ParamEvent::SetTarget:
1233 case ParamEvent::CancelValues:
1234 // These cannot be possible types for the saved event
1235 // because they can't be created.
1236 // createCancelValuesEvent doesn't allow them (SetValue,
1237 // SetTarget, CancelValues) or cancelScheduledValues()
1238 // doesn't create such an event (SetValueCurve).
1239 NOTREACHED();
1240 break;
1241 case ParamEvent::LastType:
1242 // Illegal event type.
1243 NOTREACHED();
1244 break;
1245 }
1246
1247 // Cache the new value so we don't keep computing it over and over.
1248 nextEvent->setCancelledValue(value2);
1249 }
1250 } break;
1251 case ParamEvent::SetValueCurve:
1252 // Everything needed for this was handled when cancelling was
1253 // done.
1254 break;
1255 case ParamEvent::SetTarget:
1256 case ParamEvent::CancelValues:
1257 // Nothing special needs to be done for SetTarget or
1258 // CancelValues followed by CancelValues.
1259 break;
1260 case ParamEvent::LastType:
1261 NOTREACHED();
1262 break;
1263 }
1264 }
1265
1266 return std::make_tuple(value2, time2, nextEventType);
1267 }
1268
1269 std::tuple<size_t, float, unsigned> AudioParamTimeline::processLinearRamp(
1270 const AutomationState& currentState,
1271 float* values,
1272 size_t currentFrame,
1273 float value,
1274 unsigned writeIndex) {
1275 auto numberOfValues = currentState.numberOfValues;
1276 auto fillToFrame = currentState.fillToFrame;
1277 auto time1 = currentState.time1;
1278 auto time2 = currentState.time2;
1279 auto value1 = currentState.value1;
1280 auto value2 = currentState.value2;
1281 auto sampleRate = currentState.sampleRate;
1282
1283 double deltaTime = time2 - time1;
1284 float k = deltaTime > 0 ? 1 / deltaTime : 0;
1285 const float valueDelta = value2 - value1;
1286 #if CPU(X86) || CPU(X86_64)
1287 if (fillToFrame > writeIndex) {
1288 // Minimize in-loop operations. Calculate starting value and increment.
1289 // Next step: value += inc.
1290 // value = value1 +
1291 // (currentFrame/sampleRate - time1) * k * (value2 - value1);
1292 // inc = 4 / sampleRate * k * (value2 - value1);
1293 // Resolve recursion by expanding constants to achieve a 4-step loop
1294 // unrolling.
1295 // value = value1 +
1296 // ((currentFrame/sampleRate - time1) + i * sampleFrameTimeIncr) * k
1297 // * (value2 -value1), i in 0..3
1298 __m128 vValue =
1299 _mm_mul_ps(_mm_set_ps1(1 / sampleRate), _mm_set_ps(3, 2, 1, 0));
1300 vValue = _mm_add_ps(vValue, _mm_set_ps1(currentFrame / sampleRate - time1));
1301 vValue = _mm_mul_ps(vValue, _mm_set_ps1(k * valueDelta));
1302 vValue = _mm_add_ps(vValue, _mm_set_ps1(value1));
1303 __m128 vInc = _mm_set_ps1(4 / sampleRate * k * valueDelta);
1304
1305 // Truncate loop steps to multiple of 4.
1306 unsigned fillToFrameTrunc =
1307 writeIndex + ((fillToFrame - writeIndex) / 4) * 4;
1308 // Compute final time.
1309 DCHECK_LE(fillToFrameTrunc, numberOfValues);
1310 currentFrame += fillToFrameTrunc - writeIndex;
1311
1312 // Process 4 loop steps.
1313 for (; writeIndex < fillToFrameTrunc; writeIndex += 4) {
1314 _mm_storeu_ps(values + writeIndex, vValue);
1315 vValue = _mm_add_ps(vValue, vInc);
1316 }
1317 }
1318 // Update |value| with the last value computed so that the
1319 // .value attribute of the AudioParam gets the correct linear
1320 // ramp value, in case the following loop doesn't execute.
1321 if (writeIndex >= 1)
1322 value = values[writeIndex - 1];
1323 #endif
1324 // Serially process remaining values.
1325 for (; writeIndex < fillToFrame; ++writeIndex) {
1326 float x = (currentFrame / sampleRate - time1) * k;
1327 // value = (1 - x) * value1 + x * value2;
1328 value = value1 + x * valueDelta;
1329 values[writeIndex] = value;
1330 ++currentFrame;
1331 }
1332
1333 return std::make_tuple(currentFrame, value, writeIndex);
1334 }
1335
1336 std::tuple<size_t, float, unsigned> AudioParamTimeline::processExponentialRamp(
1337 const AutomationState& currentState,
1338 float* values,
1339 size_t currentFrame,
1340 float value,
1341 unsigned writeIndex) {
1342 auto fillToFrame = currentState.fillToFrame;
1343 auto time1 = currentState.time1;
1344 auto time2 = currentState.time2;
1345 auto value1 = currentState.value1;
1346 auto value2 = currentState.value2;
1347 auto sampleRate = currentState.sampleRate;
1348
1349 if (value1 * value2 <= 0) {
1350 // It's an error if value1 and value2 have opposite signs or if one of
1351 // them is zero. Handle this by propagating the previous value, and
1352 // making it the default.
1353 value = value1;
1354
1355 for (; writeIndex < fillToFrame; ++writeIndex)
1356 values[writeIndex] = value;
1357 } else {
1358 double deltaTime = time2 - time1;
1359 double numSampleFrames = deltaTime * sampleRate;
1360 // The value goes exponentially from value1 to value2 in a duration of
1361 // deltaTime seconds according to
1362 //
1363 // v(t) = v1*(v2/v1)^((t-t1)/(t2-t1))
1364 //
1365 // Let c be currentFrame and F be the sampleRate. Then we want to
1366 // sample v(t) at times t = (c + k)/F for k = 0, 1, ...:
1367 //
1368 // v((c+k)/F) = v1*(v2/v1)^(((c/F+k/F)-t1)/(t2-t1))
1369 // = v1*(v2/v1)^((c/F-t1)/(t2-t1))
1370 // *(v2/v1)^((k/F)/(t2-t1))
1371 // = v1*(v2/v1)^((c/F-t1)/(t2-t1))
1372 // *[(v2/v1)^(1/(F*(t2-t1)))]^k
1373 //
1374 // Thus, this can be written as
1375 //
1376 // v((c+k)/F) = V*m^k
1377 //
1378 // where
1379 // V = v1*(v2/v1)^((c/F-t1)/(t2-t1))
1380 // m = (v2/v1)^(1/(F*(t2-t1)))
1381
1382 // Compute the per-sample multiplier.
1383 float multiplier = powf(value2 / value1, 1 / numSampleFrames);
1384 // Set the starting value of the exponential ramp.
1385 value = value1 * powf(value2 / value1,
1386 (currentFrame / sampleRate - time1) / deltaTime);
1387
1388 for (; writeIndex < fillToFrame; ++writeIndex) {
1389 values[writeIndex] = value;
1390 value *= multiplier;
1391 ++currentFrame;
1392 }
1393 // |value| got updated one extra time in the above loop. Restore it to
1394 // the last computed value.
1395 if (writeIndex >= 1)
1396 value /= multiplier;
1397
1398 // Due to roundoff it's possible that value exceeds value2. Clip value
1399 // to value2 if we are within 1/2 frame of time2.
1400 if (currentFrame > time2 * sampleRate - 0.5)
1401 value = value2;
1402 }
1403
1404 return std::make_tuple(currentFrame, value, writeIndex);
1405 }
1406
1407 std::tuple<size_t, float, unsigned> AudioParamTimeline::processSetTarget(
1408 const AutomationState& currentState,
1409 float* values,
1410 size_t currentFrame,
1411 float value,
1412 unsigned writeIndex) {
1413 auto numberOfValues = currentState.numberOfValues;
1414 auto fillToFrame = currentState.fillToFrame;
1415 auto time1 = currentState.time1;
1416 auto value1 = currentState.value1;
1417 auto sampleRate = currentState.sampleRate;
1418 auto controlRate = currentState.controlRate;
1419 auto fillToEndFrame = currentState.fillToEndFrame;
1420 auto event = currentState.event;
1421
1422 // Exponential approach to target value with given time constant.
1423 //
1424 // v(t) = v2 + (v1 - v2)*exp(-(t-t1/tau))
1425 //
1426 float target = value1;
1427 float timeConstant = event->timeConstant();
1428 float discreteTimeConstant =
1429 static_cast<float>(AudioUtilities::discreteTimeConstantForSampleRate(
1430 timeConstant, controlRate));
1431
1432 // Set the starting value correctly. This is only needed when the
1433 // current time is "equal" to the start time of this event. This is
1434 // to get the sampling correct if the start time of this automation
1435 // isn't on a frame boundary. Otherwise, we can just continue from
1436 // where we left off from the previous rendering quantum.
1437 {
1438 double rampStartFrame = time1 * sampleRate;
1439 // Condition is c - 1 < r <= c where c = currentFrame and r =
1440 // rampStartFrame. Compute it this way because currentFrame is
1441 // unsigned and could be 0.
1442 if (rampStartFrame <= currentFrame && currentFrame < rampStartFrame + 1) {
1443 value = target +
1444 (value - target) *
1445 exp(-(currentFrame / sampleRate - time1) / timeConstant);
1446 } else {
1447 // Otherwise, need to compute a new value bacause |value| is the
1448 // last computed value of SetTarget. Time has progressed by one
1449 // frame, so we need to update the value for the new frame.
1450 value += (target - value) * discreteTimeConstant;
1451 }
1452 }
1453
1454 // If the value is close enough to the target, just fill in the data
1455 // with the target value.
1456 if (fabs(value - target) < kSetTargetThreshold * fabs(target) ||
1457 (!target && fabs(value) < kSetTargetZeroThreshold)) {
1458 for (; writeIndex < fillToFrame; ++writeIndex)
1459 values[writeIndex] = target;
1460 } else {
1461 #if CPU(X86) || CPU(X86_64)
1462 if (fillToFrame > writeIndex) {
1463 // Resolve recursion by expanding constants to achieve a 4-step
1464 // loop unrolling.
1465 //
1466 // v1 = v0 + (t - v0) * c
1467 // v2 = v1 + (t - v1) * c
1468 // v2 = v0 + (t - v0) * c + (t - (v0 + (t - v0) * c)) * c
1469 // v2 = v0 + (t - v0) * c + (t - v0) * c - (t - v0) * c * c
1470 // v2 = v0 + (t - v0) * c * (2 - c)
1471 // Thus c0 = c, c1 = c*(2-c). The same logic applies to c2 and c3.
1472 const float c0 = discreteTimeConstant;
1473 const float c1 = c0 * (2 - c0);
1474 const float c2 = c0 * ((c0 - 3) * c0 + 3);
1475 const float c3 = c0 * (c0 * ((4 - c0) * c0 - 6) + 4);
1476
1477 float delta;
1478 __m128 vC = _mm_set_ps(c2, c1, c0, 0);
1479 __m128 vDelta, vValue, vResult;
1480
1481 // Process 4 loop steps.
1482 unsigned fillToFrameTrunc =
1483 writeIndex + ((fillToFrame - writeIndex) / 4) * 4;
1484 DCHECK_LE(fillToFrameTrunc, numberOfValues);
1485
1486 for (; writeIndex < fillToFrameTrunc; writeIndex += 4) {
1487 delta = target - value;
1488 vDelta = _mm_set_ps1(delta);
1489 vValue = _mm_set_ps1(value);
1490
1491 vResult = _mm_add_ps(vValue, _mm_mul_ps(vDelta, vC));
1492 _mm_storeu_ps(values + writeIndex, vResult);
1493
1494 // Update value for next iteration.
1495 value += delta * c3;
1496 }
1497 }
1498 #endif
1499 // Serially process remaining values
1500 for (; writeIndex < fillToFrame; ++writeIndex) {
1501 values[writeIndex] = value;
1502 value += (target - value) * discreteTimeConstant;
1503 }
1504 // The previous loops may have updated |value| one extra time.
1505 // Reset it to the last computed value.
1506 if (writeIndex >= 1)
1507 value = values[writeIndex - 1];
1508 currentFrame = fillToEndFrame;
1509 }
1510
1511 return std::make_tuple(currentFrame, value, writeIndex);
1512 }
1513
1514 std::tuple<size_t, float, unsigned> AudioParamTimeline::processSetValueCurve(
1515 const AutomationState& currentState,
1516 float* values,
1517 size_t currentFrame,
1518 float value,
1519 unsigned writeIndex) {
1520 auto numberOfValues = currentState.numberOfValues;
1521 auto fillToFrame = currentState.fillToFrame;
1522 auto time1 = currentState.time1;
1523 auto sampleRate = currentState.sampleRate;
1524 auto startFrame = currentState.startFrame;
1525 auto endFrame = currentState.endFrame;
1526 auto fillToEndFrame = currentState.fillToEndFrame;
1527 auto event = currentState.event;
1528
1529 const Vector<float> curve = event->curve();
1530 const float* curveData = curve.data();
1531 unsigned numberOfCurvePoints = curve.size();
1532
1533 float curveEndValue = event->curveEndValue();
1534
1535 // Curve events have duration, so don't just use next event time.
1536 double duration = event->duration();
1537 // How much to step the curve index for each frame. This is basically
1538 // the term (N - 1)/Td in the specification.
1539 double curvePointsPerFrame = event->curvePointsPerSecond() / sampleRate;
1540
1541 if (!numberOfCurvePoints || duration <= 0 || sampleRate <= 0) {
1542 // Error condition - simply propagate previous value.
1543 currentFrame = fillToEndFrame;
1544 for (; writeIndex < fillToFrame; ++writeIndex)
1545 values[writeIndex] = value;
1546 return std::make_tuple(currentFrame, value, writeIndex);
1547 }
1548
1549 // Save old values and recalculate information based on the curve's
1550 // duration instead of the next event time.
1551 size_t nextEventFillToFrame = fillToFrame;
1552
1553 // fillToEndFrame = min(endFrame,
1554 // ceil(sampleRate * (time1 + duration))),
1555 // but compute this carefully in case sampleRate*(time1 + duration) is
1556 // huge. fillToEndFrame is an exclusive upper bound of the last frame
1557 // to be computed, so ceil is used.
1558 {
1559 double curveEndFrame = ceil(sampleRate * (time1 + duration));
1560 if (endFrame > curveEndFrame)
1561 fillToEndFrame = static_cast<size_t>(curveEndFrame);
1562 else
1563 fillToEndFrame = endFrame;
1564 }
1565
1566 // |fillToFrame| can be less than |startFrame| when the end of the
1567 // setValueCurve automation has been reached, but the next automation
1568 // has not yet started. In this case, |fillToFrame| is clipped to
1569 // |time1|+|duration| above, but |startFrame| will keep increasing
1570 // (because the current time is increasing).
1571 fillToFrame = (fillToEndFrame < startFrame) ? 0 : fillToEndFrame - startFrame;
1572 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues));
1573
1574 // Index into the curve data using a floating-point value.
1575 // We're scaling the number of curve points by the duration (see
1576 // curvePointsPerFrame).
1577 double curveVirtualIndex = 0;
1578 if (time1 < currentFrame / sampleRate) {
1579 // Index somewhere in the middle of the curve data.
1580 // Don't use timeToSampleFrame() since we want the exact
1581 // floating-point frame.
1582 double frameOffset = currentFrame - time1 * sampleRate;
1583 curveVirtualIndex = curvePointsPerFrame * frameOffset;
1584 }
1585
1586 // Set the default value in case fillToFrame is 0.
1587 value = curveEndValue;
1588
1589 // Render the stretched curve data using linear interpolation.
1590 // Oversampled curve data can be provided if sharp discontinuities are
1591 // desired.
1592 unsigned k = 0;
1593 #if CPU(X86) || CPU(X86_64)
1594 if (fillToFrame > writeIndex) {
1595 const __m128 vCurveVirtualIndex = _mm_set_ps1(curveVirtualIndex);
1596 const __m128 vCurvePointsPerFrame = _mm_set_ps1(curvePointsPerFrame);
1597 const __m128 vNumberOfCurvePointsM1 = _mm_set_ps1(numberOfCurvePoints - 1);
1598 const __m128 vN1 = _mm_set_ps1(1.0f);
1599 const __m128 vN4 = _mm_set_ps1(4.0f);
1600
1601 __m128 vK = _mm_set_ps(3, 2, 1, 0);
1602 int aCurveIndex0[4];
1603 int aCurveIndex1[4];
1604
1605 // Truncate loop steps to multiple of 4
1606 unsigned truncatedSteps = ((fillToFrame - writeIndex) / 4) * 4;
1607 unsigned fillToFrameTrunc = writeIndex + truncatedSteps;
1608 DCHECK_LE(fillToFrameTrunc, numberOfValues);
1609
1610 for (; writeIndex < fillToFrameTrunc; writeIndex += 4) {
1611 // Compute current index this way to minimize round-off that would
1612 // have occurred by incrementing the index by curvePointsPerFrame.
1613 __m128 vCurrentVirtualIndex =
1614 _mm_add_ps(vCurveVirtualIndex, _mm_mul_ps(vK, vCurvePointsPerFrame));
1615 vK = _mm_add_ps(vK, vN4);
1616
1617 // Clamp index to the last element of the array.
1618 __m128i vCurveIndex0 = _mm_cvttps_epi32(
1619 _mm_min_ps(vCurrentVirtualIndex, vNumberOfCurvePointsM1));
1620 __m128i vCurveIndex1 = _mm_cvttps_epi32(_mm_min_ps(
1621 _mm_add_ps(vCurrentVirtualIndex, vN1), vNumberOfCurvePointsM1));
1622
1623 // Linearly interpolate between the two nearest curve points.
1624 // |delta| is clamped to 1 because currentVirtualIndex can exceed
1625 // curveIndex0 by more than one. This can happen when we reached
1626 // the end of the curve but still need values to fill out the
1627 // current rendering quantum.
1628 _mm_storeu_si128((__m128i*)aCurveIndex0, vCurveIndex0);
1629 _mm_storeu_si128((__m128i*)aCurveIndex1, vCurveIndex1);
1630 __m128 vC0 =
1631 _mm_set_ps(curveData[aCurveIndex0[3]], curveData[aCurveIndex0[2]],
1632 curveData[aCurveIndex0[1]], curveData[aCurveIndex0[0]]);
1633 __m128 vC1 =
1634 _mm_set_ps(curveData[aCurveIndex1[3]], curveData[aCurveIndex1[2]],
1635 curveData[aCurveIndex1[1]], curveData[aCurveIndex1[0]]);
1636 __m128 vDelta = _mm_min_ps(
1637 _mm_sub_ps(vCurrentVirtualIndex, _mm_cvtepi32_ps(vCurveIndex0)), vN1);
1638
1639 __m128 vValue = _mm_add_ps(vC0, _mm_mul_ps(_mm_sub_ps(vC1, vC0), vDelta));
1640
1641 _mm_storeu_ps(values + writeIndex, vValue);
1642 }
1643 // Pass along k to the serial loop.
1644 k = truncatedSteps;
1645 }
1646 if (writeIndex >= 1)
1647 value = values[writeIndex - 1];
1648 #endif
1649 for (; writeIndex < fillToFrame; ++writeIndex, ++k) {
1650 // Compute current index this way to minimize round-off that would
1651 // have occurred by incrementing the index by curvePointsPerFrame.
1652 double currentVirtualIndex = curveVirtualIndex + k * curvePointsPerFrame;
1653 unsigned curveIndex0;
1654
1655 // Clamp index to the last element of the array.
1656 if (currentVirtualIndex < numberOfCurvePoints) {
1657 curveIndex0 = static_cast<unsigned>(currentVirtualIndex);
1658 } else {
1659 curveIndex0 = numberOfCurvePoints - 1;
1660 }
1661
1662 unsigned curveIndex1 = std::min(curveIndex0 + 1, numberOfCurvePoints - 1);
1663
1664 // Linearly interpolate between the two nearest curve points.
1665 // |delta| is clamped to 1 because currentVirtualIndex can exceed
1666 // curveIndex0 by more than one. This can happen when we reached
1667 // the end of the curve but still need values to fill out the
1668 // current rendering quantum.
1669 DCHECK_LT(curveIndex0, numberOfCurvePoints);
1670 DCHECK_LT(curveIndex1, numberOfCurvePoints);
1671 float c0 = curveData[curveIndex0];
1672 float c1 = curveData[curveIndex1];
1673 double delta = std::min(currentVirtualIndex - curveIndex0, 1.0);
1674
1675 value = c0 + (c1 - c0) * delta;
1676
1677 values[writeIndex] = value;
1678 }
1679
1680 // If there's any time left after the duration of this event and the
1681 // start of the next, then just propagate the last value of the
1682 // curveData. Don't modify |value| unless there is time left.
1683 if (writeIndex < nextEventFillToFrame) {
1684 value = curveEndValue;
1685 for (; writeIndex < nextEventFillToFrame; ++writeIndex)
1686 values[writeIndex] = value;
1687 }
1688
1689 // Re-adjust current time
1690 currentFrame += nextEventFillToFrame;
1691
1692 return std::make_tuple(currentFrame, value, writeIndex);
1693 }
1694
1695 std::tuple<size_t, float, unsigned> AudioParamTimeline::processCancelValues(
1696 const AutomationState& currentState,
1697 float* values,
1698 size_t currentFrame,
1699 float value,
1700 unsigned writeIndex) {
1701 auto fillToFrame = currentState.fillToFrame;
1702 auto time1 = currentState.time1;
1703 auto sampleRate = currentState.sampleRate;
1704 auto controlRate = currentState.controlRate;
1705 auto fillToEndFrame = currentState.fillToEndFrame;
1706 auto event = currentState.event;
1707 auto eventIndex = currentState.eventIndex;
1708
1709 // If the previous event was a SetTarget or ExponentialRamp
1710 // event, the current value is one sample behind. Update
1711 // the sample value by one sample, but only at the start of
1712 // this CancelValues event.
1713 if (event->hasDefaultCancelledValue()) {
1714 value = event->value();
1715 } else {
1716 double cancelFrame = time1 * sampleRate;
1717 if (eventIndex >= 1 && cancelFrame <= currentFrame &&
1718 currentFrame < cancelFrame + 1) {
1719 ParamEvent::Type lastEventType = m_events[eventIndex - 1]->getType();
1720 if (lastEventType == ParamEvent::SetTarget) {
1721 float target = m_events[eventIndex - 1]->value();
1722 float timeConstant = m_events[eventIndex - 1]->timeConstant();
1723 float discreteTimeConstant = static_cast<float>(
1724 AudioUtilities::discreteTimeConstantForSampleRate(timeConstant,
1725 controlRate));
1726 value += (target - value) * discreteTimeConstant;
1727 }
1728 }
1729 }
1730
1731 // Simply stay at the current value.
1732 for (; writeIndex < fillToFrame; ++writeIndex)
1733 values[writeIndex] = value;
1734
1735 currentFrame = fillToEndFrame;
1736
1737 return std::make_tuple(currentFrame, value, writeIndex);
1738 }
1739
1740 unsigned AudioParamTimeline::fillWithDefault(float* values,
1741 float defaultValue,
1742 size_t endFrame,
1743 unsigned writeIndex) {
1744 size_t index = writeIndex;
1745
1746 for (; index < endFrame; ++index)
1747 values[index] = defaultValue;
1748
1749 return index;
1750 }
1751
1578 } // namespace blink 1752 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698