WASAPI:识别环回录制中的非活动频道

时间:2018-01-19 07:04:12

标签: c++ audio real-time wasapi

我有一个DSP软件,可以在共享环回模式下使用WASAPI api捕获音频播放。

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

这部分工作正常,但现在我希望能够检测到实际播放的频道数量。换句话说,我怎样才能检测到音频播放是否是立体声,5.1,7.1?

问题是:
*由于环回必须使用共享模式,因此可以播放多个源 *此分析必须实时完成。不能等到播放完毕 *检测任何播放源和暂时静音的频道

完全没有使用的频道之间的差异

我认为最好的解决方案是如果我可以检索所有播放源/子混音的列表,并查询它们各自的频道数。这样我就不必分析音频数据流了。

2 个答案:

答案 0 :(得分:0)

环回记录以端点上定义的混合格式进行,因此无论原始音频格式是什么,您都可以使用混合格式获取数据,从可能的多个播放源混合并转换为此类共享格式。

  

WASAPI环回包含正在播放的所有音频的混合...

     

GetMixFormat方法检索音频引擎用于共享模式流内部处理的流格式......

     

应用程序使用GetMixFormat或IsFormatSupported为共享模式或独占模式流查找适当的格式后,应用程序可以调用Initialize方法初始化具有该格式的流。尝试初始化共享模式流的应用程序,其格式与从GetMixFormat方法获得的混合格式不同,但具有相同数量的通道和与混合格式相同的采样率,可能会成功。在调用Initialize之前,应用程序可以调用IsFormatSupported来验证Initialize是否接受格式。

即使WASAPI在音频格式方面提供了一些灵活性,在回送捕获时,通道配置和采样率也是由共享格式定义的。

当你得到混音时,你无法真正识别“非活跃”频道:这些信息在混合到共享格式时会丢失。

此外,可以通过控制面板以交互方式配置实际的共享格式:

enter image description here

答案 1 :(得分:0)

好的,我现在可以解决我的问题。据我所知,您无法检测共享混音中的子混音,因此唯一的选择是分析音频流/捕获缓冲区。

首先在我的主捕获循环期间,我为所有正在播放的频道设置当前时间戳。

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

非常简单的解决方案,但似乎有效。