WASAPI 的问题

Posted

技术标签:

【中文标题】WASAPI 的问题【英文标题】:Problems with WASAPI 【发布时间】:2012-10-21 03:07:05 【问题描述】:

我正在为一个程序开发音频代码,该程序需要能够在各种设备上录制和播放,其中一些是高端设备,具有各种不同的 wav 和 AIFF 格式。我希望能够使用 WASAPI 库,但我遇到了一些重大问题。目前最大的问题是,据我所知,设备只能播放格式完全匹配的流。

这就是我正在做的——我将设备(这里我只是获取默认的控制台设备)设置为:

hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pPlaybackDevice);

我通过以下方式激活设备:

hr = pPlaybackDevice->Activate( __uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&pTakeAudioClient);

然后我检查混合格式:

hr = pTakeAudioClient->GetMixFormat(&pWaveFormatEx);

但是,如果我在调用 Initialize 时使用不同的格式:

hr = pTakeAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,hnsRequestedDuration, 0, pAnotherWaveFormatEx,NULL);

我得到一个错误。似乎该文件绝对必须采用 GetMixFormat 返回的格式。如果我调用 IsFormatSupported 来了解我可以提交哪些格式:

hr = pTakeAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &waveFormatEx, &pAnotherWaveFormatEx);

我得到E_INVALIDARG,即使两个结构完全相同。根据 WASAPI 文档,当“参数 ShareMode 是 AUDCLNT_SHAREMODE_SHAREDAUDCLNT_SHAREMODE_EXCLUSIVE 以外的值”时会返回。我通过AUDCLNT_SHAREMODE_SHARED。这似乎是文档中的错误。

为了实验,我尝试:

hr = pTakeAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &waveFormatEx, NULL);

错误返回是0x8889000e - 我无法找到对该错误的引用。 您可以提供的任何帮助都将非常感激,即使它是“使用 MMSystem”。我会从 MMSystem 开始,只是我们需要能够在有多个设备时控制播放设备。

【问题讨论】:

【参考方案1】:

0x8889000e = AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED (HRESULT reading utility),这几乎说明了原因:此格式不适用于独占模式音频客户端。而且您可能不需要它独占,共享模式可能就足够了。无论如何,要通过 WASAPI 进行录制和播放,您需要协商一种硬件支持的格式,这通常是 PCM 音频格式之一。

要在格式之间进行转换,您可以使用多种 API(ACM、DirectShow、Media Foundation)。 DirectShow 和 Media Foundation 等一些 API 既可以将播放的数据自动转换为支持的格式,也可以通过音频设备播放。

【讨论】:

【参考方案2】:

我知道这是一个非常古老的线程,但这种情况显然已经得到改善,尽管在提出问题时该选项可能已经可用,但我不确定(和文档,就像大多数微软的东西一样,通常不是很有帮助)。

无论如何,根据我的经验,假设您想使用标准 PCM 音频,关键因素似乎是您要求的采样率。大多数声卡似乎不会接受在这方面与其“混合格式”中报告的内容不同的任何内容(这是用于共享音频模式)。 因此,您可以接受卡的采样率,并以该采样率发送所有内容(如果这对您来说是一个可行的选择),或者您可以请求音频驱动程序根据需要在输出链中插入转换器。

最简单的方法是在发出Initialize() 调用时使用 AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM 标志,这将按照我所说的进行,并将您请求的任何源音频格式转换为设备支持的格式。 似乎甚至可以使用 IAudioClockAdjustment::SetSampleRate 即时更改 SR,但我自己从未尝试过。请查看 this page 中的不同标志以获取更多信息。

【讨论】:

以上是关于WASAPI 的问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 wasapi 渲染音频的问题

渲染音频流(WASAPI / WINAPI)

WASAPI 捕获的数据包不对齐

使用 WASAPI 录制音频流

为啥我的 WASAPI 监听器即使在没有播放的时候也会触发?

C# NAudio asio 和 wasapi