In Web Audio, why does contextTime lag currentTime by more than baseLatency?

Viewed 726

As I understand it, the audio context has:

  • .currentTime, the time at the beginning of the next schedule-able 128-sample frame buffer (previous buffers having already been sent)

  • .baseLatency, the time it takes to transfer scheduled audio from WebAudio land to the OS

  • .getOutputTimestamp().contextTime, a timestamp for the sample frame currently being handed to the OS

By this understanding, context.getOutputTimestamp().contextTime should never be less than context.currentTime - context.baseLatency.

But it is! In my tests in Chrome on a fast MacBook it is less than that by as much as -0.025s. That's > 1000 sample frames behind.

const context = new AudioContext();

// Let the audio clock settle
setTimeout(function() {
    const currentTime = context.currentTime;
    const contextTime = context.getOutputTimestamp().contextTime;
    console.assert(
        contextTime > (currentTime - context.baseLatency),
        'contextTime', contextTime,
        'currentTime', currentTime,
        'baseLatency', context.baseLatency,
        'contextTime - (currentTime - baseLatency)', contextTime - (currentTime - context.baseLatency)
    );
}, 1000);

Are my assumptions about what it should do skewed, or is the API lying to me about it's baseLatency?

2 Answers

My assumptions are skewed. The Web Audio spec makes this clear in the notes under the section getOutputTimestamp (https://www.w3.org/TR/webaudio/#dom-audiocontext-getoutputtimestamp).

The third bullet in my question is wrong. .getOutputTimestamp().contextTime is not a timestamp for the sample frame currently being handed to the audio driver as I state in the question. It is, as it's name suggests, a timestamp for the sample frame currently being output from the audio driver.

As @Raymond hints at in his answer, the correct latency to compare this timestamp against is outputLatency (which is not implemented as of Jan 2019).

The .baseLatency is basically the number of audio samples need by the WebAudio implementation to work smoothly. It can be as lows as 128 (but no lower) and can be significantly larger (8000 or more). For Macs, the default value is 256. This is used to smooth out any jittering of the audio clock. Mac's have very low jitter so 256 (or 128) works well. Linux machines tend not to be as accurate so 512 or higher is used. (For chrome.)

This does not include any additional buffering that might be between webaudio and the browser audio system and the browser to the OS, and from the OS to the actual output device. (I understand Bluetooth devices can sometimes have huge delays.)

There is an outputLatency attribute that is supposed to show this, but AFAIK, it's not implemented in any browser yet.

Related