W3C home > Mailing lists > Public > public-audio@w3.org > July to September 2014

Re: Round Trip Latency test

From: Björn Melinder <bjorn.melinder@gmail.com>
Date: Wed, 3 Sep 2014 13:29:18 +0200
Message-ID: <CAGpT7-kWY32HHEhYnWxddSr-PD=fVuoAF11+CGFaLt3SkQEBcQ@mail.gmail.com>
To: Stephen Band <stephband@cruncher.ch>
Cc: Norbert Schnell <Norbert.Schnell@ircam.fr>, Chris Wilson <cwilso@google.com>, Alex Russell <slightlyoff@google.com>, public-audio@w3.org
I made an empirical test to measure the latency impact of a
ScriptProcessorNode with 16384 frames:

http://jsfiddle.net/5md6natw/5/

The test starts with a direct path from getUserMedia to
audioContext.destination. Pressing the flip button changes the rendering
path to use a ScriptProcessor in-between. Same context, so the web audio to
hardware i/o latency stays the same.

To run the test, I placed headphones next to my MacBook mic, tapped the mic
and recorded the echo-like noise using my phone. Measured the recorded echo
delay in Audacity, the echo delay was exactly 16384 * 2 samples shorter in
the direct path compared to the script processor path, which corresponds to
the double buffering. So I believe Stephens assumption is correct, and the
nice latency meter shows correct values.

Furthermore, a Chrome developer helped me to disable echo cancellation
which reduced the Mac latency to 20ms :) So maybe the meter could utilize
that to show better numbers? E.g.

var constraints = { audio: { optional: [{ echoCancellation: false }] } };

Cheers,
Björn


On Tue, Sep 2, 2014 at 11:43 PM, Stephen Band <stephband@cruncher.ch> wrote:

