void AudioBufferSourceHandler::handleStoppableSourceNode() { // If the source node is not looping, and we have a buffer, we can determine when the source // would stop playing. This is intended to handle the (uncommon) scenario where start() has // been called but is never connected to the destination (directly or indirectly). By stopping // the node, the node can be collected. Otherwise, the node will never get collected, leaking // memory. // // If looping was ever done (m_didSetLooping = true), give up. We can't easily determine how // long we looped so we don't know the actual duration thus far, so don't try to do anything // fancy. if (!m_didSetLooping && buffer() && isPlayingOrScheduled() && m_minPlaybackRate > 0) { // Adjust the duration to include the playback rate. Only need to account for rate < 1 // which makes the sound last longer. For rate >= 1, the source stops sooner, but that's // ok. double actualDuration = buffer()->duration() / m_minPlaybackRate; double stopTime = m_startTime + actualDuration; // See crbug.com/478301. If a source node is started via start(), the source may not start // at that time but one quantum (128 frames) later. But we compute the stop time based on // the start time and the duration, so we end up stopping one quantum early. Thus, add a // little extra time; we just need to stop the source sometime after it should have stopped // if it hadn't already. We don't need to be super precise on when to stop. double extraStopTime = kExtraStopFrames / static_cast<double>(context()->sampleRate()); stopTime += extraStopTime; if (context()->currentTime() > stopTime) { // The context time has passed the time when the source nodes should have stopped // playing. Stop the node now and deref it. (But don't run the onEnded event because the // source never actually played.) finishWithoutOnEnded(); } } }
void AudioScheduledSourceHandler::finish() { finishWithoutOnEnded(); if (m_hasEndedListener && context()->executionContext()) { context()->executionContext()->postTask(FROM_HERE, createCrossThreadTask(&AudioScheduledSourceHandler::notifyEnded, PassRefPtr<AudioScheduledSourceHandler>(this))); } }
void AudioScheduledSourceHandler::finish() { finishWithoutOnEnded(); if (context()->getExecutionContext()) { context()->getExecutionContext()->postTask( BLINK_FROM_HERE, createCrossThreadTask(&AudioScheduledSourceHandler::notifyEnded, PassRefPtr<AudioScheduledSourceHandler>(this))); } }