spatialaudio / python-sounddevice

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

Error while threading #366

Open JacquiG29 opened 2 years ago

JacquiG29 commented 2 years ago

I have the following issue: I am creating a thread that is dedicated to record and post process my audio. In my main program I am streaming the real time audio according to the wire.py example. I already tried both functions separately and they work but everytime that I want to multithread them I got the following error:

StdErr: Expression 'ret' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 1736
Expression 'AlsaOpen( &alsaApi->baseHostApiRep, params, streamDir, &self->pcm )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 1904
Expression 'PaAlsaStreamComponent_Initialize( &self->capture, alsaApi, inParams, StreamDirection_In, NULL != callback )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2171
Expression 'PaAlsaStream_Initialize( stream, alsaHostApi, inputParameters, outputParameters, sampleRate, framesPerBuffer, callback, streamFlags, userData )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 2839
Exception in thread hilo_1:
Traceback (most recent call last):
  File "/usr/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.9/threading.py", line 892, in run
    self._target(*self._args, **self._kwargs)
  File "/home/user/Prueba/multihilo.py", line 163, in grabacion_filtrada
    myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=1, blocksize= True)
  File "/home/user/.local/lib/python3.9/site-packages/sounddevice.py", line 274, in rec
    ctx.start_stream(InputStream, samplerate, ctx.input_channels,
  File "/home/user/.local/lib/python3.9/site-packages/sounddevice.py", line 2572, in start_stream
    self.stream = StreamClass(samplerate=samplerate,
  File "/home/user/.local/lib/python3.9/site-packages/sounddevice.py", line 1415, in __init__
    _StreamBase.__init__(self, kind='input', wrap_callback='array',
  File "/home/user/.local/lib/python3.9/site-packages/sounddevice.py", line 892, in __init__
    _check(_lib.Pa_OpenStream(self._ptr, iparameters, oparameters,
  File "/home/user/.local/lib/python3.9/site-packages/sounddevice.py", line 2737, in _check
    raise PortAudioError(errormsg, err)
sounddevice.PortAudioError: Error opening InputStream: Device unavailable [PaErrorCode -9985]

I am using Ubuntu 21.04. The device that I want to select from the sd.query_devices() is this: 8 USB PnP Sound Device: Audio (hw:3,0), ALSA (1 in, 2 out) and I am selecting it with this code line: sd.default.device = 8,8

Thank you for your help

HaHeho commented 2 years ago

It is difficult to understand what is going wrong without the actual code. Please post a minimal example that showcases the behavior you're struggling with.

JacquiG29 commented 2 years ago

Thanks for the replay

My main code is the following:

if __name__ == '__main__':
    try:
        #THREAD
        t1=threading.Thread(name="hilo_1",target=grabacion_filtrada)    
        t1.start()

        while True:
            with sd.Stream(device=(args.input_device, args.output_device),
                        samplerate=args.samplerate, blocksize=args.blocksize,
                        dtype=args.dtype, latency=args.latency,
                        channels=args.channels, callback=callback):
                input()

    # Reset by pressing CTRL + C
    except KeyboardInterrupt:
        print("Measurement stopped by User")

And the function that I am calling in my thread is the next one:

def grabacion_filtrada():    
    while True:
        modo=1
        filename='Prueba'

        print ("recording...")
        myrecording = sd.rec(int(seconds * fs), samplerate=fs, channels=1)
        sd.wait()  # Wait until recording is finished
        print ("finished recording")

        print ("filtering...")    
        raw_data = myrecording.flatten() #simple string
        kalman_filt=Kalman(raw_data,varMeas,varProcess)
        kalman_filt = np.asarray(kalman_filt)
        write(filename[0:len(filename)]+'.wav', fs,kalman_filt)    

        print ("end filtering")

I get the error that I post every time my function called ¨grabacion_filtrada()¨ is trying to record. I hope this pieces of code make it more understandable. Thank you for your help.

HaHeho commented 2 years ago

I don't think I understand what you are trying to do or how often these loops are iterated for example.

Isn't maybe the problem that sd.Stream(... and sd.rec(... try to access the same interface simultaneously? I'm not sure right now weather that is supposed to be possible. But anyways, doing that seems like it should simply be implemented differently?

Is the objective that the input data is passed straight to output as well as simultaneously captured (+ processed + saved)? If so, then we can think of a more appropriate "signal flow" to be implemented.

JacquiG29 commented 2 years ago

Isn't maybe the problem that sd.Stream(... and sd.rec(... try to access the same interface simultaneously? I'm not sure right now weather that is supposed to be possible. But anyways, doing that seems like it should simply be implemented differently?

I was able to access to it simultaneously in windows, but when I tried it in Ubuntu it failed and my implementation will be on Ubuntu that's why I'm struggling with it.

Is the objective that the input data is passed straight to output as well as simultaneously captured (+ processed + saved)? If so, then we can think of a more appropriate "signal flow" to be implemented.

This actually what I am trying to do

HaHeho commented 2 years ago

I was able to access to it simultaneously in windows, but when I tried it in Ubuntu it failed and my implementation will be on Ubuntu that's why I'm struggling with it.

Interesting.

Is the objective that the input data is passed straight to output as well as simultaneously captured (+ processed + saved)? If so, then we can think of a more appropriate "signal flow" to be implemented.

This actually what I am trying to do

Then before suggesting a potentially better solution to implement this ... The processing is efficient enough to be performed in real-time (on a block-by-block) basis? Is the execution in the scope of a few seconds or rather of arbitrarily long length?

JacquiG29 commented 2 years ago

So I tried my processing in real time and I think that it is efficient enough to be performed. In the other hand, the execution won't have a defined duration.