Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: Source/modules/webaudio/AudioParamTimeline.cpp

Issue 1277443005: Use interpolation for setValueCurveAtTime (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Corrected test thresholds and results Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « LayoutTests/webaudio/resources/audio-testing.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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)
OLDNEW
« no previous file with comments | « LayoutTests/webaudio/resources/audio-testing.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698