Windows音频API

一、Windows 音频体系结构

Windows的音频应用程序大部分通过微软提供的上层api完成音频处理和数据流抓取。基于api封装的媒体库或应用包括Media Foundation,MME(waveIn/waveOut),Directsound等。Wasapi:Windows audio session API

最高级别 Api

最高级别 Api 用于应用程序开发。 这些 Api 中当前正在使用和支持。

XAML MediaElement 类(C#,VB, C++)

HTML音频对象视频对象<标记>(由网站和 Windows Web 应用)

Windows.Media.Capture 命名空间(C#,VB, C++)

Microsoft 媒体基础(C++)

这些较旧的 Api 已弃用。

DirectShow

DirectSound

PlaySound

Windows.Media.MediaControlContract

低级别 Api

对于音频流,建议这些低级别 Api。

Wasapi 就可以了(高性能,但更复杂)

IXAudio2 (通常用于游戏)

MIDI

二、音频API和音频采集和设备之间的调用关系

Audio Engine:

混合并处理音频流

加载音频处理对象,它们是处理音频信号的特定于硬件的插件

   Audio Service:

 安装或控制音频流

 实施winows策略,完成背景音频播放处理等

   (audio)EndPoint device:

 (音频)输入输出设备:speaker,microphone等

   Shared Mode & Exclusive Mode

 共享模式和排它模式,前者共享设备,后者独享设备

   Core Audio API:

 一系列音频相关的API组合,可以相互组合完成音频控制,音频流捕获和音频控制等操作

2. 常用api介绍

2.1 IAudioClient

客户端设备句柄,通过 IMMDevice Activate获取。

IMMDevice 通过IMMDeviceEnumerator枚举或者直接获取当前默认的输入输出设备。相关对象和api:IMMDeviceEnumerator EnumAudioEndpoints、GetDefaultAudioEndpoint

其中GetDefaultAudioEndpoint的第一个参数eRender 设置为输出设备speaker,eCapture为输入设备microphone。

例如:

immDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL,

 reinterpret_cast<void**>(&audioClient)

2.2 IAudioCaptureClient

对应audioClient的capture服务。启动服务前,需要初始化audioClient.

audioClient->GetService(__uuidof(IAudioCaptureClient),

 reinterpret_cast<void**>(outCaputureClient));

2.3 IAudioSessionControl

一组相关的音频流,获取当前会话,可以单独控制当前会话的音量等属性。

IAudioClient :: Initialize 初始化时会将音频流分配不同的会话。

相关接口:IAudioSessionManager::GetAudioSessionControl

2.4 IAudioSessionManager

通过该接口,可以获取音频session控制和volume控制

2.5 IAudioStreamVolume

通过该接口可以控制音频流各个通道的音量

相关接口:IAudioClient::GetService

3. 音频采集

通过扩展屏中的音频抓取通过audioClient和audioCaptureClient在共享模式下抓取默认speaker音频数据。

3.1

IMMDeviceEnumerator* deviceEnum

::CoCreateInstance(CLSID_MMDEVICE_ENUMERATOR, nullptr, CLSCTX_ALL,

IID_MMDEVICE_ENUMERATOR, reinterpret_cast<void**>(&deviceEnum))

3.2

IMMDevice* device

deviceEnum->GetDefaultAudioEndpoint(eRender, eConsole, &device)

3.3

IAudioClient* audioClient

device->Activate(IID_IAUDIO_CLIENT, CLSCTX_ALL, NULL,

 reinterpret_cast<void**>(&audioClient))

3.4

WAVEFORMATEX* wavFmtX

IAudioCaptureClient** outCaputureClient

audioClient->GetMixFormat(&wavFmtX);

audioClient->Initialize(

 AUDCLNT_SHAREMODE_SHARED,

 AUDCLNT_STREAMFLAGS_LOOPBACK,

 hnsBufferDuration,

 0,

wavFmtX,

 nullptr);

audioClient->GetService(IID_IAUDIO_CAPTURE_CLIENT,

 reinterpret_cast<void**>(outCaputureClient));

3.5

audioClient->Start()

3.6

循环获取数据

audioCaptureClient->GetBuffer(&audioData, &framesReadNum, &flag, &devPos, &pcPos)

3.7

audioClient->Stop();

audioCaptureClient->Release();

audioClient->Release();

三、代码示例

采集示例:https://docs.microsoft.com/zh-cn/windows/win32/coreaudio/capturing-a-stream
CoInitialize(NULL);
pFile = fopen("D://00.work//record.pcm", "wb");
fwrite(pData, numFramesAvailable*pwfx->nBlockAlign,1,  pPcmFile);

播放示例:https://docs.microsoft.com/zh-cn/windows/win32/coreaudio/rendering-a-stream
CoInitialize(NULL);
fp = fopen("D://00.work//record.pcm", "rb");
fread(pData, numFramesAvailable*pwfx->nBlockAlign,1, fp);

示例详解:https://www.jianshu.com/p/968f684ecd83

关键数据结构:WAVEFORMATEX 
//设置属性-1
//pwfx->wFormatTag = WAVE_FORMAT_PCM;
//pwfx->wBitsPerSample = 16;//FOSSID
//pwfx->cbSize = 0; //该字段一般为0,否则标识的是扩展格式的信息 WAVEFORMATEXTENSIBLE
//pwfx->nBlockAlign = pwfx->nChannels * pwfx->wBitsPerSample / 8;//FOSSID
//pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;//FOSSID
//设置属性-1 end

////设置属性-2
//tmpWfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
//tmpWfx.Samples.wValidBitsPerSample = 32;
//tmpWfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
//tmpWfx.Format.wBitsPerSample = 32;
//tmpWfx.Format.cbSize = 22;
//tmpWfx.Format.nChannels = 2;
//tmpWfx.Format.nSamplesPerSec = 48000;
//tmpWfx.Format.nBlockAlign = tmpWfx.Format.nChannels * tmpWfx.Format.wBitsPerSample / 8;
//tmpWfx.Format.nAvgBytesPerSec = tmpWfx.Format.nSamplesPerSec * tmpWfx.Format.nBlockAlign;
////设置属性-2-end

WAVEFORMATEX *pwfx = NULL;
WAVEFORMATEXTENSIBLE tmpWfx = { 0 };
WAVEFORMATEXTENSIBLE* ptmpWfx = (WAVEFORMATEXTENSIBLE*)pwfx;

https://blog.csdn.net/yi7900/article/details/7481599
在windows平台上,WebRTC采用的是Windows Core Audio和Windows Wave技术来管理音频设备,还提供了一个混音管理器。利用音频设备,可以实现声音输出,音量控制等功能。源代码在webrtc\modules\audio_device\main目录下,包含接口和各个平台的源代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,667评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,361评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,700评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,027评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,988评论 5 361
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,230评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,705评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,366评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,496评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,405评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,453评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,725评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,803评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,015评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,514评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,111评论 2 341