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 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 MutexTryLocker tryLocker(m_eventsLock); | 252 MutexTryLocker tryLocker(m_eventsLock); |
253 if (!tryLocker.locked() || !context || !m_events.size() || context->curr
entTime() < m_events[0].time()) { | 253 if (!tryLocker.locked() || !context || !m_events.size() || context->curr
entTime() < m_events[0].time()) { |
254 hasValue = false; | 254 hasValue = false; |
255 return defaultValue; | 255 return defaultValue; |
256 } | 256 } |
257 } | 257 } |
258 | 258 |
259 // Ask for just a single value. | 259 // Ask for just a single value. |
260 float value; | 260 float value; |
261 double sampleRate = context->sampleRate(); | 261 double sampleRate = context->sampleRate(); |
262 double startTime = context->currentTime(); | 262 size_t startFrame = context->currentSampleFrame(); |
263 double endTime = startTime + 1.1 / sampleRate; // time just beyond one sampl
e-frame | |
264 double controlRate = sampleRate / AudioHandler::ProcessingSizeInFrames; // o
ne parameter change per render quantum | 263 double controlRate = sampleRate / AudioHandler::ProcessingSizeInFrames; // o
ne parameter change per render quantum |
265 value = valuesForTimeRange(startTime, endTime, defaultValue, &value, 1, samp
leRate, controlRate); | 264 value = valuesForFrameRange(startFrame, startFrame + 1, defaultValue, &value
, 1, sampleRate, controlRate); |
266 | 265 |
267 hasValue = true; | 266 hasValue = true; |
268 return value; | 267 return value; |
269 } | 268 } |
270 | 269 |
271 float AudioParamTimeline::valuesForTimeRange( | 270 float AudioParamTimeline::valuesForFrameRange( |
272 double startTime, | 271 size_t startFrame, |
273 double endTime, | 272 size_t endFrame, |
274 float defaultValue, | 273 float defaultValue, |
275 float* values, | 274 float* values, |
276 unsigned numberOfValues, | 275 unsigned numberOfValues, |
277 double sampleRate, | 276 double sampleRate, |
278 double controlRate) | 277 double controlRate) |
279 { | 278 { |
280 // We can't contend the lock in the realtime audio thread. | 279 // We can't contend the lock in the realtime audio thread. |
281 MutexTryLocker tryLocker(m_eventsLock); | 280 MutexTryLocker tryLocker(m_eventsLock); |
282 if (!tryLocker.locked()) { | 281 if (!tryLocker.locked()) { |
283 if (values) { | 282 if (values) { |
284 for (unsigned i = 0; i < numberOfValues; ++i) | 283 for (unsigned i = 0; i < numberOfValues; ++i) |
285 values[i] = defaultValue; | 284 values[i] = defaultValue; |
286 } | 285 } |
287 return defaultValue; | 286 return defaultValue; |
288 } | 287 } |
289 | 288 |
290 return valuesForTimeRangeImpl(startTime, endTime, defaultValue, values, numb
erOfValues, sampleRate, controlRate); | 289 return valuesForFrameRangeImpl(startFrame, endFrame, defaultValue, values, n
umberOfValues, sampleRate, controlRate); |
291 } | 290 } |
292 | 291 |
293 float AudioParamTimeline::valuesForTimeRangeImpl( | 292 float AudioParamTimeline::valuesForFrameRangeImpl( |
294 double startTime, | 293 size_t startFrame, |
295 double endTime, | 294 size_t endFrame, |
296 float defaultValue, | 295 float defaultValue, |
297 float* values, | 296 float* values, |
298 unsigned numberOfValues, | 297 unsigned numberOfValues, |
299 double sampleRate, | 298 double sampleRate, |
300 double controlRate) | 299 double controlRate) |
301 { | 300 { |
302 ASSERT(values); | 301 ASSERT(values); |
303 if (!values) | 302 if (!values) |
304 return defaultValue; | 303 return defaultValue; |
305 | 304 |
306 // Return default value if there are no events matching the desired time ran
ge. | 305 // Return default value if there are no events matching the desired time ran
ge. |
307 if (!m_events.size() || endTime <= m_events[0].time()) { | 306 if (!m_events.size() || (endFrame / sampleRate <= m_events[0].time())) { |
308 for (unsigned i = 0; i < numberOfValues; ++i) | 307 for (unsigned i = 0; i < numberOfValues; ++i) |
309 values[i] = defaultValue; | 308 values[i] = defaultValue; |
310 return defaultValue; | 309 return defaultValue; |
311 } | 310 } |
312 | 311 |
313 // Maintain a running time and index for writing the values buffer. | 312 // Maintain a running time (frame) and index for writing the values buffer. |
314 double currentTime = startTime; | 313 size_t currentFrame = startFrame; |
315 unsigned writeIndex = 0; | 314 unsigned writeIndex = 0; |
316 | 315 |
317 // If first event is after startTime then fill initial part of values buffer
with defaultValue | 316 // If first event is after startFrame then fill initial part of values buffe
r with defaultValue |
318 // until we reach the first event time. | 317 // until we reach the first event time. |
319 double firstEventTime = m_events[0].time(); | 318 double firstEventTime = m_events[0].time(); |
320 if (firstEventTime > startTime) { | 319 if (firstEventTime > startFrame / sampleRate) { |
321 double fillToTime = std::min(endTime, firstEventTime); | 320 // |fillToFrame| is an exclusive upper bound, so use ceil() to compute t
he bound from the |
322 unsigned fillToFrame = AudioUtilities::timeToSampleFrame(fillToTime - st
artTime, sampleRate); | 321 // firstEventTime. |
323 fillToFrame = std::min(fillToFrame, numberOfValues); | 322 size_t fillToFrame = std::min(endFrame, static_cast<size_t>(ceil(firstEv
entTime * sampleRate))); |
| 323 ASSERT(fillToFrame >= startFrame); |
| 324 fillToFrame -= startFrame; |
| 325 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues))
; |
324 for (; writeIndex < fillToFrame; ++writeIndex) | 326 for (; writeIndex < fillToFrame; ++writeIndex) |
325 values[writeIndex] = defaultValue; | 327 values[writeIndex] = defaultValue; |
326 | 328 |
327 currentTime = fillToTime; | 329 currentFrame += fillToFrame; |
328 } | 330 } |
329 | 331 |
330 float value = defaultValue; | 332 float value = defaultValue; |
331 | 333 |
332 // Go through each event and render the value buffer where the times overlap
, | 334 // Go through each event and render the value buffer where the times overlap
, |
333 // stopping when we've rendered all the requested values. | 335 // stopping when we've rendered all the requested values. |
334 // FIXME: could try to optimize by avoiding having to iterate starting from
the very first event | 336 // FIXME: could try to optimize by avoiding having to iterate starting from
the very first event |
335 // and keeping track of a "current" event index. | 337 // and keeping track of a "current" event index. |
336 int n = m_events.size(); | 338 int n = m_events.size(); |
337 for (int i = 0; i < n && writeIndex < numberOfValues; ++i) { | 339 for (int i = 0; i < n && writeIndex < numberOfValues; ++i) { |
338 ParamEvent& event = m_events[i]; | 340 ParamEvent& event = m_events[i]; |
339 ParamEvent* nextEvent = i < n - 1 ? &(m_events[i + 1]) : 0; | 341 ParamEvent* nextEvent = i < n - 1 ? &(m_events[i + 1]) : 0; |
340 | 342 |
341 // Wait until we get a more recent event. | 343 // Wait until we get a more recent event. |
342 if (nextEvent && nextEvent->time() < currentTime) | 344 if (nextEvent && nextEvent->time() < currentFrame / sampleRate) { |
343 continue; | 345 // But if the current event is a SetValue event and the event time i
s between |
| 346 // currentFrame - 1 and curentFrame (in time). we don't want to skip
it. If we do skip |
| 347 // it, the SetValue event is completely skipped and not applied, whi
ch is wrong. Other |
| 348 // events don't have this problem. (Because currentFrame is unsigne
d, we do the time |
| 349 // check in this funny, but equivalent way.) |
| 350 double eventFrame = event.time() * sampleRate; |
| 351 |
| 352 // Condition is currentFrame - 1 < eventFrame <= currentFrame, but c
urrentFrame is |
| 353 // unsigned and could be 0, so use currentFrame < eventFrame + 1 ins
tead. |
| 354 if (!((event.type() == ParamEvent::SetValue |
| 355 && (eventFrame <= currentFrame) |
| 356 && (currentFrame < eventFrame + 1)))) |
| 357 continue; |
| 358 } |
344 | 359 |
345 float value1 = event.value(); | 360 float value1 = event.value(); |
346 double time1 = event.time(); | 361 double time1 = event.time(); |
347 float value2 = nextEvent ? nextEvent->value() : value1; | 362 float value2 = nextEvent ? nextEvent->value() : value1; |
348 double time2 = nextEvent ? nextEvent->time() : endTime + 1; | 363 double time2 = nextEvent ? nextEvent->time() : endFrame / sampleRate + 1
; |
349 | 364 |
350 double deltaTime = time2 - time1; | 365 double deltaTime = time2 - time1; |
351 float k = deltaTime > 0 ? 1 / deltaTime : 0; | 366 float k = deltaTime > 0 ? 1 / deltaTime : 0; |
352 double sampleFrameTimeIncr = 1 / sampleRate; | |
353 | 367 |
354 double fillToTime = std::min(endTime, time2); | 368 // |fillToEndFrame| is the exclusive upper bound of the last frame to be
computed for this |
355 unsigned fillToFrame = AudioUtilities::timeToSampleFrame(fillToTime - st
artTime, sampleRate); | 369 // event. It's either the last desired frame (|endFrame|) or derived fr
om the end time of |
356 fillToFrame = std::min(fillToFrame, numberOfValues); | 370 // the next event (time2). We compute ceil(time2*sampleRate) because fil
lToEndFrame is the |
| 371 // exclusive upper bound. Consider the case where |startFrame| = 128 an
d time2 = 128.1 |
| 372 // (assuming sampleRate = 1). Since time2 is greater than 128, we want
to output a value |
| 373 // for frame 128. This requires that fillToEndFrame be at least 129. T
his is achieved by |
| 374 // ceil(time2). |
| 375 size_t fillToEndFrame = std::min(endFrame, static_cast<size_t>(ceil(time
2 * sampleRate))); |
| 376 ASSERT(fillToEndFrame >= startFrame); |
| 377 size_t fillToFrame = fillToEndFrame - startFrame; |
| 378 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numberOfValues))
; |
357 | 379 |
358 ParamEvent::Type nextEventType = nextEvent ? static_cast<ParamEvent::Typ
e>(nextEvent->type()) : ParamEvent::LastType /* unknown */; | 380 ParamEvent::Type nextEventType = nextEvent ? static_cast<ParamEvent::Typ
e>(nextEvent->type()) : ParamEvent::LastType /* unknown */; |
359 | 381 |
360 // First handle linear and exponential ramps which require looking ahead
to the next event. | 382 // First handle linear and exponential ramps which require looking ahead
to the next event. |
361 if (nextEventType == ParamEvent::LinearRampToValue) { | 383 if (nextEventType == ParamEvent::LinearRampToValue) { |
362 const float valueDelta = value2 - value1; | 384 const float valueDelta = value2 - value1; |
363 #if CPU(X86) || CPU(X86_64) | 385 #if CPU(X86) || CPU(X86_64) |
364 // Minimize in-loop operations. Calculate starting value and increme
nt. Next step: value += inc. | 386 // Minimize in-loop operations. Calculate starting value and increme
nt. Next step: value += inc. |
365 // value = value1 + (currentTime - time1) * k * (value2 - value1); | 387 // value = value1 + (currentFrame/sampleRate - time1) * k * (value2
- value1); |
366 // inc = sampleFrameTimeIncr * k * (value2 - value1); | 388 // inc = 4 / sampleRate * k * (value2 - value1); |
367 // Resolve recursion by expanding constants to achieve a 4-step loop
unrolling. | 389 // Resolve recursion by expanding constants to achieve a 4-step loop
unrolling. |
368 // value = value1 + ((currentTime - time1) + i * sampleFrameTimeInc
r) * k * (value2 -value1), i in 0..3 | 390 // value = value1 + ((currentFrame/sampleRate - time1) + i * sample
FrameTimeIncr) * k * (value2 -value1), i in 0..3 |
369 __m128 vValue = _mm_mul_ps(_mm_set_ps1(sampleFrameTimeIncr), _mm_set
_ps(3, 2, 1, 0)); | 391 __m128 vValue = _mm_mul_ps(_mm_set_ps1(1 / sampleRate), _mm_set_ps(3
, 2, 1, 0)); |
370 vValue = _mm_add_ps(vValue, _mm_set_ps1(currentTime - time1)); | 392 vValue = _mm_add_ps(vValue, _mm_set_ps1(currentFrame / sampleRate -
time1)); |
371 vValue = _mm_mul_ps(vValue, _mm_set_ps1(k * valueDelta)); | 393 vValue = _mm_mul_ps(vValue, _mm_set_ps1(k * valueDelta)); |
372 vValue = _mm_add_ps(vValue, _mm_set_ps1(value1)); | 394 vValue = _mm_add_ps(vValue, _mm_set_ps1(value1)); |
373 __m128 vInc = _mm_set_ps1(4 * sampleFrameTimeIncr * k * valueDelta); | 395 __m128 vInc = _mm_set_ps1(4 / sampleRate * k * valueDelta); |
374 | 396 |
375 // Truncate loop steps to multiple of 4. | 397 // Truncate loop steps to multiple of 4. |
376 unsigned fillToFrameTrunc = writeIndex + ((fillToFrame - writeIndex)
/ 4) * 4; | 398 unsigned fillToFrameTrunc = writeIndex + ((fillToFrame - writeIndex)
/ 4) * 4; |
377 // Compute final time. | 399 // Compute final time. |
378 currentTime += sampleFrameTimeIncr * (fillToFrameTrunc - writeIndex)
; | 400 currentFrame += fillToFrameTrunc - writeIndex; |
| 401 |
379 // Process 4 loop steps. | 402 // Process 4 loop steps. |
380 for (; writeIndex < fillToFrameTrunc; writeIndex += 4) { | 403 for (; writeIndex < fillToFrameTrunc; writeIndex += 4) { |
381 _mm_storeu_ps(values + writeIndex, vValue); | 404 _mm_storeu_ps(values + writeIndex, vValue); |
382 vValue = _mm_add_ps(vValue, vInc); | 405 vValue = _mm_add_ps(vValue, vInc); |
383 } | 406 } |
384 #endif | 407 #endif |
385 // Serially process remaining values. | 408 // Serially process remaining values. |
386 for (; writeIndex < fillToFrame; ++writeIndex) { | 409 for (; writeIndex < fillToFrame; ++writeIndex) { |
387 float x = (currentTime - time1) * k; | 410 float x = (currentFrame / sampleRate - time1) * k; |
388 // value = (1 - x) * value1 + x * value2; | 411 // value = (1 - x) * value1 + x * value2; |
389 value = value1 + x * valueDelta; | 412 value = value1 + x * valueDelta; |
390 values[writeIndex] = value; | 413 values[writeIndex] = value; |
391 currentTime += sampleFrameTimeIncr; | 414 ++currentFrame; |
392 } | 415 } |
393 } else if (nextEventType == ParamEvent::ExponentialRampToValue) { | 416 } else if (nextEventType == ParamEvent::ExponentialRampToValue) { |
394 if (value1 <= 0 || value2 <= 0) { | 417 if (value1 <= 0 || value2 <= 0) { |
395 // Handle negative values error case by propagating previous val
ue. | 418 // Handle negative values error case by propagating previous val
ue. |
396 for (; writeIndex < fillToFrame; ++writeIndex) | 419 for (; writeIndex < fillToFrame; ++writeIndex) |
397 values[writeIndex] = value; | 420 values[writeIndex] = value; |
398 } else { | 421 } else { |
399 float numSampleFrames = deltaTime * sampleRate; | 422 float numSampleFrames = deltaTime * sampleRate; |
400 // The value goes exponentially from value1 to value2 in a durat
ion of deltaTime seconds (corresponding to numSampleFrames). | 423 // The value goes exponentially from value1 to value2 in a durat
ion of deltaTime |
| 424 // seconds according to |
| 425 // |
| 426 // v(t) = v1*(v2/v1)^((t-t1)/(t2-t1)) |
| 427 // |
| 428 // Let c be currentFrame and F be the sampleRate. Then we want
to sample v(t) |
| 429 // at times t = (c + k)/F for k = 0, 1, ...: |
| 430 // |
| 431 // v((c+k)/F) = v1*(v2/v1)^(((c/F+k/F)-t1)/(t2-t1)) |
| 432 // = v1*(v2/v1)^((c/F-t1)/(t2-t1)) |
| 433 // *(v2/v1)^((k/F)/(t2-t1)) |
| 434 // = v1*(v2/v1)^((c/F-t1)/(t2-t1)) |
| 435 // *[(v2/v1)^(1/(F*(t2-t1)))]^k |
| 436 // |
| 437 // Thus, this can be written as |
| 438 // |
| 439 // v((c+k)/F) = V*m^k |
| 440 // |
| 441 // where |
| 442 // V = v1*(v2/v1)^((c/F-t1)/(t2-t1)) |
| 443 // m = (v2/v1)^(1/(F*(t2-t1))) |
| 444 |
401 // Compute the per-sample multiplier. | 445 // Compute the per-sample multiplier. |
402 float multiplier = powf(value2 / value1, 1 / numSampleFrames); | 446 float multiplier = powf(value2 / value1, 1 / numSampleFrames); |
403 | 447 // Set the starting value of the exponential ramp. |
404 // Set the starting value of the exponential ramp. This is the s
ame as multiplier ^ | |
405 // AudioUtilities::timeToSampleFrame(currentTime - time1, sample
Rate), but is more | |
406 // accurate, especially if multiplier is close to 1. | |
407 value = value1 * powf(value2 / value1, | 448 value = value1 * powf(value2 / value1, |
408 AudioUtilities::timeToSampleFrame(currentTime - time1, sampl
eRate) / numSampleFrames); | 449 (currentFrame / sampleRate - time1) / deltaTime); |
409 | 450 |
410 for (; writeIndex < fillToFrame; ++writeIndex) { | 451 for (; writeIndex < fillToFrame; ++writeIndex) { |
411 values[writeIndex] = value; | 452 values[writeIndex] = value; |
412 value *= multiplier; | 453 value *= multiplier; |
413 currentTime += sampleFrameTimeIncr; | 454 ++currentFrame; |
414 } | 455 } |
415 } | 456 } |
416 } else { | 457 } else { |
417 // Handle event types not requiring looking ahead to the next event. | 458 // Handle event types not requiring looking ahead to the next event. |
418 switch (event.type()) { | 459 switch (event.type()) { |
419 case ParamEvent::SetValue: | 460 case ParamEvent::SetValue: |
420 case ParamEvent::LinearRampToValue: | 461 case ParamEvent::LinearRampToValue: |
421 case ParamEvent::ExponentialRampToValue: | 462 case ParamEvent::ExponentialRampToValue: |
422 { | 463 { |
423 currentTime = fillToTime; | 464 currentFrame = fillToEndFrame; |
424 | 465 |
425 // Simply stay at a constant value. | 466 // Simply stay at a constant value. |
426 value = event.value(); | 467 value = event.value(); |
427 for (; writeIndex < fillToFrame; ++writeIndex) | 468 for (; writeIndex < fillToFrame; ++writeIndex) |
428 values[writeIndex] = value; | 469 values[writeIndex] = value; |
429 | 470 |
430 break; | 471 break; |
431 } | 472 } |
432 | 473 |
433 case ParamEvent::SetTarget: | 474 case ParamEvent::SetTarget: |
434 { | 475 { |
435 currentTime = fillToTime; | 476 // Exponential approach to target value with given time cons
tant. |
| 477 // |
| 478 // v(t) = v2 + (v1 - v2)*exp(-(t-t1/tau)) |
| 479 // |
436 | 480 |
437 // Exponential approach to target value with given time cons
tant. | |
438 float target = event.value(); | 481 float target = event.value(); |
439 float timeConstant = event.timeConstant(); | 482 float timeConstant = event.timeConstant(); |
440 float discreteTimeConstant = static_cast<float>(AudioUtiliti
es::discreteTimeConstantForSampleRate(timeConstant, controlRate)); | 483 float discreteTimeConstant = static_cast<float>(AudioUtiliti
es::discreteTimeConstantForSampleRate(timeConstant, controlRate)); |
441 | 484 |
| 485 // Set the starting value correctly. This is only needed wh
en the current time |
| 486 // is "equal" to the start time of this event. This is to g
et the sampling |
| 487 // correct if the start time of this automation isn't on a f
rame boundary. |
| 488 // Otherwise, we can just continue from where we left off fr
om the previous |
| 489 // rendering quantum. |
| 490 |
| 491 { |
| 492 double rampStartFrame = time1 * sampleRate; |
| 493 // Condition is c - 1 < r <= c where c = currentFrame an
d r = |
| 494 // rampStartFrame. Compute it this way because currentF
rame is unsigned and |
| 495 // could be 0. |
| 496 if (rampStartFrame <= currentFrame && currentFrame < ram
pStartFrame + 1) |
| 497 value = target + (value - target) * exp(-(currentFra
me / sampleRate - time1) / timeConstant); |
| 498 } |
442 #if CPU(X86) || CPU(X86_64) | 499 #if CPU(X86) || CPU(X86_64) |
443 // Resolve recursion by expanding constants to achieve a 4-s
tep loop unrolling. | 500 // Resolve recursion by expanding constants to achieve a 4-s
tep loop unrolling. |
444 // v1 = v0 + (t - v0) * c | 501 // v1 = v0 + (t - v0) * c |
445 // v2 = v1 + (t - v1) * c | 502 // v2 = v1 + (t - v1) * c |
446 // v2 = v0 + (t - v0) * c + (t - (v0 + (t - v0) * c)) * c | 503 // v2 = v0 + (t - v0) * c + (t - (v0 + (t - v0) * c)) * c |
447 // v2 = v0 + (t - v0) * c + (t - v0) * c - (t - v0) * c * c | 504 // v2 = v0 + (t - v0) * c + (t - v0) * c - (t - v0) * c * c |
448 // v2 = v0 + (t - v0) * c * (2 - c) | 505 // v2 = v0 + (t - v0) * c * (2 - c) |
449 // Thus c0 = c, c1 = c*(2-c). The same logic applies to c2 a
nd c3. | 506 // Thus c0 = c, c1 = c*(2-c). The same logic applies to c2 a
nd c3. |
450 const float c0 = discreteTimeConstant; | 507 const float c0 = discreteTimeConstant; |
451 const float c1 = c0 * (2 - c0); | 508 const float c1 = c0 * (2 - c0); |
(...skipping 17 matching lines...) Expand all Loading... |
469 // Update value for next iteration. | 526 // Update value for next iteration. |
470 value += delta * c3; | 527 value += delta * c3; |
471 } | 528 } |
472 #endif | 529 #endif |
473 // Serially process remaining values | 530 // Serially process remaining values |
474 for (; writeIndex < fillToFrame; ++writeIndex) { | 531 for (; writeIndex < fillToFrame; ++writeIndex) { |
475 values[writeIndex] = value; | 532 values[writeIndex] = value; |
476 value += (target - value) * discreteTimeConstant; | 533 value += (target - value) * discreteTimeConstant; |
477 } | 534 } |
478 | 535 |
| 536 currentFrame = fillToEndFrame; |
| 537 |
479 break; | 538 break; |
480 } | 539 } |
481 | 540 |
482 case ParamEvent::SetValueCurve: | 541 case ParamEvent::SetValueCurve: |
483 { | 542 { |
484 DOMFloat32Array* curve = event.curve(); | 543 DOMFloat32Array* curve = event.curve(); |
485 float* curveData = curve ? curve->data() : 0; | 544 float* curveData = curve ? curve->data() : 0; |
486 unsigned numberOfCurvePoints = curve ? curve->length() : 0; | 545 unsigned numberOfCurvePoints = curve ? curve->length() : 0; |
487 | 546 |
488 // Curve events have duration, so don't just use next event
time. | 547 // Curve events have duration, so don't just use next event
time. |
489 double duration = event.duration(); | 548 double duration = event.duration(); |
490 double durationFrames = duration * sampleRate; | 549 double durationFrames = duration * sampleRate; |
491 // How much to step the curve index for each frame. We want
the curve index to | 550 // How much to step the curve index for each frame. We want
the curve index to |
492 // be exactly equal to the last index (numberOfCurvePoints -
1) after | 551 // be exactly equal to the last index (numberOfCurvePoints -
1) after |
493 // durationFrames - 1 frames. In this way, the last output
value will equal the | 552 // durationFrames - 1 frames. In this way, the last output
value will equal the |
494 // last value in the curve array. | 553 // last value in the curve array. |
495 double curvePointsPerFrame; | 554 double curvePointsPerFrame; |
496 | 555 |
497 // If the duration is less than a frame, we want to just out
put the last curve | 556 // If the duration is less than a frame, we want to just out
put the last curve |
498 // value. Do this by setting curvePointsPerFrame to be more
than number of | 557 // value. Do this by setting curvePointsPerFrame to be more
than number of |
499 // points in the curve. Then the curveVirtualIndex will alw
ays exceed the last | 558 // points in the curve. Then the curveVirtualIndex will alw
ays exceed the last |
500 // curve index, so that the last curve value will be used. | 559 // curve index, so that the last curve value will be used. |
501 if (durationFrames > 1) | 560 if (durationFrames > 1) |
502 curvePointsPerFrame = (numberOfCurvePoints - 1) / (durat
ionFrames - 1); | 561 curvePointsPerFrame = (numberOfCurvePoints - 1) / (durat
ionFrames - 1); |
503 else | 562 else |
504 curvePointsPerFrame = numberOfCurvePoints + 1; | 563 curvePointsPerFrame = numberOfCurvePoints + 1; |
505 | 564 |
506 if (!curve || !curveData || !numberOfCurvePoints || duration
<= 0 || sampleRate <= 0) { | 565 if (!curve || !curveData || !numberOfCurvePoints || duration
<= 0 || sampleRate <= 0) { |
507 // Error condition - simply propagate previous value. | 566 // Error condition - simply propagate previous value. |
508 currentTime = fillToTime; | 567 currentFrame = fillToEndFrame; |
509 for (; writeIndex < fillToFrame; ++writeIndex) | 568 for (; writeIndex < fillToFrame; ++writeIndex) |
510 values[writeIndex] = value; | 569 values[writeIndex] = value; |
511 break; | 570 break; |
512 } | 571 } |
513 | 572 |
514 // Save old values and recalculate information based on the
curve's duration | 573 // Save old values and recalculate information based on the
curve's duration |
515 // instead of the next event time. | 574 // instead of the next event time. |
516 unsigned nextEventFillToFrame = fillToFrame; | 575 size_t nextEventFillToFrame = fillToFrame; |
517 double nextEventFillToTime = fillToTime; | 576 |
518 fillToTime = std::min(endTime, time1 + duration); | 577 // Use ceil here for the same reason as using ceil above: fi
llToEndFrame is an |
519 // |fillToTime| can be less than |startTime| when the end of
the | 578 // exclusive upper bound of the last frame to be computed. |
| 579 fillToEndFrame = std::min(endFrame, static_cast<size_t>(ceil
(sampleRate*(time1 + duration)))); |
| 580 // |fillToFrame| can be less than |startFrame| when the end
of the |
520 // setValueCurve automation has been reached, but the next a
utomation has not | 581 // setValueCurve automation has been reached, but the next a
utomation has not |
521 // yet started. In this case, |fillToTime| is clipped to |ti
me1|+|duration| | 582 // yet started. In this case, |fillToFrame| is clipped to |t
ime1|+|duration| |
522 // above, but |startTime| will keep increasing (because the
current time is | 583 // above, but |startFrame| will keep increasing (because the
current time is |
523 // increasing). | 584 // increasing). |
524 fillToFrame = AudioUtilities::timeToSampleFrame(std::max(0.0
, fillToTime - startTime), sampleRate); | 585 fillToFrame = (fillToEndFrame < startFrame) ? 0 : fillToEndF
rame - startFrame; |
525 fillToFrame = std::min(fillToFrame, numberOfValues); | 586 fillToFrame = std::min(fillToFrame, static_cast<size_t>(numb
erOfValues)); |
526 | 587 |
527 // Index into the curve data using a floating-point value. | 588 // Index into the curve data using a floating-point value. |
528 // We're scaling the number of curve points by the duration
(see curvePointsPerFrame). | 589 // We're scaling the number of curve points by the duration
(see curvePointsPerFrame). |
529 double curveVirtualIndex = 0; | 590 double curveVirtualIndex = 0; |
530 if (time1 < currentTime) { | 591 if (time1 < currentFrame / sampleRate) { |
531 // Index somewhere in the middle of the curve data. | 592 // Index somewhere in the middle of the curve data. |
532 // Don't use timeToSampleFrame() since we want the exact
floating-point frame. | 593 // Don't use timeToSampleFrame() since we want the exact
floating-point frame. |
533 double frameOffset = (currentTime - time1) * sampleRate; | 594 double frameOffset = currentFrame - time1 * sampleRate; |
534 curveVirtualIndex = curvePointsPerFrame * frameOffset; | 595 curveVirtualIndex = curvePointsPerFrame * frameOffset; |
535 } | 596 } |
536 | 597 |
537 // Set the default value in case fillToFrame is 0. | 598 // Set the default value in case fillToFrame is 0. |
538 value = curveData[numberOfCurvePoints - 1]; | 599 value = curveData[numberOfCurvePoints - 1]; |
539 | 600 |
540 // Render the stretched curve data using linear interpolatio
n. Oversampled | 601 // Render the stretched curve data using linear interpolatio
n. Oversampled |
541 // curve data can be provided if sharp discontinuities are d
esired. | 602 // curve data can be provided if sharp discontinuities are d
esired. |
542 unsigned k = 0; | 603 unsigned k = 0; |
543 #if CPU(X86) || CPU(X86_64) | 604 #if CPU(X86) || CPU(X86_64) |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 } else { | 658 } else { |
598 curveIndex0 = numberOfCurvePoints - 1; | 659 curveIndex0 = numberOfCurvePoints - 1; |
599 } | 660 } |
600 | 661 |
601 unsigned curveIndex1 = std::min(curveIndex0 + 1, numberO
fCurvePoints - 1); | 662 unsigned curveIndex1 = std::min(curveIndex0 + 1, numberO
fCurvePoints - 1); |
602 | 663 |
603 // Linearly interpolate between the two nearest curve po
ints. |delta| is | 664 // Linearly interpolate between the two nearest curve po
ints. |delta| is |
604 // clamped to 1 because currentVirtualIndex can exceed c
urveIndex0 by more | 665 // clamped to 1 because currentVirtualIndex can exceed c
urveIndex0 by more |
605 // than one. This can happen when we reached the end of
the curve but still | 666 // than one. This can happen when we reached the end of
the curve but still |
606 // need values to fill out the current rendering quantum
. | 667 // need values to fill out the current rendering quantum
. |
| 668 ASSERT(curveIndex0 < numberOfCurvePoints); |
| 669 ASSERT(curveIndex1 < numberOfCurvePoints); |
607 float c0 = curveData[curveIndex0]; | 670 float c0 = curveData[curveIndex0]; |
608 float c1 = curveData[curveIndex1]; | 671 float c1 = curveData[curveIndex1]; |
609 double delta = std::min(currentVirtualIndex - curveIndex
0, 1.0); | 672 double delta = std::min(currentVirtualIndex - curveIndex
0, 1.0); |
610 | 673 |
611 value = c0 + (c1 - c0) * delta; | 674 value = c0 + (c1 - c0) * delta; |
612 | 675 |
613 values[writeIndex] = value; | 676 values[writeIndex] = value; |
614 } | 677 } |
615 | 678 |
616 // If there's any time left after the duration of this event
and the start | 679 // If there's any time left after the duration of this event
and the start |
617 // of the next, then just propagate the last value. | 680 // of the next, then just propagate the last value of the cu
rveData. |
| 681 value = curveData[numberOfCurvePoints - 1]; |
618 for (; writeIndex < nextEventFillToFrame; ++writeIndex) | 682 for (; writeIndex < nextEventFillToFrame; ++writeIndex) |
619 values[writeIndex] = value; | 683 values[writeIndex] = value; |
620 | 684 |
621 // Re-adjust current time | 685 // Re-adjust current time |
622 currentTime = nextEventFillToTime; | 686 currentFrame = nextEventFillToFrame; |
623 | 687 |
624 break; | 688 break; |
625 } | 689 } |
626 case ParamEvent::LastType: | 690 case ParamEvent::LastType: |
627 ASSERT_NOT_REACHED(); | 691 ASSERT_NOT_REACHED(); |
628 break; | 692 break; |
629 } | 693 } |
630 } | 694 } |
631 } | 695 } |
632 | 696 |
633 // If there's any time left after processing the last event then just propag
ate the last value | 697 // If there's any time left after processing the last event then just propag
ate the last value |
634 // to the end of the values buffer. | 698 // to the end of the values buffer. |
635 for (; writeIndex < numberOfValues; ++writeIndex) | 699 for (; writeIndex < numberOfValues; ++writeIndex) |
636 values[writeIndex] = value; | 700 values[writeIndex] = value; |
637 | 701 |
638 return value; | 702 return value; |
639 } | 703 } |
640 | 704 |
641 } // namespace blink | 705 } // namespace blink |
642 | 706 |
643 #endif // ENABLE(WEB_AUDIO) | 707 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |