Skip to content

Commit 19e8af2

Browse files
Mahesh Bharadwaj Kannanchromium-wpt-export-bot
authored andcommitted
[WebAudio] Fix AudioBufferSourceNode start duration loop underflow
The end_frame calculation in AudioBufferSourceHandler::RenderFromBuffer was incorrectly using the duration argument from start() to constrain the physical read boundary of the audio buffer even when looping was enabled. This caused the loop calculation (virtual_delta_frames) to underflow and evaluate to a negative number, failing internal sanity checks and causing the audio node to immediately output silence. This CL fixes the issue by allowing the read boundary (end_frame) to extend to the full buffer length when looping, and relying on buffer_played_frames_ to act as the duration stopwatch instead. Bug: 40910590 Change-Id: I8ac1efd0e5ca97c9287a3bc876e5827e0ac6b698 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7850471 Reviewed-by: Michael Wilson <mjwilson@chromium.org> Commit-Queue: Mahesh Kannan <kmaheshb@google.com> Cr-Commit-Position: refs/heads/main@{#1632602}
1 parent 4c52381 commit 19e8af2

1 file changed

Lines changed: 46 additions & 0 deletions

File tree

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>
5+
audiobuffersource-loop-short-duration.html
6+
</title>
7+
<script src="/resources/testharness.js"></script>
8+
<script src="/resources/testharnessreport.js"></script>
9+
</head>
10+
<body>
11+
<script id="layout-test-code">
12+
promise_test(async () => {
13+
let sampleRate = 48000;
14+
let context = new OfflineAudioContext(1, 128, sampleRate);
15+
16+
let buffer = context.createBuffer(1, 10, sampleRate);
17+
let data = buffer.getChannelData(0);
18+
for (let i = 0; i < 10; ++i) {
19+
data[i] = 1.0;
20+
}
21+
22+
let source = context.createBufferSource();
23+
source.buffer = buffer;
24+
source.loop = true;
25+
// loopStart > duration
26+
source.loopStart = 5 / sampleRate;
27+
source.loopEnd = 8 / sampleRate;
28+
29+
source.connect(context.destination);
30+
// Play only 2 frames (duration = 2/sampleRate)
31+
source.start(0, 0, 2 / sampleRate);
32+
33+
let renderedBuffer = await context.startRendering();
34+
let renderedData = renderedBuffer.getChannelData(0);
35+
let expected = new Float32Array(128);
36+
expected[0] = 1.0;
37+
expected[1] = 1.0;
38+
assert_array_equals(
39+
renderedData,
40+
expected,
41+
'Rendered data should be exactly 2 frames of 1.0 followed by silence'
42+
);
43+
}, 'audiobuffersource-loop-short-duration');
44+
</script>
45+
</body>
46+
</html>

0 commit comments

Comments
 (0)