I have an application where I have some other signal referenced to the system clock (time.time()
) and I would like to record the audio input and figure out when it happened relative to the other signal.
At first I tried using the callback API, thinking that they would occur right when the data was available from the sound card. You would expect the callbacks to occur regularly with a difference of roughly the sample period * number of samples, but as other have noted, this isn't the case.
I also tried the blocking API, thinking perhaps it would return when the data was first available, but that seems to have the same problems. There is also the concept of the adc clock in portaudio
, which in callback mode gives current_time
and input_buffer_adc_time
relative to some other clock, which would probably provide the information I need. But both of those values are usually zero (Ubuntu 14 with the default microphone input from my motherboard, not sure which lower level API it is using), and one of them is occasionally nonzero.
I'm willing to use portaudio
directly if this can't be achieved in pyaudio
, but regardless I just need to be able to figure out when a sample (not specific sample, any will do) happened in time.time()
units (posix epoch time) to 100 microseconds or better. It seems like pyaudio
hides a lot the options from portaudio
.
I should also note that there are two components to this timing. I'm mostly interested in the long term component, such that if I record one event, and then another event an hour later, I know how far apart those two events were according to the system clock. There is also probably a short term latency effect such that the system time I get will consistently be 1 ms after the actual event. I can measure that latency directly once I get the long term part working.
edit: I found this paper which discusses this problem. It sounds like the current_time
and input_buffer_adc_time
are the preferred way of doing this, so maybe the thing I should work on is figuring out how to use a different underlying API that actually has this information working?