我尝试了不同的方法在声音设备中播放正弦波,它们工作正常,直到我尝试一次叠加多个频率。每当没有频率播放时,我的扬声器也会发出很大的刮擦声。我已将我的代码简化为:
import sounddevice
import numpy
SAMPLE_RATE = 44100
frequencies = {440: 0, 550: 0, 660: 0}
# hz: start_index
def callback(outdata: numpy.ndarray, frames: int, time, status) -> None:
"""writes sound output to 'outdata' from sound_queue."""
# params may need annotations... :/
result = None
for frequency, start_index in frequencies.items():
t = (start_index + numpy.arange(frames)) / SAMPLE_RATE
t = t.reshape(-1, 1)
wave = numpy.sin(2 * numpy.pi * frequency * t)
if result is None:
result = wave
else:
result += wave
frequencies[frequency] += frames
if result is None:
result = numpy.arange(frames) / SAMPLE_RATE
result = result.reshape(-1, 1)
outdata[:] = result
stream = sounddevice.OutputStream(channels=1, samplerate=SAMPLE_RATE, callback=callback)
stream.start()
while True:
pass
我发现如果你对它进行两处更改,这段代码就可以工作。
第一个变化是这个 while 循环:
while True:
pass
这个循环将使用近 100% 的 CPU,留给回调函数运行的时间很少。
我把这个改为反复睡觉:
while True:
time.sleep(1)
这减少了 CPU 使用率。
我还增加了一次请求的帧数。
我改变了这一行:
stream = sounddevice.OutputStream(channels=1, samplerate=SAMPLE_RATE, callback=callback)
进入这个:
stream = sounddevice.OutputStream(channels=1, blocksize=SAMPLE_RATE, samplerate=SAMPLE_RATE, callback=callback)
我这样做是因为我发现你回调的
frames
参数是 15。(这是在 Mac 上,对你来说可能不同。)我发现请求一秒钟的音频使 numpy 能够更有效地生成它,并防止了奇怪的故障噪音。
在我这样做之后,我听到拨号音。 (我想这就是你想要的。)
看起来你正在添加三个未衰减的正弦函数,这将产生一个输出,在频率相位接近相同的点处,振幅达到 -3 到 +3。
另外,如果您更改频率,您可能会产生爆音。
我希望这有帮助。