> Ah yes, you're right. I was assuming that the output buffer starts to play
> at the same time as the input buffer gets filled with new data onaudioprocess.
> But you're right, perhaps that's a totally erroneous assumption.
>
> I suppose another way to do it would be to record a bunch of echos after a
> single impulse and measure the time between them. You could do that with a
> single script processor.
>
>
>
> On 2 September 2014 23:29, Norbert Schnell <Norbert.Schnell@ircam.fr>
> wrote:
>
>> Hi Stephen,
>>
>> These two lines seem to assume that the latency through
>> the ScriptProcessorNode is twice its buffer size:
>>   - 89: outputTimes.push(bufferLength * frame + bufferLength);
>>   - 104: inputTimes.push(bufferLength * frame + n - bufferLength);
>>
>> Is that really always the case?
>>
>> The only idea I had so far to reliably measure the latency through the
>> ScriptProcessorNode was to send a sort of time code (e.g. a ramp counting
>> the samples of a second generated via an AudioBufferSourceNode) through a
>> ScriptProcessorNode (that just copies the input into the output) and to
>> compare (e.g. subtract) the signal coming out of the node with the signal
>> going into the node.
>> I guess, one would need an additional ScriptProcessorNode to look at the
>> result…
>>
>> (BTW: The time code can also be used to see if frames get lost on the way
>> into the audio process code.)
>>
>> Norbert
>>
>> On 02 Sep 2014, at 22:59, Stephen Band <stephband@cruncher.ch> wrote:
>>
>> Hey Stephen,
>>>
>>
>>
>> do you have an un-minimized version of your code?
>>
>>
>>
>> Did you see this? The meat and potatoes of the code is in this gist:
>>
>> https <https://gist.github.com/stephband/f032a69c54f3a5d0ebf9>://
>> <https://gist.github.com/stephband/f032a69c54f3a5d0ebf9>gist.github.com
>> <https://gist.github.com/stephband/f032a69c54f3a5d0ebf9>
>> /stephband/f032a69c54f3a5d0ebf9
>> <https://gist.github.com/stephband/f032a69c54f3a5d0ebf9>
>>
>> Bjorn Melinder also had a look at it. I didn't get chance to look at what
>> he said in his latest two posts, yet.
>>
>>
>> If you're hopping process boundaries, and you usually are, you'll need to
>>> double-buffer.  That's 6ms.  The input has the same buffering - so you're
>>> up to 12ms.  And that's an idealized path...)  This is why even pro audio
>>> hardware frequently has a "direct pass-through"... :)
>>
>> For sound.io I'm working on a looper that compensates for latency, so
>> that you can use the direct channel of a pro audio interface and process
>> loops through sound.io, yet still expect the loops to stay in time with
>> you.
>>
>> I just tested my Metric Halo and I'm getting 38ms at 48000. That's not as
>> good as I thought it was, there may well be some mistakes in the
>> assumptions I've made in the code.
>>
>> Stephen.
>>
>>
>> On 2 Sep 2014 22:29, "Chris Wilson" <cwilso@google.com> wrote:
>>
>>> Hey Stephen,
>>> do you have an un-minimized version of your code?  I can't understand
>>> how you're accounting for the inherent ScriptProcessor latency.  I also
>>> didn't see a clear 2x drop when I doubled my sample rate, which I wanted to
>>> investigate.
>>>
>>> The design of the Web Audio API was intended to provide low-latency in
>>> audio; realistically, <10ms is hard to do without an optimized audio path
>>> *and* a high sample rate.  (A single 128-sample block at 44.1kHz is just
>>> under 3ms.  If you're hopping process boundaries, and you usually are,
>>> you'll need to double-buffer.  That's 6ms.  The input has the same
>>> buffering - so you're up to 12ms.  And that's an idealized path...)  This
>>> is why even pro audio hardware frequently has a "direct pass-through"... :)
>>>
>>>
>>>
>>>
>>> On Sat, Aug 30, 2014 at 2:21 PM, Alex Russell <slightlyoff@google.com>
>>> wrote:
>>>
>>>> On Sat, Aug 30, 2014 at 12:46 PM, Stephen Band <stephband@cruncher.ch>
>>>> wrote:
>>>>
>>>>> It's nothing to do with the UI really.
>>>>>
>>>>
>>>> I understand that this wasn't in any way a test of UI, but in terms of
>>>> the goal of reducing latency, I'd have assumed that being able to match UI
>>>> closely (in response to input, e.g.) would be a goal and impls are some
>>>> distance of that (although we also have bad delay in touch inputs for
>>>> various reasons that are boring).
>>>>
>>>>> You're doing well if you get less than 40ms out of a standard sound
>>>>> card, but if you use a good external audio interface you could see as low
>>>>> as 5ms.
>>>>>
>>>>> Above 15-20ms is when the ear starts to hear two distinct sounds,
>>>>> although it can be uncomfortable to sing and monitor with a latency of
>>>>> >10ms.
>>>>>
>>>> Thanks for the context.
>>>>
>>>>> So I would say a good latency would be <10ms. But good luck getting
>>>>> there :)
>>>>>
>>>> Looks like we're gonna need it = )
>>>>
>>>>
>>>>>  On 30 Aug 2014 21:21, "Alex Russell" <slightlyoff@google.com> wrote:
>>>>>
>>>>>> What's a "good" number for this? I'm assuming less than a UI frame
>>>>>> (16ms) is preferred? I'm seeing ~50ms on Chrome Dev/OS X/MBP and FF doesn't
>>>>>> seem to detect all of the signals in my view.
>>>>>>
>>>>>>
>>>>>> On Sat, Aug 30, 2014 at 11:24 AM, Stephen Band <stephband@cruncher.ch
>>>>>> > wrote:
>>>>>>
>>>>>>> In case someone should find it useful, here's a round-trip latency
>>>>>>> tester:
>>>>>>>
>>>>>>> https://sound.io/latency/
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>
>>>
>>
>
>
> --
>
> Cheers,
> Stephen
>
>
> <http://cruncher.ch>
>                *web*: cruncher.ch
>                *twitter*: @cruncher <http://twitter.com/cruncher>
>                *phone*: +41 76 547 30 32
>                *email*: stephband@cruncher.ch
>
Received on Wednesday, 3 September 2014 11:29:45 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 6 January 2015 21:50:14 UTC