音视频系列之iOS: 音频采集 AudioUnit

news/2024/7/20 14:00:28 标签: 移动开发, 内存管理

AudioUnit是什么? 它是ios端进行音视频采集的框架,最全,最屌的!但是缺点就是学习成本大,但是大没关系,既然您已经看到这里,想必就是想搞音视频,这点小的困难应该能克服的。


我这边就先看怎么用,用完在讲讲具体的是什么东西比较好,这也是我一向学习新东西的习惯和方法,这个世界上的理论很多,真理也很多,我们可以选择接收和不接受,如果你看看下面的实现结果如果不满意就可以直接关闭,如果有兴趣可以欢迎一直看下去咯!

废话不多说了,我也没时间了,直接介绍:

操作流程:

no1: 描述音频元件: kAudioUnitType_Output。kAudioUnitSubType_RemoteIO/kAudioUnitManufacturerApple   这个知道就行,不需要了解

no2: 使用AudioComponentFindNext : 这个就当作是生产AudioUnit 的工厂

no3 : AudioComponentInstanceNew: 顾名思义,就是Audio Unit 的实例

no4:  AudioUnitSetProperty函数为录制和回放开启IO

no5: 使用 AudioStreamBasicDescription 结构体描述音频格式,并使用AudioUnitSetProperty进行设置

no6: 使用 AudioUnitSetProperty 设置音频录制与放播的回调函数

no7: 分配缓冲区

no8: 初始化Audio Unit

no9: 启动Audio  Unit


理论:

Core Audio

数字音频处理的基础设施,它是应用程序用来处理音频的一组软件框架,所有关于iOS音频开发的接口都是由Core Audio来提供或者经过它提供的接口来进行封装的。Apple官方对Core Audio的框架分层图示如下:





OutputOnlyWithRenderCallback_2x.png

较复杂的构建

输入端有两路音频流,都是通过rendercallback方式抓取数据,其中一路音频流直接给入到Mixer Unit中,另一路先经过EQ Unit处理后给入到Mixer Unit中,


OutputOnlyWithRenderCallbackExtended_2x.png

Tips

1. 多线程及内存管理

尽可能的避免render callback方法内做加锁及处理耗时较高的操作,这样可以最大限度的提升实时性能,如果播放数据或者采集数据存在不同线程读写的情况,必需要加锁保护,推荐pthread相关lock方法性能比其它锁要高

音频的输入输出一般都是一个持续的过程,在采集与播放的callback中,应尽量复用buffer及避免多次buffer拷贝,而不是每次回调都重新申请和释放,在适当的位置加上@autoreleasepool避免长时间运行内存不断上涨

2. 格式

Core Audio Type中定义了AudioStreamBasicDescription结构,Audio Unit及其它很多音频API对格式的配置都需要用到它,根据需要将该结构的信息填充正确,下面是44.1K,stereo,16bit的填充例子

audioDescription.mSampleRate = 44100;

audioDescription.mChannelsPerFrame = 2;

audioDescription.mBitsPerChannel = 16;

audioDescription.mFramesPerPacket = 1;

audioDescription.mFormatID = kAudioFormatLinearPCM;

audioDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;

audioDescription.mBytesPerFrame = (audioDescription.mBitsPerChannel/8) * audioDescription.mChannelsPerFrame;

audioDescription.mBytesPerPacket = audioDescription.mBytesPerFrame ;

苹果官方建议在整个Audio Processing Graph或者Unit之间尽量以相同的音频格式流通,尽管Audio Unit的输入输出可以不同。另外在Unit之间输入输出连接点要保持一致。

3. 音质

在使用过程中,Audio Unit的format是可以动态改变的,但存在一种情况,Unit在销毁前最好恢复到默认创建时的format,否则在销毁后再重建Unit后,可能出现播放音质变差(音量变小,声音粗糙)的情况。

在使用VoiceProcessing I/O Unit过程,遇到在有些iphone上开启扬声器后,Unit从Mic采集过来的数据为空或者噪音的情况,从APP STORE中下载了其它的VOIP类型的APP也同样存在该问题,后来将AudioUnitSubType改成RemoteIO类型后,问题消失,怀疑苹果在VoiceProcessing Unit上对回声消除功能的处理上有bug

