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

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

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

Powered by Google App Engine
This is Rietveld 408576698