| 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; | |
| 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 |
| OLD | NEW |