4. AudioSession

既然使用了音频特性,就会用到AudioSession,随着功能需求跟进,与它相关的问题也瞒多的,比如路由管理(听筒扬声器、线控耳机、蓝牙耳机),打断处理(interruption、iphone call)等,这里以Audio Unit为主,就不对它进行详细描述了,需要注意的是

音频的路由变更(用户挺拔耳机,或者代码调用强制切换)涉及到iOS硬件上输入和输出设备的改变,I/O类型Unit的采集和播放线程在切换过程中会阻塞一定时间(200ms左右),如果是语音对讲类对实时性要求较高的应用场景要考虑丢包策略。

在APP前台工作时,iPhone来电或者用户主动切换到其它音频类APP后,要及时处理音频的打断机制,在恰当的时机停止及恢复Unit的工作,由于iOS平台对资源的独占方式,iPhone在通话等操作时,APP中的Unit是无法初始化或者继续工作的。

作者:MasonFu

链接:http://www.jianshu.com/p/5d18180c69b8

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


http://www.niftyadmin.cn/n/1337423.html

相关文章

超过父控件的部分不能响应事件怎么办

##前言 ###一个朋友问我过一个这样的问题,他在底部的tabBar上面加了一个控件,这个控件超出了底部的tabBar,超出的部分无法响应事件,怎么办? ###相信大家应该明白为什么不能响应事件的原因,就是响应者链条么,你父控件不能响应,系统就认为你也不能响应,具体的内容请看这篇博客 我…

AVSpeechSynthesizer语音合成

记录一下 self.speechSynthesizer [[AVSpeechSynthesizer alloc] init];AVSpeechUtterance *utterance [AVSpeechUtterance speechUtteranceWithString:"FlyElephant"];AVSpeechSynthesisVoice *voiceType [AVSpeechSynthesisVoice voiceWithLanguage:"en-US…

SecureCRT发送键盘按键对应表(转义字符)

\r 发送回车(CR) \n 发送换行符(LF) \b 发送退格 \e 发送一个转义 \t 发送一个标签 \\ 发送一个反斜杠字符 \v 将剪贴板的内容粘贴到活动状态会话窗口 \p 暂停一秒钟 >如有问题,请联系我&#xff1a…

mysql 矩阵乘法,向量与矩阵相乘

最近在看"程序员的数学"系列的"线性代数"部分,当阅读向量矩阵乘法的时候,感觉各种别扭。以前学习的时候,简单的把向量乘以矩阵简化理解成矩阵乘以一维矩阵,然后交换位置进行矩阵乘法。也就是 n 维向量乘以 m*…

matlab rgb图片,使用MATLAB对数据进行位操作以及RGB图片显示

fd fopen(video_test_pattern_avalon_generator_source_data.txt); //打开像素源文件A fscanf(fd,%d); //读入文件中的数据fclose(fd);%先申明向量用于存储数据B zeros(224,224);C zeros(224,224);R1 zeros(50176,1);R2 zeros(50176,1);R3 zeros(224,224);G1 zeros(501…

深入理解Mysql数据库主从延迟

1什么会增加主从延迟? 1 网络不好 2 从库硬件差 3 索引没做好,从库执行慢 4 从库锁等待,多见于myisam 5 主库写频繁,从库单线程执行慢 6 使用row复制,或mix使用行复制 2如何优化,减少延迟时间? …

PHP数组的随机函数产生4位验证码,php如何使用随机函数rand()生成一个数字验证码?...

暮色呼如参考这个$code"";//画布$imageimagecreatetruecolor(80, 25);imagefill($image, 0, 0, imagecolorallocate($image, 255, 255, 255));for($i0;$i<4;$i){ $rand_colorimagecolorallocate($image, rand(0,155), rand(0,155), rand(0,155)); $code_tmp…

Springboot-添加对jsp支持

1&#xff0c;在项目的配置文件加入以下依赖 <dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><scope>provided</scope></dependency><!--支持jsp --><dependency><g…