我正在开发一个程序的音频代码,该程序需要能够在各种设备上录制和播放,其中一些设备是高端的,具有各种不同的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_SHARED
或AUDCLNT_SHAREMODE_EXCLUSIVE
以外的值时,返回”。我正在通过AUDCLNT_SHAREMODE_SHARED
。这似乎是文档中的错误。
为了实验起见,我尝试着这个谜团加深:
hr = pTakeAudioClient->IsFormatSupported(AUDCLNT_SHAREMODE_EXCLUSIVE, &waveFormatEx, NULL);
错误返回为0x8889000e
- 我无法找到对该错误的引用。
即使是“使用MMSystem”,也会非常感谢您提供的任何帮助。我会从MMSystem开始,除了我们需要能够在有多个设备时控制播放设备。
答案 0 :(得分:1)
0x8889000e
= AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED
(HRESULT
reading utility),其中几乎说明了原因:此格式不适用于独占模式音频客户端。而且您可能不需要它独占,共享模式可能已经足够了。无论如何,要通过WASAPI进行录制和播放,您需要协商硬件支持的格式,这通常是PCM音频格式之一。
要在格式之间进行转换,您可以使用多种API(ACM,DirectShow,Media Foundation)。 DirectShow和Media Foundation等一些API既可以将播放的数据自动转换为支持的格式,也可以通过音频设备播放。
答案 1 :(得分:1)
我知道这是一个非常古老的主题,但是这种情况显然已得到改善,虽然在提出问题时可能已经提供了选项,但我不确定(和文档一样,微软的大多数事情,通常不是很有帮助。)
无论如何,根据我的经验,假设您想使用标准PCM音频,关键因素似乎是您要求的采样率。在这方面,大多数声卡看起来都不会接受与“混音格式”中报道的不同(这是针对共享音频模式)。 因此,您可以接受卡的采样率,并以该采样率发送所有内容(如果这是您可行的选项),或者您可以请求音频驱动程序根据需要在输出链中插入转换器。
最简单的方法是在发出Initialize()
呼叫时使用AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM标志,这样做就是我所说的,并将您请求的任何源音频格式转换为支持的设备格式。
看起来甚至可以使用IAudioClockAdjustment::SetSampleRate动态更改SR,但我自己从未尝试过这个问题。请查看this page中的不同标志以获取更多信息。