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, AudioParamHandler& detune) | 56 AudioBufferSourceHandler::AudioBufferSourceHandler(AudioNode& node, float sample
Rate, AudioParamHandler& playbackRate, AudioParamHandler& detune) |
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_detune(detune) | 60 , m_detune(detune) |
55 , m_isLooping(false) | 61 , m_isLooping(false) |
56 , m_loopStart(0) | 62 , m_loopStart(0) |
57 , m_loopEnd(0) | 63 , m_loopEnd(0) |
58 , m_virtualReadIndex(0) | 64 , m_virtualReadIndex(0) |
59 , m_isGrain(false) | 65 , m_isGrain(false) |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 double AudioBufferSourceHandler::computePlaybackRate() | 489 double AudioBufferSourceHandler::computePlaybackRate() |
484 { | 490 { |
485 double dopplerRate = 1; | 491 double dopplerRate = 1; |
486 if (m_pannerNode) | 492 if (m_pannerNode) |
487 dopplerRate = m_pannerNode->dopplerRate(); | 493 dopplerRate = m_pannerNode->dopplerRate(); |
488 | 494 |
489 // Incorporate buffer's sample-rate versus AudioContext's sample-rate. | 495 // Incorporate buffer's sample-rate versus AudioContext's sample-rate. |
490 // Normally it's not an issue because buffers are loaded at the | 496 // Normally it's not an issue because buffers are loaded at the |
491 // AudioContext's sample-rate, but we can handle it in any case. | 497 // AudioContext's sample-rate, but we can handle it in any case. |
492 double sampleRateFactor = 1.0; | 498 double sampleRateFactor = 1.0; |
493 if (buffer()) | 499 if (buffer()) { |
494 sampleRateFactor = buffer()->sampleRate() / sampleRate(); | 500 // Use doubles to compute this to full accuracy. |
| 501 sampleRateFactor = buffer()->sampleRate() / static_cast<double>(sampleRa
te()); |
| 502 } |
495 | 503 |
496 // Use finalValue() to incorporate changes of AudioParamTimeline and | 504 // Use finalValue() to incorporate changes of AudioParamTimeline and |
497 // AudioSummingJunction from m_playbackRate AudioParam. | 505 // AudioSummingJunction from m_playbackRate AudioParam. |
498 double basePlaybackRate = m_playbackRate->finalValue(); | 506 double basePlaybackRate = m_playbackRate->finalValue(); |
499 | 507 |
500 double finalPlaybackRate = dopplerRate * sampleRateFactor * basePlaybackRate
; | 508 double finalPlaybackRate = dopplerRate * sampleRateFactor * basePlaybackRate
; |
501 | 509 |
502 // Take the detune value into account for the final playback rate. | 510 // Take the detune value into account for the final playback rate. |
503 finalPlaybackRate *= pow(2, m_detune->finalValue() / 1200); | 511 finalPlaybackRate *= pow(2, m_detune->finalValue() / 1200); |
504 | 512 |
(...skipping 30 matching lines...) Expand all Loading... |
535 void AudioBufferSourceHandler::clearPannerNode() | 543 void AudioBufferSourceHandler::clearPannerNode() |
536 { | 544 { |
537 if (m_pannerNode) { | 545 if (m_pannerNode) { |
538 m_pannerNode->breakConnection(); | 546 m_pannerNode->breakConnection(); |
539 m_pannerNode.clear(); | 547 m_pannerNode.clear(); |
540 } | 548 } |
541 } | 549 } |
542 | 550 |
543 void AudioBufferSourceHandler::handleStoppableSourceNode() | 551 void AudioBufferSourceHandler::handleStoppableSourceNode() |
544 { | 552 { |
545 // If the source node is not looping, and we have a buffer, we can determine
when the | 553 // If the source node is not looping, and we have a buffer, we can determine
when the source |
546 // source would stop playing. | 554 // would stop playing. This is intended to handle the (uncommon) scenario w
here start() has |
| 555 // been called but is never connected to the destination (directly or indire
ctly). By stopping |
| 556 // the node, the node can be collected. Otherwise, the node will never get
collected, leaking |
| 557 // memory. |
547 if (!loop() && buffer() && isPlayingOrScheduled()) { | 558 if (!loop() && buffer() && isPlayingOrScheduled()) { |
548 double stopTime = m_startTime + buffer()->duration(); | 559 // See crbug.com/478301. If a source node is started via start(), the so
urce may not start |
| 560 // at that time but one quantum (128 frames) later. But we compute the
stop time based on |
| 561 // the start time and the duration, so we end up stopping one quantum ea
rly. Thus, add a |
| 562 // little extra time; we just need to stop the source sometime after it
should have stopped |
| 563 // if it hadn't already. We don't need to be super precise on when to s
top. |
| 564 double extraStopTime = kExtraStopFrames / static_cast<double>(context()-
>sampleRate()); |
| 565 double stopTime = m_startTime + buffer()->duration() + extraStopTime; |
| 566 |
549 if (context()->currentTime() > stopTime) { | 567 if (context()->currentTime() > stopTime) { |
550 // The context time has passed the time when the source nodes should
have stopped | 568 // The context time has passed the time when the source nodes should
have stopped |
551 // playing. Stop the node now and deref it. (But don't run the onEnd
ed event because the | 569 // playing. Stop the node now and deref it. (But don't run the onEnd
ed event because the |
552 // source never actually played.) | 570 // source never actually played.) |
553 finishWithoutOnEnded(); | 571 finishWithoutOnEnded(); |
554 } | 572 } |
555 } | 573 } |
556 } | 574 } |
557 | 575 |
558 void AudioBufferSourceHandler::finish() | 576 void AudioBufferSourceHandler::finish() |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 } | 672 } |
655 | 673 |
656 void AudioBufferSourceNode::start(double when, double grainOffset, double grainD
uration, ExceptionState& exceptionState) | 674 void AudioBufferSourceNode::start(double when, double grainOffset, double grainD
uration, ExceptionState& exceptionState) |
657 { | 675 { |
658 audioBufferSourceHandler().start(when, grainOffset, grainDuration, exception
State); | 676 audioBufferSourceHandler().start(when, grainOffset, grainDuration, exception
State); |
659 } | 677 } |
660 | 678 |
661 } // namespace blink | 679 } // namespace blink |
662 | 680 |
663 #endif // ENABLE(WEB_AUDIO) | 681 #endif // ENABLE(WEB_AUDIO) |
OLD | NEW |