Repository navigation
fix: resume a paused AudioBufferQueueSourceNode - #1434
Closed
HilloriDesai wants to merge 2 commits into
Closed
HilloriDesai wants to merge 2 commits into
HilloriDesai wants to merge 2 commits into
Conversation
pause() stopped the node through AudioScheduledSourceNode::stop(0). For a started node, stop(0) takes the stop-before-start branch, which marks the node finished and disables it for good (excludeFromProcessablePull_), so resume() played silence and the queue never ended. pause() now unschedules a node that has not rendered yet, and otherwise lets the render path stop it, where disable() keeps the buffers while paused. stop() on a paused node finishes it right away (a paused node is already silent, and an empty queue never reaches the render path), and a second stop() is a no-op. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WPT non-regression comparisonPASS — no regressions · 0 improved section(s) · overall 3430 → 3430 (0) Unchanged sections (28)
Baseline: Workflow run · this comment is updated on every push. |
Member
|
on it |
4 of 7 tasks
Member
|
issue fixed in #1436, it has a little different approach, but the issue is fixed |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No existing issue. The bug is described below and covered by new tests.
Introduced changes
Bug: on 1.0.0, calling
AudioBufferQueueSourceNode.pause()and thenresume()plays silence. The node never reaches the end of its queue, soonPositionChangedandonBufferEndedstop firing. We hit this in a streaming TTS player on a Pixel 4a (Android 13).Cause:
pause()calledAudioScheduledSourceNode::stop(0.0).stop(0)satisfiesstopFrame <= startFrame, so the node is markedFINISHEDandAudioNode::disable()runs.disable()is sticky. On the next quantum it setsexcludeFromProcessablePull_, and nothing ever clears it.resume()then callsstart(), which resets the playback state, but the graph never pulls the node again.endedonpause().Fix (all in
AudioBufferQueueSourceNode;AudioScheduledSourceNodeis unchanged):pause():stopTime_ = 0, so the render path stops the node on its next quantum. The node's owndisable()keeps the buffers whileisPaused_is set.isPaused_is set in both cases.disable(): no longer clearsisPaused_.start()(that is,resume()) orstop()clears it.stop()on a paused node:whenis: oneended, then the buffers are cleared.processNodereturns beforeupdatePlaybackInfo.stop()would also undo a pending pause, or compare againststartTime_ == -1, which UBSan flags as an out-of-range cast tosize_t.stop()on a finished node: a no-op. JS doesn't guard a secondstop().Tests (
AudioBufferQueueSourceTest, rendered throughprocessGraph):PauseThenResumeContinuesFromPausedFrame: the paused node is silent and fires noended, andresume()continues from the exact frame where it paused.PauseBeforeFirstQuantumThenResumePlaysFromStart:pause()right afterstart(), thenresume().StopWhilePausedStaysSilentAndEndsOnce: each case must stay silent, fireendedexactly once, and treat a secondstop()as a no-op. The cases are:stop(0)after the pause has rendered;pause()andstop(later)in the same batch;stop()inside the next quantum;stop()after a pause before the first quantum;The first two tests fail on
main; the third fails on each intermediate version of the fix.Checklist
Validation
yarn test:cpp(smoke)--ubasanAudioBufferQueueSourceTestandAudioScheduledSourceTestwith--tsan🤖 Generated with Claude Code