Если вы не возражаете, чтобы все входные и выходные сигналы одновременно находились в памяти, вы можете использовать sd.playrec()
. Вы не сможете уменьшить задержку с помощью собственного кода, используя sd.Stream
. sd.playrec()
внутренне использует sd.Stream
и не добавляет задержки.
Если вы хотите уменьшить задержку, вы должны попытаться использовать более низкие значения для параметров blocksize
и / или latency
. Учтите, однако, что низкие значения будут более нестабильными и могут привести к сбоям при воспроизведении / записи.
Если вы не хотите, чтобы все данные одновременно находились в памяти, вы не можете использовать sd.playrec()
и можете попробовать его с sd.Stream
, как в приведенном выше примере.
Однако обратите внимание , что очередь в этих двух соседних строках в лучшем случае бесполезна:
qr.put(indata.copy())
rec_file.write(qr.get())
Можно также написать:
rec_file.write(indata)
Но, пожалуйста, не надо!
Запись в файл может слишком долго блокировать обратный вызов звука, что приводит к пропаданию звука.
Поэтому рекомендуется использовать очередь (и indata.copy()
в качестве ну).
Но вы должны только записать в свой qr
в функции обратного вызова. чтение должно произойти в другой точке.
Вы должны сделать неблокирующий qr.get_nowait()
в while
l oop до или после q.put(...)
и запишите данные в файл.
В функции обратного вызова вы не должны выполнять блокировку qr.put(indata.copy())
, потому что это опять же может заблокировать обратный вызов аудио, что приведет к выпадения. Вместо этого вы должны использовать qr.put_nowait()
. Чтобы избежать полной очереди, вы должны удалить аргумент maxsize
из qr
(но оставить его в другой очереди!).
Наконец, после выхода из диспетчера контекста with stream
может все еще быть данные, оставшиеся в qr
, которые еще не были записаны в файл.
Итак, после того, как поток закрыт, вы должны убедиться, что очистили «очередь записи» и записать оставшиеся блоки в файл.