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 音频边录边播相关推荐

  1. Unity实现边录边播

    Unity实现边录边播 引言 实现一个小功能,实现录音功能,边录边播,单机版的. 权限申请 现在在安卓端和IOS端使用麦克风时都需要申请权限,所以在麦克风录音之前我们需要先申请权限. /// < ...

  2. android 录音原始文件_Android 录音详解(一)—— MediaRecorder、AudioRecord、生成wav格式、边录边播...

    Android 录音详解(一)-- MediaRecorder.AudioRecord.生成wav格式.边录边播 越来越多的 APP 都用到了手机的录音功能,比如搜索.聊天.输入.K歌等... 本系列 ...

  3. iOS音频播放 (八):NowPlayingCenter和RemoteControl

    转自 码农人生 ChengYin's coding life http://msching.github.io/blog/2014/11/06/audio-in-ios-8/ iOS音频播放 (八): ...

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

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

  5. iOS音频播放(一):概述

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

  6. 一步一步教你实现iOS音频频谱动画(一)

    如果你想先看看最终效果再决定看不看文章 -> bilibili 示例代码下载 第二篇:一步一步教你实现iOS音频频谱动画(二) 基于篇幅考虑,本次教程分为两篇文章,本篇文章主要讲述音频播放和频谱 ...

  7. iOS音频播放 (二):AudioSession 转

    原文出处 :http://msching.github.io/blog/2014/07/08/audio-in-ios-2/ 前言 本篇为<iOS音频播放>系列的第二篇. 在实施前一篇中所 ...

  8. iOS音频的后台播放总结(后台网络请求歌曲,Remote控制,锁屏封面,各种打断)...

    iOS音频的后台播放总结(后台网络请求歌曲,Remote控制,锁屏封面,各种打断) 2013-12-11 21:13 1416人阅读 评论(0) 收藏 举报  分类: cocoa SDK(139)  ...

  9. iOS 音频视频图像合成那点事

    代码地址如下: http://www.demodashi.com/demo/13420.html 人而无信不知其可 前言 很久很久没有写点什么了,只因为最近事情太多了,这几天终于闲下来了,趁此机会,记 ...

最新文章

  1. 不知道发这些有啥用!多分享些技术噻...
  2. java cellformat_java使用jxl对excel表导出进行样式的设置
  3. jQuery EasyUI Datagrid组件的完整的基础DOM结构
  4. .NET (c#)序列化和反序列化
  5. MySQL 锁信息和事务
  6. 计算机网络【四】数据链路层基本概念+点到点通信(PPP协议)
  7. [css] 说说你对css的will-change属性的理解,它有什么作用呢?
  8. Python 列表(List)
  9. MessageBox模态对话框[转]
  10. Spring AOP配置文件
  11. Raki的读paper小记:A Concise Model for Multi-Criteria Chinese Word Segmentation with Transformer Encoder
  12. iphone转android通讯录,苹果IPHONE通讯录电话簿转到安卓手机csv,vcf方法(ITUNES,OUTLOOK,EXCEL)...
  13. 树莓派无法打开摄像头模块,无法识别摄像头
  14. 【Linux】Cachecloud安装部署图文并茂
  15. android建脚本,Android Studio Gradle构建脚本(示例代码)
  16. 科罗拉多大学波尔得分校计算机科学,科罗拉多大学波尔得分校计算机科学本科专业-(20页)-原创力文档...
  17. 华为0基础——名字的美丽度
  18. Intellij创建自己的TODO
  19. Python map() 函数 特殊用法
  20. 牛客网-《刷C语言百题》第三期

热门文章

  1. 神经网络与深度学习笔记汇总三
  2. angular5监听浏览器的前进和后退按钮(PlatformLocation)
  3. python 局域网通信 socket server client
  4. 简简单单右键菜单-闲情偶寄-iteye技术网站
  5. vector的find
  6. python参考手册小说_用Python给自己DIY一款小说阅读器,你要不看看?
  7. Android图片底部对齐(scaleType底部对齐)
  8. php execl内存不足,PHPExcel读取Excel文件出现内存不足 各种情况处理办法
  9. 关于并行计算的相关总结
  10. 修改windows启动画面:Logonui.exe