0

複数のオーディオ ストリームを同時に再生するアプリケーションのオーディオ コードを提供しています。さまざまなオプションのすべてに少し混乱しており、よくわからない特定のことがいくつかあります。

ボリュームの取得と設定に IAudioClient 呼び出しを使用しています。複数のストリームのボリュームを取得する最良の方法はありますか?

IAudioClient::Initialize を呼び出す必要があるようです。この関数には、WAVEFORMATEX 構造体が必要です。ボリューム設定で使用するチャネル数以外のパラメータはありますか? また、Initialize は 1 回しか使用できないようで、ボリュームの設定と読み取りが何度も行われます。IAudioClient への参照を保存して毎回使用する必要がありますか? または、ボリュームを取得または設定するたびに解放できますか?

同じデバイス (エンドポイント) で再生されている 2 つのストリームを区別するにはどうすればよいですか?

ボリュームを設定するコードは次のとおりです (スペースを節約するために、各呼び出しが成功したことを確認するための通常のチェックは省略されています)。

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);
4

1 に答える 1

0

チャンネル数と音量は関係ありません。IAudioStreamVolumeT インターフェイスを取得するために必要なボリュームを調整しますIChannelAudioVolumeMSDN の書き込みを参照してください。

IAudioStreamVolume インターフェイスを使用すると、クライアントは、オーディオ ストリーム内のすべてのチャネルのボリューム レベルを制御および監視できます。クライアントは、パラメータ riid を REFIID IID_IAudioStreamVolume に設定して IAudioClient::GetService メソッドを呼び出すことにより、ストリーム オブジェクトの IAudioStreamVolume インターフェイスへの参照を取得します。

これがコードスニペットです。合成された正弦波をより大きな音量で数秒間再生し、その後、音量を更新して静かに再生し続けます。

#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;
}
于 2012-11-18T09:07:52.210 に答える