Как записать звук с помощью WasapiLoopbackCapture, когда из динамика в c # не выходит голос? - PullRequest
0 голосов
/ 15 сентября 2018

Ниже приведен пример кода для записи звука, поступающего из динамика.Работает нормально.Но он записывает звук только тогда, когда какой-то звук выходит из динамика.Если нет звука, то это не запись.На самом деле я делаю запись экрана с голосом системы.Длина звука, записанного с помощью wasapiloop, не соответствует длине записи экрана, поскольку wasapiloop записывает звук только при наличии звука из динамика.

WasapiCapture waveLoop = new WasapiLoopbackCapture();
waveLoop.Initialize();
waveLoop.DataAvailable += waveLoop_DataAvailable;
waveLoop.Stopped += waveLoop_Stopped;
waveLoop.Start();

Я видел один похожий вопрос о стеке, но я не понял его полностью.

CSCore кольцевая запись при отключении звука

Любая помощь очень ценится.

Ответы [ 2 ]

0 голосов
/ 01 апреля 2019

Играть в тишину. Васапи подумает, что нужно что-то записать, и отправит аудио на устройство обратной связи.

https://mathewsachin.github.io/blog/2017/07/28/mixing-audio.html

Также @Hans Passant написал эту ссылку в комментарии:

https://blogs.msdn.microsoft.com/matthew_van_eerde/2008/12/16/sample-wasapi-loopback-capture-record-what-you-hear/

0 голосов
/ 15 сентября 2018

По замыслу WASAPI loopback capture генерирует данные только при реальном воспроизведении - вы уже поняли это.Если ваша цель заключается в создании непрерывного потока данных, вы несете ответственность за генерацию звуковых байтов тишины для промежутков между данными, генерируемыми при захвате с обратной связью.Данные закольцованного захвата поставляются с метками времени и флагами разрыва, так что вы можете применить простую математику и определить количество байтов нуля / тишины для добавления.

ОБНОВЛЕНИЕ.Проверив код NAudio (особенно здесь ), я вижу проблему для точной математики для вычисления байта тишины в событии DataAvailable: NAudio игнорирует DataDiscontinuity, также известный как AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY флаг, сообщаемый при захвате с обратной связью.

С захватом с обратной связью будут генерироваться аудиопакеты определенной длительности (например, длиной 10 мс), когда на конечной точке имеются данные воспроизведения.Эти пакеты доступны для чтения через интерфейс WasapiLoopbackCapture.Буферизация отсутствует, и пока считываемые данные непрерывны, вызов GetBuffer не поднимает флаг DataDiscontinuity.Таким образом, у вас есть флаг с вашим первым пакетом, а затем, пока вы не увидите его в следующий раз, вы будете обрабатывать данные как непрерывные.

Когда воспроизведение останавливается и захват с обратной связью прекращает выдавать данные, новых данных из * 1019 нет*.Однако вы знаете размер / длительность пакета, и при отсутствии данных вашему таймеру необходимо заменить эти отсутствующие данные байтами молчания (также полезно позаботиться о частично заполненном последнем пакете в последовательности с соответствующим размером пакета молчания).Вы будете вводить байты молчания до тех пор, пока GetBuffer вызов не будет успешным и вам не будут доступны новые данные.У вас будет флаг DataDiscontinuity, чтобы указать новую последовательность данных.

С этого момента вы должны прекратить молчать и снова использовать считанные данные.Кроме того, поскольку вы знаете, что буферизация не задействована, было бы неплохо использовать пакет с разрывом для обновления ваших временных записей: когда у вас есть пакет, вы можете предположить, что его последний байт соответствует моменту времени, когда GetBuffer был успешным.Оттуда вы можете получить количество байтов тишины, чтобы заполнить для идеальной непрерывности вашего объединенного потока.

Поэтому идея состоит в том, чтобы взять флаг DataDiscontinuity от NAudio, чтобы он не терялся, добавьте таймер дляСвоевременное генерирование байтов тишины и сбор всего вместе с проверкой непрерывности, добавлением байтов тишины в обратный вызов таймера и объединением всего в непрерывную подачу.

...