| 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 |