音频采集-AudioUnit

AudioUnit简介

  AudioUnit这个名字取得还是比较形象的,它的主体就是一系列的unit,不同unit能够实现不同的功能,将一个或多个unit添加到AUGraph(Audio Processing Graph)中,并建立unit之间的连接,音频数据顺次通过各个节点即可完成我们最终需求。

   AUGraph连接一组 audio unit 之间的输入和输出,构成一张图,同时也为audio unit 的输入提供了回调.

  https://developer.apple.com/documentation/audiotoolbox/audio_unit_processing_graph_services

图2. AudioUnit in iOS

 

 

  • Input element 和 Output element 都是 I/O unit 的一部分,可以将它们视为一个独立的个体,单独启动或禁止每一个 Element,默认情况下,Element 1 禁用,Element 0 开启。
  • 音频输入硬件麦克风直接连着 Element 1, Element 1 的 Input scope 对你是不可见的,你首次访问硬件输入的音频数据是位于 Element 1 的 Output scope。
  • 音频输出硬件扬声器直接连着 Element 0,Element 0 的 Output scope 对你是不可见的,数据从 Element 1 的 Output scope 传递到 Element 0 的 Input scope。

每一个 Element都有自己的 input scope 和 output scope,当描述 I/O unit 的时候可能会有困惑,相当于这样描述,你收到收据来自 input element 的 output scope,发送数据到 output element 的 input scope。
I/O unit 是唯一能够在 audio processing graph 中启动和停止音频流的 audio unit。I/O unit 负责在音频单元APP中的音频流。

Audio Processing Graphs 管理 Audio Units

AUGraph 用于构建和管理 audio units 处理链,可以利用多个 audio units 和多个回调函数功能,创建几乎任何你可以想象的音频处理解决方案。
AUGraph 增加了线程安全,让你可以即时重新配置处理链,例如你可以安全插入一个均衡器,甚至在音频播放时可以交换混音器输入的其它回调函数。实际上,AUGraph 提供了 iOS 中唯一可以在音频应用程序中执行这种动态重新配置的 API 。
Audio Processing Graph 使用了 AUNode 表示上 graph 中 一个单独的 audio unit ,当使用 Audio Processing Graphs,通常与包含 audio units 的代理 AUNode 交互,而不是直接使用 audio unit。
当将 graph 组合时,需要配置每一个 audio unit ,并且必须通过 audio unit API 直接与 audio unit 交互,节点单元本身是不可以配置的,通过这种方式,需要使用这两种 API。
通常情况下,Audio Processing Graphs 通常需要三个任务,将节点添加到 Graph 中,直接配置由节点表示的 audio unit,互连节点。

#Audio Processing Graph 有一个 I/O Unit

每一个 audio processing graph 有一个 I/O unit,无论你是录音,播放,同步 I/O。Graphs 通过 AUGraphStart 和 AUGraphStop 启动和停止音频流,通过函数 AudioOutputUnitStart 和 AudioOutputUnitStop 传递开始和停止消息到 I/O unit。

Audio Processing Graphs 提供线程安全

audio processing graph 使用“待办事项列表”提供线程安全,API 的一些函数添加工作单元到稍后执行的更改列表中,在你指定完整的更改好,让 graph 实现他们。
这是一些 audio processing graph 支持的重配置函数

  • 添加或删除音频单元节点(AUGraphAddNode,AUGraphRemoveNode)
  • 添加或删除节点间的连接(AUGraphConnectNodeInput,AUGraphDisconnectNodeInput)
  • 渲染回调函数连接到 aduio unit 的输入总线(AUGraphSetNodeInputCallback)

下面看一个重配置 audio processing graph 的例子,构建一个 graph 包含 Multichannel Mixer unit 和 Remote I/O unit,将声音输入到混频器的两个输入总线上。从混合器输出数据到 I/O unit 的 Output element 上。

iOS系统一共提供了如下4类unit。

     其中,I/O主要负责和设备打交道,比如采集和播放;Mixing负责将不同来源的音频数据进行混合;Effect是对音频数据进行音效处理;Format Conversion主要是进行格式转换比如重采样等。这里有一个优化的点是音频格式转换 Multichannel Mixer 本身就能够实现格式转换的功能,输入和输出的音频数据格式可以不同,利用这一点可以节省一个格式转换unit。

使用AudioUnit进行音频采集

在直播应用中,我们主要是使用Remote I/O unit来进行采集工作。 在一个AUGraph中只允许有一个I/O unit。Remote I/O需要同时负责采集和播放的功能。当用户开启耳返功能时,要将采集到的声音,处理之后再送回当前节点直接播放,这样可以将采集和播放的延时控制在50ms以内,主播才察觉不到声音的延时。

低延时,从采集到播放回环可以到10ms的级别

可以动态变更配置组合

可以直接获得后台执行权限

基本的步骤如下:

第一步:实例化AUGraph.调用NewAUGraph创建实例AUGraph。

第二步:创建AUNode.调用 AUGraphAddNode创建 AUNode。这个有以上4种类型的AUNode。

第三步:打开AUGraph。AUGraphOpen(_auGraph)。

第四步:再通过AUGraphNodeInfo获取节点对应的AudioUnit。

第五步:设置AUUnit 属性AudioUnitSetProperty。配置每个AudioUnit的属性。

第六步:设置数据回调。Render Callback Function,调用AudioUnitSetProperty 设置麦克风输出回调

第七步:调用AUGraphClearConnections 链接。将units 建立连接

第八步:.启动AUGraph。AUGraphStart

以上过程大家都可以到Apple官方的文档中找到具体的说明和代码示例。

https://developer.apple.com/documentation/audiounit

在直播录制中比较关键的一步就是Render Callback Function。

AudioUnit每次都是处理一段音频数据,每次处理完成一段数据的时候,这个回调函数就会被调用一次。在这个回调函数中,通过AudioUnit的AudioUnitRender方法,可以AUGraph中的某一个节点中获取到一段处理后的音频PCM数据。同时,如果需要进行耳返播放,在这个回调中也需要将取得的音频数据送入到回调函数的最后一个参数ioData对应的buffer中。

在设置unit的属性时,需要注意的是一些公共的属性。比如音频格式属性和MaximumFramesPerSlice。如果音频格式设置错误,往往会出现AUGraph启动失败或者声音异常等问题。比如,使用iOS内置的麦克风或者有线耳机时,设备支持的采样率比较高,44.1KHz 能正常工作,我们整条音频通路上基本上都采用的是44.1KHz。但是当使用蓝牙设备时,一般蓝牙设备无法支持44.1KHz采集和播放,通常都是16KHz甚至更低。此时I/O Unit无法继续使用之前的配置。需要按照实际支持的采样率进行配置。

AudioUnit还要求两个单元衔接处的音频数据格式必须保持一致,当AUGraph中不同unit支持的格式不同时(比如在支持蓝牙设备或者使用回声消除模块时,I/O unit要求的格式和其他单元的有可能不同),此时就需要分别设置格式,并通过格式转换unit或mixer unit对格式进行转换。

如果MaximumFramesPerSlice设置错误,可能会出现声音异常的情况。 MaximumFramesPerSlice 表示的是每次回调送入或取出的音频数据的长度,在AUGraph的所有节点的这个属性也需要保持一致否则会导致有的unit丢弃数据,而出现声音异常 。

使用AudioUnit进行音效处理

这里所谓的音效处理,主要是指对原本的声音进行一些改变,比如混响效果,变声效果等。用到手段主要是数字信号处理提供的一系列时间和频域的工具,将输入的PCM数据经过运算后得到变化后的声音。

4.1 混响效果(reverberation)

我们在音乐厅,剧院,礼堂等比较空旷的室内说话或唱歌时,往往能听到和平时不一样的声音,主要是声音在墙壁上多次反射后叠加在一起,听起来就有了混响的效果。在声音处理中,我们可以人为的将声音缓存起来,延时一定时间后,和原声音叠加,就能够模拟出混响的效果。AudioUnit提供了kAudioUnitSubType_Reverb2来实现混响效果的生成。将该unit接入到AUGraph中之后,配置参数即可实现混响的效果。虽然混响原理是比较简单,但实际上为了模拟自然界中实际的音效,计算过程还是相当复杂的,要模拟出不同的大小的空间,不同材质的墙壁,障碍物的多少,需要输入比较多的参数来参与运算。iOS的reverb unit提供了7个参数。我们在直播应用中提供了4个不同场景的模拟(录音棚,演唱会,KTV,小舞台),主要是通过调整如下参数实现的:

kReverb2Param_DryWetMix混响效果声的大小与空间大小无关,而只与空间内杂物的多少以及墙壁及物体的材质有关;

kReverb2Param_DecayTimeAt0Hz / kReverb2Param_DecayTimeAtNyquist衰减时间,整个混响的总长度,与空间大小比较相关,越空旷越长。

4.2 变声效果

变声效果主要是在频域上对人的声音进行一定的处理,我们知道男声一般比较低沉,女声比较尖锐,这个主要说的是音调。通过对声音音调的调整,可以让低沉的男声听上去像尖锐女声。iOS提供了kAudioUnitSubType_NewTimePitch的unit来实现音调的调整。值得注意的是kAudioUnitSubType_NewTimePitch不是输入Effect类的,而是属于FormatConverter类的。通过设置TimePitch unit的kNewTimePitchParam_Pitch属性即可。

/// pitchShift为具体数值(0表示不变,负数表明调低沉,正数调尖锐)AudioUnitSetParameter(pitchUnit, kNewTimePitchParam_Pitch, kAudioUnitScope_Global, 0, pitchShift, 0);

变男声,需要强化突出低沉的特点,将音调调低,设置负数参数即可;

变女声,需要强化突出尖锐的特点,将音调调高,设置正数即可;

机器人音效,机器人的音效是一个组合效果,我们印象中的机器人音效都是老电影中的那种,音调比较高,而且有重音。所以我们采用的是TimePitch unit + Delay unit的方式。Delay unit也是iOS提供的一个将声音延时叠加的unit,但是比混音要简单很多,只有单次叠加;

庄严宏大音效,想象一下佛祖之类的声音,一般都是自带回声,而且比较男性化,所以我们选择的是TimePitch unit + Reverb unit的方式来实现。

这里推荐一个自己调音效的参考软件voxal voice changer。大家可以在这个软件上自己将不同的工具组件组合起来,调试参数,实时听到参数对应的结果。当效果满意后再移植到AudioUnit中。

图3 voixal voice changer

总结

以上大概介绍了怎么用AudioUnit来实现iOS直播中的音频采集,怎么使用AudioUnit中的音效组件来实现混响和变声效果。但是AudioUnit的潜力还远没有挖掘完,比如还可以将背景音乐播放,混音,回声消除等其他移动多媒体音频相关的功能纳入到这个框架中。

 

文章https://www.jianshu.com/p/5d18180c69b8作者讲解比较详细



作者:泥孩儿0107
链接:https://www.jianshu.com/p/dd6f312b0c2b
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值