spatialaudio / python-sounddevice

:sound: Play and Record Sound with Python :snake:
https://python-sounddevice.readthedocs.io/
MIT License
1.02k stars 149 forks source link

Timing module functions and callback stream in sounddevice #314

Open csarami opened 3 years ago

csarami commented 3 years ago

Hi,

I am on macOS Mojave and trying to type-specific moments. In my application that I am developing, I need to store the times after a specific action/function is triggered in the callback function and other functions in a python module. My goal is to create three different plots on the same time axis.

I understand that: The time (in callback arg list) values are monotonically increasing and have the unspecified origin which is time.currentTime from the callback argument. I also read:

The PortAudio stream callback runs at very high or real-time priority. It is required to consistently meet its time deadlines. Do not allocate memory, access the file system, call library functions or call other functions from the stream callback that may block or take an unpredictable amount of time to complete. With the exception of cpu_load it is not permissible to call PortAudio API functions from within the stream callback.

one way would be using the same timing in callback function and other functions as in:

import sounddevice as sd
import time
duration = 5.5  # seconds

times = list()
def callback(indata, outdata, frames, time, status):
    global times
    if status:
        print(status)
    times.append(time.time())
    outdata[:] = indata

with sd.Stream(channels=2, callback=callback):
    sd.sleep(int(duration * 1000))

However, this produce error below:

input overflow From cffi callback <function _StreamBase.init..callback_ptr at 0x109a00dd0>: Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/sounddevice.py", line 881, in callback_ptr callback, idata, odata, frames, time, status) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/sounddevice.py", line 2678, in _wrap_callback callback(args) File "timed_callbackex.py", line 11, in callback times.append(time.time()) AttributeError: cdata 'struct PaStreamCallbackTimeInfo ' has no field 'time'

So for the development purposes what do you guys recommend for the timing of the steam and other actions as the audio steams input is processed say from a microphone?

Any help would be much appreciated.

mgeier commented 3 years ago

Inside your callback() function, the time parameter is shadowing the time module.

However, if you want to use the timing information from PortAudio, you should not mix it with the time module, because those times are not compatible.

But you can use the information from Stream.time, which is compatible with the time parameter of the callback function.

mgeier commented 3 years ago

See also https://stackoverflow.com/q/66286390/.