流式处理音频呈现器
(SAR) 流式音频呈现器是用于呈现音频的媒体接收器。 SAR 的每个实例都呈现一个音频流。 若要呈现多个流,请使用 SAR 的多个实例。
若要创建 SAR,请调用以下函数之一:
- MFCreateAudioRenderer。 返回指向 SAR 的指针。
- MFCreateAudioRendererActivate。 返回指向激活对象的指针,该对象可用于创建 SAR。
如果要播放受保护的内容,则需要返回激活对象的第二个函数,因为激活对象必须序列化到受保护的进程。 对于清晰的内容,可以使用任一函数。
SAR 可以接收 PCM 或 IEEE 浮点格式的未压缩音频。 如果播放速率快于 1×,SAR 会自动调整音调。
配置音频呈现器
SAR 支持多个配置属性。 设置这些属性的机制取决于调用哪个函数来创建 SAR。 如果使用 MFCreateAudioRenderer 函数,请执行以下操作:
- 通过调用 MFCreateAttributes 创建新的属性存储。
- 将属性添加到属性存储。
- 将属性存储传递到 pAudioAttributes 参数中的 MFCreateAudioRenderer 函数。
如果使用 MFCreateAudioRendererActivate 函数,该函数将返回指向 ppActivate 参数中的 IMFAttributes 接口的指针。 使用此指针添加属性。
有关配置属性的列表,请参阅 音频呈现器属性。
选择音频终结点设备
音频终结点设备是呈现或捕获音频的硬件设备。 示例包括扬声器、耳机、麦克风和 CD 播放器。 SAR 始终使用音频呈现设备。 可通过两种方式选择设备。
第一种方法是使用 IMMDeviceEnumerator 接口枚举系统上的音频呈现设备。 此接口记录在核心音频 API 文档中。
- 创建设备枚举器对象。
- 使用设备枚举器枚举音频呈现设备。 每个设备都由指向 IMMDevice 接口的指针表示。
- 根据设备属性或用户选择选择设备。
- 调用 IMMDevice::GetId 获取设备标识符。
- 将设备标识符设置为 MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID 属性的值。
可以按音频设备 的角色指定音频设备,而不是枚举设备。 音频角色标识一般使用类别。 例如, 主机 角色是为游戏和系统通知定义的,而 多媒体 角色是为音乐和电影定义的。 每个角色分配有一个音频呈现设备,用户可以更改这些分配。 如果指定设备角色,SAR 将使用为该角色分配的任何音频设备。 若要指定设备角色,请设置 MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE 属性。
本节中列出的两个属性互斥。 如果未设置其中任一项,SAR 将使用分配给 eConsole 角色的音频设备。
以下代码枚举音频呈现设备,并将列表中的第一个设备分配给 SAR。 此示例使用 MFCreateAudioRenderer 函数创建 SAR。
#include <mmdeviceapi.h>
HRESULT hr = S_OK;
IMMDeviceEnumerator *pEnum = NULL; // Audio device enumerator.
IMMDeviceCollection *pDevices = NULL; // Audio device collection.
IMMDevice *pDevice = NULL; // An audio device.
IMFAttributes *pAttributes = NULL; // Attribute store.
IMFMediaSink *pSink = NULL; // Streaming audio renderer (SAR)
LPWSTR wstrID = NULL; // Device ID.
// Create the device enumerator.
hr = CoCreateInstance(
__uuidof(MMDeviceEnumerator),
NULL,
CLSCTX_ALL,
__uuidof(IMMDeviceEnumerator),
(void**)&pEnum
);
// Enumerate the rendering devices.
if (SUCCEEDED(hr))
{
hr = pEnum->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &pDevices);
}
// Get ID of the first device in the list.
if (SUCCEEDED(hr))
{
hr = pDevices->Item(0, &pDevice);
}
if (SUCCEEDED(hr))
{
hr = pDevice->GetId(&wstrID);
}
// Create an attribute store and set the device ID attribute.
if (SUCCEEDED(hr))
{
hr = MFCreateAttributes(&pAttributes, 2);
}
if (SUCCEEDED(hr))
{
hr = pAttributes->SetString(
MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID,
wstrID
);
}
// Create the audio renderer.
if (SUCCEEDED(hr))
{
hr = MFCreateAudioRenderer(pAttributes, &pSink);
}
SAFE_RELEASE(pEnum);
SAFE_RELEASE(pDevices);
SAFE_RELEASE(pDevice);
SAFE_RELEASE(pAttributes);
CoTaskMemFree(wstrID);
若要为 SAR 创建激活对象,请将调用 IMMDevice::GetId 后显示的代码更改为以下内容:
IMFActivate *pActivate = NULL; // Activation object.
if (SUCCEEDED(hr))
{
hr = MFCreateAudioRendererActivate(&pActivate);
}
if (SUCCEEDED(hr))
{
hr = pActivate->SetString(
MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID,
wstrID
);
}
SAFE_RELEASE(pActivate);
选择音频会话
音频会话是应用程序可以共同管理的一组相关音频流。 应用程序可以控制每个会话的音量级别和静音状态。 会话由 GUID 标识。 若要指定 SAR 的音频会话,请使用 MF_AUDIO_RENDERER_ATTRIBUTE_SESSION_ID 属性。 如果未设置此属性,则 SAR 会加入该进程的默认会话(由 GUID_NULL 标识)。
默认情况下,音频会话特定于进程,这意味着它仅包含来自调用进程的流。 若要加入跨进程会话,请使用值 MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS_CROSSPROCESS 设置 MF_AUDIO_RENDERER_ATTRIBUTE_FLAGS 属性。
创建 SAR 后,使用 IMFAudioPolicy 接口将会话加入到一组会话,所有这些会话都由控制面板中的同一个音量控件控制。 还可以使用此接口来设置显示在音量控件中的显示名称和图标。
控制卷级别
若要控制 SAR 音频会话中所有流的主音量级别,请使用 IMFSimpleAudioVolume 接口。 若要控制单个流的音量,或控制流中单个通道的音量,请使用 IMFAudioStreamVolume 接口。 这两个接口都是通过调用 IMFGetService::GetService 获取的。 可以直接在 SAR 上调用 GetService ,也可以在媒体会话上调用它。 音量级别表示为衰减值。 对于每个通道,衰减级别是主音量和通道音量的乘积。
相关主题