OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2010, Google Inc. All rights reserved. | 2 * Copyright (C) 2010, 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 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 29 matching lines...) Expand all Loading... | |
40 | 40 |
41 namespace blink { | 41 namespace blink { |
42 | 42 |
43 const double DefaultGrainDuration = 0.020; // 20ms | 43 const double DefaultGrainDuration = 0.020; // 20ms |
44 | 44 |
45 // Arbitrary upper limit on playback rate. | 45 // Arbitrary upper limit on playback rate. |
46 // Higher than expected rates can be useful when playing back oversampled buffer s | 46 // Higher than expected rates can be useful when playing back oversampled buffer s |
47 // to minimize linear interpolation aliasing. | 47 // to minimize linear interpolation aliasing. |
48 const double MaxRate = 1024; | 48 const double MaxRate = 1024; |
49 | 49 |
50 // Number of extra frames to use when determining if a source node can be stoppe d. This should be | |
51 // at least one rendering quantum, but we add one more quantum for good measure. This doesn't need | |
52 // to be extra precise, just more than one rendering quantum. See |handleStoppa bleSourceNode()|. | |
53 // FIXME: Expose the rendering quantum somehow instead of hardwiring a value her e. | |
54 const int kExtraStopFrames = 256; | |
55 | |
50 AudioBufferSourceHandler::AudioBufferSourceHandler(AudioNode& node, float sample Rate, AudioParamHandler& playbackRate) | 56 AudioBufferSourceHandler::AudioBufferSourceHandler(AudioNode& node, float sample Rate, AudioParamHandler& playbackRate) |
51 : AudioScheduledSourceHandler(NodeTypeAudioBufferSource, node, sampleRate) | 57 : AudioScheduledSourceHandler(NodeTypeAudioBufferSource, node, sampleRate) |
52 , m_buffer(nullptr) | 58 , m_buffer(nullptr) |
53 , m_playbackRate(playbackRate) | 59 , m_playbackRate(playbackRate) |
54 , m_isLooping(false) | 60 , m_isLooping(false) |
55 , m_loopStart(0) | 61 , m_loopStart(0) |
56 , m_loopEnd(0) | 62 , m_loopEnd(0) |
57 , m_virtualReadIndex(0) | 63 , m_virtualReadIndex(0) |
58 , m_isGrain(false) | 64 , m_isGrain(false) |
59 , m_grainOffset(0.0) | 65 , m_grainOffset(0.0) |
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
482 double AudioBufferSourceHandler::computePlaybackRate() | 488 double AudioBufferSourceHandler::computePlaybackRate() |
483 { | 489 { |
484 double dopplerRate = 1.0; | 490 double dopplerRate = 1.0; |
485 if (m_pannerNode) | 491 if (m_pannerNode) |
486 dopplerRate = m_pannerNode->dopplerRate(); | 492 dopplerRate = m_pannerNode->dopplerRate(); |
487 | 493 |
488 // Incorporate buffer's sample-rate versus AudioContext's sample-rate. | 494 // Incorporate buffer's sample-rate versus AudioContext's sample-rate. |
489 // Normally it's not an issue because buffers are loaded at the | 495 // Normally it's not an issue because buffers are loaded at the |
490 // AudioContext's sample-rate, but we can handle it in any case. | 496 // AudioContext's sample-rate, but we can handle it in any case. |
491 double sampleRateFactor = 1.0; | 497 double sampleRateFactor = 1.0; |
492 if (buffer()) | 498 if (buffer()) { |
493 sampleRateFactor = buffer()->sampleRate() / sampleRate(); | 499 // Use doubles to compute this to full accuracy. |
500 sampleRateFactor = buffer()->sampleRate() / static_cast<double>(sampleRa te()); | |
501 } | |
494 | 502 |
495 // Use finalValue() to incorporate changes of AudioParamTimeline and | 503 // Use finalValue() to incorporate changes of AudioParamTimeline and |
496 // AudioSummingJunction from m_playbackRate AudioParam. | 504 // AudioSummingJunction from m_playbackRate AudioParam. |
497 double basePlaybackRate = m_playbackRate->finalValue(); | 505 double basePlaybackRate = m_playbackRate->finalValue(); |
498 | 506 |
499 double finalPlaybackRate = dopplerRate * sampleRateFactor * basePlaybackRate ; | 507 double finalPlaybackRate = dopplerRate * sampleRateFactor * basePlaybackRate ; |
500 | 508 |
501 // Sanity check the total rate. It's very important that the resampler not | 509 // Sanity check the total rate. It's very important that the resampler not |
502 // get any bad rate values. | 510 // get any bad rate values. |
503 finalPlaybackRate = clampTo(finalPlaybackRate, 0.0, MaxRate); | 511 finalPlaybackRate = clampTo(finalPlaybackRate, 0.0, MaxRate); |
(...skipping 30 matching lines...) Expand all Loading... | |
534 m_pannerNode->breakConnection(); | 542 m_pannerNode->breakConnection(); |
535 m_pannerNode.clear(); | 543 m_pannerNode.clear(); |
536 } | 544 } |
537 } | 545 } |
538 | 546 |
539 void AudioBufferSourceHandler::handleStoppableSourceNode() | 547 void AudioBufferSourceHandler::handleStoppableSourceNode() |
540 { | 548 { |
541 // If the source node is not looping, and we have a buffer, we can determine when the | 549 // If the source node is not looping, and we have a buffer, we can determine when the |
542 // source would stop playing. | 550 // source would stop playing. |
543 if (!loop() && buffer() && isPlayingOrScheduled()) { | 551 if (!loop() && buffer() && isPlayingOrScheduled()) { |
544 double stopTime = m_startTime + buffer()->duration(); | 552 // See crbug.com/478301. If a source node is started via start(), the so urce won't start at |
553 // that time but one quantum (128 frames) later. But we compute the sto p time based on the | |
554 // start time and the duration, so we end up stopping one quantum early. Thus, add a little | |
555 // extra time; we just need to stop the source sometime after it should have stopped if it | |
556 // hadn't already. | |
557 double extraStopTime = kExtraStopFrames / static_cast<double>(context()- >sampleRate()); | |
558 double stopTime = m_startTime + buffer()->duration() + extraStopTime; | |
Ken Russell (switch to Gerrit)
2015/04/22 19:01:50
This seems like a classic rounding error. Does the
Raymond Toy
2015/04/22 20:19:45
Without this fix, it's the last few frames for the
| |
559 | |
545 if (context()->currentTime() > stopTime) { | 560 if (context()->currentTime() > stopTime) { |
546 // The context time has passed the time when the source nodes should have stopped | 561 // The context time has passed the time when the source nodes should have stopped |
547 // playing. Stop the node now and deref it. (But don't run the onEnd ed event because the | 562 // playing. Stop the node now and deref it. (But don't run the onEnd ed event because the |
548 // source never actually played.) | 563 // source never actually played.) |
549 finishWithoutOnEnded(); | 564 finishWithoutOnEnded(); |
550 } | 565 } |
551 } | 566 } |
552 } | 567 } |
553 | 568 |
554 void AudioBufferSourceHandler::finish() | 569 void AudioBufferSourceHandler::finish() |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
643 } | 658 } |
644 | 659 |
645 void AudioBufferSourceNode::start(double when, double grainOffset, double grainD uration, ExceptionState& exceptionState) | 660 void AudioBufferSourceNode::start(double when, double grainOffset, double grainD uration, ExceptionState& exceptionState) |
646 { | 661 { |
647 audioBufferSourceHandler().start(when, grainOffset, grainDuration, exception State); | 662 audioBufferSourceHandler().start(when, grainOffset, grainDuration, exception State); |
648 } | 663 } |
649 | 664 |
650 } // namespace blink | 665 } // namespace blink |
651 | 666 |
652 #endif // ENABLE(WEB_AUDIO) | 667 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |