WASAPI: определение неактивных каналов при петлевой записи

У меня есть программное обеспечение DSP, которое записывает звук, воспроизводимый с помощью API-интерфейса WASAPI в режиме совместного использования шлейфа.

hr = _pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_LOOPBACK, 0, 0, _pFormat, 0);

Эта часть отлично работает, но теперь я хочу определить количество реально воспроизводимых каналов. Другими словами, как я смогу определить, является ли воспроизводимый звук стереофоническим, 5.1, 7.1?

Проблема в:
* Поскольку шлейф должен использовать общий режим, может быть воспроизведено несколько источников.
* Этот анализ должен быть сделан в режиме реального времени. Не могу дождаться окончания воспроизведения.
* Обнаружение разницы между каналом, который вообще не используется никаким источником воспроизведения, и каналом, который временно отключен

Лучшее решение на мой взгляд было бы, если бы я мог получить список всех воспроизводимых источников / субмиксов и запросить их каждый на количество каналов. Таким образом, мне не нужно анализировать сам поток аудиоданных.

2 ответа

Решение

Хорошо, теперь у меня есть решение моей проблемы. Насколько я знаю, вы не можете обнаружить субмиксы в общем миксе, поэтому единственным вариантом было проанализировать аудио поток / буфер захвата.

Сначала во время основного цикла захвата я установил текущую метку времени для всех воспроизводимых каналов.

const time_t now = Date::getCurrentTimeMillis();
//Iterate all capture frames
for (i = 0; i < numFramesAvailable; ++i) {
    for (j = 0; j < _nChannelsIn; ++j) {
        //Identify which channels are playing.
        if (pCaptureBuffer[j] != 0) {
            _pUsedChannels[j] = now;
        }
    }
}

Затем каждую секунду я вызываю эту функцию, которая оценивает, сыграл ли канал последнюю секунду. На основании того, какие каналы играют, я могу сделать условную маршрутизацию.

void checkUsedChannels() {
    const time_t now = Date::getCurrentTimeMillis();
    //Compare now against last used timestamp and determine active channels
    for (size_t i = 0; i < _nChannelsIn; ++i) {
        if (now - _pUsedChannels[i] > 1000) {
            _pUsedChannels[i] = 0;
        }
    }
    //Update conditional routing
    for (const Input *pInut : _inputs) {
        pInut->evalConditions();
    }
}

Очень простое решение, но оно работает.

Циклическая запись происходит в формате микса, определенного в конечной точке, поэтому независимо от того, каким был исходный аудиоформат, вы получаете данные в формате микса, микшированные из, возможно, нескольких воспроизводимых источников, а также конвертируемые в такой общий формат.

Петля WASAPI содержит микс всего воспроизводимого аудио...

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

После того, как приложение использует GetMixFormat или IsFormatSupported, чтобы найти подходящий формат для потока в совместно используемом режиме или в режиме исключительного режима, приложение может вызвать метод Initialize для инициализации потока с этим форматом. Приложение, которое пытается инициализировать поток совместно используемого режима с форматом, который не идентичен формату микширования, полученному из метода GetMixFormat, но имеет то же количество каналов и ту же частоту выборки, что и формат микширования, вероятно, будет успешным, Перед вызовом Initialize приложение может вызвать IsFormatSupported, чтобы проверить, что Initialize примет формат.

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

Когда вы получаете микс, вы не можете идентифицировать "неактивные" каналы: эта информация теряется во время микширования в общий формат.

Кроме того, фактический общий формат может быть настроен в интерактивном режиме через панель управления:

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