python-sounddevice icon indicating copy to clipboard operation
python-sounddevice copied to clipboard

How to read/write stream in blocking mode?

Open rawatnaresh opened this issue 4 years ago • 4 comments

I'm trying to achieve something like this using sounddevice

Read stream from mic -> send to the server using socket -> processing on server -> return the processed audio -> write data to the Speaker

as I assumed this cannot be achieved using callbacks approach so I'm trying to use the blocking approach

import sounddevice as sd
import sys

CHUNK = 4096

stream = sd.Stream(
  device=("Built-in Microphone", "Built-in Output"),
  samplerate=44100,
  channels=2,
  blocksize=CHUNK)

def main(argv):
  while True:
    indata, overflowed = stream.read(CHUNK)
    # sending data to socket server
    # doing some processing in the server
    # data returned from the socket is written  to the outputstream(speaker)
    stream.write(indata)

if __name__ == "__main__":
  main(sys.argv)

I'm getting an error when I try to read in blocking mode

 indata, overflowed = stream.read(CHUNK)
  File "/usr/local/lib/python3.9/site-packages/sounddevice.py", line 1450, in read
    data, overflowed = RawInputStream.read(self, frames)
  File "/usr/local/lib/python3.9/site-packages/sounddevice.py", line 1230, in read
    _check(err)
  File "/usr/local/lib/python3.9/site-packages/sounddevice.py", line 2738, in _check
    raise PortAudioError(errormsg, err)
sounddevice.PortAudioError: Stream is stopped [PaErrorCode -9983]

also, I'm not sure If I can do some heavy processing, like calling socket, using a non-blocking approach

rawatnaresh avatar Feb 22 '21 10:02 rawatnaresh

I assumed this cannot be achieved using callbacks approach

It should also be possible with the "callback" approach, but in your case the blocking interface is probably easier to use.

I don't have a lot of experience with the blocking interface, so I can't comment on its usage in your example code.

Stream is stopped [PaErrorCode -9983]

Well, the stream is stopped, so I guess you should start it before calling read() or write() on it. See the docs: https://python-sounddevice.readthedocs.io/en/0.4.1/api/streams.html#sounddevice.Stream.

I'm not sure If I can do some heavy processing, like calling socket, using a non-blocking approach

You can certainly do that, but you shouldn't do it directly in the callback function. One way to do it would be to use a queue to communicate between the callback function and the rest of your code. Some of the examples use such a queue.

mgeier avatar Feb 23 '21 13:02 mgeier

Hi! I'm not sure if this is still a relevant question or you already managed to solved it, but anyways, here it is.

import sounddevice as sd
import sys

CHUNK = 4096

stream = sd.Stream(
  device=("Built-in Microphone", "Built-in Output"),
  samplerate=44100,
  channels=2,
  blocksize=CHUNK)

def main(argv):
    stream.start() # <––––––– This was missing
    while True:
        indata, overflowed = stream.read(CHUNK)
        # sending data to socket server
        # doing some processing in the server
        # data returned from the socket is written  to the outputstream(speaker)
        stream.write(indata)

if __name__ == "__main__":
  main(sys.argv)

You were missing the initializing of the stream by means of stream.start(). I just added that to your main block and it seems to work fine. You only have to be careful with feedback since maybe your default devices can interact with each other, e.g., microphone and speakers on your laptop. This will create a feedback loop.

nico-franco-gomez avatar Mar 01 '22 10:03 nico-franco-gomez

I'm trying to achieve something like this using sounddevice

Read stream from mic -> send to the server using socket -> processing on server -> return the processed audio -> write data to the Speaker

as I assumed this cannot be achieved using callbacks approach so I'm trying to use the blocking approach

import sounddevice as sd
import sys

CHUNK = 4096

stream = sd.Stream(
  device=("Built-in Microphone", "Built-in Output"),
  samplerate=44100,
  channels=2,
  blocksize=CHUNK)

def main(argv):
  while True:
    indata, overflowed = stream.read(CHUNK)
    # sending data to socket server
    # doing some processing in the server
    # data returned from the socket is written  to the outputstream(speaker)
    stream.write(indata)

if __name__ == "__main__":
  main(sys.argv)

I'm getting an error when I try to read in blocking mode

 indata, overflowed = stream.read(CHUNK)
  File "/usr/local/lib/python3.9/site-packages/sounddevice.py", line 1450, in read
    data, overflowed = RawInputStream.read(self, frames)
  File "/usr/local/lib/python3.9/site-packages/sounddevice.py", line 1230, in read
    _check(err)
  File "/usr/local/lib/python3.9/site-packages/sounddevice.py", line 2738, in _check
    raise PortAudioError(errormsg, err)
sounddevice.PortAudioError: Stream is stopped [PaErrorCode -9983]

also, I'm not sure If I can do some heavy processing, like calling socket, using a non-blocking approach

Hi, Were you able to achieve this? I am also trying to do the same but can't seem to figure it out. I'd appreciate any help.

qalabeabbas49 avatar Jul 29 '22 09:07 qalabeabbas49

Do you sound natural when recording and playing at the same time? When I speak quickly, my voice goes up and down, sometimes I swallow words often, and there is an echo. The headphones I wear, my spk is far away from the mic

LXP-Never avatar Jan 11 '23 16:01 LXP-Never