[Portaudio] Reported latency

Ross Bencina rossb-lists at audiomulch.com
Mon Dec 7 20:20:14 EST 2015


Hi Erik,

I'll try to answer from inline below...

 > PS. I’m on CoreAudio, Mac OS X 10.10

That's useful. Each host API has to implement their own timing 
mechanisms. You should definitely test against all of your targets.

On 8/12/2015 9:48 AM, Erik Ronström wrote:
> Hi List,
>
> (Apologies if this has been asked before, but I haven’t yet found an
> answer by searching the web)
>
> I want to synchronize recorded audio with the track that was played
> back during recording. As far as I understand, this means offsetting
> the recorded audio by (inputLatency + outputLatency). The problem is
> that I cannot make sense of the latency values that PortAudio
> reports.

Roughly speaking yes.


> There seems to be four latency values of interest here: the suggested
> latency (set by PaStreamParameters), the ”actual” latency (as
> reported by PaStreamInfo), the difference between inputBufferAdcTime
> and outputBufferDacTime in PaStreamCallback, and finally, the
> ”real-world” actual latency.

The PaStreamParameters are just requests/suggestions.

(In theory) the PaStreamInfo latencies are as close as PA is able to 
statically report (which varies in accuracy) based on allocated buffers 
and any additional info provided by the native API (often not much).

inputBufferAdcTime and outputBufferDacTime are functions of the current 
buffer fill levels, and the time at which buffers were captured. It 
stands to reason that these calculations could be more accurate, but 
also suggests that in your case there might be an error in the 
calculation of the PaStreamInfo input latency with the particular host 
API that you are testing.


> To get the ”real-world” latency I recorded the backtrack playing from
> the computer speaker directly into the internal microphone, and
> looked at the audio file. I did this several times, and there is no
> measurable difference between the offsets of the different
> recordings.
>
>
> These are the values of one test (input/output, rounded to ms):
> Suggested Latency: 0.010 / 0.010 ”Actual” Latency (PaStreamInfo):
> 0.059 / 0.020 Diff ADC/DAC: 0.035 ”Real-world”: 0.044
>
> And another: Suggested Latency: 0.040 / 0.040 ”Actual” Latency
> (PaStreamInfo): 0.233 / 0.061 Diff ADC/DAC: 0.110 ”Real-world”:
> 0.157

Are these observations with different hardware? To clarify: Is the "Diff 
ADC/DAC" derived from inputBufferAdcTime and outputBufferDacTime?


> I’m certainly not an expert on these matters, but to me the values
> reported by PaStreamInfo looks weird – the input latency cannot
> possibly be 59 ms when the recorded ”echo” starts 44 ms into the
> file?!

True. It's possible that there is a bug either in the buffer phase 
handling or in the calculation of the latency. This code is different 
for each host API.

In the case of PA/CoreAudio this is further complicated by the fact that 
there are two full-duplex code paths depending on whether the input and 
output are on the same CoreAudio device, or on two separate devices (the 
latter case also applies to drivers that expose their audio as two 
separate sub-devices). In the latter case, PA/CoreAudio introduces an 
extra ring-buffer to adapt the two half-duplex streams into a single 
stream. This code path is likely to be used if one of your inputs is the 
microphone.


To reduce the number of moving parts, are you able to test your code 
with a full-duplex device (e.g. a pro audio interface)? Or else, create 
a full-duplex aggregate device and test that. This should present a 
single full-duplex device to PortAudio.


> Furthermore, I would have expected some sort of match between
> the PaStreamInfo latency values and the ADC/DAC diff. Here, I can see
> no obvious relation between them.

One guess is that it could be that there is a power-of-two buffer being 
allocated and you have stepped over a size boundary.



> The ADC/DAC diff seems to be closest to the real-world values, and in
> the first example,

That would make sense to me. inputBufferAdcTime and outputBufferDacTime 
are calculated from all available information including buffer fill 
levels, whereas the static PaStreamInfo latencies don't take this into 
account (and may also be mis-calculated in this case).


> I could have just accepted the 9 ms diff for the
> unknown latency which lays outside of the knowledge of PortAudio. But
> in that case, it wouldn’t have increased so much in the second
> example, I would rather have expected a constant addition.

Yes, I agree that behavior is mysterious.

> How is this supposed to be done? Is it even possible to have the
> system roundtrip latency automatically calculated? (But even if the
> answer is no, the values reported by PaStreamInfo still don’t make
> any sense IMO!)

In theory there are two options: (1) PaStreamInfo or (2) 
inputBufferAdcTime and outputBufferDacTime. For your case I'd use 
PaStreamInfo.

To move forward with this I'll need answers to the questions above.

Also, for your use-case would it be reasonable to require users to use a 
synchronised full-duplex device, or do you absolutely need time 
alignment from two arbitrary devices (like internal mic)?

Thanks,

Ross.


> Best regards Erik
>
> PS. I’m on CoreAudio, Mac OS X 10.10


More information about the Portaudio mailing list