Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 |
| OLD | NEW |