spatialaudio / python-sounddevice

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

fail to load asio driver with a thread #442

Open SoulProficiency opened 1 year ago

SoulProficiency commented 1 year ago

I want to use a pyqt5 GUI to playback a sound with a soundcard. The index of my asio Fireface USB is 66.

import sounddevice as sd
data, fs = sf.read(....)
asio_out = sd.AsioSettings(channel_selectors=[1, 2, 3, 4, 5,6,7,8])
sd.default.extra_settings = None,asio_out
sd.default.device[1] = 66
# mapping from 1 to 8
sd.play(data, samplerate=fs,mapping=[1])
sd.wait()

its work.so i try to use this function within a pyqt5 GUI and create a thread to control.


class New_thread(Qthread):
     def __init__(self,wave_dir,flag):
           super(New_thread,self).__init__()
           self.flag = flag
           self.wave_dir = wave_dir
     def run(self):
           if self.flag:
                 # run 
                 data,fs = soundfile.read(self.weave_dir)
                 asio_out = sd.AsioSetting(channel_selections = [1,2,3,4,5,6,7,8])
                 sd.default.extra_setting = None,asio_out
                 sd.default.device[1] = 66
                 sd.play(data, samplerate=fs,mapping=[1])
                 sd.wait()
           else:
                 # create new thread to stop playing back
                 data = np.empty((1000))
                 sd.default.device[1] = 66
                 sd.play(data, samplerate=48000,mapping=[1])
                 sd.stop()

but its fail.

Traceback (most recent call last):
  File ".\GUI_FOR_LISTENING_TEST.py", line 64, in run
    sd.play(data, samplerate=fs,mapping=[1])
  File "D:\Users\Administrator\miniconda3\envs\listening3.8\lib\site-packages\sounddevice.py", line 175, in play
    ctx.start_stream(OutputStream, samplerate, ctx.output_channels,
  File "D:\Users\Administrator\miniconda3\envs\listening3.8\lib\site-packages\sounddevice.py", line 2582, in start_stream
    self.stream = StreamClass(samplerate=samplerate,
  File "D:\Users\Administrator\miniconda3\envs\listening3.8\lib\site-packages\sounddevice.py", line 1494, in __init__
    _StreamBase.__init__(self, kind='output', wrap_callback='array',
  File "D:\Users\Administrator\miniconda3\envs\listening3.8\lib\site-packages\sounddevice.py", line 898, in __init__
    _check(_lib.Pa_OpenStream(self._ptr, iparameters, oparameters,
  File "D:\Users\Administrator\miniconda3\envs\listening3.8\lib\site-packages\sounddevice.py", line 2745, in _check
    raise PortAudioError(errormsg, err, hosterror_info)
sounddevice.PortAudioError: Error opening OutputStream: Unanticipated host error [PaErrorCode -9999]: 'Failed to load ASIO driver' [ASIO error 0]

how can we fix it,thanks a lot.

soundcare info:Fireface UFX, connected with 8 loudspeakers 0fb2f1d303bbc74500cd3a8b0a0e419 3 2

mgeier commented 1 year ago

Maybe running on a different thread is simply not supported by ASIO?

Just try to start the stream on the main thread.

For a GUI example, see https://github.com/spatialaudio/python-sounddevice/blob/master/examples/rec_gui.py

vividyellow commented 1 year ago

Maybe running on a different thread is simply not supported by ASIO?

Just try to start the stream on the main thread.

For a GUI example, see https://github.com/spatialaudio/python-sounddevice/blob/master/examples/rec_gui.py

you're right, thanks. solve it by running it in another process.

JulienPez commented 1 year ago

I'd like to emphasize the very good remark of @mgeier with my personal experience:

I created a script composed of a GUI and some sounddevice code, which finds its close origin from examples/asyncio_generators.py. I developped everything on MacOS and it worked there. When I tried to run it on Windows, crack the error:

Error opening Stream: Unanticipated host error [PaErrorCode -9999]: 'Failed to load ASIO driver' [ASIO error 0]
File "C:\Users\AtelierEQUIUM\AppData\Local\Programs\Python\Python310\Lib\site-packages\sounddevice.py", line 2745, in _check raise PortAudioError(errormsg, err, hosterror_info)

I have tried on the same computer and same device examples/play_sine.py and a very simple implementation of sd.playrec and it works.

Here is a part of my code with this threading thing that I suppose being the issue.

import threading
import asyncio
import sounddevice as sd

class App()
      def _asyncio_thread(self):
             try:
                  self.async_loop.run_until_complete(self.audio_trigger()) # goes to something very close to examples/asyncio_generators.py
            except: pass
      def __init__(self):
            # do some GUI stuff that calls this following line when starting audio:
            threading.Thread(target=self._asyncio_thread, args=()).start()

async_loop = asyncio.new_event_loop()
asyncio.set_event_loop(async_loop)
app = App(async_loop)

SOLUTION: Just had to remove this threading.Thread(target=self._asyncio_thread, args=()).start(), replace it by a simple self._asyncio_thread() and it works smoothly.

Windows 10 Soundcard: RME FIreface 802a