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以内,主播才察觉不到声音的延时。

基本的步骤如下:

  1. 实例化AUGraph,将用到units添加进去;

  2. 配置每个AudioUnit的属性;

  3. 设置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音频采集过程中的音效实现的更多相关文章

  1. jenkins自动化构建iOS应用配置过程中遇到的问题

    最近配置jenkins来自动构建iOS应用,期间遇上不少问题.在这里分享给大家,也给自己留个底,方便下次解决问题. 首先说明下基本情况,我们因为部署jenkins的机器不是Mac,所以不能安装Xcod ...

  2. ios授权登录过程中一直提示“没有安装qq”

    遇到问题:http://www.cocoachina.com/ask/questions/show/107029 之前都登录都很正常,这两天突然出现这个问题,没有安装qq软件的iphone手机上登录的 ...

  3. alsa音频播放过程中的基本概念

    以下为 ALSA-Project/FramesPeriods[1] 学习笔记 1, sample_rate: 即每秒进行多少次采样,常见的比如 8000.16000.44100和48000等 2, s ...

  4. iOS 集成支付宝过程中 我遇到的一些坑,请大家注意啦(ALI69错误,ALI64错误)

    支付宝很早一段时间就集成了,之前由于一直忙于开发就没有总结,今天整理桌面的时候看到,当时做支付时候的一些散落的笔记,就稍微整理一下,给大家分享一下. 第一:当时调用支付宝的时候,总是调不起来,进过断点 ...

  5. 一篇对iOS音频比较完善的文章

    转自:http://www.cnblogs.com/iOS-mt/p/4268532.html 感谢作者:梦想通 前言 从事音乐相关的app开发也已经有一段时日了,在这过程中app的播放器几经修改我也 ...

  6. IOS 音频播放

    iOS音频播放 (一):概述 前言 从事音乐相关的app开发也已经有一段时日了,在这过程中app的播放器几经修改我也因此对于iOS下的音频播放实现有了一定的研究.写这个系列的博客目的一方面希望能够抛砖 ...

  7. iOS音频播放 (五):AudioQueue

    码农人生 ChengYin's coding life 主页 Blog 分类 Categories 归档 Archives 关于 About Weibo GitHub RSS Where there ...

  8. 3.3 Spring5源码---循环依赖过程中spring读取不完整bean的最终解决方案

    根据之前解析的循环依赖的源码, 分析了一级缓存,二级缓存,三级缓存的作用以及如何解决循环依赖的. 然而在多线程的情况下, Spring在创建bean的过程中, 可能会读取到不完整的bean. 下面, ...

  9. iOS 实时音频采集与播放Audio Unit使用

    前言 在iOS中有很多方法可以进行音视频采集.如 AVCaptureDevice, AudioQueue以及Audio Unit.其中 Audio Unit是最底层的接口,它的优点是功能强大,延迟低; ...

随机推荐

  1. python3.5安装pyHook,解决【TypeError: MouseSwitch() missing 8 required positional arguments: 'msg', 'x', 'y', 'data', 'time', 'hwnd', and 'window_name'】这个错误!

    为什么安装 pyHook包:为Windows中的全局鼠标和键盘事件提供回调. Python应用程序为用户输入事件注册事件处理程序,例如鼠标左键,鼠标左键,键盘键等 先要实时获取系统的鼠标位置或者键盘输 ...

  2. 【C#入门教案-02】用记事本编写第一个C#程序-Hello World

    02-用记事本编写第一个C#程序-Hello World 广东职业技术学院  欧浩源 [1]进行.NET程序开发的最基本环境配备 .NET Framework + 代码编辑工具(记事本或Noetpad ...

  3. Azure IoT Edge on Windows 10 IoT Core

    在今年的Build大会上,微软推出了Azure IoT Edge的第一个版本(https://github.com/Azure/iot-edge ).该版本的主要特点就是将计算能力由Azure端推送至 ...

  4. MySQL学习——基本命令(1)

    MySQL添加新用户.为用户创建数据库.为新用户分配权限 参考博客http://blog.csdn.net/u013216667/article/details/70158452 一.登录MySQL ...

  5. Servlet与Jsp的结合使用实现信息管理系统二

    PS:前面说了抽取框架的搭建,接着就要我们开始进入网址的时候就要查到全部信息并显示在首页,我们用到的MySql数据库,具体步骤是: 创建数据库,创建表,添加信息 项目中调入mysql的jar包 mys ...

  6. mysql 各数据类型的 大小及长度

    数字型 类型 大小 范围(有符号) 范围(无符号) 用途 TINYINT 1 字节 (-128,127) (0,255) 小整数值 SMALLINT 2 字节 (-32 768,32 767) (0, ...

  7. 移动GIS未来的前景GIS解决方案应用

    目前,在我国一些发达地区,移动GIS所需的两个技术前提——移动互联网的普及和智能终端的普及都已经得到了满足,特别是平板电脑.智能手机的流行,苹果产品的风靡,为移动GIS的应用提供了肥沃的土壤,而GIS ...

  8. 用phpmailer发送邮件提示SMTP Error: Could not connect to SMTP host解决办法

    之前做项目的时候做了一个用phpmailer发送邮件的功能<CI框架结合PHPmailer发送邮件>,昨天步署上线(刚开始用新浪云,嫌贵,换成阿里了),测试的时候,发送邮件却意外报错了.. ...

  9. Android 跨进程启动Activity黑屏(白屏)的三种解决方案

    原文链接:http://www.cnblogs.com/feidu/p/8057012.html 当Android跨进程启动Activity时,过程界面很黑屏(白屏)短暂时间(几百毫秒?).当然从桌面 ...

  10. SAML2.0 协议初识(一)

    一.什么是 SAML 协议? SAML 即安全断言标记语言,英文全称是 Security Assertion Markup Language.它是一个基于 XML 的标准,用于在不同的安全域(secu ...