iOS音频采集过程中的音效实现
1、背景
在移动直播中, 声音是主播和观众互动的重要途径之一, 为了丰富直播的内容,大家都会想要在声音上做一些文章, 在采集录音的基础上玩一些花样。
比如演唱类的直播间中, 主播伴随着背景音乐演唱. 这时有些主播就会希望能够给自己声音增加混响的效果, 营造出在舞台剧场等环境下演唱的氛围. 再比如有些搞笑类的直播间, 主播会希望给自己的声音添加变声的效果, 女变男,男变女或者变成机器人等等. 为了实现这些需求我们需要对采集的声音进行处理, 并且为了让主播实时听到这些处理后的效果,以便根据效果进行调整,我们也需要提供低延时的回放,将变化后的声音播放给主播听.对声音处理的方案比较多,这里介绍一下金山云直播SDK中所采用的基于iOS提供的AudioUnit的方案。
iOS系统提供了非常丰富的音频相关的API,涵盖了从采集,处理到播放等各个环节,并且按照需求的层次进行了分组。
图1. Core Audio Overview
其中,离底层的驱动和硬件最近的就是AudioUnit系列的API,很多其他高层的API,都是对AudioUnit的封装. 比如AVFoundation、AudioQueue、AVAudioEngine等。
缺点:
涉及到的专有概念比较多,接口复杂
提供C风格的API
优点:
低延时,从采集到播放回环可以到10ms的级别
可以动态变更配置组合
可以直接获得后台执行权限
1、AudioUnit简介
AudioUnit这个名字取得还是比较形象的,它的主体就是一系列的unit,不同unit能够实现不同的功能,将一个或多个unit添加到AUGraph(Audio Processing Graph)中,并建立unit之间的连接,音频数据顺次通过各个节点即可完成我们最终需求。
图2. AudioUnit in iOS
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以内,主播才察觉不到声音的延时。
基本的步骤如下:
实例化AUGraph,将用到units添加进去;
配置每个AudioUnit的属性;
设置Render Callback Function;
4.将units 建立连接;
5.启动AUGraph。
以上过程大家都可以到Apple官方的文档中找到具体的说明和代码示例。
在直播录制中比较关键的一步就是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丢弃数据,而出现声音异常 。
1、使用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的潜力还远没有挖掘完,比如还可以将背景音乐播放,混音,回声消除等其他移动多媒体音频相关的功能纳入到这个框架中。
iOS音频采集过程中的音效实现的更多相关文章
- jenkins自动化构建iOS应用配置过程中遇到的问题
最近配置jenkins来自动构建iOS应用,期间遇上不少问题.在这里分享给大家,也给自己留个底,方便下次解决问题. 首先说明下基本情况,我们因为部署jenkins的机器不是Mac,所以不能安装Xcod ...
- ios授权登录过程中一直提示“没有安装qq”
遇到问题:http://www.cocoachina.com/ask/questions/show/107029 之前都登录都很正常,这两天突然出现这个问题,没有安装qq软件的iphone手机上登录的 ...
- alsa音频播放过程中的基本概念
以下为 ALSA-Project/FramesPeriods[1] 学习笔记 1, sample_rate: 即每秒进行多少次采样,常见的比如 8000.16000.44100和48000等 2, s ...
- iOS 集成支付宝过程中 我遇到的一些坑,请大家注意啦(ALI69错误,ALI64错误)
支付宝很早一段时间就集成了,之前由于一直忙于开发就没有总结,今天整理桌面的时候看到,当时做支付时候的一些散落的笔记,就稍微整理一下,给大家分享一下. 第一:当时调用支付宝的时候,总是调不起来,进过断点 ...
- 一篇对iOS音频比较完善的文章
转自:http://www.cnblogs.com/iOS-mt/p/4268532.html 感谢作者:梦想通 前言 从事音乐相关的app开发也已经有一段时日了,在这过程中app的播放器几经修改我也 ...
- IOS 音频播放
iOS音频播放 (一):概述 前言 从事音乐相关的app开发也已经有一段时日了,在这过程中app的播放器几经修改我也因此对于iOS下的音频播放实现有了一定的研究.写这个系列的博客目的一方面希望能够抛砖 ...
- iOS音频播放 (五):AudioQueue
码农人生 ChengYin's coding life 主页 Blog 分类 Categories 归档 Archives 关于 About Weibo GitHub RSS Where there ...
- 3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案
根据之前解析的循环依赖的源码, 分析了一级缓存,二级缓存,三级缓存的作用以及如何解决循环依赖的. 然而在多线程的情况下, Spring在创建bean的过程中, 可能会读取到不完整的bean. 下面, ...
- iOS 实时音频采集与播放Audio Unit使用
前言 在iOS中有很多方法可以进行音视频采集.如 AVCaptureDevice, AudioQueue以及Audio Unit.其中 Audio Unit是最底层的接口,它的优点是功能强大,延迟低; ...
随机推荐
- ShoneSharp语言(S#)的设计和使用介绍系列(2)— 掀开盖头
ShoneSharp语言(S#)的设计和使用介绍 系列(2)- 掀开盖头 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneSharp. ...
- PHP防止SQL注入和XSS攻击
PHP防止SQL注入和XSS攻击PHP防范SQL注入是一个非常重要的安全手段.一个优秀的PHP程序员除了要能顺利的编写代码,还需要具备使程序处于安全环境下的能力.说到网站安全,就不得不提到SQL注入( ...
- .net程序员做的第一个安卓APP
我从毕业之后一直做的是ASP.NET,从毕业到现在都已经五六个年头了.一个事物接触久了就会慢慢没有了新鲜感热情也褪去的差不多了,我又是对新事物比较感兴趣的,虽说Android早就不算什么新事物,当对于 ...
- 批量去BOM头 遍历目录及子文件,文件夹 PHP源码
任意php文件,把最后一行替换成自己的目录 即可 <?php class KillBom { public static $m_Ext = ['txt', 'php', 'js', 'c ...
- 原生Js实现拖拽(适用于pc和移动端)
效果: HTML和CSS部分 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- 程序员的自我救赎---3.1:理解Oauth2.0
<前言> (一) Winner2.0 框架基础分析 (二)PLSQL报表系统 (三)SSO单点登录 (四) 短信中心与消息中心 (五)钱包系统 (六)GPU支付中心 (七)权限系统 (八) ...
- kali git 环境配置
kali 配置很简单,输入apt-get install git 我输入时返回了错误,执行命令dpkg --configure -a 就行了
- 初识AOP与动态代理
AOP AOP是指在jvm运行时, 动态将代码切入到指定位置. OOP是一个维度上写代码, AOP是把他切开来, 变成立体的. 这样的好处是: 业务逻辑跟辅助逻辑分离, 例如日志打印, 性能监控, 安 ...
- eclipse中Cannot change version of project facet Dynamic Web Module to 2.5.
Cannot change version of project facet Dynamic Web Module to 2.5.这个错误可能很多人都碰到过,这里网上查了一些资料,解决的问题.所以这里 ...
- webrtc视频数据render流程