音频播放(iOS开发)
音频处理
一.录音
- 录音应用场景
- 语音聊天
- 即时通讯软件中,都包含语音发送功能
- 语音备忘录
- 录一段音频,来记录某件事情
- 语音聊天
- 录音功能实现
- 导入AVFoundation框架
- 作用:一些多媒体的处理,基本上都是用这个框架
- #import <AVFoundation/AVFoundation.h>
- 使用AVAudioRecorder进行录音
- 创建录音文件存放路径
- 设置录音附加设置项
- #import <AVFoundation/AVAudioSettings.h>
- 录音参数设置,保存到字典中,不需要掌握,固定的设置
- 设置编码格式:AVFormatIDKey
- 采样率:AVSampleRateKey
- 通道数:AVNumberOfChannelsKey
- 音频质量,采样质量:AVEncoderAudioQualityKey
- 根据路径以及设置项,创建录音对象
- _audioRecorder = [[AVAudioRecorder alloc] initWithURL:url settings:recordSettings error:nil];
- 准备录音
- [self.audioRecorder prepareToRecord];
- 开始录音
- [self.audioRecorder record];
- 停止录音
- [self.audioRecorder stop];
- 导入AVFoundation框架
- 概念补充
- 编码
- 概念:编码是信息从一种形式转换为另一种形式的过程
- 编码格式:
- PCM:脉冲编码调制,是一种非压缩音频数字化技术,是一种未压缩的原音重现,数字模式下,音频的厨师信号是PCM
- MP3
- AAC:AAC其实是"高级音频编码(advanced audio coding)"的缩写,它是被设计用来取代MP3格式的
- HE-AAC:HE-AAC是AAC的一个超集,这个"HE"代表的是"high efficiency",HE-AAC是专门为低比特率所优化的一种音频编码格式
- AMR:AMR全称是"adaptive multi-rate"的缩写,它也是专门为低比特率所优化的一种音频编码格式
- ALAC:它全称是"Apple Lossless",这是一种没有任何质量损失的音频编码方式,也就是我们说的无损压缩
- IMA4:这是一个在16bit音频文件下按照4:1的压缩比来进行压缩的格式
- 文件格式(不同的文件格式,可保存不同的编码格式编码的文件)
- wav
- 特点:音质最好的格式,对应PCM编码
- 适用:多媒体开发/保存音乐/音效素材
- mp3
- 特点:音质好,压缩比比较高,被大量软件和硬件支持
- 适用:适合用于比较高要求的音乐欣赏
- caf
- 特点:适用于几乎iOS中所有的编码格式
- wav
- 编码
- 开发经验
- caf文件格式,因为某些编码设置,文件可能会很大,而且caf格式并不是很通用,所以在开发过程中,一般会进行压缩转码为MP3格式
- lame静态库
- 简介
- LAME是一个开源的MP3音频压缩软件
- LAME是一个递归缩写,来自LAME Ain't an MP3 Encoder(LAME不是MP3编码器)
- 它自1998年以来由一个开源社区开发,目前是公认有损品质MP3中压缩效果最好的编码器
- 提升权限
- sudo -s
- 下载lame的最新版本并解压
- 生成静态库
- 下载build的脚本
- 修改脚本权限(所有人有可执行权限)
- chmod a+x 脚本名称
- 执行脚本
- ./脚本名称
- 导入静态库到工程,开始使用
- 简介
二.音效播放
1.音效概念简介
- 音效和音乐的区别
- 其实并没有严格意义上的限定,一般在开发中,将时间比较短,播放频率比较高的,当做音效处理
- 将播放时间比较长,需要监听播放进度,控制播放速率等操作的音频当做音乐处理
2.导入AVFoundation框架
- 其实音效处理对应的框架是AudioToolbox,只不过AVFoundation框架包含了此框架
3.使用对应的API,开始播放音效
- 根据音效文件,生成SystemSoundID
- 获取URL
- CFURLRef urlRef = (__bridge CFURLRef)([[NSBundle mainBundle] URLForResource:@"m_16.wav" withExtension:nil]);
- 创建保存soundID的变量
- SystemSoundID soundID;
- 通过URL和SoundID的地址,接收对应的音效SoundID
- AudioServicesCreateSystemSoundID(urlRef, &soundID);
- 获取URL
- 播放音效
- AudioServicesPlaySystemSound(soundID);
- 效果:直接播放,没有震动效果
- AudioServicesPlayAlertSound(soundID);
- 效果:直接播放,有震动效果
- AudioServicesPlaySystemSoundWithCompletion(soundID,block);
- 效果:带有播放完成回调代码块
- AudioServicesPlaySystemSound(soundID);
- 根据SoundID释放内存
- AudioServicesDisposeSystemSoundID(soundID);
- 代码优化,播放工具类的封装
- 优化SoundID的生成,不需要每次都创建一遍
- 封装播放逻辑,供多处调用
三.音乐播放
1.音乐播放
- 导入AVFoundation框架
- 使用AVAudioPlayer类,进行播放音乐
- 根据音频文件URL,创建AVAudioPlayer对象
- 获取资源URL
- NSURL *url = [[NSBundle mainBundle] URLForResource:@"test.mp3" withExtension:nil];
- 根据资源URL,创建AVAudioPlayer对象
- AVAuioPlayer audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
- 获取资源URL
- 准备播放
- [self.audioPlayer prepareToPlay];
- 开始播放
- [self.audioPlayer play];
- 根据音频文件URL,创建AVAudioPlayer对象
- 附加设置
- 暂停
- [self.audioPlayer pause];
- 停止
- [self.audioPlayer stop];
- 停止某个音乐,下次再播放,会从当前位置开始播放
- self.audioPlayer.currentTime = 0;
- 重置当前播放时间
- [self.audioPlayer stop];
- 快进
- 系统已经对currentTime做了容错处理,不用担心事件为负数或者大于音乐总时长
- self.audioPlayer.currentTime += 5;
- 倍速播放
- 1.0为正常
- 设置允许调整播放速率,注意,此方法必须设置在准备播放之前(经测试,在播放前也可以)
- self.audioPlayer = nil;
- self.audioPlayer.enableRate = YES;
- self.audioPlayer.rate = 2.0;
- 音量调节
- 音量调节范围:0.0~1.0
- self.audioPlayer.volume = slider.value;
- 监听播放事件
- 设置代理
- 实现代理方法
- 暂停
- 后台播放
- 注意:模拟器测试不准确,以真机为准
- 勾选后台模式
- 激活音频播放会话
- 在iOS中每个应用都有一个音频会话,这个会话就可以通过AVAudioSessiion来表示
- AVAudioSession同样存在于AVFoundation框架中,它是单例模式设计,通过sharedInstance进行访问
- 音频会话类型简介
- AVAudioSessionCategoryAmbient
- 混音播放,可以与其他音频应用同时播放
- AVAudioSessionCategorySoloAmbient
- 独占播放
- AVAudioSessionCategoryPlayback
- 后台播放,也是独占的
- AVAudioSessionCategoryRecord
- 录音模式,用于录音时使用
- AVAudioSessionCategoryPlayAndRecord
- 播放和录音,此时可以录音也可以播放
- AVAudioSessionCategoryProcessing
- 硬件解码音频,此时不能播放和录制
- AVAudioSessionCategoryMultiRoute
- 多种输入输出,例如可以耳机/USB设备同时播放
- AVAudioSessionCategoryAmbient
- 代码实现
- 获取音频会话
- AVAudioSession *session = [AVAudioSession sharedInstace];
- 设置会话分类
- [session setCategory: AVAudioSessionCategoryPlayback error:nil];
- 激活会话
- [session setActive:YES error:nil];
- 获取音频会话
- 代码封装重构(注意容错处理)
- 结合QQ音乐案例进行封装
- 使用须知
- 每一个AVPlayer对象对应一个音频播放,如果想播放多个音频,就需要创建多个AVPlayer
- 使用AVAudioPlayer类,只能播放本地资源,不能播放远程音乐
- 测试环境
- 后台播放,需要使用真机进行测试,模拟器测试不准确
2.模仿QQ音乐
- 搭建项目结构
- 划分项目功能模块,创建文件夹结构
- 音乐列表
- 主要负责展示音乐列表,当点击某一个音乐时,就播放对应音乐,停止其他音乐播放
- 音乐详情
- 主要负责展示音乐详情,包含音乐名称/歌手/专辑图片/歌词/进度以及控制逻辑
- 音乐列表
- 拖入必要的资源和工具类,以及第三方框架(可以使用时再拖入)
- 根据界面跳转逻辑,搭建Storyboard,并创建好对应的控制器
- 导航控制器为初始控制器,其根控制器为UITableViewController(QQ音乐列表控制器)
- 当点击QQ音乐列表控制器某一行时,跳转到详情控制爱UIViewController
- 划分项目功能模块,创建文件夹结构
- 实现音乐列表功能
- 界面基本设置
- 背景图片
- 隐藏导航栏
- 状态栏设置为白色
- 加载QQ列表数据
- 经验:千万不要把获取数据的实现逻辑写在控制器中,不利于维护和重用,也不利于后期扩展
- 创建数据模型
- 根据音乐列表plist文件内容,创建对应的音乐数据模型xxxMusicModel
- 创建数据操作工具类
- 主要负责数据的获取,和以后数据的操作
- 此处提供,供外界调用的获取数据的接口
- 请使用block将数据传递出去,不要直接返回一个数组(因为后期如果改为从网络获取列表,因为网络获取数据是异步的,所以返回的结果可能为nil)
- 获取所有音乐列表的接口如下:
- getMusicModelsWithResultBlock:block
- 在表格控制器内,调用数据操作类提供的接口,加载数据并显示
- 音乐列表界面展示
- 使用自定义cell,以便后期扩充
- 预留好对接接口
- 经验:知道到时候在哪里调用真正的外接播放接口/停止接口,为了统一管理
- 播放接口
- 停止播放接口
- 实现音乐播放功能
- 经验:千万不要把播放的业务实现逻辑直接写在控制器里面,应当抽取一个工具类
- 高级经验:针对于音乐播放功能,建议分为两层
- 最底层负责单个音乐的播放/暂停/停止等操作
- 上层则负责播放的业务逻辑,比如上一首/下一首/随机播放/顺序播放等
- 这样易于维护,重用和扩展
- 封装单个音乐文件操作的工具类(xxxAudioTool)
- 接口1:根据音频名称播放音频
- playAudioWithName:
- 接口2:暂停音频
- pauseCurrentAudio
- 接口3:停止音频
- stopCurrentAudio
- 接口1:根据音频名称播放音频
- 封装多个音乐文件操作的工具类(xxxMusicOperationTool)
- 接口1:根据音乐数据模型,播放一首音乐
- playMusicWithMusicModel:
- 接口2:暂停当前音乐
- pauseCurrentMusic
- 接口3:停止当前音乐
- stopCurrentMusic
- 接口1:根据音乐数据模型,播放一首音乐
- 重要建议:
- 将此工具类设计成为一个单例
- 因为会有很多界面使用,而且多个界面操作的数据一致
- 功能测试
- 在预留接口中,调用工具类的对应接口,然后测试
- 音乐列表功能开发结束
- 界面基本设置
- 详情界面实现
- 音乐详情界面搭建
- 分析界面结构,选择合适控件搭建界面
- 注意将同一组子控件使用一个父控件进行包装,方便添加约束布局
- 稍微不好构思的地方在于歌词界面和专辑界面的切换,需要借助UIScrollView
- 关联属性和方法到对应的详情控制器,方便后续的动画和赋值操作
- 扩展音乐播放工具类接口,实现播放业务逻辑,并展示音乐详情
- 扩展多个音乐操作的工具类(xxxMusicOperationTool)的上一首/下一首等接口
- 接口1:播放上一首音乐
- preMusic
- 接口2:播放下一首音乐
- nextMusic
- 接口1:播放上一首音乐
- 在控制器对应的关联方法中,调用不同的播放接口,进行测试
- 将需要展示的数据按"刷新频率"进行分类,分别提供"单次刷新"和"实时刷新"方法
- 需要根据不同的数据刷新频率,采用不同的刷新策略
- 如果实时刷新,就可以使用NSTimer,使用定时任务不断刷新,展示最新数据,比如播放进度,就需要不断刷新
- 而歌曲图片和作者,只需要刷新一次
- 汇总所有需要刷新的字段,根据字段,创建歌曲播放信息数据模型(此数据模型由多个音乐操作的工具类同一提供)
- 不要非常零散的单独获取,到处拼凑
- 之所以由工具类统一提供歌曲播放信息数据模型,主要原因
- 因为此功能,应该划分到此类的业务逻辑中
- 只有这个类,最了解当前音乐的播放信息
- 直接从控制器预留的"单次刷新"和"实时刷新"刷新方法中,从多个音乐操作的工具类中获取最新的音乐播放数据
- 扩展多个音乐操作的工具类(xxxMusicOperationTool)的上一首/下一首等接口
- 实时更新歌词,并实现进度展示
- 创建歌词数据模型(xxxLrcModel)
- 属性列表
- 每一句歌词开始时间
- @property (nonatomic, assign) double beginTime;
- 每一句歌词结束时间
- @property (nonatomic, assign) double endTime;
- 每一句歌词的内容
- @property (nonatomic, copy) NSString *lrcText;
- 创建歌词解析工具类(xxxLrcTool),负责解析不同歌曲对应的歌词文件
- 根据歌词文件名称,解析歌词
- getLrcModelsWithLrcName:
- 根据某个时间点,获取歌词模型数组中对应的歌词模型
- getLrcModelInModels:withTime:
- 根据歌词文件名称,解析歌词
- 使用UITableView展示歌词
- 单独抽离一个控制器,负责管理歌词
- 根据当前播放进度,实时滚动切换歌词
- 根据每句歌词的播放进度,通过颜色展示单句歌词进度
- 自定义集成自UILabel的子类
- 重写drawRect:方法
- CGRect fillRect = CGRectMake(0,0,rect.size.width*self.progress,rect.size.height);
- [[UIColor greenColor] set];
- UIRectFillUsingBlendMode(fillRect,kCGBlendModeSourceIn);
- 创建歌词数据模型(xxxLrcModel)
- 音乐详情界面搭建
- 后台播放实现
- 勾选后台模式->音频播放
- 激活音频播放会话
- 获取音频会话
- 设置会话分类
- 激活会话
- 显示锁屏界面,并接收远程事件
- 显示锁屏信息
- 获取锁屏信息中心
- MPNowPlayingInfoCenter *playInfoCenter = [MPNowPlayingInfoCenter defaultCenter];
- 创建锁屏信息(信息从多音乐操作工具类中获取,并保存到可变字典dic中)
- 设置锁屏信息
- playInfoCenter.nowPlayingInfo = dic;
- 接收远程控制事件
- [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
- 获取锁屏信息中心
- 接收远程事件
- 可以监听远程事件的前提
- 必须启动远程事件接收
- 必须可以成为第一响应者
- 应用程序必须是该事件的控制者
- 在控制器中需要实现的方法
- remoteControlReceivedWithEvent:
- 补充:事件类型对应的含义
- UIEventSubtypeNone
- 不包含任何字事件类型
- UIEventSubtypeMotionShake
- 摇晃事件(从iOS3.0开始支持此事件)
- 远程控制自事件类型(从iOS4.0开始支持远程控制事件)
- UIEventSubtypeRemoteControlPlay
- 播放事件(操作:停滞状态下,按二级线控中间按钮一下)
- UIEventSubtypeRemoteControlPause
- 暂停事件
- UIEventSubtypeRemoteControlStop
- 停止事件
- UIEventSubtypeRemoteControlTogglePlayPause
- 播放或暂停切换(操作:播放或暂停状态下,按耳机线控中间按钮一下)
- UIEventSubtypeRemoteControlNextTrack
- 下一曲(操作:按耳机线控中间按钮两下)
- UIEventSubtypeRemoteControlPreviousTrack
- 上一曲(操作:按耳机线控中间按钮三下)
- UIEventSubtypeRemoteControlBeginSeekingBackward
- 快退开始(操作:按耳机线控中间按钮三下不要松开)
- UIEventSubtypeRemoteControlEndSeekingBackward
- 快退停止(操作:按耳机线控中间按钮三下到了快退的位置松开)
- UIEventSubtypeRemoteControlBeginSeekingForward
- 快进开始(操作:按耳机线控中间按钮两下不要松开)
- UIEventSubtypeRemoteControlEndSeekingForward
- 快进停止(操作:按耳机线控中间按钮两下到了快进的位置松开)
- UIEventSubtypeNone
- 可以监听远程事件的前提
- 显示锁屏信息
- 锁屏界面显示歌词
- 实现方案:利用锁屏显示图片设置项,实时的将歌词绘制到图片上,组成一个新的图片,设置为锁屏的图片
- 绘制步骤
- 开启图形上下文
- 绘制背景图片
- 获取歌词信息,并绘制
- 从图形上下文中获取混合图片
- 关闭图形上下文
- 注意:效率优化
- 功能完善,细节处理
- 通过进度条拖拽,控制播放进度
- 通过点击进度条某个位置,控制播放进度
- 自动播放下一首
- 列表歌词页的歌词进度展示
- iOS9.0新推出的Storyboard Reference
3.播放远程音乐
- 使用AVPlayer来播放远程音乐
- 方案1:
- 根据URL,创建AVPlayer
- self.player = [[AVPlayer alloc] initWithURL:remoteURL];
- 播放
- [self.player play];
- 根据URL,创建AVPlayer
- 方案2:
- 根据AVPlayerItem,创建AVPlayer
- NSURL *remoteURL = [NSURL URLWithString:remoteURL];
- AVPlayerItem *playerItem = [AVPlayerItem playerItemWihtURL:remoteURL];
- self.player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
- 播放
- [self.player play];
- 根据AVPlayerItem,创建AVPlayer
- 方案对比
- 如果通过方案1播放某个远程音频,那么后面如果想要更改音乐,则需要重新创建AVPlayer对象
- 方案2就可以直接通过更改播放项来间接更换播放远程音乐
音频播放(iOS开发)的更多相关文章
- 聊聊iOS开发中耳机的那点事(监听耳机拔插、耳机线控)-b
如果说一个项目出现的最重大的事故,那无疑就是开发人员使用了不可控的元素. 前言 iOS开发当中有关于视音频播放的开发不在少数,用户时常会使用到一种输出设备,那就是"耳机",这一篇博 ...
- 最简单的视音频播放示例9:SDL2播放PCM
本文记录SDL播放音频的技术.在这里使用的版本是SDL2.实际上SDL本身并不提供视音频播放的功能,它只是封装了视音频播放的底层API.在Windows平台下,SDL封装了Direct3D这类的API ...
- 最简单的视音频播放示例7:SDL2播放RGB/YUV
本文记录SDL播放视频的技术.在这里使用的版本是SDL2.实际上SDL本身并不提供视音频播放的功能,它只是封装了视音频播放的底层API.在Windows平台下,SDL封装了Direct3D这类的API ...
- 最简单的视音频播放演示样例7:SDL2播放RGB/YUV
===================================================== 最简单的视音频播放演示样例系列文章列表: 最简单的视音频播放演示样例1:总述 最简单的视音频 ...
- 视频和音频播放的演示最简单的例子9:SDL2广播PCM
===================================================== 最简单的视频和音频播放的演示样品系列列表: 最简单的视音频播放演示样例1:总述 最简单的视音 ...
- iOS开发系列--音频播放、录音、视频播放、拍照、视频录制
--iOS多媒体 概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制, ...
- IOS开发之简单音频播放器
今天第一次接触IOS开发的UI部分,之前学OC的时候一直在模拟的使用Target-Action回调模式,今天算是真正的用了一次.为了熟悉一下基本控件的使用方法,和UI部分的回调,下面开发了一个特别简易 ...
- iOS开发----音频播放、录音、视频播放、拍照、视频录制
随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操 ...
- iOS开发拓展篇—封装音频文件播放工具类
iOS开发拓展篇—封装音频文件播放工具类 一.简单说明 1.关于音乐播放的简单说明 (1)音乐播放用到一个叫做AVAudioPlayer的类 (2)AVAudioPlayer常用方法 加载音乐文件 - ...
随机推荐
- WebService积累
1.缺点,无法传输复杂对象:如无法序列化key/value结构的类型参数以及相关一维集合接口(Hashtable等打上标签[Serializable]即可序列化,不过继承的IDictionary并不可 ...
- Java OCR tesseract 图像智能字符识别技术 Java实现
Java OCR tesseract 图像智能字符识别技术 Java代码实现 接着上一篇OCR所说的,上一篇给大家介绍了tesseract 在命令行的简单用法,当然了要继承到我们的程序中,还是需要代码 ...
- Oracle----Key Word
desc|describe table_name DCL----column ----add -- add one column alter table product ); -- add multi ...
- CHANGE DEFAULT FTP PORT FOR VSFTP
http://twincreations.co.uk/change-default-ftp-port-for-vsftp/ http://www.cnblogs.com/kuliuheng/p/320 ...
- 从一个脚本谈loadrunner的脚本初始化
昨天一个同事问我,如何实现下列代码中 InputStream类is对象的实例化? * LoadRunner Java script. (Build: _build_number_) * * Scrip ...
- LINUX中的虚拟文件系统结构
我的博客:www.while0.com 以下以2.6.32版本的内核源码为例: 虚拟文件系统与具体文件系统之间是几组操作函数的对应,包括file_operations,dentry_operation ...
- amaze UI的使用
1.放置在独立的位置 2.引入核心css与js <link href="{sh::PUB}amaze-ui/css/amazeui.min.css" rel="st ...
- 【转】 Xcode基本操作 -- 不错
原文网址:http://blog.csdn.net/phunxm/article/details/17044337 1.Xcode IDE概览 说明:从左到右,依次是“导航窗格(Navigator)- ...
- spring jdbc.property的配置与使用
jdbc.properties driver=com.mysql.jdbc.Driver url=jdbc:mysql://127.0.0.1:3306/ssi1 username=root pass ...
- android Service Activity三种交互方式(付源码)
android SDK提供了Service,用于类似Linix守护进程或者windows的服务. Service有两种类型: 本地服务(Local Service):用于应用程序内部 远程服务(Rem ...