SoundCard
SoundCard copied to clipboard
Runtime error when attempting to initialize player in "exclusive_mode"
Hi,
I am attempting to generate real-time audio with low latency on a Windows 10 system with python 3.7. If I try to set the exclusive_mode
argument to speaker.player()
to True
, mediafoundation.py throws an error at line 92: RuntimeError: invalid argument
Here is a snippet of code that generates the error for me:
speaker = soundcard.default_speaker()
with speaker.player(samplerate=48000, blocksize=1200, exclusive_mode=True) as audioplayer:
pass
The values of samplerate
and blocksize
(and channels
, which I left as default) do not seem to matter here, the error always happens when I set exclusive_mode=True
.
Here is the full error when I run the above snippet in an interactive session:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python\Anaconda3\lib\site-packages\soundcard\mediafoundation.py", line 435, in player
return _Player(self._audio_client(), samplerate, channels, blocksize, False, exclusive_mode)
File "C:\Python\Anaconda3\lib\site-packages\soundcard\mediafoundation.py", line 542, in __init__
_com.check_error(hr)
File "C:\Python\Anaconda3\lib\site-packages\soundcard\mediafoundation.py", line 92, in check_error
raise RuntimeError("invalid argument")
RuntimeError: invalid argument
My PC has Realtek audio:
>>> print(speaker)
<Speaker Speakers (Realtek(R) Audio) (2 channels)>
Thanks! Overall this library seems very helpful and a bit easier to use than pyaudio.
I suspect that the error is Windows' way of telling you that you can't open this device in exclusive mode. Perhaps because some other process is using it, or because exclusive mode is not available for every kind of sound card?
Hm I have the same error with different devices. With the python sounddevice library and other applications I can activate the exclusive mode.
In that case this might be a bug. I'd be grateful for any help in debugging this, as I don't currently have a lot of time to devote to open source at the moment.
Thanks for the response @bastibe and thanks for commenting about your error @fmorillo. I had some time to take a look at this tonight and made some progress. In _AudioClient.__init__
, the streamflag 0x00100000
is incompatible with exclusive_mode
(See MS docs here).
Moving the streamflag definition into the if exclusive_mode/else
block to only use that flag for shared mode may fix this issue. Now my code snippet from the OP still returns an error, but instead of "invalid argument"
it returns "unsupported format"
which seems like another rabbit hole for another day. Still, this seems like progress.
Some relevant documentation for the "unsupported format" error: https://docs.microsoft.com/en-us/windows/win32/coreaudio/device-formats https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-isformatsupported https://docs.microsoft.com/en-us/windows/win32/coreaudio/exclusive-mode-streams https://docs.microsoft.com/en-us/windows/win32/api/mmreg/ns-mmreg-waveformatextensible?redirectedfrom=MSDN https://docs.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-initialize
Brilliant! Thank you for investigating this!
So we might be restricted to a pre-set sample rate if we open a device in exclusive mode. Or perhaps we have to change the device's sample rate, as opposed to the AudioClient's.
I pushed a relevant commit (5060713) to my fork, but I'm not sure if there's any point in making a pull request since I do not actually have exclusive mode working.
You can create the pull request at any time if you want to ask for help, just mark is as work-in-progress. I'm afraid I can't help much at the moment, sorry.