-
Notifications
You must be signed in to change notification settings - Fork 151
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Importing sounddevice interrupts other audio streams on Windows when exclusive mode is enabled #496
Comments
Then you should open one! This doesn't seem like anything that can be solved from the Python side. To be sure, you could replace your step 3 with some other software that uses PortAudio, for example Audacity, and listen if it behaves the same. |
Great call. I've tested the same scenario with Audacity and it doesn't exhibit this issue. In fact, using Audacity's PortAudio binary (instead of the ones linked in |
Hmm, that's interesting. I don't know exactly how the DLL from Audacity is built, probably with Conan. I found https://github.com/audacity/audacity/blob/52708c770ffcd98cb86527cd7756413c4179f7fe/conan/conanfile.py#L119-L121, which suggests that WDM-KS is disabled. Maybe that causes the problem? It could be something completely different, though. I don't know if that helps, but you could also try some older versions of the DLL, e.g. https://github.com/spatialaudio/portaudio-binaries/blob/d9765fc440e4181576b5a801afd2e3624ac2edd9/libportaudio64bit.dll and https://github.com/spatialaudio/portaudio-binaries/blob/bab7ef6a62415c2c83bdb632585fa439d3edc48b/libportaudio64bit.dll. |
I made a little experiment building the DLL with MSVC, can you please try the DLL from https://github.com/spatialaudio/portaudio-binaries/actions/runs/6523747765? |
All three linked binaries unfortunately exhibit the same issue.
Audacity's PortAudio binary does indeed support fewer APIs, namely just: MME, DirectSound and WASAPI; while the PortAudio bundled with To help triangulate the root cause, I've tested another PortAudio binary and found that FlexASIO's bundled PortAudio binary also does not exhibit the issue like Audacity's. The most distinct differences are that it's built without the ASIO SDK (so API support is the same as |
Thanks for testing this. It's good to know that switching from MXE cross-compiling (on my local computer) to directly compiling with MSVC (via Github Actions) doesn't change the behavior. Feel free to experiment with my |
After some experimentation compiling different builds of PortAudio, it's clear that building PortAudio with ASIO causes the problem. Since the problem is upstream and its root cause unclear (could be PortAudio or the ASIO SDK), would it be possible to modify |
Thanks for testing this, that's very interesting.
Well, this should already be possible, but it is platform-dependent. On Linux, you can simply put a custom On macOS it should work similarly. On Windows, however, I don't know if/how it works. We might also have to add another library name to the code: python-sounddevice/sounddevice.py Lines 63 to 65 in 4aa98dc
It would be great if you could check this out and suggest any changes that are necessary to make it work properly.
Yes, this might also be possible, it has already been discussed some time ago: #130.
Providing a different DLL is a follow-up concern, but if we create the DLLs with CI (as in my experimental |
Hello, I wanted to confirm that when using the .dll from the FLEXASIO .exe, other audio streams are not interrupted when I import the sounddevice module in Python 3.10 on Windows 10. I simply replaced the Lib\site-packages_sounddevice_data\portaudio-binaries\libportaudio64bit.dll with the portaudio.dll from the FlexASIO\x64 folder, and then renamed it. Thank you for providing this workaround! |
I think the best approach would be bundling it with
Glad to help, thanks for confirming @Prosperelucel |
Before jumping into work-arounds, I would like clarification on two questions:
It would be good to know if this has been discussed already in the PortAudio project and if there are any ideas to solve this within PortAudio. There should at least be an issue at https://github.com/PortAudio/portaudio/issues before we start a work-around here. |
Yes, unfortunately.
Latest ongoing discussion: PortAudio/portaudio#858 Relevant issues in the PortAudio project:
Alright, sounds great. Ideally, the issue is resolved upstream and a new version of sounddevice can then be released with the fixed PortAudio binaries. However, it seems that the issue is much more fundamental with PortAudio's ASIO support. That said, I'm open to seeing where the ongoing issue discussion at PortAudio leads and alternative ideas with regards to this issue's fix. |
Thanks for further looking into that! I found this interesting: PortAudio/portaudio#696 (comment):
I'm one of those people who were not aware of that. Do you also experience the startup delay mentioned at PortAudio/portaudio#696 (comment)? I'm wondering if we should provide a DLL without ASIO by default and provide a work-around to enable ASIO for those who need it? I don't know how many people actually want to use the |
Yes. With the Realtek ASIO driver I had, which I assume many would also have through Realtek's audio drivers, importing sounddevice adds a noticeable >=1 second delay, to the point where I decided to lazy load the library instead before I knew the actual root cause.
Some users likely depend on ASIO for the low-latency it offers, if it is necessary for their use case (e.g. minimal latency for live recording->processing->playback), but for the majority of cases I'd imagine most users do not specify a specific host API, ASIO or otherwise. Having ASIO be optional and enabled explicitly would be the better default in my opinion. Though, existing users would need to be alerted to the change, and they should have an environ flag or otherwise simple method to enable ASIO. Perhaps a simpler change would be to move ASIO support to package extras, so the necessary binary is packaged if the user installs e.g. |
That's very good to know, I wasn't aware of that.
I'd just make a 0.5.0 release and mention the breaking change in the release notes.
I didn't think about that. This sounds good, but is it even possible with wheel packages? |
I just remembered one more thing to try: https://www.lfd.uci.edu/~gohlke/pythonlibs/#sounddevice |
I installed the python 3.9 version |
Thanks for confirming that! What is currently blocking me is that I don't know how to name a custom DLL and where to put it (see #496 (comment)). Can someone please help? Once this works and is documented, we can hopefully make progress here. |
A little update: I have finally installed Windows on a VirtualBox and tried the DLL lookup. I have documented how to do it in #518. I have also worked on compiling different DLLs with Github Actions at spatialaudio/portaudio-binaries#14. I'm planning to use the DLLs without ASIO by default for the next release. |
Apologies for the drive-by comment, but I would certainly like to understand why you are suggesting people put an application DLL in If you are suggesting this because some installer is already putting the PortAudio DLL there, then that installer has a bug and should be fixed. |
No problem at all, I'm glad for any help I can get! I'm not a Windows user, so I know nothing about the rituals.
It's really simple: I did a web search for "DLL search path" and found that path on a random page. I tried it in VirtualBox, and it worked, done!
I'm open for other suggestions!
OK, sounds reasonable, but what is "the executable"?
I'm fine with putting it there, but I don't know if there is an unambiguous way to locate that path on a user's system, especially given about a million different ways to set up virtual environments and Python versions etc.
No, that's not it, there was no installer involved. |
I am not familiar with how Python manages DLL dependencies of Python packages. I think the cleanest way would be to search for the location (using any kind of search tool) of the existing The main thing I take issue with regarding your original suggestion is you are telling people to make a system-wide change that can potentially affects all apps on the machine, just to fix an issue with |
Well, Python doesn't really manage any DLLs, except that I'm using I just need users to put If you know any alternatives to
I'm not sure if that's what you mean, but the "existing DLL" is in Here is the whole mechanism: python-sounddevice/sounddevice.py Lines 61 to 83 in a7c3259
Users can of course overwrite the DLL in
I think I understand your concern. I simply don't know a better place where to put it (which I can explain to users and which works on a majority of systems out there). |
Sorry for the long absence @mgeier. Unfortunately, I haven't had much success with other alternative solutions, and so was stuck for a bit regarding this issue. With regards to finding the DLL/library, From my experimentation on both Windows and Linux, the environment variable implementation suggested in PR #499 works well for both library names / relative paths (if relying on system libraries or searching in The main drawback of such an approach, would be that developers that rely on sounddevice with ASIO (or alternative binaries), will have to provide their own ASIO-built/alternative portaudio binaries with their application, and set the Since the issue with ASIO is exclusively on Windows as far as I can tell, an amendment to PR #498 (i.e., shipping both ASIO/non-ASIO binaries with sounddevice_data and loading the non-ASIO binary by default) would be a simpler implementation with better distribution of binaries with this package. Or maybe providing both options. Though I'd like to hear your thoughts on this so far. |
@arkrow Thanks for looking up the source for The only reasonably common non-system-wide directory I could find in @dechamps Would you think this is acceptable? Or do you have a better idea?
I'm still very much skeptical if introducing and checking a brand-new environment variable is really necessary, since the same thing can be achieved by copying As for providing ASIO and non-ASIO DLLs, that's already prepared in spatialaudio/portaudio-binaries#14. |
The only safe PATH directory for manually adding custom binaries to, would have to be manually created and added for such purposes (e.g. For the scope of this issue, using DLLs without ASIO is a great step forward for default behaviour and would solve this issue. Thanks for the work on spatialaudio/portaudio-binaries#14. Now, to provide ASIO-support for those who need it without: (1) messing with the PATH directories; (2) changing the initialization behaviour to be manually called instead of triggering on import, and (3) monkey-patching. The only way left would be through setting an import os
# other imports
os.environ["SD_ENABLE_ASIO"] = 1
import sounddevice as sd Full disclaimer, though, I have no need for ASIO (in fact, it's the one causing issues due to poor drivers on many Windows PCs), so as far this GitHub issue is concerned, it'll be closed once the new default binaries without ASIO are released. However, I'd like to encourage anyone who relies on sounddevice with ASIO to add their insights/feedback to this discussion. Perhaps here, or if it's closed, in a new PR/issue. |
That's good to know, then that's what I'll recommend in #518. |
I have prepared the removal of ASIO support here: #539. Please check if that version indeed solves the problem described in this issue. If everything works fine, I'll release that in version 0.5.0. |
Yes, I've tested both the current live version again, and the one linked, and I can confirm that the wheels linked in #539 fixes this behavior. Many thanks for your work on this issue @mgeier. |
Thanks for testing, @arkrow! |
Done: https://pypi.org/project/sounddevice/0.5.0/ I think this issue can be closed now. Let me know if something is not working as intended! |
We need to re-enable it with an environment variable. See: https://python-sounddevice.readthedocs.io/en/0.5.1/installation.html#asio-support And: spatialaudio/python-sounddevice#496
As the title mentions, importing sounddevice interrupts any currently playing audio streams momentarily on Windows when exclusive mode is enabled on the sound device. This issue seems to originate from PortAudio's initialization logic, however, I can't seem to pinpoint the problematic code there, and there isn't a similar issue opened there either.
To replicate the issue:
import sounddevice
(can be run in the python interactive interpreter; the current audio stream will be interrupted as a result)This issue does not occur if exclusive mode is disabled in the sound device. I'd assume this issue can be reproduced on Windows 7 as well.
The text was updated successfully, but these errors were encountered: