【问题标题】:Setting volumes for multiple streams using Media Foundation使用 Media Foundation 为多个流设置音量
【发布时间】:2012-11-18 04:47:36
【问题描述】:

我正在为将同时播放多个音频流的应用程序提供音频代码。我对所有不同的选项都感到有些困惑,并且有些具体的事情我不太了解。

我正在使用 IAudioClient 调用来获取和设置音量。这是为多个流获取音量的最佳方式吗?

看来我必须调用 IAudioClient::Initialize。此函数需要 WAVEFORMATEX 结构。除了音量设置中使用的通道数之外,还有其他参数吗?此外,Initialize 似乎只能使用一次,并且音量设置和读取会发生多次。我应该保存对 IAudioClient 的引用并每次都使用它,还是每次获取或设置音量时都可以释放它?

如何区分在同一设备(端点)上播放的两个流?

这是设置音量的代码(通过常规检查确保每次调用成功消除以节省空间):

hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&DeviceEnumerator));
hr = DeviceEnumerator->GetDevice((wchar_t *)currentPlaybackDevice.id, &pPlaybackDevice);
hr = pPlaybackDevice->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, reinterpret_cast<void **>(&pPlaybackClient));
hr = pPlaybackClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, 0, 0, &pWaveFormat, 0);
hr = pPlaybackClient->GetService(__uuidof(IAudioStreamVolume), (void **)&pStreamVolume);
hr = pStreamVolume->GetChannelCount(&channels);
for(UINT32 i = 0; i < channels; i++)
     chanVolumes[i] = playbackLevel;
hr = pStreamVolume->SetAllVolumes(channels, chanVolumes);

【问题讨论】:

    标签: windows visual-c++ audio ms-media-foundation


    【解决方案1】:

    通道数与音量无关。 T 调节音量需要获取接口IAudioStreamVolumeIChannelAudioVolume。见MSDN writes

    IAudioStreamVolume 接口使客户端能够控制和 监控音频流中所有通道的音量。 客户端获得对 IAudioStreamVolume 接口的引用 通过调用 IAudioClient::GetService 方法的流对象 参数 riid 设置为 REFIID IID_IAudioStreamVolume。

    这是为您准备的代码 sn-p。它以更大的音量播放合成的正弦波几秒钟,然后继续以更新的音量继续安静地播放。

    #define _USE_MATH_DEFINES
    #include <math.h>
    #include <mmdeviceapi.h>
    #include <audioclient.h>
    
    #define _A  ATLASSERT
    #define __C ATLENSURE_SUCCEEDED
    #define __D ATLENSURE_THROW
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        __C(CoInitialize(NULL));
        CComPtr<IMMDeviceEnumerator> pMmDeviceEnumerator;
        __C(pMmDeviceEnumerator.CoCreateInstance(__uuidof(MMDeviceEnumerator)));
        CComPtr<IMMDevice> pMmDevice;
        __C(pMmDeviceEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &pMmDevice));
        CComPtr<IAudioClient> pAudioClient;
        __C(pMmDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (VOID**) &pAudioClient));
        CComHeapPtr<WAVEFORMATEX> pWaveFormatEx;
        __C(pAudioClient->GetMixFormat(&pWaveFormatEx));
        static const REFERENCE_TIME g_nBufferTime = 60 * 1000 * 10000i64; // 1 minute
        __C(pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, g_nBufferTime, 0, pWaveFormatEx, NULL));
        #pragma region Data
        CComPtr<IAudioRenderClient> pAudioRenderClient;
        __C(pAudioClient->GetService(__uuidof(IAudioRenderClient), (VOID**) &pAudioRenderClient));
        UINT32 nSampleCount = (UINT32) (g_nBufferTime / (1000 * 10000i64) * pWaveFormatEx->nSamplesPerSec) / 2;
        _A(pWaveFormatEx->wFormatTag == WAVE_FORMAT_EXTENSIBLE);
        const WAVEFORMATEXTENSIBLE* pWaveFormatExtensible = (const WAVEFORMATEXTENSIBLE*) (const WAVEFORMATEX*) pWaveFormatEx;
        _A(pWaveFormatExtensible->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
        // ASSU: Mixing format is IEEE Float PCM
        BYTE* pnData = NULL;
        __C(pAudioRenderClient->GetBuffer(nSampleCount, &pnData));
        FLOAT* pfFloatData = (FLOAT*) pnData;
        for(UINT32 nSampleIndex = 0; nSampleIndex < nSampleCount; nSampleIndex++)
            for(WORD nChannelIndex = 0; nChannelIndex < pWaveFormatEx->nChannels; nChannelIndex++)
                pfFloatData[nSampleIndex * pWaveFormatEx->nChannels + nChannelIndex] = sin(1000.0f * nSampleIndex / pWaveFormatEx->nSamplesPerSec * 2 * M_PI);
        __C(pAudioRenderClient->ReleaseBuffer(nSampleCount, 0));
        #pragma endregion
        CComPtr<ISimpleAudioVolume> pSimpleAudioVolume;
        __C(pAudioClient->GetService(__uuidof(ISimpleAudioVolume), (VOID**) &pSimpleAudioVolume));
        __C(pSimpleAudioVolume->SetMasterVolume(0.50f, NULL));
        _tprintf(_T("Playing Loud\n"));
        __C(pAudioClient->Start());
        Sleep(5 * 1000);
        _tprintf(_T("Playing Quiet\n"));
        __C(pSimpleAudioVolume->SetMasterVolume(0.10f, NULL));
        Sleep(15 * 1000);
        // NOTE: We don't care for termination crash
        return 0;
    }
    

    【讨论】:

    • 我想我的问题还不够清楚。我正在使用 IAudioStreamVolume。该代码有效,但不影响当前流的音量。
    • 我不明白。它有效,还是现在有效?而且您的帖子问题也不同 - 如何在单个会话中单独设置音量(其中简单的 A 是在同一端点上使用单独的会话)。您可能还想查看ISimpleAudioVolume,其中描述了您有一些影响会话量的选项。
    • 代码有效,但不改变音量。看起来我缺少的是将媒体会话与音量相关联的方法。你能解释一下这种关系吗?
    • 我添加了代码 sn-p,它会根据播放时间更新音量。代码也在这里 - alax.info/svn/public/trunk/Utilities/Miscellaneous/…
    • 我很欣赏代码。这个特定的应用程序有多个流,据我所知,ISimpleAudioVolume 不允许控制多个流。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-10
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    相关资源
    最近更新 更多