如何在回调中优雅地停止python sounddevice
我使用和播放音频的“硬方法”,即使用非阻塞回调。注意:使用sd.play()要容易得多,但是我选择了这个patk,因为在我的最终版本中,我想在回调方法中进行额外的处理 我可以检测何时到达声音文件的末尾,但不清楚如何在播放最后一个排队的缓冲区后告诉sounddevice停止 下面是一个不起作用的回调示例:它播放整个声音文件,但在处理最后一个缓冲区后不会停止。在回调中,我提出了如何在回调中优雅地停止python sounddevice,python,audio,python-sounddevice,Python,Audio,Python Sounddevice,我使用和播放音频的“硬方法”,即使用非阻塞回调。注意:使用sd.play()要容易得多,但是我选择了这个patk,因为在我的最终版本中,我想在回调方法中进行额外的处理 我可以检测何时到达声音文件的末尾,但不清楚如何在播放最后一个排队的缓冲区后告诉sounddevice停止 下面是一个不起作用的回调示例:它播放整个声音文件,但在处理最后一个缓冲区后不会停止。在回调中,我提出了sd.CallbackStop(),但流状态从未变为stopped: def callback(outdata, f
sd.CallbackStop()
,但流状态从未变为stopped
:
def callback(outdata, frame_count, time, status):
view = sf.read(frame_count, dtype='float32', out=outdata)
if (view.size != outdata.size): # this was the last buffer.
print('stopping')
sd.CallbackStop()
with sd.OutpuStream(samplerate=sf.samplerate,
channels=sf.channels,
dtype=np.float32,
callback=callback) as ss:
while (ss.active):
time.sleep(0.1)
啊!如果您不
提出异常,异常将无法正常工作!!回调的正确代码是:
def callback(outdata, frame_count, time, status):
view = sf.read(frame_count, dtype='float32', out=outdata)
if (view.size != outdata.size): # this was the last buffer.
# zero the part of outdata not written into by sf.read()
outdata[view.shape[0]:,:].fill(0.0)
print('stopping')
raise sd.CallbackStop()
。。。它工作得非常完美,一路播放到最后,在播放完最后一个缓冲区后停止。我很高兴听到它可以工作,但您的示例代码看起来根本无法工作!我想你不是指sf.read()
而是指mysoundfile.read()
,对吗?还请注意,您应该始终使用有意义的值填充outdata
,但在上一个块中,您只填充了部分。在我的代码中未显示:将声音文件导入为声音文件
,将声音文件(文件名)导入为sf:
,因此sf.read()
实际上是正确的。还有一个好问题:outdata的未写入部分在最后一次调用中应该是零填充的。我将相应地测试和编辑该示例。@Matthias:您同意修复方案吗?是的,现在看起来不错!你仍然可以用len(view)
替换view.shape[0]
,也可以用len()
替换size
的东西,但我想这是个品味问题。我误解了sf
,因为我通常使用导入声音文件作为sf
。您应该知道,如果在某个时候(从硬盘)读取声音文件的速度由于某种原因而减慢,这可能会导致播放出现故障。这就是为什么sf.play()
坚持在开始播放之前将整个数组存储在内存中。更正:我当然是指sd.play()
而不是sf.play()
!您可能应该补充一点,使用.Done有一种更简单的方法。我明确表示,我希望能够在它们经过时触摸它们。