前言
在iOS中有很多方法可以进行音视频采集。如 AVCaptureDevice, AudioQueue以及Audio Unit。其中 Audio Unit是最底层的接口,它的优点是功能强大,延迟低; 而缺点是学习成本高,难度大。
对于一般的iOS应用程序,AVCaptureDevice和AudioQueue完全够用了。但对于音视频直播,最好还是使用 Audio Unit 进行处理,这样可以达到最佳的效果,著名的 WebRTC 就使用的 Audio Unit 做的音频采集与播放。今天我们就重点介绍一下Audio Unit的基本知识和使用。
Audio Unit在 iOS架构中所处的位置:
基本概念
  • Audio Unit的种类
共可分为四大类,並可细分为七种:
  • Audo Unit 的内部结构
Audio Unit 内部结构分为两大部分,Scope 与Element。其中 scope 又分三种,分別是 input scope, output scope, global scope。而 element 则是 input scope 或 output scope 內的一部分。
  • Audio Unit 的输入与输出
下图是一个 I/O type 的 Audio Unit,其输入为麦克风,其输出为喇叭。这是一个最简单的Audio Unit使用范例。
;desc.componentFlagsMask = 0;desc.componentManufacturer = kAudioUnitManufacturer_Apple; // 获得一个元件AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc); // 获得 Audio Unitstatus = AudioComponentInstanceNew(inputComponent, &audioUnit);checkStatus(status); // 为录制打开 IOUInt32 flag = 1;status = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag));checkStatus(status); // 为播放打开 IOstatus = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag));checkStatus(status); // 描述格式audioFormat.mSampleRate = 44100.00;audioFormat.mFormatID = kAudioFormatLinearPCM;audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;audioFormat.mFramesPerPacket = 1;audioFormat.mChannelsPerFrame = 1;audioFormat.mBitsPerChannel = 16;audioFormat.mBytesPerPacket = 2;audioFormat.mBytesPerFrame = 2; // 设置格式status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &audioFormat, sizeof(audioFormat));checkStatus(status);status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &audioFormat, sizeof(audioFormat));checkStatus(status); // 设置数据采集回调函数AURenderCallbackStruct callbackStruct;callbackStruct.inputProc = recordingCallback;callbackStruct.inputProcRefCon = self;status = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, kInputBus, &callbackStruct, sizeof(callbackStruct));checkStatus(status); // 设置声音输出回调函数。当speaker需要数据时就会调用回调函数去获取数据。它是 "拉" 数据的概念。callbackStruct.inputProc = playbackCallback;callbackStruct.inputProcRefCon = self;status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, kOutputBus, &callbackStruct, sizeof(callbackStruct));checkStatus(status); // 关闭为录制分配的缓冲区(我们想使用我们自己分配的)flag = 0;status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_ShouldAllocateBuffer, kAudioUnitScope_Output, kInputBus, &flag, sizeof(flag)); // 初始化status = AudioUnitInitialize(audioUnit);checkStatus(status);
开启 Audio Unit
OSStatus status = AudioOutputUnitStart(audioUnit);checkStatus(status);
关闭 Audio Unit
OSStatus status = AudioOutputUnitStop(audioUnit);checkStatus(status);
结束 Audio Unit
AudioComponentInstanceDispose(audioUnit);
录制回调
static OSStatus recordingCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { // TODO:// 使用 inNumberFrames 计算有多少数据是有效的// 在 AudioBufferList 里存放着更多的有效空间 AudioBufferList *bufferList; //bufferList里存放着一堆 buffers, buffers的长度是动态的。 // 获得录制的采样数据 OSStatus status; status = AudioUnitRender([audioInterface audioUnit], ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, bufferList); checkStatus(status); // 现在,我们想要的采样数据已经在bufferList中的buffers中了。 DoStuffWithTheRecordedAudio(bufferList); return noErr;}
播放回调
static OSStatus playbackCallback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { // Notes: ioData 包括了一堆 buffers // 尽可能多的向ioData中填充数据,记得设置每个buffer的大小要与buffer匹配好。return noErr;}
结束
Audio Unit可以做很多非常棒的的工作。如混音,音频特效,录制等等。它处于 iOS 开发架构的底层,特别合适于音视频直播这种场景中使用。
“知识无穷尽,只取我所需”。
ios音视频演示app:https://github.com/starrtc/ios-demo

iOS 实时音频采集与播放Audio Unit使用的更多相关文章

  1. iOS中声音采集与播放的实现(使用AudioQueue)

    都说iOS最恶心的部分是流媒体,其中恶心的恶心之处更在即时语音. 所以我们先不谈即时语音,研究一下,iOS中声音采集与播放的实现. 要在iOS设备上实现录音和播放功能,苹果提供了简单的做法,那就是利用 ...

  2. iOS 微信 音频 视频自动播放

    iOS 微信 音频 视频自动播放 http://www.w3ctech.com/topic/1165

  3. 【iOS录音与播放】实现利用音频队列,通过缓存进行对声音的采集与播放

    都说iOS最恶心的部分是流媒体,其中恶心的恶心之处更在即时语音. 所以我们先不谈即时语音,研究一下,iOS中声音采集与播放的实现. 要在iOS设备上实现录音和播放功能,苹果提供了简单的做法,那就是利用 ...

  4. AudioToolbox--利用AudioQueue音频队列,通过缓存对声音进行采集与播放

    都说iOS最恶心的部分是流媒体,其中恶心的恶心之处更在即时语音. 所以我们先不谈即时语音,研究一下,iOS中声音采集与播放的实现. 要在iOS设备上实现录音和播放功能,苹果提供了简单的做法,那就是利用 ...

  5. 如何让音频跟视频在ios跟android上自动播放

    如何让音频跟视频在ios跟android上自动播放 <audio autoplay ><source src="audio/alarm1.mp3" type=&q ...

  6. 在iOS微信浏览器中自动播放HTML5 audio(音乐)的2种正确方式

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. iOS 9音频应用播放音频之iOS 9音频播放进度

    iOS 9音频应用播放音频之iOS 9音频播放进度 iOS 9音频应用开发播放进度 音频文件在播放后经过了多久以及还有多久才可以播放完毕,想必是用户所关注的问题.为了解决这一问题,在很多的音乐播放器中 ...

  8. IOS音频架构之Audio Unit

    在前面的章节部分我们已经对IOS音频结构有了一个清晰的认识,知道Audio Unit是位于整个音频结构的最底层,这一层非常多API已经開始和硬件打交道了.所以比較复杂,有了前面的基础再来看这个部分就比 ...

  9. iOS音频采集过程中的音效实现

    1.背景 在移动直播中, 声音是主播和观众互动的重要途径之一, 为了丰富直播的内容,大家都会想要在声音上做一些文章, 在采集录音的基础上玩一些花样. 比如演唱类的直播间中, 主播伴随着背景音乐演唱. ...

随机推荐

  1. unity, Gizmos.DrawMesh一个坑

    错误写法(画不出来): void OnDrawGizmos(){ Mesh mesh=new Mesh(); mesh.vertices=... mesh.triangles=... //mesh.R ...

  2. 本地启动spark-shell

    由于spark-1.3作为一个里程碑式的发布, 加入众多的功能特性,所以,有必要好好的研究一把,spark-1.3需要scala-2.10.x的版本支持,而系统上默认的scala的版本为2.9,需要进 ...

  3. curl以cookie的方式登录

    curl -o /dev/null -s -w ‘%{time_connect}:%{time_starttransfer}:%{time_total}’ --cookie "UM_dist ...

  4. linux分享一:网络设置

    在Linux中,TCP/IP网络的配置信息存在几个不同的文件里面,这些文件分别就是 /etc/sysconfig/network. 网卡配置文件. /etc/hostc. /ect/resolv.co ...

  5. mybatis 多数据源

    <environments default="development"> <environment id="development"> ...

  6. Vivado SPI Flash程序下载

    由于Vivado下载程序步骤和ISE有较大差异,特此写此文章,希望对大家有所帮助. 1,下载文件生成 在.bit文件生成后,在TCL中输入 write_cfgmem -format mcs -inte ...

  7. vue2.x 路由懒加载 优化打包体积

    当打包构建应用时,Javascript 包会变得非常大,影响页面加载.如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了. 结合 Vue 的异步组 ...

  8. Android异步载入学习笔记之四:利用缓存优化网络载入图片及ListView载入优化

    假设不做不论什么处理.直接用网络载入图片在网速快的情况下可能没什么不好的感觉.可是假设使用移动流量或是网络不好的时候.问题就来了,要么用户会抱怨流量使用太多.要么抱怨图片载入太慢.如论从哪个角度出发, ...

  9. android 自己定义视频播放器之2/1

    非常久没更新博客,相信大家年后都比較忙. 今天给大家带来了一款视频播放器,首先确认的得有几点. 1.首先得有个播放视频的view. 2.加点额外功能进去左边上下滑动调节亮度,右边上下滑动调节声量: 3 ...

  10. 使用tar命令解压的时候报错not in gzip format

    使用tar命令解压一个xx.tar.gz压缩包的时候报错not in gzip format,后用file xx.tar.gz查看一下格式发现是html document text格式的...