Как изящно остановить Python SoundDevice из обратного вызова

Я использую Python SoundDevice и PySoundFile для воспроизведения звука "трудным путем", то есть с использованием неблокирующего обратного вызова. (Подсказка для Matthias и команды - эти пакеты просты в использовании и делают все, что мне нужно.) Примечание: использовать sd.play() гораздо проще, но я Я выбрал этот патк, потому что в моей окончательной версии я хочу выполнить дополнительную обработку в методе обратного вызова.

Я могу определить, когда я достиг конца звукового файла, но не ясно, как сказать звуковому устройству остановиться после того, как оно воспроизводит последний буфер в очереди.

Вот пример обратного вызова, который НЕ РАБОТАЕТ: он воспроизводит весь звуковой файл, но не останавливается после обработки последнего буфера. В обратном звонке поднимаю 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)

1 ответ

Doh! Исключения не работают очень хорошо, если вы не raise их!! Правильный код для обратного вызова:

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()

... и он работает просто отлично, играя до конца и останавливаясь после того, как последний буфер был воспроизведен.

Другие вопросы по тегам