UID | tech.root | title | ms.date | targetos | description | prerelease | req.assembly | req.construct-type | req.ddi-compliance | req.header | req.idl | req.include-header | req.max-support | req.namespace | req.redist | req.target-min-winverclnt | req.target-min-winversvr | req.target-type | req.unicode-ansi | topic_type | api_type | api_location | api_name | f1_keywords | dev_langs | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
NN:audioclient.IAudioEffectsManager |
CoreAudio |
IAudioEffectsManager |
06/15/2021 |
Windows |
Provides management functionality for the audio effects pipeline |
false |
iface |
audioclient.h |
Windows Build 22000 |
|
|
|
|
|
|
Provides management functionality for the audio effects pipeline for the associated audio stream, allowing applications to get the current list of effects, set the state of effects, and to register for notifications when the list of effects or effect states change.
Get an instance of this interface by calling IAudioClient::GetService passing in the interface pointer of the IAudioEffectsManager interface.
wil::com_ptr_nothrow<IAudioEffectsManager> audioEffectsManager;
RETURN_IF_FAILED(client->GetService(IID_PPV_ARGS(&audioEffectsManager)));
The following example demonstrates the IAudioEffectsManager.GetAudioEffects to detect whether the AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION effect is present on the specified audio stream.
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;
}
The following example demonstrates using the IAudioEffectsManager.SetAudioEffectState to disable the AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION effect.
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;
}
The following example demonstrates using the IAudioEffectsManager.SetAudioEffectState to enable the AUDIO_EFFECT_TYPE_DEEP_NOISE_SUPPRESSION effect.
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;
}
The following code example demonstrates a class that implements IAudioEffectsChangedNotificationClient to receive notifications when the list of audio effects changes or the resources needed to enable an effect changes. In the OnAudioStreamEffectsChanged callback, the example calls GetAudioEffects to get the current list of effects.
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;
}