我计划用Python实现一个类似DSP的信号处理器。它应该通过ALSA捕获音频片段,对其进行处理,然后通过ALSA播放。在

为了开始工作,我写了以下代码(非常简单)。在import alsaaudio

inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NORMAL)

inp.setchannels(1)

inp.setrate(96000)

inp.setformat(alsaaudio.PCM_FORMAT_U32_LE)

inp.setperiodsize(1920)

outp = alsaaudio.PCM(alsaaudio.PCM_PLAYBACK, alsaaudio.PCM_NORMAL)

outp.setchannels(1)

outp.setrate(96000)

outp.setformat(alsaaudio.PCM_FORMAT_U32_LE)

outp.setperiodsize(1920)

while True:

l, data = inp.read()

# TODO: Perform some processing.

outp.write(data)

问题是,音频“结巴”而不是无间隙。我试着用PCM模式做实验,把它设为PCM_ASYNC或PCM_NONBLOCK,但问题仍然存在。我认为问题是“两个后续调用之间”的样本输入读取()“丢失。在

有没有一种方法可以在Python中“连续地”捕获音频(最好不需要太“特定的”/“非标准”的库)?我希望信号总是“在后台”被捕获到某个缓冲区,从中我可以读取一些“瞬时状态”,而音频则进一步被捕获到缓冲区中,即使是在我执行读取操作的时候。我怎样才能做到这一点?在

即使我使用一个专用的进程/线程来捕获音频,这个进程/线程也至少必须(1)从源读取音频,(2)然后将其放入某个缓冲区(然后“信号处理”进程/线程从中读取)。因此,这两个操作在时间上仍然是连续的,因此样本将丢失。我如何避免这种情况?在

非常感谢你的建议!在

编辑2:现在我让它运行了。在

^{pr2}$

然而,当我甚至对音频数据进行最细微的修改时(例如,注释该行),我会在输出处得到大量噪声和极端失真。似乎我没有正确处理PCM数据。奇怪的是,“液位计”等的输出似乎都有道理。但是,当我稍微偏移它时,输出是完全失真的(但是是连续的)。在

编辑3:我刚发现我的算法(不包括在这里)在我将它们应用于wave文件时起作用。因此,问题实际上似乎归结为ALSA API。在

编辑4:我终于找到了问题。他们是下面的。在

1st-在请求PCM_U32_LE格式时,ALSA悄悄地“退回”到PCM_U8_LE格式,因此我假设每个样本的宽度为4字节,从而错误地解释了数据。当我要求PCM格式时,它能工作。在

第二个-ALSA输出似乎期望以字节为单位的周期大小,尽管它们在规范中明确指出,它应该以帧的形式出现。因此,如果使用32位采样深度,则必须将周期大小设置为输出的四倍。在

第三,即使在Python中(这里有一个“全局解释器锁”),进程也比线程慢。通过更改为线程可以大大降低延迟,因为I/O线程基本上不做任何计算密集型的操作。在

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