我使用pyaudio录制音频,然后将其分块处理(例如,每5秒一次)。我在回调模式下使用pyaudio,其中有一个回调函数,每录制1500个音频样本就调用该函数,在该函数中,这些样本被添加到队列中。我还保存样本到一个wav文件,因为他们正在被记录,只是为了验证他们是预期的。在
q = Queue.Queue()
flag = False
waveFile = wave.open('recording.wav', 'wb')
waveFile.setnchannels(1)
waveFile.setsampwidth(2)
waveFile.setframerate(RATE)
def callback(in_data, frame_count, time_info, status):
silent = is_silent(in_data)
if silent == False:
numpydata = np.fromstring(in_data, dtype=np.int16)
waveFile.writeframes(in_data)
q.put(numpydata)
callback_flag = pyaudio.paContinue
elif silent == True and flag == True:
numpydata = np.fromstring(in_data, dtype=np.int16)
if len(numpydata) != 0:
waveFile.writeframes(in_data)
q.put(numpydata)
waveFile.close()
callback_flag = pyaudio.paComplete
else:
callback_flag = pyaudio.paContinue
return (in_data, callback_flag)
p=pyaudio.PyAudio() # start the PyAudio class
stream=p.open(format=pyaudio.paInt16,channels=1,rate=RATE,input=True,frames_per_buffer=1500, stream_callback = callback) #uses default input device
一旦队列不再是空的,我就进入一个while循环,该循环将队列中的数据添加到一个单独的缓冲区,然后在添加5秒音频时处理该缓冲区中的数据。在
^{pr2}$我的问题是,我注意到音频信号中奇怪的意外故障,就好像程序暂时停止录制几个样本,然后又重新启动一样。我可以通过在Audacity中打开录制的wav文件并放大信号来看到这一点。我认为这是因为pyaudio在一个单独的线程中为每1500个样本调用回调函数,有时它可能会尝试调用回调函数,但上一个回调函数的线程仍然处于打开状态,该回调函数尚未完成,数据仍在添加到队列中等等(如果这是解释不连贯,我不太清楚该用什么术语)。在
有人知道我怎么解决这个问题吗?有没有一种方法可以同步它,使每个回调函数只在前一个回调函数完成处理后才被调用?在
在回调函数中应该非常小心。最值得注意的是,你不应该读写其中的文件。 您提到您只为调试而编写文件,但这实际上可能会导致问题。在
另外,您应该始终检查回调函数的
status
参数。这会告诉你是否有超支或不足。 如果遇到超限或欠载,可以尝试增加块大小(和延迟),直到它们消失。在下面是我制作的一个示例脚本,它记录到一个声音文件中:rec_unlimited.py。 下面是一个绘制输入信号的例子:plot_input.py。您可以将其调整为执行任何其他处理而不是打印。在
实际上已经是这样了,对回调函数的调用永远不会重叠。但是,如果一次调用回调函数的时间太长,那么将生成的输出数据发送到声卡就太晚了,并且必须丢弃这些音频数据,从而导致音频丢失。这被称为“输出不足”。 如果前一次调用回调函数花费的时间太长,那么将有太多可用的音频输入数据,其中一些数据将不得不丢弃,再次导致退出。这称为“输入溢出”。在
相关问题 更多 >
编程相关推荐