Win32 API 日本語リファレンス
ホームMedia.Audio › IAudioEffectsManager

IAudioEffectsManager

COM
IID4460b3ae-4b44-4527-8676-7548a8acd260継承元IUnknown自前メソッド開始 vtbl3

公式ドキュメント

オーディオエフェクトパイプラインの管理機能を提供します

解説(Remarks)

このインターフェイスのインスタンスは、IAudioEffectsManager インターフェイスのインターフェイスポインターを渡して IAudioClient::GetService を呼び出すことで取得します。

wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));

次の例は、IAudioEffectsManager.GetAudioEffects を使用して、指定したオーディオストリームに AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION エフェクトが存在するかどうかを検出する方法を示します。

HRESULT IsPlatformDeepNoiseSuppressionPresent(_In_ IAudioClient *client, _Out_ bool *isPresent)
{
    *isPresent = false;
    wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
    RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));
    wil::unique_cotaskmem_array_ptr<AUDIO_EFFECT> effects;
    UINT32 numEffects;
    RETURN_IF_FAILED(audioEffectsManager->GetAudioEffects(&effects, &numEffects));

    for (UINT32 i = 0; i < numEffects; i++)
    {
        // Check if noise suppression is part of the current effects
        if (effects[i].id == AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION)
        {
            *isPresent = true;
            return S_OK;
        }
    }

    return S_OK;
}

次の例は、IAudioEffectsManager.SetAudioEffectState を使用して AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION エフェクトを無効にする方法を示します。

HRESULT TryDisablePlatformDeepNoiseSuppression(_In_ IAudioClient *client)
{
    wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
    RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));
    wil::unique_cotaskmem_array_ptr<AudioEffect> effects;
    UINT32 numEffects;
    RETURN_IF_FAILED(audioEffectsManager->GetAudioEffects(&effects, &numEffects));

    for (UINT32 i = 0; i < numEffects; i++)
    {
        if (effects[i].id == AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION)
        {
            // Check if deep noise suppression can be set and if it is currently on
            if (effects[i].canSetState && effects[i].state == AUDIO_EFFECT_STATE_ON)
            {
                HRESULT hr = audioEffectsManager->SetAudioEffectState(effects[i].id, AUDIO_EFFECT_STATE_OFF);

                // If canSetState changed to false, or the effect was removed, SetAudioEffectState
                // can fail with one of the following error codes.
                if (hr != AUDCLNT_E_EFFECT_NOT_AVAILABLE && hr != AUDCLNT_E_EFFECT_STATE_READ_ONLY)
                {
                    return hr;
                }
            }

            return S_OK;
        }
    }

    return S_OK;
}

次の例は、IAudioEffectsManager.SetAudioEffectState を使用して AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION エフェクトを有効にする方法を示します。

HRESULT TryEnablePlatformDeepNoiseSuppression(_In_ IAudioClient *client)
{
    wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
    RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));
    wil::unique_cotaskmem_array_ptr<AUDIO_EFFECT> effects;
    UINT32 numEffects;
    RETURN_IF_FAILED(audioEffectsManager->GetAudioEffects(&effects, &numEffects));

    for (UINT32 i = 0; i < numEffects; i++)
    {
        if (effects[i].id == AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION)
        {
            // Check if deep noise suppression can be set and if it is currently off
            if (effects[i].canSetState && effects[i].state == AUDIO_EFFECT_STATE_OFF)
            {
                HRESULT hr = audioEffectsManager->SetAudioEffectState(effects[i].id, AUDIO_EFFECT_STATE_ON);

                // If canSetState changed to false, or the effect was removed, SetAudioEffectState
                // can fail with one of the following error codes.
                if (hr != AUDCLNT_E_EFFECT_NOT_AVAILABLE && hr != AUDCLNT_E_EFFECT_STATE_READ_ONLY)
                {
                    return hr;
                }
            }

            return S_OK;
        }
        }

        return S_OK;
}

次のコード例は、オーディオエフェクトの一覧が変化したとき、またはエフェクトを有効にするために必要なリソースが変化したときに通知を受け取るために IAudioEffectsChangedNotificationClient を実装するクラスを示します。OnAudioStreamEffectsChanged コールバックでは、この例は GetAudioEffects を呼び出して現在のエフェクトの一覧を取得します。

class AudioEffectsChangedHandler :
    public winrt::implements<AudioEffectsChangedHandler, IAudioEffectsChangedNotificationClient>
{

    public:
    AudioEffectsChangedHandler(_In_ IAudioClient *client) : m_client(client){}
    STDMETHOD(OnAudioEffectsChanged)()
    {
        OnAudioStreamEffectsChanged(m_client.get());
        return S_OK;
    }
    private:
    wil::com_ptr_nothrow<IAudioClient> m_client;

};

wil::com_ptr_nothrow<IAudioEffectsChangedNotificationClient> g_effectsChangedHandler;

HRESULT RegisterAudioStreamEffectsChangedEvent(_In_ IAudioClient *client)
{
    if (!g_effectsChangedHandler)
    {
        wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
        RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));

        // Register for the audio effects changed notification
        g_effectsChangedHandler = winrt::make<AudioEffectsChangedHandler>(client).get();
        RETURN_IF_NULL_ALLOC(g_effectsChangedHandler);

        return audioEffectsManager->RegisterAudioEffectsChangedNotificationCallback(
            g_effectsChangedHandler.get());
    }
    return S_OK;
}

HRESULT UnregisterAudioStreamEffectsChangedEvent(_In_ IAudioClient *client)
{
    if (g_effectsChangedHandler != nullptr)
    {
        wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
        RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));

        // Unregister from the audio effects changed notification 
        return audioEffectsManager->UnregisterAudioEffectsChangedNotificationCallback(
            g_effectsChangedHandler.get());
        }

        return S_OK;
}

HRESULT OnAudioStreamEffectsChanged(_In_ IAudioClient *client)
{
    // Re-query the list of effects since there was some change
    wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
    RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));
    wil::unique_cotaskmem_array_ptr<AUDIO_EFFECT> effects;
    UINT32 numEffects;
    RETURN_IF_FAILED(audioEffectsManager->GetAudioEffects(&effects, &numEffects));

    for (UINT32 i = 0; i < numEffects; i++)
    {

        // Here the app can check which effects are still enabled, and check if there are new
        // effects that now can be enabled.
        // As an example, the following code enables any effect that can be enabled, if it is not
        // already enabled.
        if (effects[i].canSetState && effects[i].state == AUDIO_EFFECT_STATE_OFF)
        {
            HRESULT hr = audioEffectsManager->SetAudioEffectState(effects[i].id, AUDIO_EFFECT_STATE_ON));
            if (hr == AUDCLNT_E_EFFECT_NOT_AVAILABLE || hr == AUDCLNT_E_EFFECT_STATE_READ_ONLY)
            {
                hr = S_OK;
            }
            RETURN_IF_FAILED(hr);

        }
    }

    return S_OK;
}

メソッド 4

vtbl = vtable インデックス(0始まり)。HSP等からCOMメソッドをインデックス指定で呼ぶ際に使用します。0〜2 は IUnknown。

vtbl 3 HRESULT RegisterAudioEffectsChangedNotificationCallback(IAudioEffectsChangedNotificationClient* client)

AudioEffectsChangedNotificationClient インターフェイスを登録します。

clientIAudioEffectsChangedNotificationClient*in登録する IAudioEffectsChangedNotificationClient インターフェイス。

戻り値

説明
S_OK 成功
AUDCLNT_E_DEVICE_INVALIDATED 関連付けられたオーディオストリームが破棄されました。

解説(Remarks)

コールバックインターフェイスの登録を解除するには、UnregisterAudioEffectsChangedNotificationCallback を呼び出します。

次のコード例は、オーディオエフェクトの一覧が変化したとき、またはエフェクトを有効にするために必要なリソースが変化したときに通知を受け取るために IAudioEffectsChangedNotificationClient を実装するクラスを示します。OnAudioStreamEffectsChanged コールバックでは、この例は GetAudioEffects を呼び出して現在のエフェクトの一覧を取得します。

class AudioEffectsChangedHandler :
    public winrt::implements<AudioEffectsChangedHandler, IAudioEffectsChangedNotificationClient>
{

    public:
    AudioEffectsChangedHandler(_In_ IAudioClient *client) : m_client(client){}
    STDMETHOD(OnAudioEffectsChanged)()
    {
        OnAudioStreamEffectsChanged(m_client.get());
        return S_OK;
    }
    private:
    wil::com_ptr_nothrow<IAudioClient> m_client;

};

wil::com_ptr_nothrow<IAudioEffectsChangedNotificationClient> g_effectsChangedHandler;

HRESULT RegisterAudioStreamEffectsChangedEvent(_In_ IAudioClient *client)
{
    if (!g_effectsChangedHandler)
    {
        wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
        RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));

        // Register for the audio effects changed notification
        g_effectsChangedHandler = winrt::make<AudioEffectsChangedHandler>(client).get();
        RETURN_IF_NULL_ALLOC(g_effectsChangedHandler);

        return audioEffectsManager->RegisterAudioEffectsChangedNotificationCallback(
            g_effectsChangedHandler.get());
    }
    return S_OK;
}

HRESULT UnregisterAudioStreamEffectsChangedEvent(_In_ IAudioClient *client)
{
    if (g_effectsChangedHandler != nullptr)
    {
        wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
        RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));

        // Unregister from the audio effects changed notification 
        return audioEffectsManager->UnregisterAudioEffectsChangedNotificationCallback(
            g_effectsChangedHandler.get());
        }

        return S_OK;
}

HRESULT OnAudioStreamEffectsChanged(_In_ IAudioClient *client)
{
    // Re-query the list of effects since there was some change
    wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
    RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));
    wil::unique_cotaskmem_array_ptr<AUDIO_EFFECT> effects;
    UINT32 numEffects;
    RETURN_IF_FAILED(audioEffectsManager->GetAudioEffects(&effects, &numEffects));

    for (UINT32 i = 0; i < numEffects; i++)
    {

        // Here the app can check which effects are still enabled, and check if there are new
        // effects that now can be enabled.
        // As an example, the following code enables any effect that can be enabled, if it is not
        // already enabled.
        if (effects[i].canSetState && effects[i].state == AUDIO_EFFECT_STATE_OFF)
        {
            HRESULT hr = audioEffectsManager->SetAudioEffectState(effects[i].id, AUDIO_EFFECT_STATE_ON));
            if (hr == AUDCLNT_E_EFFECT_NOT_AVAILABLE || hr == AUDCLNT_E_EFFECT_STATE_READ_ONLY)
            {
                hr = S_OK;
            }
            RETURN_IF_FAILED(hr);

        }
    }

    return S_OK;
}
vtbl 4 HRESULT UnregisterAudioEffectsChangedNotificationCallback(IAudioEffectsChangedNotificationClient* client)

IAudioEffectsChangedNotificationClient インターフェイスの登録を解除します。

clientIAudioEffectsChangedNotificationClient*in登録を解除する IAudioEffectsChangedNotificationClient インターフェイス。

戻り値

説明
S_OK 成功
AUDCLNT_E_DEVICE_INVALIDATED 関連付けられたオーディオストリームが破棄されました。

解説(Remarks)

コールバックインターフェイスを登録するには、RegisterAudioEffectsChangedNotificationCallback を呼び出します。

vtbl 5 HRESULT GetAudioEffects(AUDIO_EFFECT** effects, DWORD* numEffects)

関連付けられたオーディオストリームの現在のオーディオエフェクトの一覧を取得します。

effectsAUDIO_EFFECT**out現在のオーディオエフェクトの一覧を表す AUDIO_EFFECT 構造体の配列へのポインターを受け取ります。
numEffectsDWORD*inouteffects で返される AUDIO_EFFECT 構造体の数を受け取ります。

戻り値

以下を含む(ただしこれらに限定されない)HRESULT を返します。

説明
S_OK 成功
AUDCLNT_E_DEVICE_INVALIDATED 関連付けられたオーディオストリームが破棄されました。

解説(Remarks)

配列の解放は呼び出し元が CoTaskMemFree を使用して行う責任があります。

オーディオエフェクトの一覧が変化したときに通知を受け取るには、IAudioEffectsChangedNotificationClient を登録します。

次の例は、IAudioEffectsManager.GetAudioEffects を使用して、指定したオーディオストリームに AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION エフェクトが存在するかどうかを検出する方法を示します。

HRESULT IsPlatformDeepNoiseSuppressionPresent(_In_ IAudioClient *client, _Out_ bool *isPresent)
{
    *isPresent = false;
    wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
    RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));
    wil::unique_cotaskmem_array_ptr<AUDIO_EFFECT> effects;
    UINT32 numEffects;
    RETURN_IF_FAILED(audioEffectsManager->GetAudioEffects(&effects, &numEffects));

    for (UINT32 i = 0; i < numEffects; i++)
    {
        // Check if noise suppression is part of the current effects
        if (effects[i].id == AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION)
        {
            *isPresent = true;
            return S_OK;
        }
    }

    return S_OK;
}
vtbl 6 HRESULT SetAudioEffectState(GUID effectId, AUDIO_EFFECT_STATE state)

