Alsaaudio record and playback

4.5k Views Asked by At

I was just playing around with sound input and output on a raspberry pi using python. My plan was to read the input of a microphone, manipulate it and playback the manipulated audio. At the moment I tried to read and playback the audio. The reading seems to work, since i wrote the read data into a wave file in the last step, and the wave file seemed fine. But the playback is noise sounds only. Playing the wave file worked as well, so the headset is fine. I think maybe I got some problem in my settings or the output format. The code:

import alsaaudio as audio
import time
import audioop


#Input & Output Settings
periodsize = 1024
audioformat = audio.PCM_FORMAT_FLOAT_LE
channels = 16
framerate=8000

#Input Device
inp = audio.PCM(audio.PCM_CAPTURE,audio.PCM_NONBLOCK,device='hw:1,0')
inp.setchannels(channels)
inp.setrate(framerate)
inp.setformat(audioformat)
inp.setperiodsize(periodsize)

#Output Device
out = audio.PCM(audio.PCM_PLAYBACK,device='hw:0,0')
out.setchannels(channels)
out.setrate(framerate)
out.setformat(audioformat)
out.setperiodsize(periodsize)


#Reading the Input
allData = bytearray()
count = 0
while True:
    #reading the input into one long bytearray
    l,data = inp.read()
    for b in data:
        allData.append(b)

    #Just an ending condition
    count += 1
    if count == 4000:
        break

    time.sleep(.001)


#splitting the bytearray into period sized chunks
list1 = [allData[i:i+periodsize] for i in range(0, len(allData), periodsize)]

#Writing the output
for arr in list1:
    # I tested writing the arr's to a wave file at this point
    # and the wave file was fine
    out.write(arr)

Edit: Maybe I should mention, that I am using python 3

2

There are 2 best solutions below

0
Mein Name On BEST ANSWER

I just found the answer. audioformat = audio.PCM_FORMAT_FLOAT_LE this format isn't the one used by my Headset (just copied and pasted it without a second thought). I found out about my microphones format (and additional information) by running speaker-test in the console.

Since my speakers format is S16_LE the code works fine with audioformat = audio.PCM_FORMAT_S16_LE

0
Oleg Kokorin On

consider using plughw (alsa subsystem supporting resampling/conversion) for the sink part of the chain at least:

#Output Device out = audio.PCM(audio.PCM_PLAYBACK,device='plughw:0,0')

this should help to negotiate sampling rate as well as the data format.

periodsize is better to estimate based on 1/times of the sample rate like:

periodsize = framerate / 8 (8 = times for 8000 KHz sampling rate)

and sleeptime is better to estimate as a half of the time necessary to play periodsize:

sleeptime = 1.0 / 16 (1.0 - is a second, 16 = 2*times for 8000 KHz sampling rate)