Trying to record from microphone and playback in real time
Asked Answered
L

2

9

I'm trying to record data from my microphone and then play it back through the speakers in real time, and with some delays, but I'm having some problems with it. I chose to use python and alsaaudio, and my current script I'm having problems with can be found here. This works with what I have this far(not the delay part), but produces some clicking. alsaaudio docs has this to say:

The most common reason for problems with playback of PCM audio is that writes to PCM devices must exactly match the data rate of the device.

If too little data is written to the device, it will underrun, and ugly clicking sounds will occur. Conversely, of too much data is written to the device, the write function will either block (PCM_NORMAL mode) or return zero (PCM_NONBLOCK mode).

I seem to be misunderstanding the docs, it says this about write():

PCM.write(data)

Writes (plays) the sound in data. The length of data must be a multiple of the frame size, and should be exactly the size of a period

a period in my script is 160.

it says this about read():

In PCM_NORMAL mode, this function blocks until a full period is available, and then returns a tuple (length,data) where length is the number of frames of captured data, and data is the captured sound frames as a string. The length of the returned data will be periodsize*framesize bytes.

in my script, period_size*frame_size should also be equal to 160, but when I print the length(part of tuple read() returns) i'm getting 940. Obviously I seem to not be passing the right amount of data to out.write(), but I'm not sure where to go. I put this code together mostly through examples I found, and I just started working with alsaaudio / sound, trying to put together some interesting projects, so I don't know a whole lot yet.

I also wanted to record live from the microphone, then playback with a 100ms delay, hence the commented time.sleep(). If I uncomment it, the length seems to go from 940 to -32 repeatedly, eventually causing out.write() to throw an exception (not enough data).

Could someone tell me how (or what's wrong with my script) I'd go about recording and playing back sound data in real time, and with a 100ms delay?

Laise answered 18/8, 2011 at 5:13 Comment(0)
C
1

you can't use sleep(0.1) to delay the output by 100ms. you need to create a buffer which hold the 100ms audio data:

buf = []
while True:
    l, data = inp.read()
    buf.append(data)
    if len(buffer)>=10:
        out.write(buf[0])
        del buf[0]

change 10 to some number that will cause 100ms delay.

Chilli answered 18/8, 2011 at 6:59 Comment(2)
I see, thanks. I've done that and it definitely works with a delay(still with clicking), but I'm unsure how I could determine what number would cause the right delay. I tried printing elapsed time like this and fiddling with the number, but it doesn't seem to change. Also that seems to more echoLaise
Nevermind about the echo, haha. Microphone was just close to the speakers, duh.Laise
O
0

Have you tried alsaloop? Try "man alsaloop". You can select latency through that command as well.

Ocular answered 2/10, 2012 at 12:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.