Skip to content

AudioBufferSourceNode: start() offset prose inverts the negative-playbackRate loopStart comparison #2690

Description

@cdumez

The prose describing the offset argument of start() states the negative-playbackRate clamp with the comparison inverted relative to the normative playback algorithm. Read literally it makes the offset argument almost useless whenever loop is true and the rate is negative. It appears to be a transcription error from #2031.

Current text

From the offset argument of start():

If offset is greater than loopEnd, playbackRate is positive or zero, and loop is true, playback will begin at loopEnd. If offset is greater than loopStart, playbackRate is negative, and loop is true, playback will begin at loopStart.

What the normative algorithm says

From the playback algorithm:

if (!started) {
    if (loop && computedPlaybackRate >= 0 && offset >= actualLoopEnd) {
        offset = actualLoopEnd;
    }
    if (computedPlaybackRate < 0 && loop && offset < actualLoopStart) {
        offset = actualLoopStart;
    }
    bufferTime = offset;
    started = true;
}
| Rate | Algorithm clamps when | Prose says clamp when |
|---|---|---|
| positive or zero | `offset >= actualLoopEnd` | `offset` greater than `loopEnd` ✓ |
| negative | `offset < actualLoopStart` | `offset` greater than `loopStart` ✗ |

The positive-rate sentence agrees with the algorithm. The negative-rate sentence inverts it.

Why this looks like a typo rather than an intentional rule

Issue #2031, which requested this sentence, asked for the opposite comparison:

The similar instruction "For negative playbackRate, if offset is less than loopStart, playback will begin at loopStart (and immediately loop to loopEnd)" applies in the other case.

Implementations and tests

webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-playbackrate-negative.html in WPT covers both directions, and encodes the algorithm's reading:

  • "AudioBufferSourceNode clamps offset to loopStart for playbackRate < 0" — 8-frame buffer, loopStart frame 4, loopEnd frame 6, offset frame 2. Since the offset is below loopStart, it is clamped, expecting [5, 6, 5, 6].
  • "AudioBufferSourceNode loops backwards with negative rate (offset in loop)" — the configuration in the table above, where the offset is above loopStart. It is not clamped, expecting [3, 2, 3, 2, …].

Under the prose reading the second test would expect [2, 3, 2, 3, …].

Implementation status:

  • Chrome — clamps only when the playhead is below the loop start (if (is_looping_ && virtual_read_index < virtual_start_frame) in AudioBufferSourceHandler), matching the algorithm.
  • WebKit — currently begins playback at loopStart in this configuration, matching the prose reading, and fails the second subtest above.
  • Firefox — It seems it does not implement negative playbackRate at all?; ComputeFinalOutSampleRate returns the buffer sample rate when the computed rate is not positive, so a negative rate plays forward at 1×. Not informative for this question.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs DiscussionThe issue needs more discussion before it can be fixed.category: enhancementSubstantive changes that do not add new features. https://www.w3.org/policies/process/#class-3

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions