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 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 break; | 357 break; |
358 } | 358 } |
359 | 359 |
360 case ParamEvent::SetValueCurve: | 360 case ParamEvent::SetValueCurve: |
361 { | 361 { |
362 DOMFloat32Array* curve = event.curve(); | 362 DOMFloat32Array* curve = event.curve(); |
363 float* curveData = curve ? curve->data() : 0; | 363 float* curveData = curve ? curve->data() : 0; |
364 unsigned numberOfCurvePoints = curve ? curve->length() : 0; | 364 unsigned numberOfCurvePoints = curve ? curve->length() : 0; |
365 | 365 |
366 // Curve events have duration, so don't just use next event
time. | 366 // Curve events have duration, so don't just use next event
time. |
367 float duration = event.duration(); | 367 double duration = event.duration(); |
368 float durationFrames = duration * sampleRate; | 368 double durationFrames = duration * sampleRate; |
369 float curvePointsPerFrame = static_cast<float>(numberOfCurve
Points) / durationFrames; | 369 // How much to step the curve index for each frame. We want
the curve index to |
| 370 // be exactly equal to the last index (numberOfCurvePoints -
1) after |
| 371 // durationFrames - 1 frames. In this way, the last output
value will equal the |
| 372 // last value in the curve array. |
| 373 double curvePointsPerFrame; |
| 374 |
| 375 // If the duration is less than a frame, we want to just out
put the last curve |
| 376 // value. Do this by setting curvePointsPerFrame to be more
than number of |
| 377 // points in the curve. Then the curveVirtualIndex will alw
ays exceed the last |
| 378 // curve index, so that the last curve value will be used. |
| 379 if (durationFrames > 1) |
| 380 curvePointsPerFrame = (numberOfCurvePoints - 1) / (durat
ionFrames - 1); |
| 381 else |
| 382 curvePointsPerFrame = numberOfCurvePoints + 1; |
370 | 383 |
371 if (!curve || !curveData || !numberOfCurvePoints || duration
<= 0 || sampleRate <= 0) { | 384 if (!curve || !curveData || !numberOfCurvePoints || duration
<= 0 || sampleRate <= 0) { |
372 // Error condition - simply propagate previous value. | 385 // Error condition - simply propagate previous value. |
373 currentTime = fillToTime; | 386 currentTime = fillToTime; |
374 for (; writeIndex < fillToFrame; ++writeIndex) | 387 for (; writeIndex < fillToFrame; ++writeIndex) |
375 values[writeIndex] = value; | 388 values[writeIndex] = value; |
376 break; | 389 break; |
377 } | 390 } |
378 | 391 |
379 // Save old values and recalculate information based on the
curve's duration | 392 // Save old values and recalculate information based on the
curve's duration |
380 // instead of the next event time. | 393 // instead of the next event time. |
381 unsigned nextEventFillToFrame = fillToFrame; | 394 unsigned nextEventFillToFrame = fillToFrame; |
382 float nextEventFillToTime = fillToTime; | 395 double nextEventFillToTime = fillToTime; |
383 fillToTime = std::min(endTime, time1 + duration); | 396 fillToTime = std::min(endTime, time1 + duration); |
384 fillToFrame = AudioUtilities::timeToSampleFrame(fillToTime -
startTime, sampleRate); | 397 fillToFrame = AudioUtilities::timeToSampleFrame(fillToTime -
startTime, sampleRate); |
385 fillToFrame = std::min(fillToFrame, numberOfValues); | 398 fillToFrame = std::min(fillToFrame, numberOfValues); |
386 | 399 |
387 // Index into the curve data using a floating-point value. | 400 // Index into the curve data using a floating-point value. |
388 // We're scaling the number of curve points by the duration
(see curvePointsPerFrame). | 401 // We're scaling the number of curve points by the duration
(see curvePointsPerFrame). |
389 float curveVirtualIndex = 0; | 402 double curveVirtualIndex = 0; |
390 if (time1 < currentTime) { | 403 if (time1 < currentTime) { |
391 // Index somewhere in the middle of the curve data. | 404 // Index somewhere in the middle of the curve data. |
392 // Don't use timeToSampleFrame() since we want the exact
floating-point frame. | 405 // Don't use timeToSampleFrame() since we want the exact
floating-point frame. |
393 float frameOffset = (currentTime - time1) * sampleRate; | 406 double frameOffset = (currentTime - time1) * sampleRate; |
394 curveVirtualIndex = curvePointsPerFrame * frameOffset; | 407 curveVirtualIndex = curvePointsPerFrame * frameOffset; |
395 } | 408 } |
396 | 409 |
397 // Render the stretched curve data using nearest neighbor sa
mpling. | 410 // Set the default value in case fillToFrame is 0. |
398 // Oversampled curve data can be provided if smoothness is d
esired. | 411 value = curveData[numberOfCurvePoints - 1]; |
399 for (; writeIndex < fillToFrame; ++writeIndex) { | |
400 // Ideally we'd use round() from MathExtras, but we're i
n a tight loop here | |
401 // and we're trading off precision for extra speed. | |
402 unsigned curveIndex = static_cast<unsigned>(0.5 + curveV
irtualIndex); | |
403 | 412 |
404 curveVirtualIndex += curvePointsPerFrame; | 413 // Render the stretched curve data using linear interpolatio
n. Oversampled |
| 414 // curve data can be provided if sharp discontinuities are d
esired. |
| 415 for (unsigned k = 0; writeIndex < fillToFrame; ++writeIndex,
++k) { |
| 416 // Compute current index this way to minimize round-off
that would have |
| 417 // occurred by incrementing the index by curvePointsPerF
rame. |
| 418 double currentVirtualIndex = curveVirtualIndex + k * cur
vePointsPerFrame; |
| 419 unsigned curveIndex0; |
405 | 420 |
406 // Bounds check. | 421 // Clamp index to the last element of the array. |
407 if (curveIndex < numberOfCurvePoints) | 422 if (currentVirtualIndex < numberOfCurvePoints) { |
408 value = curveData[curveIndex]; | 423 curveIndex0 = static_cast<unsigned>(currentVirtualIn
dex); |
| 424 } else { |
| 425 curveIndex0 = numberOfCurvePoints - 1; |
| 426 } |
| 427 |
| 428 unsigned curveIndex1 = std::min(curveIndex0 + 1, numberO
fCurvePoints - 1); |
| 429 |
| 430 // Linearly interpolate between the two nearest curve po
ints. |delta| is |
| 431 // clamped to 1 because currentVirtualIndex can exceed c
urveIndex0 by more |
| 432 // than one. This can happen when we reached the end of
the curve but still |
| 433 // need values to fill out the current rendering quantum
. |
| 434 float c0 = curveData[curveIndex0]; |
| 435 float c1 = curveData[curveIndex1]; |
| 436 double delta = std::min(currentVirtualIndex - curveIndex
0, 1.0); |
| 437 |
| 438 value = c0 + (c1 - c0) * delta; |
409 | 439 |
410 values[writeIndex] = value; | 440 values[writeIndex] = value; |
411 } | 441 } |
412 | 442 |
413 // If there's any time left after the duration of this event
and the start | 443 // If there's any time left after the duration of this event
and the start |
414 // of the next, then just propagate the last value. | 444 // of the next, then just propagate the last value. |
415 for (; writeIndex < nextEventFillToFrame; ++writeIndex) | 445 for (; writeIndex < nextEventFillToFrame; ++writeIndex) |
416 values[writeIndex] = value; | 446 values[writeIndex] = value; |
417 | 447 |
418 // Re-adjust current time | 448 // Re-adjust current time |
419 currentTime = nextEventFillToTime; | 449 currentTime = nextEventFillToTime; |
420 | 450 |
421 break; | 451 break; |
422 } | 452 } |
423 } | 453 } |
424 } | 454 } |
425 } | 455 } |
426 | 456 |
427 // If there's any time left after processing the last event then just propag
ate the last value | 457 // If there's any time left after processing the last event then just propag
ate the last value |
428 // to the end of the values buffer. | 458 // to the end of the values buffer. |
429 for (; writeIndex < numberOfValues; ++writeIndex) | 459 for (; writeIndex < numberOfValues; ++writeIndex) |
430 values[writeIndex] = value; | 460 values[writeIndex] = value; |
431 | 461 |
432 return value; | 462 return value; |
433 } | 463 } |
434 | 464 |
435 } // namespace blink | 465 } // namespace blink |
436 | 466 |
437 #endif // ENABLE(WEB_AUDIO) | 467 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |