音频采集-windows采集-----02-----wasapi主要函数介绍

一 com接口初始化

wasapi是windows com组件的接口,所以需要进行com组件的初始化。

/**
 * @brief 使用com组件的函数前的初始化函数.
 * @param pvReserved 保留位,传NULL即可。
 * @param dwCoInit 标志位。
*/
_Check_return_
WINOLEAPI
CoInitializeEx(
    _In_opt_ LPVOID pvReserved,
    _In_ DWORD dwCoInit
    );

/**
 * @brief com组件的反初始化函数.
*/
WINOLEAPI_(void)
CoUninitialize(
    void
    );

调用例子:

// 为当前线程初始化COM库并设置并发模式 
hr_retrun = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (FAILED(hr_retrun))
{
  printf("无法在线程中初始化 COM:: %x\n", hr_retrun);
  return hr_retrun;
}

/* 中间处理逻辑... */

// 反初始化
CoUninitialize();

二 MMDevice API

音频client利用MMDevice API来发现audio endpoint devices, 为devices创建驱动实例等。
头文件:

#include <MMDeviceAPI.h>

2.1 创建 IMMDeviceEnumerator interface

// 枚举你的音频设备,你可以在这个时候获取到你机器上所有可用的设备,并指定你需要用到的那个设置
//用指定的类标识符创建一个Com对象,用指定的类标识符创建一个未初始化的对象
//参数1:创建的Com对象的类标识符(CLSID)
//参数2:指向接口IUnknown的指针
//参数3:运行可执行代码的上下文
//参数4:创建的Com对象的接口标识符
//参数5:用来接收指向Com对象接口地址的指针变量
_Check_return_
WINOLEAPI
CoCreateInstance(
    _In_ REFCLSID rclsid,
    _In_opt_ LPUNKNOWN pUnkOuter,
    _In_ DWORD dwClsContext,
    _In_ REFIID riid,
    _COM_Outptr_ _At_(*ppv, _Post_readable_size_(_Inexpressible_(varies))) LPVOID  FAR * ppv
    );

2.2 获取默认音频设备GetDefaultAudioEndpoint

/**
 * @brief 获取默认音频采集设备.
 * @param dataFlow 指定采集的音频设备,例如eRender-采集声卡,eCapture-麦克风。
 * @param role 角色,eConsole-控制台,eMultimedia-多媒体,eCommunications-通讯。
 * @param ppEndpoint 传入传出参数,得到的音频采集设备。
*/
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetDefaultAudioEndpoint( 
    /* [annotation][in] */ 
    _In_  EDataFlow dataFlow,
    /* [annotation][in] */ 
    _In_  ERole role,
    /* [annotation][out] */ 
    _Out_  IMMDevice **ppEndpoint) = 0;

例如调用例子:

// 采集麦克风
hr_retrun = pEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole, &pDevice);

// 采集声卡
hr_retrun = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice); 

三 WASAPI

头文件:

#include <AudioClient.h>

3.1 IMMDevice::Activate

IMMDevice::Activate来获取an audio endpoint device的IAudioClient interface引用。

/**
 * @brief 获取IAudioClient interface引用.
 * @param iid 接口id。
 * @param dwClsCtx 类上下文标志(Class Context Flags),指定对象的创建上下文。
 * @param pActivationParams 指向 PROPVARIANT 结构的指针,用于传递附加的激活参数,一般传空。
 * @param ppInterface 传入传出参数,用于接收请求的接口指针。
*/
virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Activate( 
    /* [annotation][in] */ 
    _In_  REFIID iid,
    /* [annotation][in] */ 
    _In_  DWORD dwClsCtx,
    /* [annotation][unique][in] */ 
    _In_opt_  PROPVARIANT *pActivationParams,
    /* [annotation][iid_is][out] */ 
    _Out_  void **ppInterface)

Windows Vista,以音频采集为例,连接到endpoint device就两步:
● 1. 从设备集合中选择一个麦克风。
● 2. 用Activate激活该麦克风的音频采集接口。

  // 1. 从设备集合中选择一个麦克风(或者采集卡)。
  IMMDevice* pDevice = NULL;
#ifdef DEF_CAPTURE_MIC
	hr_retrun = pEnumerator->GetDefaultAudioEndpoint(eCapture, eConsole, &pDevice);// 采集麦克风
#else 
	hr_retrun = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);   // 采集声卡
#endif	

	// 2. 用Activate激活该麦克风的音频采集接口。
	IAudioClient* pAudioClient = NULL;
	hr_retrun = pDevice->Activate(IID_IAudioClient, CLSCTX_ALL, NULL, (void**)&pAudioClient);

3.2 IAudioClient::Initialize

IAudioClient::Initialize用来在endpoint device初始化流。

/**
 * @brief 初始化音频流.
*/
virtual HRESULT STDMETHODCALLTYPE Initialize( 
            /* [annotation][in] */ 
            _In_  AUDCLNT_SHAREMODE ShareMode,
            /* [annotation][in] */ 
            _In_  DWORD StreamFlags,
            /* [annotation][in] */ 
            _In_  REFERENCE_TIME hnsBufferDuration,
            /* [annotation][in] */ 
            _In_  REFERENCE_TIME hnsPeriodicity,
            /* [annotation][in] */ 
            _In_  const WAVEFORMATEX *pFormat,
            /* [annotation][in] */ 
            _In_opt_  LPCGUID AudioSessionGuid)

其中具体参数说明:

  1. ShareMode(AUDCLNT_SHAREMODE):
    ○ 指定音频流的共享模式,可以是以下值之一:
    ■ AUDCLNT_SHAREMODE_SHARED:共享模式,允许多个应用程序共享音频设备。
    ■ AUDCLNT_SHAREMODE_EXCLUSIVE:独占模式,应用程序独占音频设备。

  2. StreamFlags(DWORD):
    ○ 指定音频流的选项,可以是以下一个或多个标志的组合:
    ■ AUDCLNT_STREAMFLAGS_CROSSPROCESS:允许跨进程音频。
    ■ AUDCLNT_STREAMFLAGS_LOOPBACK:启用环回模式,仅适用于共享模式。
    ■ AUDCLNT_STREAMFLAGS_EVENTCALLBACK:使用事件通知。
    ■ AUDCLNT_STREAMFLAGS_NOPERSIST:不会将音频会话状态保存到注册表。
    ■ 其他标志用于特定用途,如音频效果处理等。

  3. hnsBufferDuration(REFERENCE_TIME):
    ○ 指定缓冲区的持续时间,以百纳秒为单位(100纳秒为1个单位)。
    ○ 示例:500毫秒的缓冲区大小等于 500 * 10,000 百纳秒。

  4. hnsPeriodicity(REFERENCE_TIME):
    ○ 指定周期性处理音频数据的时间间隔,以百纳秒为单位。
    ○ 如果为0,则系统决定最佳值。
    ○ 对于独占模式,必须指定非零值。

  5. pFormat(const WAVEFORMATEX*):
    ○ 指向 WAVEFORMATEX 或 WAVEFORMATEXTENSIBLE 结构的指针,指定音频流的格式。
    ○ 需要包括通道数、采样率、位深等信息。

  6. AudioSessionGuid(LPCGUID):
    ○ 指向 GUID 的指针,标识音频会话。
    ○ 可以为 nullptr,表示创建新的音频会话。

调用例子:

	WAVEFORMATEX* pwfx = NULL;
	hr_retrun = pAudioClient->GetMixFormat(&pwfx);

#ifdef DEF_CAPTURE_MIC
	hr_retrun = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED,
		AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
		hnsRequestedDuration, 0, pwfx, NULL);
#else
	hr_retrun = pAudioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 
    AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_LOOPBACK,
		hnsRequestedDuration, 0, pwfx, NULL);
#endif

3.3 IAudioClient::GetService

初始化流之后,可调用IAudioClient::GetService来获取其它 WASAPI interfaces的引用。
例如Initialize成功后,可以用IAudioClient::GetService可获取该rending设备的IAudioCaptureClient接口。

/**
 * @brief 获取其它 WASAPI interfaces的引用.
 * @param riid 接口id。
 * @param ppv 传出的接口引用。
*/
virtual HRESULT STDMETHODCALLTYPE GetService( 
            /* [annotation][in] */ 
            _In_  REFIID riid,
            /* [annotation][iid_is][out] */ 
            _Out_  void **ppv)

例如:

IAudioCaptureClient* pCaptureClient = NULL;
hr_retrun = pAudioClient->GetService(IID_IAudioCaptureClient, (void**)&pCaptureClient);

3.4 IAudioClient::Start

virtual HRESULT STDMETHODCALLTYPE Start( void)

Start是一个控制方法,客户端调用它来启动音频流。
启动流将导致IAudioClient对象开始在端点缓冲区和音频引擎之间传输数据。
它还使流的音频时钟从当前位置恢复计数。

3.5 IAudioCaptureClient::GetNextPacketSize

/**
 * @brief 获取下一个包的帧数.
 * @param pNumFramesInNextPacket 传出,下一个包的帧数。
*/
virtual HRESULT STDMETHODCALLTYPE GetNextPacketSize( 
            /* [annotation][out] */ 
            _Out_  UINT32 *pNumFramesInNextPacket)

官方介绍GetNextPacketSize的作用:

The GetNextPacketSize method retrieves the number of frames in the next data 
packet in the capture endpoint buffer.

这里有两个注意的。
(1) 单位为audio frame。
(2) 注意是采集buffer(capture endpoint buffer)。

Use this method only with shared-mode streams. It does not work 
with exclusive-mode streams.

(3) 仅在共享模式下生效,独占模式下无效。

Before calling the IAudioCaptureClient::GetBuffer method to retrieve the next 
data packet,the client can call GetNextPacketSize to retrieve the number of 
audio frames in the next packet.

The count reported by GetNextPacketSize matches the count retrieved in the 
GetBuffer call (through the pNumFramesToRead output parameter) that follows
the GetNextPacketSize call.

(4) 在调用GetBuffer之前,可调用GetNextPacketSize来获取下一个数据包的音频帧个数。

A packet always consists of an integral number of audio frames.

GetNextPacketSize must be called in the same thread as the GetBuffer 
and IAudioCaptureClient::ReleaseBuffer method calls that get and release
the packets in the capture endpoint buffer.

(5) GetNextPacketSize必须和GetBuffer及IAudioCaptureClient::ReleaseBuffer在同一线程中调用。

3.6 IAudioCaptureClient::GetBuffer

/**
 * @brief 获取其它 WASAPI interfaces的引用.
 * @param ppData 可读的下个数据包的起始地址。
 * @param pNumFramesToRead 下个数据包的长度(单位为audio frames)。客户端或者全部读取或者一个也不读。
 * @param pdwFlags 标志位。有以下值:
 * 	AUDCLNT_BUFFERFLAGS_DATA_DISCONTINUITY:表示音频数据不连续(例如,丢失了音频样本)。
 * 	AUDCLNT_BUFFERFLAGS_SILENT:表示缓冲区包含静音数据。
 * 	AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR:表示时间戳错误。
 *
 * @param pu64DevicePosition 输出参数,可选,用于接收音频设备的
 * 			位置(音频设备的位置是设备时钟中的样本位置)。
 * @param pu64QPCPosition 输出参数,可选,用于接收性能计数器
        位置(QPC, Query Performance Counter)。可以作为pts,例如obs就可以选择它作为pts。
 * 		
*/
virtual HRESULT STDMETHODCALLTYPE GetBuffer( 
            /* [annotation][out] */ 
            _Outptr_result_buffer_(_Inexpressible_("*pNumFramesToRead * pFormat->nBlockAlign"))  BYTE **ppData,
            /* [annotation][out] */ 
            _Out_  UINT32 *pNumFramesToRead,
            /* [annotation][out] */ 
            _Out_  DWORD *pdwFlags,
            /* [annotation][unique][out] */ 
            _Out_opt_  UINT64 *pu64DevicePosition,
            /* [annotation][unique][out] */ 
            _Out_opt_  UINT64 *pu64QPCPosition) 

GetBuffer作用:

Retrieves a pointer to the next available packet of data in the capture endpoint buffer.

翻译:
检索指向捕获端点缓冲区中下一个可用数据包的指针。

3.7 IAudioCaptureClient::ReleaseBuffer

/**
 * @brief 释放GetBuffer获取的内容.
 * @param pNumFramesToRead 对应GetBuffer的参数2的值。
*/
virtual HRESULT STDMETHODCALLTYPE ReleaseBuffer( 
            /* [annotation][in] */ 
            _In_  UINT32 NumFramesRead)

微软文档参考:
https://learn.microsoft.com/zh-cn/windows/win32/coreaudio/wasapi?redirectedfrom=MSDN

音视频流媒体资料领取和开发合作,加qq:1282840736

  • 17
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值