IAudioEffectsManager::SetAudioEffectState メソッド (audioclient.h) は、指定したオーディオエフェクトの状態を設定します。

effectIdGUIDin状態を変更するエフェクトの GUID 識別子。オーディオエフェクトの GUID は ksmedia.h で定義されています。
stateAUDIO_EFFECT_STATEin設定する状態を指定する AUDIO_EFFECT_STATE 列挙型の値。

戻り値

以下を含む(ただしこれらに限定されない)HRESULT を返します。

説明
S_OK 成功
AUDCLNT_E_EFFECT_NOT_AVAILABLE 指定したエフェクトは利用できません
AUDCLNT_E_EFFECT_STATE_READ_ONLY 指定したエフェクトの状態は読み取り専用です
AUDCLNT_E_DEVICE_INVALIDATED 関連付けられたオーディオストリームが破棄されました。

解説(Remarks)

関連付けられたオーディオストリームの現在のオーディオエフェクトの一覧を取得するには、GetAudioEffects を呼び出します。

次の例は、IAudioEffectsManager.SetAudioEffectState を使用して AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION エフェクトを無効にする方法を示します。

HRESULT TryDisablePlatformDeepNoiseSuppression(_In_ IAudioClient *client)
{
    wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
    RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));
    wil::unique_cotaskmem_array_ptr<AudioEffect> effects;
    UINT32 numEffects;
    RETURN_IF_FAILED(audioEffectsManager->GetAudioEffects(&effects, &numEffects));

    for (UINT32 i = 0; i < numEffects; i++)
    {
        if (effects[i].id == AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION)
        {
            // Check if deep noise suppression can be set and if it is currently on
            if (effects[i].canSetState && effects[i].state == AUDIO_EFFECT_STATE_ON)
            {
                HRESULT hr = audioEffectsManager->SetAudioEffectState(effects[i].id, AUDIO_EFFECT_STATE_OFF);

                // If canSetState changed to false, or the effect was removed, SetAudioEffectState
                // can fail with one of the following error codes.
                if (hr != AUDCLNT_E_EFFECT_NOT_AVAILABLE && hr != AUDCLNT_E_EFFECT_STATE_READ_ONLY)
                {
                    return hr;
                }
            }

            return S_OK;
        }
    }

    return S_OK;
}

次の例は、IAudioEffectsManager.SetAudioEffectState を使用して AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION エフェクトを有効にする方法を示します。

HRESULT TryEnablePlatformDeepNoiseSuppression(_In_ IAudioClient *client)
{
    wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
    RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));
    wil::unique_cotaskmem_array_ptr<AUDIO_EFFECT> effects;
    UINT32 numEffects;
    RETURN_IF_FAILED(audioEffectsManager->GetAudioEffects(&effects, &numEffects));

    for (UINT32 i = 0; i < numEffects; i++)
    {
        if (effects[i].id == AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION)
        {
            // Check if deep noise suppression can be set and if it is currently off
            if (effects[i].canSetState && effects[i].state == AUDIO_EFFECT_STATE_OFF)
            {
                HRESULT hr = audioEffectsManager->SetAudioEffectState(effects[i].id, AUDIO_EFFECT_STATE_ON);

                // If canSetState changed to false, or the effect was removed, SetAudioEffectState
                // can fail with one of the following error codes.
                if (hr != AUDCLNT_E_EFFECT_NOT_AVAILABLE && hr != AUDCLNT_E_EFFECT_STATE_READ_ONLY)
                {
                    return hr;
                }
            }

            return S_OK;
        }
        }

        return S_OK;
}
出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

HSP用 COM定義

#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"

出力引数:
#define global IID_IAudioEffectsManager "{4460B3AE-4B44-4527-8676-7548A8ACD260}"
#usecom global IAudioEffectsManager IID_IAudioEffectsManager "{}"
#comfunc global IAudioEffectsManager_RegisterAudioEffectsChangedNotificationCallback    3 sptr
#comfunc global IAudioEffectsManager_UnregisterAudioEffectsChangedNotificationCallback  4 sptr
#comfunc global IAudioEffectsManager_GetAudioEffects                                    5 var,var
#comfunc global IAudioEffectsManager_SetAudioEffectState                                6 int,int
; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。
; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。
; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。
; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。