Audio Unit框架(一)框架认识和使用

音视频开发:OpenGL + OpenGL ES + Metal 系列文章汇总

Audio Unit是一个音频处理插件。它是为应用程序添加复杂的音频操作和处理的底层的API。本文主要认识Audio Unit的原理和简单使用

主要内容:

  1. 音频单元
  2. Audio Unit使用
  3. audio processing graph
  4. 回调函数

1. 认识

Audio Unit是一个音频处理插件。它是为应用程序添加复杂的音频操作和处理的底层的API。所有的音频技术都是构建在这个框架之上的。支持混合、均衡、格式转换,用于录制、回放、离线渲染和实时对话的实时输入输出,流入VoIP(互联网协议语言)。

功能介绍:

  1. 具有低延时的实时I/O,1)如VoIP(互联网语音协议)应用程序
  2. 合成声音,进行回放,例如音乐游戏或合成乐器
  3. 一些特殊的功能,比如回声消除,均衡、混音
  4. 处理链架构,可将音频处理模块组装到灵活的网络中,

优势:

  1. 出色的响应能力:音频单元渲染的回调函数中使用的是实时优先线程,所以响应能力非常出色
  2. 动态重新配置:音频处理图的API允许我们以线程安全的方式动态组装,重新配置和重新排列复杂的音频处理链,同时处理音频

音频单元的生命周期:

  1. 运行时,获取对动态可链接库的引用
  2. 实例化音频单元
  3. 配置音频单元
  4. 初始化音频单元以使用
  5. 操作音频单元
  6. 取消分配音频单元

2. 音频单元

Audio Unit都是有音频单元组成的,这里先认识音频单元。

2.1 分类

共有七个音频单元,分为四大类。

分类
  • Effect Unit
    • 效果单元,也就是iPod均衡器,对音频数据进行音效处理
  • Mixing Unit
    • 混音器单元,可以将不同的音频混合到一起输出
    • 3D Minxer Unit
      • 可以实现3D混音效果功能,是构建OpenAL的基础,一般实现3D混音都是使用OpenAL
    • MutilChannel Minxer Unit
      • 实现多通道混音效果
      • 为任意数量的多通道或立体声流提供立体声输出
  • I/O Unit
    • Remote I/O 远程I/O单元
      • 连接输入输出硬件设备的
    • voice-processing I/O Unit语音处理I/O单元
      • 对语音进行处理,比如可以进行回声消除,提供自动增益校正,语音处理质量调整和静音。
    • Generic Output Unit 通用输出单元
      • 这个输出不连接设备,在处理链中直接发到应用程序中,一般用来进行离线的音频操作
  • Format conversion Unit
    • 格式转换组件,使用在Remote I/O Unit中,将硬件的音频格式转换成应用程序的音频格式

2.2 组件的基本特征

特征

说明:

  • I/O音频单元包含输入音频组件和输出音频组件
  • 包括输入输出scope,包括输入输出element

3. 简单使用

在iOS中提供了两种API,都可以进行操作,一种是直接操作Audio Unit,一种是操作Audio Processing Graph(在下文讲解)

Audio Unit是在Audio Processing Graph的上下文环境中工作的

过程示例:

过程示例

3.1 创建音频组件描述

创建音频组件描述

说明:

  • 它是用来创建不同类型的音频组件的
  • 音频组件描述中的参数可以在官网中查找

3.2 创建音频单元

创建音频单元

说明:

  1. 初始化音频组件
  2. 定义音频组件描述
  3. 获取音频组件的引用
  4. 实例化音频组件

3.3 设置音频单元的属性

给音频组件设置scope、element设置属性,比如音频流的格式,比如回调函数设置等。

属性是一个键值对,键是系统已经定义好的数值,值是相应的特定类型

常用方法:

  • AudioUnitGetPropertyInfo,检查属性是否可用
  • AudioUnitGetProperty,得到该属性
  • AudioUnitSetProperty,设置属性
  • AudioUnitAddPropertyListener,增加监听
  • AudioUnitRemovePropertyListnerWithUserData,移除监听

[图片上传失败...(image-dfb5d9-1661917557622)]

设置音频单元的属性

说明:

  • 这里表示给scope的element设置了一个流格式属性,属性的值是&audioFormat
  • AudioUnitSetPropety一次只能设置一个属性
  • 设置属性可以设置给scope,也可以设置给element

指定音频单元的部件:

音频单元是由scope和element组成的,所以想要操作音频单元,需要指定标识符

说明:

  1. scope
    1. kAudioUnitScope_Global :1)作用于整个音频单元,不作用音频流;2)只有一个element0元素
    2. kAudioUnitScope_Input和kAudioUnitScope_Output:作用在输入输出scope的元素称为bus,总线
  2. element
    1. element是作用在scope的,是嵌套在scope的编程上下文
  3. 关系
    1. 属性可以作用于element,也可以作用于scope
    2. 一个scope可以有多个element,同一个element可以存在于多个scope

注意:

千万千万要注意的一点是:这里是通过element是否是输入还是输出来决定这个I/O单元是用来输入还是输出的,而不是通过scope来决定的。

3.4 设置音频单元的参数

参数是用户可调节的设置,可以在音频单元正在产生音频时改变的参数。

参数也是一个键值对,key是系统已经定义好的数值,value也是数值

常用方法:

  • AudioUnitGetParameter得到参数
  • AudioUnitSetParameter设置参数

4. audio processing graph

音频处理图可以用来构建和管理音频单元处理链,它可以使用多个音频单元,和实现多个渲染回调函数,允许我们创建几乎任何我们能想象的音频处理解决方案。

特点:

  • 线程安全
    • 我们重新配置处理图时,音频处理图的API会将配置的音频单元添加到稍后要执行的更改列表中,当指定完所有的更改集后,就可以请求Graph配置他们了,这样就线程安全了。
  • 音频处理图总是会有一个完整的I/O单元
  • 能够动态的重新分配处理链
    • 可以安全的插入AUNode
    • 可以在播放音频时交换不同的渲染回调函数

AUNode的认识:

  • 音频处理图是管理AUNode的,AUNode是链的节点,作为音频单元的代理
  • 它可以看做是音频单元,但是如果要设置音频单元,还必须直接配置音频单元,AUNode本身是不可以配置的

简单过程:

  1. 将node增加到Graph中
  2. 直接配置由node配置的音频单元
  3. 互联node

代码实现:

互联Node的常用方法:

  • 添加或者删除音频单元node(AUGraphAddNode, AUGraphRemoveNode)
  • 添加或者删除node之间的连接(AUGraphConnectNodeInput, AUGraphDisconnectNodeInput)
  • 将渲染回调函数连接到音频单元的input bus(AUGraphSetNodeInputCallback)

5. 回调函数

5.1 音频流数据的获取

音频流程图:

说明:

  • 灰色箭头是调用函数的方向
  • 橙色箭头是函数返回的音频数据的方向
  • 初始的音频数据是音频帧(frame)
  • 函数回调执行完返回的音频数据是切片(slice)

过程详解:

  1. AUGraphStart函数去获取音频时,首先会直接在输出element的缓冲区中找音频数据
  2. 如果有,则直接输出,如果没有则调用连接到输入的回调函数,也就是它会调用这个绑定输入的函数
  3. 此时进入到均衡器组件,获取数据,发现也没有,就再调用输入的回调函数
  4. 此时就从应用内部获取到音频帧
  5. 拿到音频帧后就一步一步的执行回调函数并返回音频数据,也就是切片(slice)

5.2 回调函数代码实现

注释已足够详细

注意:

  • 千万要注意,回调函数必须遵守严格的性能要求
  • 回调函数是异步执行的,如果这个函数执行耗时太长,下一个函数已经到达,这个函数尚未完成执行,那么就会导致声音产生间隙

参考文档:

官方文档

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

推荐阅读更多精彩内容