如何在 python 声音设备中使用 OutputStream 播放声音文件?
How to play a sound file using an OutputStream in python sounddevice?
目标是同时播放两个声音文件,所以 sounddevice.play
功能不是一个选项。我相信我应该为每个文件制作一个 OutputStream
。现在我一直在努力让一个 OutputStream
工作。请帮忙。
到目前为止我的代码:
import soundfile as sf
import sounddevice as sd
data, fs = sf.read('sound_file.wav', dtype='float32')
def callback(outdata, frames, time, status):
outdata[:] = data
with sd.OutputStream(callback=callback):
pass
编辑: 切换为 RawOutputStream
import soundfile as sf
import sounddevice as sd
wf = sf.SoundFile('sound_file.wav')
def callback(outdata, frames, time, status):
data = wf.buffer_read(frames, dtype='float32')
if len(data) <= 0:
raise sd.CallbackAbort
if len(outdata) > len(data):
raise sd.CallbackAbort #wrong obviously
outdata[:] = data
with sd.RawOutputStream(channels=wf.channels,
callback=callback) as stream:
while stream.active:
continue
如果采样率相似,您可以将两个数据数组相加:
import numpy as np
import soundfile as sf
import sounddevice as sd
data_1, fs_1 = sf.read('sound_file_1.wav', dtype='float32')
data_2, fs_2 = sf.read('sound_file_2.wav', dtype='float32')
if len(data_1) > len(data_2):
data = data_1 + np.pad(data_2, (0, len(data_1) - len(data_2)))
else:
data = np.pad(data_1, (0, len(data_2) - len(data_1))) + data_2
# determine fs from a combination of fs_1 and fs_2 of your choosing, like
fs = min(fs_1, fs_2)
sd.play(data, fs)
import soundfile as sf
import sounddevice as sd
import threading
def _play(sound):
event =threading.Event()
def callback(outdata, frames, time, status):
data = wf.buffer_read(frames, dtype='float32')
if len(outdata) > len(data):
outdata[:len(data)] = data
outdata[len(data):] = b'\x00' * (len(outdata) - len(data))
raise sd.CallbackStop
else:
outdata[:] = data
with sf.SoundFile(sound) as wf:
stream = sd.RawOutputStream(samplerate=wf.samplerate,
channels=wf.channels,
callback=callback,
blocksize=1024,
finished_callback=event.set)
with stream:
event.wait()
def _playsound(sound):
new_thread = threading.Thread(target=_play, args=(sound,))
new_thread.start()
_playsound('sounds_file.wav')
目标是同时播放两个声音文件,所以 sounddevice.play
功能不是一个选项。我相信我应该为每个文件制作一个 OutputStream
。现在我一直在努力让一个 OutputStream
工作。请帮忙。
到目前为止我的代码:
import soundfile as sf
import sounddevice as sd
data, fs = sf.read('sound_file.wav', dtype='float32')
def callback(outdata, frames, time, status):
outdata[:] = data
with sd.OutputStream(callback=callback):
pass
编辑: 切换为 RawOutputStream
import soundfile as sf
import sounddevice as sd
wf = sf.SoundFile('sound_file.wav')
def callback(outdata, frames, time, status):
data = wf.buffer_read(frames, dtype='float32')
if len(data) <= 0:
raise sd.CallbackAbort
if len(outdata) > len(data):
raise sd.CallbackAbort #wrong obviously
outdata[:] = data
with sd.RawOutputStream(channels=wf.channels,
callback=callback) as stream:
while stream.active:
continue
如果采样率相似,您可以将两个数据数组相加:
import numpy as np
import soundfile as sf
import sounddevice as sd
data_1, fs_1 = sf.read('sound_file_1.wav', dtype='float32')
data_2, fs_2 = sf.read('sound_file_2.wav', dtype='float32')
if len(data_1) > len(data_2):
data = data_1 + np.pad(data_2, (0, len(data_1) - len(data_2)))
else:
data = np.pad(data_1, (0, len(data_2) - len(data_1))) + data_2
# determine fs from a combination of fs_1 and fs_2 of your choosing, like
fs = min(fs_1, fs_2)
sd.play(data, fs)
import soundfile as sf
import sounddevice as sd
import threading
def _play(sound):
event =threading.Event()
def callback(outdata, frames, time, status):
data = wf.buffer_read(frames, dtype='float32')
if len(outdata) > len(data):
outdata[:len(data)] = data
outdata[len(data):] = b'\x00' * (len(outdata) - len(data))
raise sd.CallbackStop
else:
outdata[:] = data
with sf.SoundFile(sound) as wf:
stream = sd.RawOutputStream(samplerate=wf.samplerate,
channels=wf.channels,
callback=callback,
blocksize=1024,
finished_callback=event.set)
with stream:
event.wait()
def _playsound(sound):
new_thread = threading.Thread(target=_play, args=(sound,))
new_thread.start()
_playsound('sounds_file.wav')