如何停止声音设备中的 stream.write 函数

How to stop a stream.write function in sounddevice

是否可以在缓冲区完全消耗之前停止 stream.write 函数? 当我尝试这样做时,声音停止了,但 stream.write 函数从未 returns.

这是一个工作示例,说明我想如何使用小型 class 播放纯音而不阻塞主线程。

import time
import sounddevice as sd
import numpy as np
from threading import Thread

toneduration = 10
samplerate = 44100
frequency = 440
amplitude = 0.5

sd.default.device = 1
sd.default.samplerate = samplerate
sd.default.channels = 2

class Sound(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.stream = sd.OutputStream()
        self.stream.start()

        vector1 = np.linspace(0, toneduration, toneduration * samplerate)
        vector2 = amplitude * np.sin(2 * np.pi * frequency * vector1)
        vector3 = np.array([vector2, vector2])
        self.soundVector = np.ascontiguousarray(vector3.T, dtype=np.float32)

    def run(self):
        self.stream.write(self.soundVector)
        print('end')

sound = Sound()
sound.start()
time.sleep(3)
sound.stream.close()

我可以播放给定持续时间的声音,但是如果我使用 stream.close() 手动停止流,该功能不会 return(永远不会显示 print('end') 消息并且线程未完成)

我必须改用回调吗?在那种情况下,我应该如何用 numpy 数组填充缓冲区?我阅读了文档中的代码示例,但我不知道该怎么做。

我想最简单的方法是使用 play() 函数,该函数默认在后台开始播放(使用从底层 PortAudio 库创建的单独线程调用的回调函数)。 然后您可以使用 stop() 函数停止播放。

如果您需要比简单的 NumPy 数组回放更复杂的东西,您可以实现自己的回调函数。 例如,您可以查看 play() 函数或 examples, e.g. play_long_file.py.

函数的实现

正如你所说,你也可以使用所谓的"blocking" API(使用write()方法)。

无论哪种方式,您通常会将音频数据拆分为一系列块。 这样,您可以安排在任何一个块之后停止播放。这也是 play() 函数内部所做的。