iOS 音频边录边播
iOS利用AudioUnit实现音频边录边播功能
上一篇文章介绍了怎么用AudioUnit实现录音功能,今天在之前的录音基础上添加播放功能。
AVAudioSession配置和音频单元初始化和录音保持一致。
在录制过程中我们对音频单元配置了麦克风作为音频输入, 现在我们要实现播放功能,现在配置扬声器作为音频输出:
UInt32 flag = 1;CheckStatus(AudioUnitSetProperty(_audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &flag, sizeof(flag)), @"扬声器配置失败", NO);
输出配置成功之后我们需要给输出配置对应的音频编码, 我们将输入输出音频编码保持一致:
CheckStatus(AudioUnitSetProperty(_ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &_streamDescription, sizeof(_streamDescription)), @"设置麦克风音频参数", NO);
CheckStatus(AudioUnitSetProperty(_ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &_streamDescription, sizeof(_streamDescription)), @"设置扬声器音频参数", NO);
注:这里肯定会有人有疑惑为什么麦克风音频参数选择Output,而扬声器却选择Input,我们先看一张图:
这就是我们使用所以用的RemoteIO图解,他包含两个I(Element),分别负责输入(用1表示),输出(用0表示)。而没个Element有自己对应的输入输出。
我们可以这样理解,Element1负责输入,Element1的input负责音频采集,然后通过自己的output输出音频,
Element0负责输出, Element0的input负责读取音频,然后通过output播放音频
我们回过头看看我们设置音频编码参数代码:
输入端参数:这里的output并非真正的扬声器输出, 而是Element1的输出
kAudioUnitScope_Output, 1
输出端参数:这里的input同样并非真正的麦克风输入, 而是Element0的输入
kAudioUnitScope_Input, 0
下一步设置播放回掉:
AURenderCallbackStruct playCallbackStruct;
playCallbackStruct.inputProcRefCon = (__bridge void *)self;
playCallbackStruct.inputProc = playCallback;
CheckStatus(AudioUnitSetProperty(_audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Group, 0, &playCallbackStruct, sizeof(playCallbackStruct)), @"设置播放回掉", NO);
最后一步就是将麦克风的音频通过回掉传入扬声器进行播放,我们看看两个回掉代码的处理:
static OSStatus recordingCallback(void *inRefCon,AudioUnitRenderActionFlags *ioActionFlags,const AudioTimeStamp *inTimeStamp,UInt32 inBusNumber,UInt32 inNumberFrames,AudioBufferList *ioData) {ViewController *controller = (__bridge ViewController *)inRefCon;controller->_bufferList.mNumberBuffers = 1;controller->_bufferList.mBuffers[0].mNumberChannels = 1;controller->_bufferList.mBuffers[0].mDataByteSize = 2 * inNumberFrames;controller->_bufferList.mBuffers[0].mData = malloc(inNumberFrames * 2);// 我们利用AudioUnitRender函数将音频数据存储起来CheckStatus(AudioUnitRender(controller->_audioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &(controller->_bufferList)), @"获取数据失败", NO);return noErr;
}
// 这个是播放驱动, 在播放过程中音频单元会通过回掉来读取音频数据,我们只需要在这里将音频数据塞入ioData中即可, AudioBufferList类似缓冲区,录制的时候将音频数据写入缓冲区, 然后播放的时候从缓冲区读取数据
static OSStatus playCallback(void *inRefCon,AudioUnitRenderActionFlags *ioActionFlags,const AudioTimeStamp *inTimeStamp,UInt32 inBusNumber,UInt32 inNumberFrames,AudioBufferList *ioData) {ViewController *controller = (__bridge ViewController *)inRefCon;// memcpy是一个c和c++内存拷贝函数, 函数原型为: void *memcpy(void *dest, const void *src, size_t n), 从scr所指内存拷贝值dest,拷贝长度为n// 我们通过拷贝将录音回掉中存入的音频, 塞入播放器的缓冲区memcpy(ioData->mBuffers[0].mData, controller->_bufferList.mBuffers[0].mData, ioData->mBuffers[0].mDataByteSize); return noErr;
}
AudioOutputUnitStart(_audioUnit);
iOS 音频边录边播相关推荐
- Unity实现边录边播
Unity实现边录边播 引言 实现一个小功能,实现录音功能,边录边播,单机版的. 权限申请 现在在安卓端和IOS端使用麦克风时都需要申请权限,所以在麦克风录音之前我们需要先申请权限. /// < ...
- android 录音原始文件_Android 录音详解(一)—— MediaRecorder、AudioRecord、生成wav格式、边录边播...
Android 录音详解(一)-- MediaRecorder.AudioRecord.生成wav格式.边录边播 越来越多的 APP 都用到了手机的录音功能,比如搜索.聊天.输入.K歌等... 本系列 ...
- iOS音频播放 (八):NowPlayingCenter和RemoteControl
转自 码农人生 ChengYin's coding life http://msching.github.io/blog/2014/11/06/audio-in-ios-8/ iOS音频播放 (八): ...
- 一篇对iOS音频比较完善的文章
iOS音频播放 (一):概述 前言 从事音乐相关的app开发也已经有一段时日了,在这过程中app的播放器几经修改我也因此对于iOS下的音频播放实现有了一定的研究.写这个系列的博客目的一方面希望能够抛砖 ...
- iOS音频播放(一):概述
(本文转自码农人生) 前言 从事音乐相关的app开发也已经有一段时日了,在这过程中app的播放器几经修改,我也因此对于iOS下的音频播放实现有了一定的研究.写这个 系列的博客目的一方面希望能够抛砖引玉 ...
- 一步一步教你实现iOS音频频谱动画(一)
如果你想先看看最终效果再决定看不看文章 -> bilibili 示例代码下载 第二篇:一步一步教你实现iOS音频频谱动画(二) 基于篇幅考虑,本次教程分为两篇文章,本篇文章主要讲述音频播放和频谱 ...
- iOS音频播放 (二):AudioSession 转
原文出处 :http://msching.github.io/blog/2014/07/08/audio-in-ios-2/ 前言 本篇为<iOS音频播放>系列的第二篇. 在实施前一篇中所 ...
- iOS音频的后台播放总结(后台网络请求歌曲,Remote控制,锁屏封面,各种打断)...
iOS音频的后台播放总结(后台网络请求歌曲,Remote控制,锁屏封面,各种打断) 2013-12-11 21:13 1416人阅读 评论(0) 收藏 举报 分类: cocoa SDK(139) ...
- iOS 音频视频图像合成那点事
代码地址如下: http://www.demodashi.com/demo/13420.html 人而无信不知其可 前言 很久很久没有写点什么了,只因为最近事情太多了,这几天终于闲下来了,趁此机会,记 ...
最新文章
- 不知道发这些有啥用!多分享些技术噻...
- java cellformat_java使用jxl对excel表导出进行样式的设置
- jQuery EasyUI Datagrid组件的完整的基础DOM结构
- .NET (c#)序列化和反序列化
- MySQL 锁信息和事务
- 计算机网络【四】数据链路层基本概念+点到点通信(PPP协议)
- [css] 说说你对css的will-change属性的理解,它有什么作用呢?
- Python 列表(List)
- MessageBox模态对话框[转]
- Spring AOP配置文件
- Raki的读paper小记:A Concise Model for Multi-Criteria Chinese Word Segmentation with Transformer Encoder
- iphone转android通讯录,苹果IPHONE通讯录电话簿转到安卓手机csv,vcf方法(ITUNES,OUTLOOK,EXCEL)...
- 树莓派无法打开摄像头模块,无法识别摄像头
- 【Linux】Cachecloud安装部署图文并茂
- android建脚本,Android Studio Gradle构建脚本(示例代码)
- 科罗拉多大学波尔得分校计算机科学,科罗拉多大学波尔得分校计算机科学本科专业-(20页)-原创力文档...
- 华为0基础——名字的美丽度
- Intellij创建自己的TODO
- Python map() 函数 特殊用法
- 牛客网-《刷C语言百题》第三期
热门文章
- 神经网络与深度学习笔记汇总三
- angular5监听浏览器的前进和后退按钮(PlatformLocation)
- python 局域网通信 socket server client
- 简简单单右键菜单-闲情偶寄-iteye技术网站
- vector的find
- python参考手册小说_用Python给自己DIY一款小说阅读器,你要不看看?
- Android图片底部对齐(scaleType底部对齐)
- php execl内存不足,PHPExcel读取Excel文件出现内存不足 各种情况处理办法
- 关于并行计算的相关总结
- 修改windows启动画面:Logonui.exe