Index: third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp |
diff --git a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp |
index 4746187d04c7ff57a88d2c5254bb6408fa236261..35731182aa8088b21deb7f47a87c1c8cdf21436e 100644 |
--- a/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp |
+++ b/third_party/WebKit/Source/modules/webaudio/AudioParamTimeline.cpp |
@@ -37,17 +37,19 @@ |
namespace blink { |
-// For a SetTarget event, if the relative difference between the current value and the target value |
-// is less than this, consider them the same and just output the target value. This value MUST be |
-// larger than the single precision epsilon of 5.960465e-8. Due to round-off, this value is not |
-// achievable in general. This value can vary across the platforms (CPU) and thus it is determined |
-// experimentally. |
+// For a SetTarget event, if the relative difference between the current value |
+// and the target value is less than this, consider them the same and just |
+// output the target value. This value MUST be larger than the single precision |
+// epsilon of 5.960465e-8. Due to round-off, this value is not achievable in |
+// general. This value can vary across the platforms (CPU) and thus it is |
+// determined experimentally. |
const float kSetTargetThreshold = 1.5e-6; |
-// For a SetTarget event, if the target value is 0, and the current value is less than this |
-// threshold, consider the curve to have converged to 0. We need a separate case from |
-// kSetTargetThreshold because that uses relative error, which is never met if the target value is |
-// 0, a common case. This value MUST be larger than least positive normalized single precision |
+// For a SetTarget event, if the target value is 0, and the current value is |
+// less than this threshold, consider the curve to have converged to 0. We need |
+// a separate case from kSetTargetThreshold because that uses relative error, |
+// which is never met if the target value is 0, a common case. This value MUST |
+// be larger than least positive normalized single precision |
// value (1.1754944e-38) because we normally operate with flush-to-zero enabled. |
const float kSetTargetZeroThreshold = 1e-20; |
@@ -76,7 +78,8 @@ static bool isPositiveAudioParamTime(double time, |
} |
String AudioParamTimeline::eventToString(const ParamEvent& event) { |
- // The default arguments for most automation methods is the value and the time. |
+ // The default arguments for most automation methods is the value and the |
+ // time. |
String args = |
String::number(event.value()) + ", " + String::number(event.time(), 16); |
@@ -273,8 +276,8 @@ void AudioParamTimeline::insertEvent(const ParamEvent& event, |
ExceptionState& exceptionState) { |
DCHECK(isMainThread()); |
- // Sanity check the event. Be super careful we're not getting infected with NaN or Inf. These |
- // should have been handled by the caller. |
+ // Sanity check the event. Be super careful we're not getting infected with |
+ // NaN or Inf. These should have been handled by the caller. |
bool isValid = event.getType() < ParamEvent::LastType && |
std::isfinite(event.value()) && std::isfinite(event.time()) && |
std::isfinite(event.timeConstant()) && |
@@ -292,17 +295,17 @@ void AudioParamTimeline::insertEvent(const ParamEvent& event, |
if (!m_events.size() && |
(event.getType() == ParamEvent::LinearRampToValue || |
event.getType() == ParamEvent::ExponentialRampToValue)) { |
- // There are no events preceding these ramps. Insert a new setValueAtTime event to set the |
- // starting point for these events. |
+ // There are no events preceding these ramps. Insert a new setValueAtTime |
+ // event to set the starting point for these events. |
m_events.insert(0, AudioParamTimeline::ParamEvent::createSetValueEvent( |
event.initialValue(), event.callTime())); |
} |
for (i = 0; i < m_events.size(); ++i) { |
if (event.getType() == ParamEvent::SetValueCurve) { |
- // If this event is a SetValueCurve, make sure it doesn't overlap any existing |
- // event. It's ok if the SetValueCurve starts at the same time as the end of some other |
- // duration. |
+ // If this event is a SetValueCurve, make sure it doesn't overlap any |
+ // existing event. It's ok if the SetValueCurve starts at the same time as |
+ // the end of some other duration. |
double endTime = event.time() + event.duration(); |
if (m_events[i].time() > event.time() && m_events[i].time() < endTime) { |
exceptionState.throwDOMException( |
@@ -311,7 +314,8 @@ void AudioParamTimeline::insertEvent(const ParamEvent& event, |
return; |
} |
} else { |
- // Otherwise, make sure this event doesn't overlap any existing SetValueCurve event. |
+ // Otherwise, make sure this event doesn't overlap any existing |
+ // SetValueCurve event. |
if (m_events[i].getType() == ParamEvent::SetValueCurve) { |
double endTime = m_events[i].time() + m_events[i].duration(); |
if (event.time() >= m_events[i].time() && event.time() < endTime) { |
@@ -343,17 +347,19 @@ bool AudioParamTimeline::hasValues() const { |
if (tryLocker.locked()) |
return m_events.size(); |
- // Can't get the lock so that means the main thread is trying to insert an event. Just |
- // return true then. If the main thread releases the lock before valueForContextTime or |
- // valuesForFrameRange runs, then the there will be an event on the timeline, so everything |
- // is fine. If the lock is held so that neither valueForContextTime nor valuesForFrameRange |
- // can run, this is ok too, because they have tryLocks to produce a default value. The |
- // event will then get processed in the next rendering quantum. |
+ // Can't get the lock so that means the main thread is trying to insert an |
+ // event. Just return true then. If the main thread releases the lock before |
+ // valueForContextTime or valuesForFrameRange runs, then the there will be an |
+ // event on the timeline, so everything is fine. If the lock is held so that |
+ // neither valueForContextTime nor valuesForFrameRange can run, this is ok |
+ // too, because they have tryLocks to produce a default value. The event will |
+ // then get processed in the next rendering quantum. |
// |
- // Don't want to return false here because that would confuse the processing of the timeline |
- // if previously we returned true and now suddenly return false, only to return true on the |
- // next rendering quantum. Currently, once a timeline has been introduced it is always true |
- // forever because m_events never shrinks. |
+ // Don't want to return false here because that would confuse the processing |
+ // of the timeline if previously we returned true and now suddenly return |
+ // false, only to return true on the next rendering quantum. Currently, once |
+ // a timeline has been introduced it is always true forever because m_events |
+ // never shrinks. |
return true; |
} |
@@ -391,10 +397,8 @@ float AudioParamTimeline::valueForContextTime( |
float value; |
double sampleRate = audioDestination.sampleRate(); |
size_t startFrame = audioDestination.currentSampleFrame(); |
- double controlRate = |
- sampleRate / |
- AudioHandler:: |
- ProcessingSizeInFrames; // one parameter change per render quantum |
+ // One parameter change per render quantum. |
+ double controlRate = sampleRate / AudioHandler::ProcessingSizeInFrames; |
value = valuesForFrameRange(startFrame, startFrame + 1, defaultValue, &value, |
1, sampleRate, controlRate, minValue, maxValue); |
@@ -444,7 +448,8 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
if (!values || !(numberOfValues >= 1)) |
return defaultValue; |
- // Return default value if there are no events matching the desired time range. |
+ // Return default value if there are no events matching the desired time |
+ // range. |
if (!m_events.size() || (endFrame / sampleRate <= m_events[0].time())) { |
for (unsigned i = 0; i < numberOfValues; ++i) |
values[i] = defaultValue; |
@@ -480,12 +485,12 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
size_t currentFrame = startFrame; |
unsigned writeIndex = 0; |
- // If first event is after startFrame then fill initial part of values buffer with defaultValue |
- // until we reach the first event time. |
+ // If first event is after startFrame then fill initial part of values buffer |
+ // with defaultValue until we reach the first event time. |
double firstEventTime = m_events[0].time(); |
if (firstEventTime > startFrame / sampleRate) { |
- // |fillToFrame| is an exclusive upper bound, so use ceil() to compute the bound from the |
- // firstEventTime. |
+ // |fillToFrame| is an exclusive upper bound, so use ceil() to compute the |
+ // bound from the firstEventTime. |
size_t fillToFrame = endFrame; |
double firstEventFrame = ceil(firstEventTime * sampleRate); |
if (endFrame > firstEventFrame) |
@@ -525,15 +530,17 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
// processed again before advancing to setValueAtTime. The number of |
// frames to be processed should be zero in this case. |
if (nextEvent && nextEvent->time() < currentFrame / sampleRate) { |
- // But if the current event is a SetValue event and the event time is between |
- // currentFrame - 1 and curentFrame (in time). we don't want to skip it. If we do skip |
- // it, the SetValue event is completely skipped and not applied, which is wrong. Other |
- // events don't have this problem. (Because currentFrame is unsigned, we do the time |
- // check in this funny, but equivalent way.) |
+ // But if the current event is a SetValue event and the event time is |
+ // between currentFrame - 1 and curentFrame (in time). we don't want to |
+ // skip it. If we do skip it, the SetValue event is completely skipped |
+ // and not applied, which is wrong. Other events don't have this problem. |
+ // (Because currentFrame is unsigned, we do the time check in this funny, |
+ // but equivalent way.) |
double eventFrame = event.time() * sampleRate; |
- // Condition is currentFrame - 1 < eventFrame <= currentFrame, but currentFrame is |
- // unsigned and could be 0, so use currentFrame < eventFrame + 1 instead. |
+ // Condition is currentFrame - 1 < eventFrame <= currentFrame, but |
+ // currentFrame is unsigned and could be 0, so use |
+ // currentFrame < eventFrame + 1 instead. |
if (!((event.getType() == ParamEvent::SetValue && |
(eventFrame <= currentFrame) && |
(currentFrame < eventFrame + 1)))) { |
@@ -551,22 +558,25 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
nextEvent ? static_cast<ParamEvent::Type>(nextEvent->getType()) |
: ParamEvent::LastType; |
- // If the current event is SetTarget and the next event is a LinearRampToValue or |
- // ExponentialRampToValue, special handling is needed. In this case, the linear and |
- // exponential ramp should start at wherever the SetTarget processing has reached. |
+ // If the current event is SetTarget and the next event is a |
+ // LinearRampToValue or ExponentialRampToValue, special handling is needed. |
+ // In this case, the linear and exponential ramp should start at wherever |
+ // the SetTarget processing has reached. |
if (event.getType() == ParamEvent::SetTarget && |
(nextEventType == ParamEvent::LinearRampToValue || |
nextEventType == ParamEvent::ExponentialRampToValue)) { |
- // Replace the SetTarget with a SetValue to set the starting time and value for the ramp |
- // using the current frame. We need to update |value| appropriately depending on |
- // whether the ramp has started or not. |
+ // Replace the SetTarget with a SetValue to set the starting time and |
+ // value for the ramp using the current frame. We need to update |value| |
+ // appropriately depending on whether the ramp has started or not. |
// |
- // If SetTarget starts somewhere between currentFrame - 1 and currentFrame, we directly |
- // compute the value it would have at currentFrame. If not, we update the value from |
- // the value from currentFrame - 1. |
+ // If SetTarget starts somewhere between currentFrame - 1 and |
+ // currentFrame, we directly compute the value it would have at |
+ // currentFrame. If not, we update the value from the value from |
+ // currentFrame - 1. |
// |
- // Can't use the condition currentFrame - 1 <= t0 * sampleRate <= currentFrame because |
- // currentFrame is unsigned and could be 0. Instead, compute the condition this way, |
+ // Can't use the condition currentFrame - 1 <= t0 * sampleRate <= |
+ // currentFrame because currentFrame is unsigned and could be 0. Instead, |
+ // compute the condition this way, |
// where f = currentFrame and Fs = sampleRate: |
// |
// f - 1 <= t0 * Fs <= f |
@@ -576,14 +586,15 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
// abs(2 * Fs * t0 - 2 * f + 1) <= 1 |
if (fabs(2 * sampleRate * event.time() - 2 * currentFrame + 1) <= 1) { |
// SetTarget is starting somewhere between currentFrame - 1 and |
- // currentFrame. Compute the value the SetTarget would have at the currentFrame. |
+ // currentFrame. Compute the value the SetTarget would have at the |
+ // currentFrame. |
value = event.value() + |
(value - event.value()) * |
exp(-(currentFrame / sampleRate - event.time()) / |
event.timeConstant()); |
} else { |
- // SetTarget has already started. Update |value| one frame because it's the value from |
- // the previous frame. |
+ // SetTarget has already started. Update |value| one frame because it's |
+ // the value from the previous frame. |
float discreteTimeConstant = static_cast<float>( |
AudioUtilities::discreteTimeConstantForSampleRate( |
event.timeConstant(), controlRate)); |
@@ -602,16 +613,17 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
double deltaTime = time2 - time1; |
float k = deltaTime > 0 ? 1 / deltaTime : 0; |
- // |fillToEndFrame| is the exclusive upper bound of the last frame to be computed for this |
- // event. It's either the last desired frame (|endFrame|) or derived from the end time of |
- // the next event (time2). We compute ceil(time2*sampleRate) because fillToEndFrame is the |
- // exclusive upper bound. Consider the case where |startFrame| = 128 and time2 = 128.1 |
- // (assuming sampleRate = 1). Since time2 is greater than 128, we want to output a value |
- // for frame 128. This requires that fillToEndFrame be at least 129. This is achieved by |
- // ceil(time2). |
+ // |fillToEndFrame| is the exclusive upper bound of the last frame to be |
+ // computed for this event. It's either the last desired frame (|endFrame|) |
+ // or derived from the end time of the next event (time2). We compute |
+ // ceil(time2*sampleRate) because fillToEndFrame is the exclusive upper |
+ // bound. Consider the case where |startFrame| = 128 and time2 = 128.1 |
+ // (assuming sampleRate = 1). Since time2 is greater than 128, we want to |
+ // output a value for frame 128. This requires that fillToEndFrame be at |
+ // least 129. This is achieved by ceil(time2). |
// |
- // However, time2 can be very large, so compute this carefully in the case where time2 |
- // exceeds the size of a size_t. |
+ // However, time2 can be very large, so compute this carefully in the case |
+ // where time2 exceeds the size of a size_t. |
size_t fillToEndFrame = endFrame; |
if (endFrame > time2 * sampleRate) |
@@ -621,15 +633,21 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
size_t fillToFrame = fillToEndFrame - startFrame; |
fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues)); |
- // First handle linear and exponential ramps which require looking ahead to the next event. |
+ // First handle linear and exponential ramps which require looking ahead to |
+ // the next event. |
if (nextEventType == ParamEvent::LinearRampToValue) { |
const float valueDelta = value2 - value1; |
#if CPU(X86) || CPU(X86_64) |
- // Minimize in-loop operations. Calculate starting value and increment. Next step: value += inc. |
- // value = value1 + (currentFrame/sampleRate - time1) * k * (value2 - value1); |
+ // Minimize in-loop operations. Calculate starting value and increment. |
+ // Next step: value += inc. |
+ // value = value1 + |
+ // (currentFrame/sampleRate - time1) * k * (value2 - value1); |
// inc = 4 / sampleRate * k * (value2 - value1); |
- // Resolve recursion by expanding constants to achieve a 4-step loop unrolling. |
- // value = value1 + ((currentFrame/sampleRate - time1) + i * sampleFrameTimeIncr) * k * (value2 -value1), i in 0..3 |
+ // Resolve recursion by expanding constants to achieve a 4-step loop |
+ // unrolling. |
+ // value = value1 + |
+ // ((currentFrame/sampleRate - time1) + i * sampleFrameTimeIncr) * k |
+ // * (value2 -value1), i in 0..3 |
__m128 vValue = |
_mm_mul_ps(_mm_set_ps1(1 / sampleRate), _mm_set_ps(3, 2, 1, 0)); |
vValue = |
@@ -649,9 +667,9 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
_mm_storeu_ps(values + writeIndex, vValue); |
vValue = _mm_add_ps(vValue, vInc); |
} |
- // Update |value| with the last value computed so that the .value attribute of the |
- // AudioParam gets the correct linear ramp value, in case the following loop doesn't |
- // execute. |
+ // Update |value| with the last value computed so that the .value |
+ // attribute of the AudioParam gets the correct linear ramp value, in case |
+ // the following loop doesn't execute. |
if (writeIndex >= 1) |
value = values[writeIndex - 1]; |
#endif |
@@ -665,21 +683,22 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
} |
} else if (nextEventType == ParamEvent::ExponentialRampToValue) { |
if (value1 * value2 <= 0) { |
- // It's an error if value1 and value2 have opposite signs or if one of them is zero. |
- // Handle this by propagating the previous value, and making it the default. |
+ // It's an error if value1 and value2 have opposite signs or if one of |
+ // them is zero. Handle this by propagating the previous value, and |
+ // making it the default. |
value = value1; |
for (; writeIndex < fillToFrame; ++writeIndex) |
values[writeIndex] = value; |
} else { |
float numSampleFrames = deltaTime * sampleRate; |
- // The value goes exponentially from value1 to value2 in a duration of deltaTime |
- // seconds according to |
+ // The value goes exponentially from value1 to value2 in a duration of |
+ // deltaTime seconds according to |
// |
// v(t) = v1*(v2/v1)^((t-t1)/(t2-t1)) |
// |
- // Let c be currentFrame and F be the sampleRate. Then we want to sample v(t) |
- // at times t = (c + k)/F for k = 0, 1, ...: |
+ // Let c be currentFrame and F be the sampleRate. Then we want to |
+ // sample v(t) at times t = (c + k)/F for k = 0, 1, ...: |
// |
// v((c+k)/F) = v1*(v2/v1)^(((c/F+k/F)-t1)/(t2-t1)) |
// = v1*(v2/v1)^((c/F-t1)/(t2-t1)) |
@@ -706,13 +725,13 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
value *= multiplier; |
++currentFrame; |
} |
- // |value| got updated one extra time in the above loop. Restore it to the last |
- // computed value. |
+ // |value| got updated one extra time in the above loop. Restore it to |
+ // the last computed value. |
if (writeIndex >= 1) |
value /= multiplier; |
- // Due to roundoff it's possible that value exceeds value2. Clip value to value2 if |
- // we are within 1/2 frame of time2. |
+ // Due to roundoff it's possible that value exceeds value2. Clip value |
+ // to value2 if we are within 1/2 frame of time2. |
if (currentFrame > time2 * sampleRate - 0.5) |
value = value2; |
} |
@@ -735,15 +754,16 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
case ParamEvent::ExponentialRampToValue: { |
currentFrame = fillToEndFrame; |
- // If we're here, we've reached the end of the ramp. If we can (because the |
- // start and end values have the same sign, and neither is 0), use the actual |
- // end value. If not, we have to propagate whatever we have. |
+ // If we're here, we've reached the end of the ramp. If we can |
+ // (because the start and end values have the same sign, and neither |
+ // is 0), use the actual end value. If not, we have to propagate |
+ // whatever we have. |
if (i >= 1 && ((m_events[i - 1].value() * event.value()) > 0)) |
value = event.value(); |
- // Simply stay at a constant value from the last time. We don't want to use the |
- // value of the event in case value1 * value2 < 0. In this case we should |
- // propagate the previous value, which is in |value|. |
+ // Simply stay at a constant value from the last time. We don't want |
+ // to use the value of the event in case value1 * value2 < 0. In this |
+ // case we should propagate the previous value, which is in |value|. |
for (; writeIndex < fillToFrame; ++writeIndex) |
values[writeIndex] = value; |
@@ -762,16 +782,16 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
AudioUtilities::discreteTimeConstantForSampleRate(timeConstant, |
controlRate)); |
- // Set the starting value correctly. This is only needed when the current time |
- // is "equal" to the start time of this event. This is to get the sampling |
- // correct if the start time of this automation isn't on a frame boundary. |
- // Otherwise, we can just continue from where we left off from the previous |
- // rendering quantum. |
+ // Set the starting value correctly. This is only needed when the |
+ // current time is "equal" to the start time of this event. This is |
+ // to get the sampling correct if the start time of this automation |
+ // isn't on a frame boundary. Otherwise, we can just continue from |
+ // where we left off from the previous rendering quantum. |
{ |
double rampStartFrame = time1 * sampleRate; |
// Condition is c - 1 < r <= c where c = currentFrame and r = |
- // rampStartFrame. Compute it this way because currentFrame is unsigned and |
- // could be 0. |
+ // rampStartFrame. Compute it this way because currentFrame is |
+ // unsigned and could be 0. |
if (rampStartFrame <= currentFrame && |
currentFrame < rampStartFrame + 1) { |
value = |
@@ -779,22 +799,23 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
(value - target) * |
exp(-(currentFrame / sampleRate - time1) / timeConstant); |
} else { |
- // Otherwise, need to compute a new value bacause |value| is the last |
- // computed value of SetTarget. Time has progressed by one frame, so we |
- // need to update the value for the new frame. |
+ // Otherwise, need to compute a new value bacause |value| is the |
+ // last computed value of SetTarget. Time has progressed by one |
+ // frame, so we need to update the value for the new frame. |
value += (target - value) * discreteTimeConstant; |
} |
} |
- // If the value is close enough to the target, just fill in the data with the |
- // target value. |
+ // If the value is close enough to the target, just fill in the data |
+ // with the target value. |
if (fabs(value - target) < kSetTargetThreshold * fabs(target) || |
(!target && fabs(value) < kSetTargetZeroThreshold)) { |
for (; writeIndex < fillToFrame; ++writeIndex) |
values[writeIndex] = target; |
} else { |
#if CPU(X86) || CPU(X86_64) |
- // Resolve recursion by expanding constants to achieve a 4-step loop unrolling. |
+ // Resolve recursion by expanding constants to achieve a 4-step loop |
+ // unrolling. |
// v1 = v0 + (t - v0) * c |
// v2 = v1 + (t - v1) * c |
// v2 = v0 + (t - v0) * c + (t - (v0 + (t - v0) * c)) * c |
@@ -830,8 +851,8 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
values[writeIndex] = value; |
value += (target - value) * discreteTimeConstant; |
} |
- // The previous loops may have updated |value| one extra time. Reset it to |
- // the last computed value. |
+ // The previous loops may have updated |value| one extra time. |
+ // Reset it to the last computed value. |
if (writeIndex >= 1) |
value = values[writeIndex - 1]; |
currentFrame = fillToEndFrame; |
@@ -846,8 +867,8 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
// Curve events have duration, so don't just use next event time. |
double duration = event.duration(); |
- // How much to step the curve index for each frame. This is basically the term |
- // (N - 1)/Td in the specification. |
+ // How much to step the curve index for each frame. This is basically |
+ // the term (N - 1)/Td in the specification. |
double curvePointsPerFrame = |
(numberOfCurvePoints - 1) / duration / sampleRate; |
@@ -859,14 +880,15 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
break; |
} |
- // Save old values and recalculate information based on the curve's duration |
- // instead of the next event time. |
+ // Save old values and recalculate information based on the curve's |
+ // duration instead of the next event time. |
size_t nextEventFillToFrame = fillToFrame; |
- // fillToEndFrame = min(endFrame, ceil(sampleRate * (time1 + duration))), but |
- // compute this carefully in case sampleRate*(time1 + duration) is huge. |
- // fillToEndFrame is an exclusive upper bound of the last frame to be computed, |
- // so ceil is used. |
+ // fillToEndFrame = min(endFrame, |
+ // ceil(sampleRate * (time1 + duration))), |
+ // but compute this carefully in case sampleRate*(time1 + duration) is |
+ // huge. fillToEndFrame is an exclusive upper bound of the last frame |
+ // to be computed, so ceil is used. |
{ |
double curveEndFrame = ceil(sampleRate * (time1 + duration)); |
if (endFrame > curveEndFrame) |
@@ -876,21 +898,23 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
} |
// |fillToFrame| can be less than |startFrame| when the end of the |
- // setValueCurve automation has been reached, but the next automation has not |
- // yet started. In this case, |fillToFrame| is clipped to |time1|+|duration| |
- // above, but |startFrame| will keep increasing (because the current time is |
- // increasing). |
+ // setValueCurve automation has been reached, but the next automation |
+ // has not yet started. In this case, |fillToFrame| is clipped to |
+ // |time1|+|duration| above, but |startFrame| will keep increasing |
+ // (because the current time is increasing). |
fillToFrame = |
(fillToEndFrame < startFrame) ? 0 : fillToEndFrame - startFrame; |
fillToFrame = |
std::min(fillToFrame, static_cast<size_t>(numberOfValues)); |
// Index into the curve data using a floating-point value. |
- // We're scaling the number of curve points by the duration (see curvePointsPerFrame). |
+ // We're scaling the number of curve points by the duration (see |
+ // curvePointsPerFrame). |
double curveVirtualIndex = 0; |
if (time1 < currentFrame / sampleRate) { |
// Index somewhere in the middle of the curve data. |
- // Don't use timeToSampleFrame() since we want the exact floating-point frame. |
+ // Don't use timeToSampleFrame() since we want the exact |
+ // floating-point frame. |
double frameOffset = currentFrame - time1 * sampleRate; |
curveVirtualIndex = curvePointsPerFrame * frameOffset; |
} |
@@ -898,8 +922,9 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
// Set the default value in case fillToFrame is 0. |
value = curveData[numberOfCurvePoints - 1]; |
- // Render the stretched curve data using linear interpolation. Oversampled |
- // curve data can be provided if sharp discontinuities are desired. |
+ // Render the stretched curve data using linear interpolation. |
+ // Oversampled curve data can be provided if sharp discontinuities are |
+ // desired. |
unsigned k = 0; |
#if CPU(X86) || CPU(X86_64) |
const __m128 vCurveVirtualIndex = _mm_set_ps1(curveVirtualIndex); |
@@ -917,8 +942,8 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
unsigned truncatedSteps = ((fillToFrame - writeIndex) / 4) * 4; |
unsigned fillToFrameTrunc = writeIndex + truncatedSteps; |
for (; writeIndex < fillToFrameTrunc; writeIndex += 4) { |
- // Compute current index this way to minimize round-off that would have |
- // occurred by incrementing the index by curvePointsPerFrame. |
+ // Compute current index this way to minimize round-off that would |
+ // have occurred by incrementing the index by curvePointsPerFrame. |
__m128 vCurrentVirtualIndex = _mm_add_ps( |
vCurveVirtualIndex, _mm_mul_ps(vK, vCurvePointsPerFrame)); |
vK = _mm_add_ps(vK, vN4); |
@@ -929,10 +954,11 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
__m128i vCurveIndex1 = _mm_cvttps_epi32(_mm_min_ps( |
_mm_add_ps(vCurrentVirtualIndex, vN1), vNumberOfCurvePointsM1)); |
- // Linearly interpolate between the two nearest curve points. |delta| is |
- // clamped to 1 because currentVirtualIndex can exceed curveIndex0 by more |
- // than one. This can happen when we reached the end of the curve but still |
- // need values to fill out the current rendering quantum. |
+ // Linearly interpolate between the two nearest curve points. |
+ // |delta| is clamped to 1 because currentVirtualIndex can exceed |
+ // curveIndex0 by more than one. This can happen when we reached |
+ // the end of the curve but still need values to fill out the |
+ // current rendering quantum. |
_mm_storeu_si128((__m128i*)aCurveIndex0, vCurveIndex0); |
_mm_storeu_si128((__m128i*)aCurveIndex1, vCurveIndex1); |
__m128 vC0 = _mm_set_ps( |
@@ -958,8 +984,8 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
} |
#endif |
for (; writeIndex < fillToFrame; ++writeIndex, ++k) { |
- // Compute current index this way to minimize round-off that would have |
- // occurred by incrementing the index by curvePointsPerFrame. |
+ // Compute current index this way to minimize round-off that would |
+ // have occurred by incrementing the index by curvePointsPerFrame. |
double currentVirtualIndex = |
curveVirtualIndex + k * curvePointsPerFrame; |
unsigned curveIndex0; |
@@ -974,10 +1000,11 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
unsigned curveIndex1 = |
std::min(curveIndex0 + 1, numberOfCurvePoints - 1); |
- // Linearly interpolate between the two nearest curve points. |delta| is |
- // clamped to 1 because currentVirtualIndex can exceed curveIndex0 by more |
- // than one. This can happen when we reached the end of the curve but still |
- // need values to fill out the current rendering quantum. |
+ // Linearly interpolate between the two nearest curve points. |
+ // |delta| is clamped to 1 because currentVirtualIndex can exceed |
+ // curveIndex0 by more than one. This can happen when we reached |
+ // the end of the curve but still need values to fill out the |
+ // current rendering quantum. |
DCHECK_LT(curveIndex0, numberOfCurvePoints); |
DCHECK_LT(curveIndex1, numberOfCurvePoints); |
float c0 = curveData[curveIndex0]; |
@@ -989,8 +1016,9 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
values[writeIndex] = value; |
} |
- // If there's any time left after the duration of this event and the start |
- // of the next, then just propagate the last value of the curveData. |
+ // If there's any time left after the duration of this event and the |
+ // start of the next, then just propagate the last value of the |
+ // curveData. |
if (writeIndex < nextEventFillToFrame) |
value = curveData[numberOfCurvePoints - 1]; |
for (; writeIndex < nextEventFillToFrame; ++writeIndex) |
@@ -1015,13 +1043,13 @@ float AudioParamTimeline::valuesForFrameRangeImpl(size_t startFrame, |
if (lastSkippedEventIndex > 0) |
m_events.remove(0, lastSkippedEventIndex - 1); |
- // If there's any time left after processing the last event then just propagate the last value |
- // to the end of the values buffer. |
+ // If there's any time left after processing the last event then just |
+ // propagate the last value to the end of the values buffer. |
for (; writeIndex < numberOfValues; ++writeIndex) |
values[writeIndex] = value; |
- // This value is used to set the .value attribute of the AudioParam. it should be the last |
- // computed value. |
+ // This value is used to set the .value attribute of the AudioParam. it |
+ // should be the last computed value. |
return values[numberOfValues - 1]; |
} |