1

I am having some problems to play the sounddevice on a Thread. I import the sounddevice as sd at the beginning. Then during running I want to play a tone on a thread using the ASIO sound card. All the configurations I need to do on the thread works well. However, when I want to play the tone I got the following Error:

sounddevice.PortAudioError: Error opening OutputStream: Unanticipated host API 2 error 0: u'Failed to load ASIO driver'

If I initialize the import at the thread everytime I need it, it work. But of course I do not want to do that. Any Idea hot to solve it?

Thanks!

Here a simple code example:

from threading import Thread
import numpy as np
import sounddevice as sd

class Test(Thread):

    def __init__(self):
        Thread.__init__(self)
        #-- Configuration of the Tone to be played
        self.fs = 44100       # sampling rate, in Hz, 44100 or 48000
        duration = 1.05  # in seconds, may be float
        f = 200.0        # sine frequency, Hz, may be float
        self.tone_data = (np.sin(2*np.pi*np.arange(self.fs*duration)*f/self.fs)).astype(np.float32)

    def run(self):                       

        #-- Configuration of the ASIO sound card
        #import sounddevice as sd
        sd.default.channels = 2
        sd.default.device = 14
        print sd.query_devices(sd.default.device)['name']
        #sd.default.latency = ('low','low')
        #asio_out = sd.AsioSettings(channel_selectors=[1, 2])
        #sd.default.extra_settings = asio_out        
        sd.default.samplerate = self.fs                
        sd.play(self.tone_data)
        sd.wait()        

w = Test()        
w.start()
Laura
  • 11
  • 3

1 Answers1

0

This seems to be a platform-specific problem. I just tried it with ALSA/Linux and it works fine. With ASIO, you probably have to do the library initialization (which happens during import time) in the same thread you are using later to create the stream (which play() does for you)?

If I initialize the import at the thread everytime I need it, it work. But of course I do not want to do that.

Why do you not want to do that? Are you aware that the use of import in Python is cached automatically? The second time you use import, only a dict lookup is done and nothing else.

But you are right, the repeated import still looks a bit strange. Did you try to do the import only once in Test.__init__()? There you could also do all the sd.default stuff.

If you still have problems during the initialization (or if you insist on having all imports at the top), you can try to use the undocumented _initialize() and _terminate() functions, see issue #3.

If you want to use multiple Thread instances, you'll get problems with the play() function, which is meant for single-threaded use. But it probably makes more sense anyway to have only one Python thread that does the audio I/O. See also PortAudio Tips – Threading.

BTW, you don't need (...).astype(np.float32), this conversion is done automatically for you.

And while I'm at it, your line sd.query_devices(sd.default.device)['name'] will break if the default input and output devices are different.

Matthias
  • 4,524
  • 2
  • 31
  • 50