Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: f075fe96bb0ef74cc09c4dfb1903c9fa03c252f2
https://github.com/WebKit/WebKit/commit/f075fe96bb0ef74cc09c4dfb1903c9fa03c252f2
Author: Ahmad Saleem <[email protected]>
Date: 2026-08-09 (Sun, 09 Aug 2026)
Changed paths:
A
LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-reverse-long-buffer-expected.txt
A
LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-reverse-long-buffer.html
M Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp
Log Message:
-----------
Reverse playback of buffers longer than 2^23 frames extrapolates outside the
source samples
https://bugs.webkit.org/show_bug.cgi?id=321386
rdar://184439324
Reviewed by Chris Dumez.
This patch aligns WebKit with Gecko / Firefox and Blink / Chromium.
renderFromBuffer() keeps its playback position in double precision, but the
reverse branch rounded that position down through floorf(), narrowing the
double to float. Above 2^23 the spacing of float is 1.0, so floorf() rounds to
nearest rather than down and can return a value greater than its argument:
floorf(8388609.5) is 8388610. The interpolation factor derived from it on the
next line is then negative, and computeSampleUsingLinearInterpolation()
extrapolates past the pair of frames it is meant to be mixing between rather
than interpolating between them. A read index rounded up to bufferLength also
trips the bounds check at the top of the loop, breaking out and leaving the
rest of the render quantum unwritten.
The threshold is 2^23 frames, roughly 190 seconds at 44.1kHz. Only the reverse
branch is affected; the forward branch truncates the double directly. The
surrounding code already uses the double overload of floor() when computing
needsInterpolation, so use std::floor() at both sites.
The test renders the same content from a short buffer and from a buffer longer
than 2^23 frames and requires the two to match, since playback depends only on
position relative to the grain. Comparing the two rather than checking absolute
sample values keeps the test independent of the interpolation or resampling
filter an implementation chooses. The pattern deliberately is not a linear
ramp: linearly extrapolating a linear signal happens to land on the correct
value, which is why the existing negative-playbackRate tests do not catch this.
Test:
imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-reverse-long-buffer.html
*
LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-reverse-long-buffer-expected.txt:
Added.
*
LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-reverse-long-buffer.html:
Added.
* Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp:
(WebCore::AudioBufferSourceNode::renderFromBuffer):
Canonical link: https://commits.webkit.org/318869@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications