spatialaudio / python-sounddevice

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

Blocking plays are cut short (Windows/MME) #283

Open rmccampbell opened 4 years ago

rmccampbell commented 4 years ago

When I call sd.play() with the blocking=True argument on Windows it seems to cut the audio off slightly before the end. This also happens when I play in non-blocking mode and then call sd.wait(). It doesn't happen if I play non-blocking and then wait via time.sleep() or just wait in interactive mode. I'm not sure if this is dependent on my particular sound drivers/etc, but I am on Windows 10 with sounddevice 0.4.0.

mgeier commented 4 years ago

Thanks for the report!

Can you please check if the problem happens with multiple host APIs?

What happens if you call sd.wait() and then wait in interactive mode?

rmccampbell commented 4 years ago

With some experimentation it looks like the problem applies to the MME host api. When I play with a device from the Windows DirectSound api it plays fine. And sd.wait() in interactive mode still seems to cut it off if it is called before the audio has finished playing. The amount cut off is very small, about .1 second.

mgeier commented 4 years ago

OK, thanks for the additional information.

It looks like this is a problem within the PortAudio library and nothing we can solve in the Python bindings.

You could try to report this to the PortAudio mailing list (http://portaudio.com/contacts.html) or at the (newly migrated) Github repo (https://github.com/PortAudio/portaudio). Ideally, you would provide example code in C to reproduce the problem (to rule out all the Python stuff).

rmccampbell commented 4 years ago

Yeah... I don't know if I want to go to the trouble of building/installing/troubleshooting PortAudio on Windows just to report a bug... I wonder if it could be "patched" by just adding some arbitrary delay in the wait() function before closing the stream? Not sure if this would be acceptable, though it could be more precise by measuring the expected time of the audio beforehand...

mgeier commented 4 years ago

I wonder if it could be "patched" by just adding some arbitrary delay in the wait() function before closing the stream? Not sure if this would be acceptable, [...]

I don't think this should be part of the sounddevice module, but if you have a concrete suggestion, I'll have a look.

But I think a proper solution can only be achieved within PortAudio.

In the meantime, you can try to just add a certain amount of zeros to the arrays you are playing back.

Or use a different host API.