试图使用pythonsounddevice低级“stream”类播放和录制带有给出错误的NumPy数组

2024-04-25 08:09:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图将音频文件分割成给定数量的NumPy块,并将它们放入RAM中播放,就像play_a_very_long_sound_file。不幸的是,我相信我对NumPy阵列和音频文件的知识一般是缺乏的。一旦这段代码开始工作,我想在回调函数中添加一个录制过程。根据我目前拥有的代码,我得到:

ValueError: could not convert string to float: ''

它发生在回调函数的第二个if块中。我试图在outdata块的末尾添加零,但不确定如何执行

另一件奇怪的事情是,我只得到一个从soundfile.read()返回的numpy数组,它通常返回一个numpy数组和一个samplerate。但我想这是因为我把它分成了几帧

def callback(outdata, frames, time, status):
  assert frames == args.blocksize
  if status.output_underflow:
    print('Output underflow: increase blocksize?', file=sys.stderr)
    raise sd.CallbackAbort
  assert not status
  try:
    data = q.get_nowait()
  except queue.Empty:
    print('Buffer is empty: increase buffersize?', file=sys.stderr)
    raise sd.CallbackAbort
  if len(data) < len(outdata):
    outdata[:len(data),0] = data
    outdata[len(data):,0] = b'\x00' * (len(outdata) - len(data))
    raise sd.CallbackStop
  else:
    outdata[:,0] = data

try:
  with sf.SoundFile(args.filename) as f:
    for _ in range(args.buffersize):
        data = f.read(frames=args.blocksize, dtype='float32')
        if data.size == 0:
            break
        q.put_nowait(data)  # Pre-fill queue
    stream = sd.OutputStream(  
        samplerate=f.samplerate, blocksize=args.blocksize,
        device=args.device, channels=f.channels, dtype='float32',
        callback=callback, finished_callback=event.set)
    with stream:
        timeout = args.blocksize * args.buffersize / f.samplerate
        while data.size != 0:
            data = f.read(args.blocksize, dtype='float32')
            q.put(data, timeout=timeout)
        event.wait()  # Wait until playback is finished

Tags: readdataframeslenifstatuscallbackargs