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 19 matching lines...) Expand all Loading... |
30 #include "wtf/CPU.h" | 30 #include "wtf/CPU.h" |
31 #include "wtf/MathExtras.h" | 31 #include "wtf/MathExtras.h" |
32 #include <algorithm> | 32 #include <algorithm> |
33 | 33 |
34 #if CPU(X86) || CPU(X86_64) | 34 #if CPU(X86) || CPU(X86_64) |
35 #include <emmintrin.h> | 35 #include <emmintrin.h> |
36 #endif | 36 #endif |
37 | 37 |
38 namespace blink { | 38 namespace blink { |
39 | 39 |
40 // For a SetTarget event, if the relative difference between the current value a
nd the target value | 40 // For a SetTarget event, if the relative difference between the current value |
41 // is less than this, consider them the same and just output the target value.
This value MUST be | 41 // and the target value is less than this, consider them the same and just |
42 // larger than the single precision epsilon of 5.960465e-8. Due to round-off, t
his value is not | 42 // output the target value. This value MUST be larger than the single precision |
43 // achievable in general. This value can vary across the platforms (CPU) and th
us it is determined | 43 // epsilon of 5.960465e-8. Due to round-off, this value is not achievable in |
44 // experimentally. | 44 // general. This value can vary across the platforms (CPU) and thus it is |
| 45 // determined experimentally. |
45 const float kSetTargetThreshold = 1.5e-6; | 46 const float kSetTargetThreshold = 1.5e-6; |
46 | 47 |
47 // For a SetTarget event, if the target value is 0, and the current value is les
s than this | 48 // For a SetTarget event, if the target value is 0, and the current value is |
48 // threshold, consider the curve to have converged to 0. We need a separate cas
e from | 49 // less than this threshold, consider the curve to have converged to 0. We need |
49 // kSetTargetThreshold because that uses relative error, which is never met if t
he target value is | 50 // a separate case from kSetTargetThreshold because that uses relative error, |
50 // 0, a common case. This value MUST be larger than least positive normalized s
ingle precision | 51 // which is never met if the target value is 0, a common case. This value MUST |
| 52 // be larger than least positive normalized single precision |
51 // value (1.1754944e-38) because we normally operate with flush-to-zero enabled. | 53 // value (1.1754944e-38) because we normally operate with flush-to-zero enabled. |
52 const float kSetTargetZeroThreshold = 1e-20; | 54 const float kSetTargetZeroThreshold = 1e-20; |
53 | 55 |
54 static bool isNonNegativeAudioParamTime(double time, | 56 static bool isNonNegativeAudioParamTime(double time, |
55 ExceptionState& exceptionState, | 57 ExceptionState& exceptionState, |
56 String message = "Time") { | 58 String message = "Time") { |
57 if (time >= 0) | 59 if (time >= 0) |
58 return true; | 60 return true; |
59 | 61 |
60 exceptionState.throwDOMException( | 62 exceptionState.throwDOMException( |
61 InvalidAccessError, message + " must be a finite non-negative number: " + | 63 InvalidAccessError, message + " must be a finite non-negative number: " + |
62 String::number(time)); | 64 String::number(time)); |
63 return false; | 65 return false; |
64 } | 66 } |
65 | 67 |
66 static bool isPositiveAudioParamTime(double time, | 68 static bool isPositiveAudioParamTime(double time, |
67 ExceptionState& exceptionState, | 69 ExceptionState& exceptionState, |
68 String message) { | 70 String message) { |
69 if (time > 0) | 71 if (time > 0) |
70 return true; | 72 return true; |
71 | 73 |
72 exceptionState.throwDOMException( | 74 exceptionState.throwDOMException( |
73 InvalidAccessError, | 75 InvalidAccessError, |
74 message + " must be a finite positive number: " + String::number(time)); | 76 message + " must be a finite positive number: " + String::number(time)); |
75 return false; | 77 return false; |
76 } | 78 } |
77 | 79 |
78 String AudioParamTimeline::eventToString(const ParamEvent& event) { | 80 String AudioParamTimeline::eventToString(const ParamEvent& event) { |
79 // The default arguments for most automation methods is the value and the time
. | 81 // The default arguments for most automation methods is the value and the |
| 82 // time. |
80 String args = | 83 String args = |
81 String::number(event.value()) + ", " + String::number(event.time(), 16); | 84 String::number(event.value()) + ", " + String::number(event.time(), 16); |
82 | 85 |
83 // Get a nice printable name for the event and update the args if necessary. | 86 // Get a nice printable name for the event and update the args if necessary. |
84 String s; | 87 String s; |
85 switch (event.getType()) { | 88 switch (event.getType()) { |
86 case ParamEvent::SetValue: | 89 case ParamEvent::SetValue: |
87 s = "setValueAtTime"; | 90 s = "setValueAtTime"; |
88 break; | 91 break; |
89 case ParamEvent::LinearRampToValue: | 92 case ParamEvent::LinearRampToValue: |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 // beginning. | 269 // beginning. |
267 insertEvent(ParamEvent::createSetValueEvent( | 270 insertEvent(ParamEvent::createSetValueEvent( |
268 curve->data()[curve->length() - 1], time + duration), | 271 curve->data()[curve->length() - 1], time + duration), |
269 exceptionState); | 272 exceptionState); |
270 } | 273 } |
271 | 274 |
272 void AudioParamTimeline::insertEvent(const ParamEvent& event, | 275 void AudioParamTimeline::insertEvent(const ParamEvent& event, |
273 ExceptionState& exceptionState) { | 276 ExceptionState& exceptionState) { |
274 DCHECK(isMainThread()); | 277 DCHECK(isMainThread()); |
275 | 278 |
276 // Sanity check the event. Be super careful we're not getting infected with Na
N or Inf. These | 279 // Sanity check the event. Be super careful we're not getting infected with |
277 // should have been handled by the caller. | 280 // NaN or Inf. These should have been handled by the caller. |
278 bool isValid = event.getType() < ParamEvent::LastType && | 281 bool isValid = event.getType() < ParamEvent::LastType && |
279 std::isfinite(event.value()) && std::isfinite(event.time()) && | 282 std::isfinite(event.value()) && std::isfinite(event.time()) && |
280 std::isfinite(event.timeConstant()) && | 283 std::isfinite(event.timeConstant()) && |
281 std::isfinite(event.duration()) && event.duration() >= 0; | 284 std::isfinite(event.duration()) && event.duration() >= 0; |
282 | 285 |
283 DCHECK(isValid); | 286 DCHECK(isValid); |
284 if (!isValid) | 287 if (!isValid) |
285 return; | 288 return; |
286 | 289 |
287 MutexLocker locker(m_eventsLock); | 290 MutexLocker locker(m_eventsLock); |
288 | 291 |
289 unsigned i = 0; | 292 unsigned i = 0; |
290 double insertTime = event.time(); | 293 double insertTime = event.time(); |
291 | 294 |
292 if (!m_events.size() && | 295 if (!m_events.size() && |
293 (event.getType() == ParamEvent::LinearRampToValue || | 296 (event.getType() == ParamEvent::LinearRampToValue || |
294 event.getType() == ParamEvent::ExponentialRampToValue)) { | 297 event.getType() == ParamEvent::ExponentialRampToValue)) { |
295 // There are no events preceding these ramps. Insert a new setValueAtTime e
vent to set the | 298 // There are no events preceding these ramps. Insert a new setValueAtTime |
296 // starting point for these events. | 299 // event to set the starting point for these events. |
297 m_events.insert(0, AudioParamTimeline::ParamEvent::createSetValueEvent( | 300 m_events.insert(0, AudioParamTimeline::ParamEvent::createSetValueEvent( |
298 event.initialValue(), event.callTime())); | 301 event.initialValue(), event.callTime())); |
299 } | 302 } |
300 | 303 |
301 for (i = 0; i < m_events.size(); ++i) { | 304 for (i = 0; i < m_events.size(); ++i) { |
302 if (event.getType() == ParamEvent::SetValueCurve) { | 305 if (event.getType() == ParamEvent::SetValueCurve) { |
303 // If this event is a SetValueCurve, make sure it doesn't overlap any exis
ting | 306 // If this event is a SetValueCurve, make sure it doesn't overlap any |
304 // event. It's ok if the SetValueCurve starts at the same time as the end
of some other | 307 // existing event. It's ok if the SetValueCurve starts at the same time as |
305 // duration. | 308 // the end of some other duration. |
306 double endTime = event.time() + event.duration(); | 309 double endTime = event.time() + event.duration(); |
307 if (m_events[i].time() > event.time() && m_events[i].time() < endTime) { | 310 if (m_events[i].time() > event.time() && m_events[i].time() < endTime) { |
308 exceptionState.throwDOMException( | 311 exceptionState.throwDOMException( |
309 NotSupportedError, | 312 NotSupportedError, |
310 eventToString(event) + " overlaps " + eventToString(m_events[i])); | 313 eventToString(event) + " overlaps " + eventToString(m_events[i])); |
311 return; | 314 return; |
312 } | 315 } |
313 } else { | 316 } else { |
314 // Otherwise, make sure this event doesn't overlap any existing SetValueCu
rve event. | 317 // Otherwise, make sure this event doesn't overlap any existing |
| 318 // SetValueCurve event. |
315 if (m_events[i].getType() == ParamEvent::SetValueCurve) { | 319 if (m_events[i].getType() == ParamEvent::SetValueCurve) { |
316 double endTime = m_events[i].time() + m_events[i].duration(); | 320 double endTime = m_events[i].time() + m_events[i].duration(); |
317 if (event.time() >= m_events[i].time() && event.time() < endTime) { | 321 if (event.time() >= m_events[i].time() && event.time() < endTime) { |
318 exceptionState.throwDOMException( | 322 exceptionState.throwDOMException( |
319 NotSupportedError, | 323 NotSupportedError, |
320 eventToString(event) + " overlaps " + eventToString(m_events[i])); | 324 eventToString(event) + " overlaps " + eventToString(m_events[i])); |
321 return; | 325 return; |
322 } | 326 } |
323 } | 327 } |
324 } | 328 } |
(...skipping 11 matching lines...) Expand all Loading... |
336 | 340 |
337 m_events.insert(i, event); | 341 m_events.insert(i, event); |
338 } | 342 } |
339 | 343 |
340 bool AudioParamTimeline::hasValues() const { | 344 bool AudioParamTimeline::hasValues() const { |
341 MutexTryLocker tryLocker(m_eventsLock); | 345 MutexTryLocker tryLocker(m_eventsLock); |
342 | 346 |
343 if (tryLocker.locked()) | 347 if (tryLocker.locked()) |
344 return m_events.size(); | 348 return m_events.size(); |
345 | 349 |
346 // Can't get the lock so that means the main thread is trying to insert an eve
nt. Just | 350 // Can't get the lock so that means the main thread is trying to insert an |
347 // return true then. If the main thread releases the lock before valueForCont
extTime or | 351 // event. Just return true then. If the main thread releases the lock before |
348 // valuesForFrameRange runs, then the there will be an event on the timeline,
so everything | 352 // valueForContextTime or valuesForFrameRange runs, then the there will be an |
349 // is fine. If the lock is held so that neither valueForContextTime nor value
sForFrameRange | 353 // event on the timeline, so everything is fine. If the lock is held so that |
350 // can run, this is ok too, because they have tryLocks to produce a default va
lue. The | 354 // neither valueForContextTime nor valuesForFrameRange can run, this is ok |
351 // event will then get processed in the next rendering quantum. | 355 // too, because they have tryLocks to produce a default value. The event will |
| 356 // then get processed in the next rendering quantum. |
352 // | 357 // |
353 // Don't want to return false here because that would confuse the processing o
f the timeline | 358 // Don't want to return false here because that would confuse the processing |
354 // if previously we returned true and now suddenly return false, only to retur
n true on the | 359 // of the timeline if previously we returned true and now suddenly return |
355 // next rendering quantum. Currently, once a timeline has been introduced it
is always true | 360 // false, only to return true on the next rendering quantum. Currently, once |
356 // forever because m_events never shrinks. | 361 // a timeline has been introduced it is always true forever because m_events |
| 362 // never shrinks. |
357 return true; | 363 return true; |
358 } | 364 } |
359 | 365 |
360 void AudioParamTimeline::cancelScheduledValues(double startTime, | 366 void AudioParamTimeline::cancelScheduledValues(double startTime, |
361 ExceptionState& exceptionState) { | 367 ExceptionState& exceptionState) { |
362 DCHECK(isMainThread()); | 368 DCHECK(isMainThread()); |
363 | 369 |
364 MutexLocker locker(m_eventsLock); | 370 MutexLocker locker(m_eventsLock); |
365 | 371 |
366 // Remove all events starting at startTime. | 372 // Remove all events starting at startTime. |
(...skipping 17 matching lines...) Expand all Loading... |
384 audioDestination.currentTime() < m_events[0].time()) { | 390 audioDestination.currentTime() < m_events[0].time()) { |
385 hasValue = false; | 391 hasValue = false; |
386 return defaultValue; | 392 return defaultValue; |
387 } | 393 } |
388 } | 394 } |
389 | 395 |
390 // Ask for just a single value. | 396 // Ask for just a single value. |
391 float value; | 397 float value; |
392 double sampleRate = audioDestination.sampleRate(); | 398 double sampleRate = audioDestination.sampleRate(); |
393 size_t startFrame = audioDestination.currentSampleFrame(); | 399 size_t startFrame = audioDestination.currentSampleFrame(); |
394 double controlRate = | 400 // One parameter change per render quantum. |
395 sampleRate / | 401 double controlRate = sampleRate / AudioHandler::ProcessingSizeInFrames; |
396 AudioHandler:: | |
397 ProcessingSizeInFrames; // one parameter change per render quantum | |
398 value = valuesForFrameRange(startFrame, startFrame + 1, defaultValue, &value, | 402 value = valuesForFrameRange(startFrame, startFrame + 1, defaultValue, &value, |
399 1, sampleRate, controlRate, minValue, maxValue); | 403 1, sampleRate, controlRate, minValue, maxValue); |
400 | 404 |
401 hasValue = true; | 405 hasValue = true; |
402 return value; | 406 return value; |
403 } | 407 } |
404 | 408 |
405 float AudioParamTimeline::valuesForFrameRange(size_t startFrame, | 409 float AudioParamTimeline::valuesForFrameRange(size_t startFrame, |
406 size_t endFrame, | 410 size_t endFrame, |
407 float defaultValue, | 411 float defaultValue, |
(...skipping 29 matching lines...) Expand all Loading... |
437 float defaultValue, | 441 float defaultValue, |
438 float* values, | 442 float* values, |
439 unsigned numberOfValues, | 443 unsigned numberOfValues, |
440 double sampleRate, | 444 double sampleRate, |
441 double controlRate) { | 445 double controlRate) { |
442 DCHECK(values); | 446 DCHECK(values); |
443 DCHECK_GE(numberOfValues, 1u); | 447 DCHECK_GE(numberOfValues, 1u); |
444 if (!values || !(numberOfValues >= 1)) | 448 if (!values || !(numberOfValues >= 1)) |
445 return defaultValue; | 449 return defaultValue; |
446 | 450 |
447 // Return default value if there are no events matching the desired time range
. | 451 // Return default value if there are no events matching the desired time |
| 452 // range. |
448 if (!m_events.size() || (endFrame / sampleRate <= m_events[0].time())) { | 453 if (!m_events.size() || (endFrame / sampleRate <= m_events[0].time())) { |
449 for (unsigned i = 0; i < numberOfValues; ++i) | 454 for (unsigned i = 0; i < numberOfValues; ++i) |
450 values[i] = defaultValue; | 455 values[i] = defaultValue; |
451 return defaultValue; | 456 return defaultValue; |
452 } | 457 } |
453 | 458 |
454 // Optimize the case where the last event is in the past. | 459 // Optimize the case where the last event is in the past. |
455 if (m_events.size() > 0) { | 460 if (m_events.size() > 0) { |
456 ParamEvent& lastEvent = m_events[m_events.size() - 1]; | 461 ParamEvent& lastEvent = m_events[m_events.size() - 1]; |
457 ParamEvent::Type lastEventType = lastEvent.getType(); | 462 ParamEvent::Type lastEventType = lastEvent.getType(); |
(...skipping 15 matching lines...) Expand all Loading... |
473 m_smoothedValue = defaultValue; | 478 m_smoothedValue = defaultValue; |
474 m_events.clear(); | 479 m_events.clear(); |
475 return defaultValue; | 480 return defaultValue; |
476 } | 481 } |
477 } | 482 } |
478 | 483 |
479 // Maintain a running time (frame) and index for writing the values buffer. | 484 // Maintain a running time (frame) and index for writing the values buffer. |
480 size_t currentFrame = startFrame; | 485 size_t currentFrame = startFrame; |
481 unsigned writeIndex = 0; | 486 unsigned writeIndex = 0; |
482 | 487 |
483 // If first event is after startFrame then fill initial part of values buffer
with defaultValue | 488 // If first event is after startFrame then fill initial part of values buffer |
484 // until we reach the first event time. | 489 // with defaultValue until we reach the first event time. |
485 double firstEventTime = m_events[0].time(); | 490 double firstEventTime = m_events[0].time(); |
486 if (firstEventTime > startFrame / sampleRate) { | 491 if (firstEventTime > startFrame / sampleRate) { |
487 // |fillToFrame| is an exclusive upper bound, so use ceil() to compute the b
ound from the | 492 // |fillToFrame| is an exclusive upper bound, so use ceil() to compute the |
488 // firstEventTime. | 493 // bound from the firstEventTime. |
489 size_t fillToFrame = endFrame; | 494 size_t fillToFrame = endFrame; |
490 double firstEventFrame = ceil(firstEventTime * sampleRate); | 495 double firstEventFrame = ceil(firstEventTime * sampleRate); |
491 if (endFrame > firstEventFrame) | 496 if (endFrame > firstEventFrame) |
492 fillToFrame = static_cast<size_t>(firstEventFrame); | 497 fillToFrame = static_cast<size_t>(firstEventFrame); |
493 DCHECK_GE(fillToFrame, startFrame); | 498 DCHECK_GE(fillToFrame, startFrame); |
494 | 499 |
495 fillToFrame -= startFrame; | 500 fillToFrame -= startFrame; |
496 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues)); | 501 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues)); |
497 for (; writeIndex < fillToFrame; ++writeIndex) | 502 for (; writeIndex < fillToFrame; ++writeIndex) |
498 values[writeIndex] = defaultValue; | 503 values[writeIndex] = defaultValue; |
(...skipping 19 matching lines...) Expand all Loading... |
518 // for this case! What should happen is the fillToFrame should be 0 so | 523 // for this case! What should happen is the fillToFrame should be 0 so |
519 // that while the event is actually run again, nothing actually gets | 524 // that while the event is actually run again, nothing actually gets |
520 // computed, and we move on to the next event. | 525 // computed, and we move on to the next event. |
521 // | 526 // |
522 // An example of this case is setValueCurveAtTime. The time at which | 527 // An example of this case is setValueCurveAtTime. The time at which |
523 // setValueCurveAtTime ends (and the setValueAtTime begins) might be | 528 // setValueCurveAtTime ends (and the setValueAtTime begins) might be |
524 // just past currentTime/sampleRate. Then setValueCurveAtTime will be | 529 // just past currentTime/sampleRate. Then setValueCurveAtTime will be |
525 // processed again before advancing to setValueAtTime. The number of | 530 // processed again before advancing to setValueAtTime. The number of |
526 // frames to be processed should be zero in this case. | 531 // frames to be processed should be zero in this case. |
527 if (nextEvent && nextEvent->time() < currentFrame / sampleRate) { | 532 if (nextEvent && nextEvent->time() < currentFrame / sampleRate) { |
528 // But if the current event is a SetValue event and the event time is betw
een | 533 // But if the current event is a SetValue event and the event time is |
529 // currentFrame - 1 and curentFrame (in time). we don't want to skip it.
If we do skip | 534 // between currentFrame - 1 and curentFrame (in time). we don't want to |
530 // it, the SetValue event is completely skipped and not applied, which is
wrong. Other | 535 // skip it. If we do skip it, the SetValue event is completely skipped |
531 // events don't have this problem. (Because currentFrame is unsigned, we
do the time | 536 // and not applied, which is wrong. Other events don't have this problem. |
532 // check in this funny, but equivalent way.) | 537 // (Because currentFrame is unsigned, we do the time check in this funny, |
| 538 // but equivalent way.) |
533 double eventFrame = event.time() * sampleRate; | 539 double eventFrame = event.time() * sampleRate; |
534 | 540 |
535 // Condition is currentFrame - 1 < eventFrame <= currentFrame, but current
Frame is | 541 // Condition is currentFrame - 1 < eventFrame <= currentFrame, but |
536 // unsigned and could be 0, so use currentFrame < eventFrame + 1 instead. | 542 // currentFrame is unsigned and could be 0, so use |
| 543 // currentFrame < eventFrame + 1 instead. |
537 if (!((event.getType() == ParamEvent::SetValue && | 544 if (!((event.getType() == ParamEvent::SetValue && |
538 (eventFrame <= currentFrame) && | 545 (eventFrame <= currentFrame) && |
539 (currentFrame < eventFrame + 1)))) { | 546 (currentFrame < eventFrame + 1)))) { |
540 // This is not the special SetValue event case, and nextEvent is | 547 // This is not the special SetValue event case, and nextEvent is |
541 // in the past. We can skip processing of this event since it's | 548 // in the past. We can skip processing of this event since it's |
542 // in past. We keep track of this event in lastSkippedEventIndex | 549 // in past. We keep track of this event in lastSkippedEventIndex |
543 // to note what events we've skipped. | 550 // to note what events we've skipped. |
544 lastSkippedEventIndex = i; | 551 lastSkippedEventIndex = i; |
545 continue; | 552 continue; |
546 } | 553 } |
547 } | 554 } |
548 | 555 |
549 // If there's no next event, set nextEventType to LastType to indicate that. | 556 // If there's no next event, set nextEventType to LastType to indicate that. |
550 ParamEvent::Type nextEventType = | 557 ParamEvent::Type nextEventType = |
551 nextEvent ? static_cast<ParamEvent::Type>(nextEvent->getType()) | 558 nextEvent ? static_cast<ParamEvent::Type>(nextEvent->getType()) |
552 : ParamEvent::LastType; | 559 : ParamEvent::LastType; |
553 | 560 |
554 // If the current event is SetTarget and the next event is a LinearRampToVal
ue or | 561 // If the current event is SetTarget and the next event is a |
555 // ExponentialRampToValue, special handling is needed. In this case, the li
near and | 562 // LinearRampToValue or ExponentialRampToValue, special handling is needed. |
556 // exponential ramp should start at wherever the SetTarget processing has re
ached. | 563 // In this case, the linear and exponential ramp should start at wherever |
| 564 // the SetTarget processing has reached. |
557 if (event.getType() == ParamEvent::SetTarget && | 565 if (event.getType() == ParamEvent::SetTarget && |
558 (nextEventType == ParamEvent::LinearRampToValue || | 566 (nextEventType == ParamEvent::LinearRampToValue || |
559 nextEventType == ParamEvent::ExponentialRampToValue)) { | 567 nextEventType == ParamEvent::ExponentialRampToValue)) { |
560 // Replace the SetTarget with a SetValue to set the starting time and valu
e for the ramp | 568 // Replace the SetTarget with a SetValue to set the starting time and |
561 // using the current frame. We need to update |value| appropriately depen
ding on | 569 // value for the ramp using the current frame. We need to update |value| |
562 // whether the ramp has started or not. | 570 // appropriately depending on whether the ramp has started or not. |
563 // | 571 // |
564 // If SetTarget starts somewhere between currentFrame - 1 and currentFrame
, we directly | 572 // If SetTarget starts somewhere between currentFrame - 1 and |
565 // compute the value it would have at currentFrame. If not, we update the
value from | 573 // currentFrame, we directly compute the value it would have at |
566 // the value from currentFrame - 1. | 574 // currentFrame. If not, we update the value from the value from |
| 575 // currentFrame - 1. |
567 // | 576 // |
568 // Can't use the condition currentFrame - 1 <= t0 * sampleRate <= currentF
rame because | 577 // Can't use the condition currentFrame - 1 <= t0 * sampleRate <= |
569 // currentFrame is unsigned and could be 0. Instead, compute the conditio
n this way, | 578 // currentFrame because currentFrame is unsigned and could be 0. Instead, |
| 579 // compute the condition this way, |
570 // where f = currentFrame and Fs = sampleRate: | 580 // where f = currentFrame and Fs = sampleRate: |
571 // | 581 // |
572 // f - 1 <= t0 * Fs <= f | 582 // f - 1 <= t0 * Fs <= f |
573 // 2 * f - 2 <= 2 * Fs * t0 <= 2 * f | 583 // 2 * f - 2 <= 2 * Fs * t0 <= 2 * f |
574 // -2 <= 2 * Fs * t0 - 2 * f <= 0 | 584 // -2 <= 2 * Fs * t0 - 2 * f <= 0 |
575 // -1 <= 2 * Fs * t0 - 2 * f + 1 <= 1 | 585 // -1 <= 2 * Fs * t0 - 2 * f + 1 <= 1 |
576 // abs(2 * Fs * t0 - 2 * f + 1) <= 1 | 586 // abs(2 * Fs * t0 - 2 * f + 1) <= 1 |
577 if (fabs(2 * sampleRate * event.time() - 2 * currentFrame + 1) <= 1) { | 587 if (fabs(2 * sampleRate * event.time() - 2 * currentFrame + 1) <= 1) { |
578 // SetTarget is starting somewhere between currentFrame - 1 and | 588 // SetTarget is starting somewhere between currentFrame - 1 and |
579 // currentFrame. Compute the value the SetTarget would have at the curre
ntFrame. | 589 // currentFrame. Compute the value the SetTarget would have at the |
| 590 // currentFrame. |
580 value = event.value() + | 591 value = event.value() + |
581 (value - event.value()) * | 592 (value - event.value()) * |
582 exp(-(currentFrame / sampleRate - event.time()) / | 593 exp(-(currentFrame / sampleRate - event.time()) / |
583 event.timeConstant()); | 594 event.timeConstant()); |
584 } else { | 595 } else { |
585 // SetTarget has already started. Update |value| one frame because it's
the value from | 596 // SetTarget has already started. Update |value| one frame because it's |
586 // the previous frame. | 597 // the value from the previous frame. |
587 float discreteTimeConstant = static_cast<float>( | 598 float discreteTimeConstant = static_cast<float>( |
588 AudioUtilities::discreteTimeConstantForSampleRate( | 599 AudioUtilities::discreteTimeConstantForSampleRate( |
589 event.timeConstant(), controlRate)); | 600 event.timeConstant(), controlRate)); |
590 value += (event.value() - value) * discreteTimeConstant; | 601 value += (event.value() - value) * discreteTimeConstant; |
591 } | 602 } |
592 m_events[i] = | 603 m_events[i] = |
593 ParamEvent::createSetValueEvent(value, currentFrame / sampleRate); | 604 ParamEvent::createSetValueEvent(value, currentFrame / sampleRate); |
594 } | 605 } |
595 | 606 |
596 float value1 = event.value(); | 607 float value1 = event.value(); |
597 double time1 = event.time(); | 608 double time1 = event.time(); |
598 | 609 |
599 float value2 = nextEvent ? nextEvent->value() : value1; | 610 float value2 = nextEvent ? nextEvent->value() : value1; |
600 double time2 = nextEvent ? nextEvent->time() : endFrame / sampleRate + 1; | 611 double time2 = nextEvent ? nextEvent->time() : endFrame / sampleRate + 1; |
601 | 612 |
602 double deltaTime = time2 - time1; | 613 double deltaTime = time2 - time1; |
603 float k = deltaTime > 0 ? 1 / deltaTime : 0; | 614 float k = deltaTime > 0 ? 1 / deltaTime : 0; |
604 | 615 |
605 // |fillToEndFrame| is the exclusive upper bound of the last frame to be com
puted for this | 616 // |fillToEndFrame| is the exclusive upper bound of the last frame to be |
606 // event. It's either the last desired frame (|endFrame|) or derived from t
he end time of | 617 // computed for this event. It's either the last desired frame (|endFrame|) |
607 // the next event (time2). We compute ceil(time2*sampleRate) because fillToE
ndFrame is the | 618 // or derived from the end time of the next event (time2). We compute |
608 // exclusive upper bound. Consider the case where |startFrame| = 128 and ti
me2 = 128.1 | 619 // ceil(time2*sampleRate) because fillToEndFrame is the exclusive upper |
609 // (assuming sampleRate = 1). Since time2 is greater than 128, we want to o
utput a value | 620 // bound. Consider the case where |startFrame| = 128 and time2 = 128.1 |
610 // for frame 128. This requires that fillToEndFrame be at least 129. This
is achieved by | 621 // (assuming sampleRate = 1). Since time2 is greater than 128, we want to |
611 // ceil(time2). | 622 // output a value for frame 128. This requires that fillToEndFrame be at |
| 623 // least 129. This is achieved by ceil(time2). |
612 // | 624 // |
613 // However, time2 can be very large, so compute this carefully in the case w
here time2 | 625 // However, time2 can be very large, so compute this carefully in the case |
614 // exceeds the size of a size_t. | 626 // where time2 exceeds the size of a size_t. |
615 | 627 |
616 size_t fillToEndFrame = endFrame; | 628 size_t fillToEndFrame = endFrame; |
617 if (endFrame > time2 * sampleRate) | 629 if (endFrame > time2 * sampleRate) |
618 fillToEndFrame = static_cast<size_t>(ceil(time2 * sampleRate)); | 630 fillToEndFrame = static_cast<size_t>(ceil(time2 * sampleRate)); |
619 | 631 |
620 DCHECK_GE(fillToEndFrame, startFrame); | 632 DCHECK_GE(fillToEndFrame, startFrame); |
621 size_t fillToFrame = fillToEndFrame - startFrame; | 633 size_t fillToFrame = fillToEndFrame - startFrame; |
622 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues)); | 634 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues)); |
623 | 635 |
624 // First handle linear and exponential ramps which require looking ahead to
the next event. | 636 // First handle linear and exponential ramps which require looking ahead to |
| 637 // the next event. |
625 if (nextEventType == ParamEvent::LinearRampToValue) { | 638 if (nextEventType == ParamEvent::LinearRampToValue) { |
626 const float valueDelta = value2 - value1; | 639 const float valueDelta = value2 - value1; |
627 #if CPU(X86) || CPU(X86_64) | 640 #if CPU(X86) || CPU(X86_64) |
628 // Minimize in-loop operations. Calculate starting value and increment. Ne
xt step: value += inc. | 641 // Minimize in-loop operations. Calculate starting value and increment. |
629 // value = value1 + (currentFrame/sampleRate - time1) * k * (value2 - val
ue1); | 642 // Next step: value += inc. |
| 643 // value = value1 + |
| 644 // (currentFrame/sampleRate - time1) * k * (value2 - value1); |
630 // inc = 4 / sampleRate * k * (value2 - value1); | 645 // inc = 4 / sampleRate * k * (value2 - value1); |
631 // Resolve recursion by expanding constants to achieve a 4-step loop unrol
ling. | 646 // Resolve recursion by expanding constants to achieve a 4-step loop |
632 // value = value1 + ((currentFrame/sampleRate - time1) + i * sampleFrameT
imeIncr) * k * (value2 -value1), i in 0..3 | 647 // unrolling. |
| 648 // value = value1 + |
| 649 // ((currentFrame/sampleRate - time1) + i * sampleFrameTimeIncr) * k |
| 650 // * (value2 -value1), i in 0..3 |
633 __m128 vValue = | 651 __m128 vValue = |
634 _mm_mul_ps(_mm_set_ps1(1 / sampleRate), _mm_set_ps(3, 2, 1, 0)); | 652 _mm_mul_ps(_mm_set_ps1(1 / sampleRate), _mm_set_ps(3, 2, 1, 0)); |
635 vValue = | 653 vValue = |
636 _mm_add_ps(vValue, _mm_set_ps1(currentFrame / sampleRate - time1)); | 654 _mm_add_ps(vValue, _mm_set_ps1(currentFrame / sampleRate - time1)); |
637 vValue = _mm_mul_ps(vValue, _mm_set_ps1(k * valueDelta)); | 655 vValue = _mm_mul_ps(vValue, _mm_set_ps1(k * valueDelta)); |
638 vValue = _mm_add_ps(vValue, _mm_set_ps1(value1)); | 656 vValue = _mm_add_ps(vValue, _mm_set_ps1(value1)); |
639 __m128 vInc = _mm_set_ps1(4 / sampleRate * k * valueDelta); | 657 __m128 vInc = _mm_set_ps1(4 / sampleRate * k * valueDelta); |
640 | 658 |
641 // Truncate loop steps to multiple of 4. | 659 // Truncate loop steps to multiple of 4. |
642 unsigned fillToFrameTrunc = | 660 unsigned fillToFrameTrunc = |
643 writeIndex + ((fillToFrame - writeIndex) / 4) * 4; | 661 writeIndex + ((fillToFrame - writeIndex) / 4) * 4; |
644 // Compute final time. | 662 // Compute final time. |
645 currentFrame += fillToFrameTrunc - writeIndex; | 663 currentFrame += fillToFrameTrunc - writeIndex; |
646 | 664 |
647 // Process 4 loop steps. | 665 // Process 4 loop steps. |
648 for (; writeIndex < fillToFrameTrunc; writeIndex += 4) { | 666 for (; writeIndex < fillToFrameTrunc; writeIndex += 4) { |
649 _mm_storeu_ps(values + writeIndex, vValue); | 667 _mm_storeu_ps(values + writeIndex, vValue); |
650 vValue = _mm_add_ps(vValue, vInc); | 668 vValue = _mm_add_ps(vValue, vInc); |
651 } | 669 } |
652 // Update |value| with the last value computed so that the .value attribut
e of the | 670 // Update |value| with the last value computed so that the .value |
653 // AudioParam gets the correct linear ramp value, in case the following lo
op doesn't | 671 // attribute of the AudioParam gets the correct linear ramp value, in case |
654 // execute. | 672 // the following loop doesn't execute. |
655 if (writeIndex >= 1) | 673 if (writeIndex >= 1) |
656 value = values[writeIndex - 1]; | 674 value = values[writeIndex - 1]; |
657 #endif | 675 #endif |
658 // Serially process remaining values. | 676 // Serially process remaining values. |
659 for (; writeIndex < fillToFrame; ++writeIndex) { | 677 for (; writeIndex < fillToFrame; ++writeIndex) { |
660 float x = (currentFrame / sampleRate - time1) * k; | 678 float x = (currentFrame / sampleRate - time1) * k; |
661 // value = (1 - x) * value1 + x * value2; | 679 // value = (1 - x) * value1 + x * value2; |
662 value = value1 + x * valueDelta; | 680 value = value1 + x * valueDelta; |
663 values[writeIndex] = value; | 681 values[writeIndex] = value; |
664 ++currentFrame; | 682 ++currentFrame; |
665 } | 683 } |
666 } else if (nextEventType == ParamEvent::ExponentialRampToValue) { | 684 } else if (nextEventType == ParamEvent::ExponentialRampToValue) { |
667 if (value1 * value2 <= 0) { | 685 if (value1 * value2 <= 0) { |
668 // It's an error if value1 and value2 have opposite signs or if one of t
hem is zero. | 686 // It's an error if value1 and value2 have opposite signs or if one of |
669 // Handle this by propagating the previous value, and making it the defa
ult. | 687 // them is zero. Handle this by propagating the previous value, and |
| 688 // making it the default. |
670 value = value1; | 689 value = value1; |
671 | 690 |
672 for (; writeIndex < fillToFrame; ++writeIndex) | 691 for (; writeIndex < fillToFrame; ++writeIndex) |
673 values[writeIndex] = value; | 692 values[writeIndex] = value; |
674 } else { | 693 } else { |
675 float numSampleFrames = deltaTime * sampleRate; | 694 float numSampleFrames = deltaTime * sampleRate; |
676 // The value goes exponentially from value1 to value2 in a duration of d
eltaTime | 695 // The value goes exponentially from value1 to value2 in a duration of |
677 // seconds according to | 696 // deltaTime seconds according to |
678 // | 697 // |
679 // v(t) = v1*(v2/v1)^((t-t1)/(t2-t1)) | 698 // v(t) = v1*(v2/v1)^((t-t1)/(t2-t1)) |
680 // | 699 // |
681 // Let c be currentFrame and F be the sampleRate. Then we want to sampl
e v(t) | 700 // Let c be currentFrame and F be the sampleRate. Then we want to |
682 // at times t = (c + k)/F for k = 0, 1, ...: | 701 // sample v(t) at times t = (c + k)/F for k = 0, 1, ...: |
683 // | 702 // |
684 // v((c+k)/F) = v1*(v2/v1)^(((c/F+k/F)-t1)/(t2-t1)) | 703 // v((c+k)/F) = v1*(v2/v1)^(((c/F+k/F)-t1)/(t2-t1)) |
685 // = v1*(v2/v1)^((c/F-t1)/(t2-t1)) | 704 // = v1*(v2/v1)^((c/F-t1)/(t2-t1)) |
686 // *(v2/v1)^((k/F)/(t2-t1)) | 705 // *(v2/v1)^((k/F)/(t2-t1)) |
687 // = v1*(v2/v1)^((c/F-t1)/(t2-t1)) | 706 // = v1*(v2/v1)^((c/F-t1)/(t2-t1)) |
688 // *[(v2/v1)^(1/(F*(t2-t1)))]^k | 707 // *[(v2/v1)^(1/(F*(t2-t1)))]^k |
689 // | 708 // |
690 // Thus, this can be written as | 709 // Thus, this can be written as |
691 // | 710 // |
692 // v((c+k)/F) = V*m^k | 711 // v((c+k)/F) = V*m^k |
693 // | 712 // |
694 // where | 713 // where |
695 // V = v1*(v2/v1)^((c/F-t1)/(t2-t1)) | 714 // V = v1*(v2/v1)^((c/F-t1)/(t2-t1)) |
696 // m = (v2/v1)^(1/(F*(t2-t1))) | 715 // m = (v2/v1)^(1/(F*(t2-t1))) |
697 | 716 |
698 // Compute the per-sample multiplier. | 717 // Compute the per-sample multiplier. |
699 float multiplier = powf(value2 / value1, 1 / numSampleFrames); | 718 float multiplier = powf(value2 / value1, 1 / numSampleFrames); |
700 // Set the starting value of the exponential ramp. | 719 // Set the starting value of the exponential ramp. |
701 value = value1 * powf(value2 / value1, | 720 value = value1 * powf(value2 / value1, |
702 (currentFrame / sampleRate - time1) / deltaTime); | 721 (currentFrame / sampleRate - time1) / deltaTime); |
703 | 722 |
704 for (; writeIndex < fillToFrame; ++writeIndex) { | 723 for (; writeIndex < fillToFrame; ++writeIndex) { |
705 values[writeIndex] = value; | 724 values[writeIndex] = value; |
706 value *= multiplier; | 725 value *= multiplier; |
707 ++currentFrame; | 726 ++currentFrame; |
708 } | 727 } |
709 // |value| got updated one extra time in the above loop. Restore it to
the last | 728 // |value| got updated one extra time in the above loop. Restore it to |
710 // computed value. | 729 // the last computed value. |
711 if (writeIndex >= 1) | 730 if (writeIndex >= 1) |
712 value /= multiplier; | 731 value /= multiplier; |
713 | 732 |
714 // Due to roundoff it's possible that value exceeds value2. Clip value
to value2 if | 733 // Due to roundoff it's possible that value exceeds value2. Clip value |
715 // we are within 1/2 frame of time2. | 734 // to value2 if we are within 1/2 frame of time2. |
716 if (currentFrame > time2 * sampleRate - 0.5) | 735 if (currentFrame > time2 * sampleRate - 0.5) |
717 value = value2; | 736 value = value2; |
718 } | 737 } |
719 } else { | 738 } else { |
720 // Handle event types not requiring looking ahead to the next event. | 739 // Handle event types not requiring looking ahead to the next event. |
721 switch (event.getType()) { | 740 switch (event.getType()) { |
722 case ParamEvent::SetValue: | 741 case ParamEvent::SetValue: |
723 case ParamEvent::LinearRampToValue: { | 742 case ParamEvent::LinearRampToValue: { |
724 currentFrame = fillToEndFrame; | 743 currentFrame = fillToEndFrame; |
725 | 744 |
726 // Simply stay at a constant value. | 745 // Simply stay at a constant value. |
727 value = event.value(); | 746 value = event.value(); |
728 | 747 |
729 for (; writeIndex < fillToFrame; ++writeIndex) | 748 for (; writeIndex < fillToFrame; ++writeIndex) |
730 values[writeIndex] = value; | 749 values[writeIndex] = value; |
731 | 750 |
732 break; | 751 break; |
733 } | 752 } |
734 | 753 |
735 case ParamEvent::ExponentialRampToValue: { | 754 case ParamEvent::ExponentialRampToValue: { |
736 currentFrame = fillToEndFrame; | 755 currentFrame = fillToEndFrame; |
737 | 756 |
738 // If we're here, we've reached the end of the ramp. If we can (becau
se the | 757 // If we're here, we've reached the end of the ramp. If we can |
739 // start and end values have the same sign, and neither is 0), use the
actual | 758 // (because the start and end values have the same sign, and neither |
740 // end value. If not, we have to propagate whatever we have. | 759 // is 0), use the actual end value. If not, we have to propagate |
| 760 // whatever we have. |
741 if (i >= 1 && ((m_events[i - 1].value() * event.value()) > 0)) | 761 if (i >= 1 && ((m_events[i - 1].value() * event.value()) > 0)) |
742 value = event.value(); | 762 value = event.value(); |
743 | 763 |
744 // Simply stay at a constant value from the last time. We don't want
to use the | 764 // Simply stay at a constant value from the last time. We don't want |
745 // value of the event in case value1 * value2 < 0. In this case we sh
ould | 765 // to use the value of the event in case value1 * value2 < 0. In this |
746 // propagate the previous value, which is in |value|. | 766 // case we should propagate the previous value, which is in |value|. |
747 for (; writeIndex < fillToFrame; ++writeIndex) | 767 for (; writeIndex < fillToFrame; ++writeIndex) |
748 values[writeIndex] = value; | 768 values[writeIndex] = value; |
749 | 769 |
750 break; | 770 break; |
751 } | 771 } |
752 | 772 |
753 case ParamEvent::SetTarget: { | 773 case ParamEvent::SetTarget: { |
754 // Exponential approach to target value with given time constant. | 774 // Exponential approach to target value with given time constant. |
755 // | 775 // |
756 // v(t) = v2 + (v1 - v2)*exp(-(t-t1/tau)) | 776 // v(t) = v2 + (v1 - v2)*exp(-(t-t1/tau)) |
757 // | 777 // |
758 | 778 |
759 float target = event.value(); | 779 float target = event.value(); |
760 float timeConstant = event.timeConstant(); | 780 float timeConstant = event.timeConstant(); |
761 float discreteTimeConstant = static_cast<float>( | 781 float discreteTimeConstant = static_cast<float>( |
762 AudioUtilities::discreteTimeConstantForSampleRate(timeConstant, | 782 AudioUtilities::discreteTimeConstantForSampleRate(timeConstant, |
763 controlRate)); | 783 controlRate)); |
764 | 784 |
765 // Set the starting value correctly. This is only needed when the cur
rent time | 785 // Set the starting value correctly. This is only needed when the |
766 // is "equal" to the start time of this event. This is to get the sam
pling | 786 // current time is "equal" to the start time of this event. This is |
767 // correct if the start time of this automation isn't on a frame bound
ary. | 787 // to get the sampling correct if the start time of this automation |
768 // Otherwise, we can just continue from where we left off from the pre
vious | 788 // isn't on a frame boundary. Otherwise, we can just continue from |
769 // rendering quantum. | 789 // where we left off from the previous rendering quantum. |
770 { | 790 { |
771 double rampStartFrame = time1 * sampleRate; | 791 double rampStartFrame = time1 * sampleRate; |
772 // Condition is c - 1 < r <= c where c = currentFrame and r = | 792 // Condition is c - 1 < r <= c where c = currentFrame and r = |
773 // rampStartFrame. Compute it this way because currentFrame is unsi
gned and | 793 // rampStartFrame. Compute it this way because currentFrame is |
774 // could be 0. | 794 // unsigned and could be 0. |
775 if (rampStartFrame <= currentFrame && | 795 if (rampStartFrame <= currentFrame && |
776 currentFrame < rampStartFrame + 1) { | 796 currentFrame < rampStartFrame + 1) { |
777 value = | 797 value = |
778 target + | 798 target + |
779 (value - target) * | 799 (value - target) * |
780 exp(-(currentFrame / sampleRate - time1) / timeConstant); | 800 exp(-(currentFrame / sampleRate - time1) / timeConstant); |
781 } else { | 801 } else { |
782 // Otherwise, need to compute a new value bacause |value| is the l
ast | 802 // Otherwise, need to compute a new value bacause |value| is the |
783 // computed value of SetTarget. Time has progressed by one frame,
so we | 803 // last computed value of SetTarget. Time has progressed by one |
784 // need to update the value for the new frame. | 804 // frame, so we need to update the value for the new frame. |
785 value += (target - value) * discreteTimeConstant; | 805 value += (target - value) * discreteTimeConstant; |
786 } | 806 } |
787 } | 807 } |
788 | 808 |
789 // If the value is close enough to the target, just fill in the data w
ith the | 809 // If the value is close enough to the target, just fill in the data |
790 // target value. | 810 // with the target value. |
791 if (fabs(value - target) < kSetTargetThreshold * fabs(target) || | 811 if (fabs(value - target) < kSetTargetThreshold * fabs(target) || |
792 (!target && fabs(value) < kSetTargetZeroThreshold)) { | 812 (!target && fabs(value) < kSetTargetZeroThreshold)) { |
793 for (; writeIndex < fillToFrame; ++writeIndex) | 813 for (; writeIndex < fillToFrame; ++writeIndex) |
794 values[writeIndex] = target; | 814 values[writeIndex] = target; |
795 } else { | 815 } else { |
796 #if CPU(X86) || CPU(X86_64) | 816 #if CPU(X86) || CPU(X86_64) |
797 // Resolve recursion by expanding constants to achieve a 4-step loop
unrolling. | 817 // Resolve recursion by expanding constants to achieve a 4-step loop |
| 818 // unrolling. |
798 // v1 = v0 + (t - v0) * c | 819 // v1 = v0 + (t - v0) * c |
799 // v2 = v1 + (t - v1) * c | 820 // v2 = v1 + (t - v1) * c |
800 // v2 = v0 + (t - v0) * c + (t - (v0 + (t - v0) * c)) * c | 821 // v2 = v0 + (t - v0) * c + (t - (v0 + (t - v0) * c)) * c |
801 // v2 = v0 + (t - v0) * c + (t - v0) * c - (t - v0) * c * c | 822 // v2 = v0 + (t - v0) * c + (t - v0) * c - (t - v0) * c * c |
802 // v2 = v0 + (t - v0) * c * (2 - c) | 823 // v2 = v0 + (t - v0) * c * (2 - c) |
803 // Thus c0 = c, c1 = c*(2-c). The same logic applies to c2 and c3. | 824 // Thus c0 = c, c1 = c*(2-c). The same logic applies to c2 and c3. |
804 const float c0 = discreteTimeConstant; | 825 const float c0 = discreteTimeConstant; |
805 const float c1 = c0 * (2 - c0); | 826 const float c1 = c0 * (2 - c0); |
806 const float c2 = c0 * ((c0 - 3) * c0 + 3); | 827 const float c2 = c0 * ((c0 - 3) * c0 + 3); |
807 const float c3 = c0 * (c0 * ((4 - c0) * c0 - 6) + 4); | 828 const float c3 = c0 * (c0 * ((4 - c0) * c0 - 6) + 4); |
(...skipping 15 matching lines...) Expand all Loading... |
823 | 844 |
824 // Update value for next iteration. | 845 // Update value for next iteration. |
825 value += delta * c3; | 846 value += delta * c3; |
826 } | 847 } |
827 #endif | 848 #endif |
828 // Serially process remaining values | 849 // Serially process remaining values |
829 for (; writeIndex < fillToFrame; ++writeIndex) { | 850 for (; writeIndex < fillToFrame; ++writeIndex) { |
830 values[writeIndex] = value; | 851 values[writeIndex] = value; |
831 value += (target - value) * discreteTimeConstant; | 852 value += (target - value) * discreteTimeConstant; |
832 } | 853 } |
833 // The previous loops may have updated |value| one extra time. Rese
t it to | 854 // The previous loops may have updated |value| one extra time. |
834 // the last computed value. | 855 // Reset it to the last computed value. |
835 if (writeIndex >= 1) | 856 if (writeIndex >= 1) |
836 value = values[writeIndex - 1]; | 857 value = values[writeIndex - 1]; |
837 currentFrame = fillToEndFrame; | 858 currentFrame = fillToEndFrame; |
838 } | 859 } |
839 break; | 860 break; |
840 } | 861 } |
841 | 862 |
842 case ParamEvent::SetValueCurve: { | 863 case ParamEvent::SetValueCurve: { |
843 Vector<float> curve = event.curve(); | 864 Vector<float> curve = event.curve(); |
844 float* curveData = curve.data(); | 865 float* curveData = curve.data(); |
845 unsigned numberOfCurvePoints = curve.size(); | 866 unsigned numberOfCurvePoints = curve.size(); |
846 | 867 |
847 // Curve events have duration, so don't just use next event time. | 868 // Curve events have duration, so don't just use next event time. |
848 double duration = event.duration(); | 869 double duration = event.duration(); |
849 // How much to step the curve index for each frame. This is basically
the term | 870 // How much to step the curve index for each frame. This is basically |
850 // (N - 1)/Td in the specification. | 871 // the term (N - 1)/Td in the specification. |
851 double curvePointsPerFrame = | 872 double curvePointsPerFrame = |
852 (numberOfCurvePoints - 1) / duration / sampleRate; | 873 (numberOfCurvePoints - 1) / duration / sampleRate; |
853 | 874 |
854 if (!numberOfCurvePoints || duration <= 0 || sampleRate <= 0) { | 875 if (!numberOfCurvePoints || duration <= 0 || sampleRate <= 0) { |
855 // Error condition - simply propagate previous value. | 876 // Error condition - simply propagate previous value. |
856 currentFrame = fillToEndFrame; | 877 currentFrame = fillToEndFrame; |
857 for (; writeIndex < fillToFrame; ++writeIndex) | 878 for (; writeIndex < fillToFrame; ++writeIndex) |
858 values[writeIndex] = value; | 879 values[writeIndex] = value; |
859 break; | 880 break; |
860 } | 881 } |
861 | 882 |
862 // Save old values and recalculate information based on the curve's du
ration | 883 // Save old values and recalculate information based on the curve's |
863 // instead of the next event time. | 884 // duration instead of the next event time. |
864 size_t nextEventFillToFrame = fillToFrame; | 885 size_t nextEventFillToFrame = fillToFrame; |
865 | 886 |
866 // fillToEndFrame = min(endFrame, ceil(sampleRate * (time1 + duration)
)), but | 887 // fillToEndFrame = min(endFrame, |
867 // compute this carefully in case sampleRate*(time1 + duration) is hug
e. | 888 // ceil(sampleRate * (time1 + duration))), |
868 // fillToEndFrame is an exclusive upper bound of the last frame to be
computed, | 889 // but compute this carefully in case sampleRate*(time1 + duration) is |
869 // so ceil is used. | 890 // huge. fillToEndFrame is an exclusive upper bound of the last frame |
| 891 // to be computed, so ceil is used. |
870 { | 892 { |
871 double curveEndFrame = ceil(sampleRate * (time1 + duration)); | 893 double curveEndFrame = ceil(sampleRate * (time1 + duration)); |
872 if (endFrame > curveEndFrame) | 894 if (endFrame > curveEndFrame) |
873 fillToEndFrame = static_cast<size_t>(curveEndFrame); | 895 fillToEndFrame = static_cast<size_t>(curveEndFrame); |
874 else | 896 else |
875 fillToEndFrame = endFrame; | 897 fillToEndFrame = endFrame; |
876 } | 898 } |
877 | 899 |
878 // |fillToFrame| can be less than |startFrame| when the end of the | 900 // |fillToFrame| can be less than |startFrame| when the end of the |
879 // setValueCurve automation has been reached, but the next automation
has not | 901 // setValueCurve automation has been reached, but the next automation |
880 // yet started. In this case, |fillToFrame| is clipped to |time1|+|dur
ation| | 902 // has not yet started. In this case, |fillToFrame| is clipped to |
881 // above, but |startFrame| will keep increasing (because the current t
ime is | 903 // |time1|+|duration| above, but |startFrame| will keep increasing |
882 // increasing). | 904 // (because the current time is increasing). |
883 fillToFrame = | 905 fillToFrame = |
884 (fillToEndFrame < startFrame) ? 0 : fillToEndFrame - startFrame; | 906 (fillToEndFrame < startFrame) ? 0 : fillToEndFrame - startFrame; |
885 fillToFrame = | 907 fillToFrame = |
886 std::min(fillToFrame, static_cast<size_t>(numberOfValues)); | 908 std::min(fillToFrame, static_cast<size_t>(numberOfValues)); |
887 | 909 |
888 // Index into the curve data using a floating-point value. | 910 // Index into the curve data using a floating-point value. |
889 // We're scaling the number of curve points by the duration (see curve
PointsPerFrame). | 911 // We're scaling the number of curve points by the duration (see |
| 912 // curvePointsPerFrame). |
890 double curveVirtualIndex = 0; | 913 double curveVirtualIndex = 0; |
891 if (time1 < currentFrame / sampleRate) { | 914 if (time1 < currentFrame / sampleRate) { |
892 // Index somewhere in the middle of the curve data. | 915 // Index somewhere in the middle of the curve data. |
893 // Don't use timeToSampleFrame() since we want the exact floating-po
int frame. | 916 // Don't use timeToSampleFrame() since we want the exact |
| 917 // floating-point frame. |
894 double frameOffset = currentFrame - time1 * sampleRate; | 918 double frameOffset = currentFrame - time1 * sampleRate; |
895 curveVirtualIndex = curvePointsPerFrame * frameOffset; | 919 curveVirtualIndex = curvePointsPerFrame * frameOffset; |
896 } | 920 } |
897 | 921 |
898 // Set the default value in case fillToFrame is 0. | 922 // Set the default value in case fillToFrame is 0. |
899 value = curveData[numberOfCurvePoints - 1]; | 923 value = curveData[numberOfCurvePoints - 1]; |
900 | 924 |
901 // Render the stretched curve data using linear interpolation. Oversa
mpled | 925 // Render the stretched curve data using linear interpolation. |
902 // curve data can be provided if sharp discontinuities are desired. | 926 // Oversampled curve data can be provided if sharp discontinuities are |
| 927 // desired. |
903 unsigned k = 0; | 928 unsigned k = 0; |
904 #if CPU(X86) || CPU(X86_64) | 929 #if CPU(X86) || CPU(X86_64) |
905 const __m128 vCurveVirtualIndex = _mm_set_ps1(curveVirtualIndex); | 930 const __m128 vCurveVirtualIndex = _mm_set_ps1(curveVirtualIndex); |
906 const __m128 vCurvePointsPerFrame = _mm_set_ps1(curvePointsPerFrame); | 931 const __m128 vCurvePointsPerFrame = _mm_set_ps1(curvePointsPerFrame); |
907 const __m128 vNumberOfCurvePointsM1 = | 932 const __m128 vNumberOfCurvePointsM1 = |
908 _mm_set_ps1(numberOfCurvePoints - 1); | 933 _mm_set_ps1(numberOfCurvePoints - 1); |
909 const __m128 vN1 = _mm_set_ps1(1.0f); | 934 const __m128 vN1 = _mm_set_ps1(1.0f); |
910 const __m128 vN4 = _mm_set_ps1(4.0f); | 935 const __m128 vN4 = _mm_set_ps1(4.0f); |
911 | 936 |
912 __m128 vK = _mm_set_ps(3, 2, 1, 0); | 937 __m128 vK = _mm_set_ps(3, 2, 1, 0); |
913 int aCurveIndex0[4]; | 938 int aCurveIndex0[4]; |
914 int aCurveIndex1[4]; | 939 int aCurveIndex1[4]; |
915 | 940 |
916 // Truncate loop steps to multiple of 4 | 941 // Truncate loop steps to multiple of 4 |
917 unsigned truncatedSteps = ((fillToFrame - writeIndex) / 4) * 4; | 942 unsigned truncatedSteps = ((fillToFrame - writeIndex) / 4) * 4; |
918 unsigned fillToFrameTrunc = writeIndex + truncatedSteps; | 943 unsigned fillToFrameTrunc = writeIndex + truncatedSteps; |
919 for (; writeIndex < fillToFrameTrunc; writeIndex += 4) { | 944 for (; writeIndex < fillToFrameTrunc; writeIndex += 4) { |
920 // Compute current index this way to minimize round-off that would h
ave | 945 // Compute current index this way to minimize round-off that would |
921 // occurred by incrementing the index by curvePointsPerFrame. | 946 // have occurred by incrementing the index by curvePointsPerFrame. |
922 __m128 vCurrentVirtualIndex = _mm_add_ps( | 947 __m128 vCurrentVirtualIndex = _mm_add_ps( |
923 vCurveVirtualIndex, _mm_mul_ps(vK, vCurvePointsPerFrame)); | 948 vCurveVirtualIndex, _mm_mul_ps(vK, vCurvePointsPerFrame)); |
924 vK = _mm_add_ps(vK, vN4); | 949 vK = _mm_add_ps(vK, vN4); |
925 | 950 |
926 // Clamp index to the last element of the array. | 951 // Clamp index to the last element of the array. |
927 __m128i vCurveIndex0 = _mm_cvttps_epi32( | 952 __m128i vCurveIndex0 = _mm_cvttps_epi32( |
928 _mm_min_ps(vCurrentVirtualIndex, vNumberOfCurvePointsM1)); | 953 _mm_min_ps(vCurrentVirtualIndex, vNumberOfCurvePointsM1)); |
929 __m128i vCurveIndex1 = _mm_cvttps_epi32(_mm_min_ps( | 954 __m128i vCurveIndex1 = _mm_cvttps_epi32(_mm_min_ps( |
930 _mm_add_ps(vCurrentVirtualIndex, vN1), vNumberOfCurvePointsM1)); | 955 _mm_add_ps(vCurrentVirtualIndex, vN1), vNumberOfCurvePointsM1)); |
931 | 956 |
932 // Linearly interpolate between the two nearest curve points. |delt
a| is | 957 // Linearly interpolate between the two nearest curve points. |
933 // clamped to 1 because currentVirtualIndex can exceed curveIndex0 b
y more | 958 // |delta| is clamped to 1 because currentVirtualIndex can exceed |
934 // than one. This can happen when we reached the end of the curve b
ut still | 959 // curveIndex0 by more than one. This can happen when we reached |
935 // need values to fill out the current rendering quantum. | 960 // the end of the curve but still need values to fill out the |
| 961 // current rendering quantum. |
936 _mm_storeu_si128((__m128i*)aCurveIndex0, vCurveIndex0); | 962 _mm_storeu_si128((__m128i*)aCurveIndex0, vCurveIndex0); |
937 _mm_storeu_si128((__m128i*)aCurveIndex1, vCurveIndex1); | 963 _mm_storeu_si128((__m128i*)aCurveIndex1, vCurveIndex1); |
938 __m128 vC0 = _mm_set_ps( | 964 __m128 vC0 = _mm_set_ps( |
939 curveData[aCurveIndex0[3]], curveData[aCurveIndex0[2]], | 965 curveData[aCurveIndex0[3]], curveData[aCurveIndex0[2]], |
940 curveData[aCurveIndex0[1]], curveData[aCurveIndex0[0]]); | 966 curveData[aCurveIndex0[1]], curveData[aCurveIndex0[0]]); |
941 __m128 vC1 = _mm_set_ps( | 967 __m128 vC1 = _mm_set_ps( |
942 curveData[aCurveIndex1[3]], curveData[aCurveIndex1[2]], | 968 curveData[aCurveIndex1[3]], curveData[aCurveIndex1[2]], |
943 curveData[aCurveIndex1[1]], curveData[aCurveIndex1[0]]); | 969 curveData[aCurveIndex1[1]], curveData[aCurveIndex1[0]]); |
944 __m128 vDelta = _mm_min_ps( | 970 __m128 vDelta = _mm_min_ps( |
945 _mm_sub_ps(vCurrentVirtualIndex, _mm_cvtepi32_ps(vCurveIndex0)), | 971 _mm_sub_ps(vCurrentVirtualIndex, _mm_cvtepi32_ps(vCurveIndex0)), |
946 vN1); | 972 vN1); |
947 | 973 |
948 __m128 vValue = | 974 __m128 vValue = |
949 _mm_add_ps(vC0, _mm_mul_ps(_mm_sub_ps(vC1, vC0), vDelta)); | 975 _mm_add_ps(vC0, _mm_mul_ps(_mm_sub_ps(vC1, vC0), vDelta)); |
950 | 976 |
951 _mm_storeu_ps(values + writeIndex, vValue); | 977 _mm_storeu_ps(values + writeIndex, vValue); |
952 } | 978 } |
953 // Pass along k to the serial loop. | 979 // Pass along k to the serial loop. |
954 k = truncatedSteps; | 980 k = truncatedSteps; |
955 // If the above loop was run, pass along the last computed value. | 981 // If the above loop was run, pass along the last computed value. |
956 if (truncatedSteps > 0) { | 982 if (truncatedSteps > 0) { |
957 value = values[writeIndex - 1]; | 983 value = values[writeIndex - 1]; |
958 } | 984 } |
959 #endif | 985 #endif |
960 for (; writeIndex < fillToFrame; ++writeIndex, ++k) { | 986 for (; writeIndex < fillToFrame; ++writeIndex, ++k) { |
961 // Compute current index this way to minimize round-off that would h
ave | 987 // Compute current index this way to minimize round-off that would |
962 // occurred by incrementing the index by curvePointsPerFrame. | 988 // have occurred by incrementing the index by curvePointsPerFrame. |
963 double currentVirtualIndex = | 989 double currentVirtualIndex = |
964 curveVirtualIndex + k * curvePointsPerFrame; | 990 curveVirtualIndex + k * curvePointsPerFrame; |
965 unsigned curveIndex0; | 991 unsigned curveIndex0; |
966 | 992 |
967 // Clamp index to the last element of the array. | 993 // Clamp index to the last element of the array. |
968 if (currentVirtualIndex < numberOfCurvePoints) { | 994 if (currentVirtualIndex < numberOfCurvePoints) { |
969 curveIndex0 = static_cast<unsigned>(currentVirtualIndex); | 995 curveIndex0 = static_cast<unsigned>(currentVirtualIndex); |
970 } else { | 996 } else { |
971 curveIndex0 = numberOfCurvePoints - 1; | 997 curveIndex0 = numberOfCurvePoints - 1; |
972 } | 998 } |
973 | 999 |
974 unsigned curveIndex1 = | 1000 unsigned curveIndex1 = |
975 std::min(curveIndex0 + 1, numberOfCurvePoints - 1); | 1001 std::min(curveIndex0 + 1, numberOfCurvePoints - 1); |
976 | 1002 |
977 // Linearly interpolate between the two nearest curve points. |delt
a| is | 1003 // Linearly interpolate between the two nearest curve points. |
978 // clamped to 1 because currentVirtualIndex can exceed curveIndex0 b
y more | 1004 // |delta| is clamped to 1 because currentVirtualIndex can exceed |
979 // than one. This can happen when we reached the end of the curve b
ut still | 1005 // curveIndex0 by more than one. This can happen when we reached |
980 // need values to fill out the current rendering quantum. | 1006 // the end of the curve but still need values to fill out the |
| 1007 // current rendering quantum. |
981 DCHECK_LT(curveIndex0, numberOfCurvePoints); | 1008 DCHECK_LT(curveIndex0, numberOfCurvePoints); |
982 DCHECK_LT(curveIndex1, numberOfCurvePoints); | 1009 DCHECK_LT(curveIndex1, numberOfCurvePoints); |
983 float c0 = curveData[curveIndex0]; | 1010 float c0 = curveData[curveIndex0]; |
984 float c1 = curveData[curveIndex1]; | 1011 float c1 = curveData[curveIndex1]; |
985 double delta = std::min(currentVirtualIndex - curveIndex0, 1.0); | 1012 double delta = std::min(currentVirtualIndex - curveIndex0, 1.0); |
986 | 1013 |
987 value = c0 + (c1 - c0) * delta; | 1014 value = c0 + (c1 - c0) * delta; |
988 | 1015 |
989 values[writeIndex] = value; | 1016 values[writeIndex] = value; |
990 } | 1017 } |
991 | 1018 |
992 // If there's any time left after the duration of this event and the s
tart | 1019 // If there's any time left after the duration of this event and the |
993 // of the next, then just propagate the last value of the curveData. | 1020 // start of the next, then just propagate the last value of the |
| 1021 // curveData. |
994 if (writeIndex < nextEventFillToFrame) | 1022 if (writeIndex < nextEventFillToFrame) |
995 value = curveData[numberOfCurvePoints - 1]; | 1023 value = curveData[numberOfCurvePoints - 1]; |
996 for (; writeIndex < nextEventFillToFrame; ++writeIndex) | 1024 for (; writeIndex < nextEventFillToFrame; ++writeIndex) |
997 values[writeIndex] = value; | 1025 values[writeIndex] = value; |
998 | 1026 |
999 // Re-adjust current time | 1027 // Re-adjust current time |
1000 currentFrame += nextEventFillToFrame; | 1028 currentFrame += nextEventFillToFrame; |
1001 | 1029 |
1002 break; | 1030 break; |
1003 } | 1031 } |
1004 case ParamEvent::LastType: | 1032 case ParamEvent::LastType: |
1005 ASSERT_NOT_REACHED(); | 1033 ASSERT_NOT_REACHED(); |
1006 break; | 1034 break; |
1007 } | 1035 } |
1008 } | 1036 } |
1009 } | 1037 } |
1010 | 1038 |
1011 // If we skipped over any events (because they are in the past), we can | 1039 // If we skipped over any events (because they are in the past), we can |
1012 // remove them so we don't have to check them ever again. (This MUST be | 1040 // remove them so we don't have to check them ever again. (This MUST be |
1013 // running with the m_events lock so we can safely modify the m_events | 1041 // running with the m_events lock so we can safely modify the m_events |
1014 // array.) | 1042 // array.) |
1015 if (lastSkippedEventIndex > 0) | 1043 if (lastSkippedEventIndex > 0) |
1016 m_events.remove(0, lastSkippedEventIndex - 1); | 1044 m_events.remove(0, lastSkippedEventIndex - 1); |
1017 | 1045 |
1018 // If there's any time left after processing the last event then just propagat
e the last value | 1046 // If there's any time left after processing the last event then just |
1019 // to the end of the values buffer. | 1047 // propagate the last value to the end of the values buffer. |
1020 for (; writeIndex < numberOfValues; ++writeIndex) | 1048 for (; writeIndex < numberOfValues; ++writeIndex) |
1021 values[writeIndex] = value; | 1049 values[writeIndex] = value; |
1022 | 1050 |
1023 // This value is used to set the .value attribute of the AudioParam. it shoul
d be the last | 1051 // This value is used to set the .value attribute of the AudioParam. it |
1024 // computed value. | 1052 // should be the last computed value. |
1025 return values[numberOfValues - 1]; | 1053 return values[numberOfValues - 1]; |
1026 } | 1054 } |
1027 | 1055 |
1028 } // namespace blink | 1056 } // namespace blink |
OLD | NEW |