尝试实时录音并播放

9 投票
2 回答
3173 浏览
提问于 2025-04-16 23:51

我正在尝试从我的麦克风录制数据,然后实时通过扬声器播放出来,还想加一些延迟,但遇到了一些问题。我选择使用Python和alsaaudio库,目前的脚本在这里可以找到 这里。到目前为止,这个脚本能正常工作(除了延迟部分),但会产生一些咔嗒声。alsaaudio的文档提到 这个

播放PCM音频时最常见的问题是,写入PCM设备的数据必须与设备的数据速率完全匹配。

如果写入的数据太少,设备会出现“下溢”,就会发出难听的咔嗒声。相反,如果写入的数据太多,写入函数要么会阻塞(PCM_NORMAL模式),要么返回零(PCM_NONBLOCK模式)。

我似乎对文档的理解有些偏差,它对write()的说明是:

PCM.write(data)

将data中的声音写入(播放)。data的长度必须是帧大小的倍数,并且应该正好等于一个周期的大小。

在我的脚本中,一个周期的大小是160。

它对read()的说明是:

在PCM_NORMAL模式下,这个函数会阻塞,直到一个完整的周期可用,然后返回一个元组(length, data),其中length是捕获数据的帧数,data是捕获的声音帧,作为字符串返回。返回的数据长度将是periodsize*framesize字节。

在我的脚本中,period_size*frame_size也应该等于160,但当我打印length(read()返回的元组的一部分)时,得到的是940。显然,我似乎没有将正确数量的数据传递给out.write(),但我不确定该怎么做。我主要是通过找到的例子拼凑这个代码,我刚开始接触alsaaudio和声音处理,想做一些有趣的项目,所以我还不太懂。

我还想从麦克风实时录音,然后以100毫秒的延迟播放,因此我注释掉了time.sleep()。如果我取消注释,它的长度似乎会在940和-32之间反复变化,最终导致out.write()抛出异常(数据不足)。

有人能告诉我怎么做(或者我的脚本哪里出错了),让我能够实时录制和播放声音数据,并加上100毫秒的延迟吗?

2 个回答

0

你试过 alsaloop 吗?可以试试输入 "man alsaloop"。通过这个命令,你还可以选择延迟时间。

1

你不能用sleep(0.1)来让输出延迟100毫秒。你需要创建一个缓冲区,用来存放100毫秒的音频数据:

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

把10改成一个能让你实现100毫秒延迟的数字。

撰写回答