Question

I wrote a little program which records voice from the microphone and sends it over network and plays it there. I'm using PyAudio for this task. It works almost fine but on both computers i get errors from ALSA that an underrun occurred. I googled a lot about it and now I know what an underrun even is. But I still don't know how to fix the problem. Most of the time the sound is just fine. But it sounds a little bit strange if underruns occur. Is there anything I should take care of in my code? It feels like I'm doing an simple error and I miss it.

My system: python: python3.3, OS: Linux Mint Debian Edition UP7, PyAudio v0.2.7

Was it helpful?

Solution

Have you considered syncing sound? You didn't provide the code, so my guess is that you need to have a timer in separate thread, that will execute every CHUNK_SIZE/RATE milliseconds code that looks like this:

silence = chr(0)*self.chunk*self.channels*2 
out_stream = ... # is the output stream opened in pyaudio

def play(data):
    # if data has not arrived, play the silence
    # yes, we will sacrifice a sound frame for output buffer consistency
    if data == '':
        data = silence
    out_stream.write(data) 

Assuming this code will execute regularly, this way we will always supply some audio data to output audio stream.

OTHER TIPS

It's possible to prevent the underruns by filling silence in if needed. That looks like that:

#...
data = s.recv(CHUNK * WIDTH) # Receive data from peer
stream.write(data) # Play sound
free = stream.get_write_available() # How much space is left in the buffer?
if free > CHUNK # Is there a lot of space in the buffer?
    tofill = free - CHUNK
    stream.write(SILENCE * tofill) # Fill it with silence
#...

The solution for me was to buffer the first 10 packets/frames of the recorded sound. Look at the snippet below

BUFFER = 10
while len(queue) < BUFFER:
    continue

while running:
    recorded_frame = queue.pop(0)
    audio.write(recorded_frame)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top