I’m the author of the
sounddevice module and I wanted to say hi and confirm and clarify a few points.
It indeed uses only PortAudio and there is nothing special done for any audio backend. Especially the Windows backends receive no special treatment, since I don’t even have a Windows computer.
I published the bundled DLLs in a separate repository, and they were cross-compiled on Linux using mxe. I myself tested them only very shortly on a VirtualBox image of Windows 10, but according to some feedback from users, they seem to work fine on “normal” Windowses, too. If you put a DLL named
portaudio.dll somewhere onto the Python path, it will be used instead of the bundled DLL. This may happen accidentally if you have pyo installed (see issue 36).
I didn’t do anything special to get lower latency than other PortAudio wrappers. In fact, I’m surprised about that, since the
sounddevice module isn’t an extension module written in C, instead it is pure Python and uses CFFI in ABI/in-line mode to access the PortAudio API.
How did you use the
sounddevice module when measuring the latency?
I wouldn’t recommend to use the play() function in your case, because it each time creates, opens and closes a new
OutputStream object. On some (cheap) soundcards, opening and closing the stream may cause clicks, which would obviously be bad for your use case. This also uses a callback function written in Python, which may be less reliable due to the GIL and the GC.
The OutputStream.write() method just passes the data to PortAudio, which might be better. But probably it’s not, I didn’t measure it …
However, there is no way to control the exact time when the sound starts, so there might be more jitter than necessary, especially when using large block sizes (but again, I don’t actually know, I’m just guessing).
I don’t know if the jitter of the above measurements (maximum 0.33 ms) is to be considered good or bad.
If you really want to get into it, you could try to write your own wrapper using CFFI’s API/out-of-line mode. This way you could implement your own callback function in C, but it also would mean that you have to have a C compiler to create your extension module (which wouldn’t be a problem since you ship binary packages anyway).
When you write your own callback function, you could try to reduce jitter at the expense of some additional latency.
Using CFFI is really simple, so if you have very special requirements, it might be better for you to skip all the PortAudio wrappers and just write your own code directly accessing the PortAudio API.