Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: c2c8b0cb3b0def5b71c991462d7b3714c46a8d62
https://github.com/WebKit/WebKit/commit/c2c8b0cb3b0def5b71c991462d7b3714c46a8d62
Author: Chris Dumez <[email protected]>
Date: 2026-08-24 (Mon, 24 Aug 2026)
Changed paths:
M
LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-playbackrate-negative-expected.txt
M
LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive-expected.txt
M
LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive.html
M Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp
Log Message:
-----------
AudioBufferSourceNode does not clamp out-of-range loopStart/loopEnd
https://bugs.webkit.org/show_bug.cgi?id=322372
Reviewed by Jean-Yves Avenard and Darin Adler.
renderFromBuffer() rejected out-of-range loop points and fell back to looping
the
entire buffer, which is what the spec's playback algorithm says. But the
loopStart/loopEnd attribute definitions say those values are clamped into the
buffer instead, and the two readings give different output. The Audio WG
resolved
the contradiction in favour of clamping in
https://github.com/WebAudio/web-audio-api/issues/2689: clamp both endpoints
first, then fall back to the entire buffer only if what is left is not a range
of
positive length. The spec PR has not landed yet, so index.bs still shows the old
guard. Blink already does this in
AudioBufferSourceHandler::UpdateEffectiveLoopPoints(), and we now match it for a
negative loopStart, a loopStart past the buffer duration, loopStart >= loopEnd,
a
negative loopEnd, a loopEnd past the duration, and the loopStart == loopEnd == 0
default.
Two configurations change. A negative loopStart looped the whole buffer and now
loops [0, loopEnd), the case the WPT test already asserted. A loopStart past the
buffer duration used to *pass* the old guard, since 0 <= loopStart < loopEnd
holds, leaving virtualMinFrame above virtualMaxFrame and a negative
virtualDeltaFrames; the playback-rate check then bailed out and rendered
silence.
Clamping makes that range empty rather than inverted, so it falls back to the
whole buffer.
The forward wrap recomputed its target from the raw m_loopStart rather than the
effective loop points, so it wrapped to loopStart even when playback had fallen
back to the whole buffer. It now uses virtualMinFrame.
One difference from Blink remains, unchanged by this patch: Blink resolves a
loopEnd of exactly 0 to the buffer duration and loops [loopStart, duration),
while the resolution maps any loopEnd <= 0 to 0 and falls back to the entire
buffer.
*
LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-playbackrate-negative-expected.txt:
Rebaselined: "loops backwards using clamped loopStart when loopStart < 0"
passes.
The two remaining failures are out-of-bounds start offsets, unrelated.
*
LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive.html:
*
LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive-expected.txt:
Case 14 expected loopStart = -8 with loopEnd = 3 to loop the whole buffer,
contradicting the WPT test. Updated to the clamped loop [0, 3), matching
Chromium's updated copy of this test.
* Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp:
(WebCore::AudioBufferSourceNode::renderFromBuffer):
Canonical link: https://commits.webkit.org/319755@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications