音频处理

一.录音

  1. 录音应用场景

    • 语音聊天

      • 即时通讯软件中,都包含语音发送功能
    • 语音备忘录
      • 录一段音频,来记录某件事情
  2. 录音功能实现
    • 导入AVFoundation框架

      • 作用:一些多媒体的处理,基本上都是用这个框架
      • #import <AVFoundation/AVFoundation.h>
    • 使用AVAudioRecorder进行录音
      1. 创建录音文件存放路径
      2. 设置录音附加设置项
        • #import <AVFoundation/AVAudioSettings.h>
        • 录音参数设置,保存到字典中,不需要掌握,固定的设置
        • 设置编码格式:AVFormatIDKey
        • 采样率:AVSampleRateKey
        • 通道数:AVNumberOfChannelsKey
        • 音频质量,采样质量:AVEncoderAudioQualityKey
      3. 根据路径以及设置项,创建录音对象
        • _audioRecorder = [[AVAudioRecorder alloc] initWithURL:url settings:recordSettings error:nil];
      4. 准备录音
        • [self.audioRecorder prepareToRecord];
      5. 开始录音
        • [self.audioRecorder record];
      6. 停止录音
        • [self.audioRecorder stop];
  3. 概念补充
    • 编码

      • 概念:编码是信息从一种形式转换为另一种形式的过程
      • 编码格式:
        • 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中所有的编码格式
  4. 开发经验
    • caf文件格式,因为某些编码设置,文件可能会很大,而且caf格式并不是很通用,所以在开发过程中,一般会进行压缩转码为MP3格式
  5. lame静态库

二.音效播放

1.音效概念简介

  • 音效和音乐的区别

    • 其实并没有严格意义上的限定,一般在开发中,将时间比较短,播放频率比较高的,当做音效处理
    • 将播放时间比较长,需要监听播放进度,控制播放速率等操作的音频当做音乐处理

2.导入AVFoundation框架

  • 其实音效处理对应的框架是AudioToolbox,只不过AVFoundation框架包含了此框架

3.使用对应的API,开始播放音效

  1. 根据音效文件,生成SystemSoundID

    • 获取URL

      • CFURLRef urlRef = (__bridge CFURLRef)([[NSBundle mainBundle] URLForResource:@"m_16.wav" withExtension:nil]);
    • 创建保存soundID的变量
      • SystemSoundID soundID;
    • 通过URL和SoundID的地址,接收对应的音效SoundID
      • AudioServicesCreateSystemSoundID(urlRef, &soundID);
  2. 播放音效
    • AudioServicesPlaySystemSound(soundID);

      • 效果:直接播放,没有震动效果
    • AudioServicesPlayAlertSound(soundID);
      • 效果:直接播放,有震动效果
    • AudioServicesPlaySystemSoundWithCompletion(soundID,block);
      • 效果:带有播放完成回调代码块
  3. 根据SoundID释放内存
    • AudioServicesDisposeSystemSoundID(soundID);
  4. 代码优化,播放工具类的封装
    • 优化SoundID的生成,不需要每次都创建一遍
    • 封装播放逻辑,供多处调用

三.音乐播放

1.音乐播放

  1. 导入AVFoundation框架
  2. 使用AVAudioPlayer类,进行播放音乐
    • 根据音频文件URL,创建AVAudioPlayer对象

      • 获取资源URL

        • NSURL *url = [[NSBundle mainBundle] URLForResource:@"test.mp3" withExtension:nil];
      • 根据资源URL,创建AVAudioPlayer对象
        • AVAuioPlayer audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
    • 准备播放
      • [self.audioPlayer prepareToPlay];
    • 开始播放
      • [self.audioPlayer play];
  3. 附加设置
    • 暂停

      • [self.audioPlayer pause];
    • 停止
      • [self.audioPlayer stop];

        • 停止某个音乐,下次再播放,会从当前位置开始播放
      • self.audioPlayer.currentTime = 0;
        • 重置当前播放时间
    • 快进
      • 系统已经对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;
    • 监听播放事件
      • 设置代理
      • 实现代理方法
  4. 后台播放
    • 注意:模拟器测试不准确,以真机为准
    • 勾选后台模式
    • 激活音频播放会话
      • 在iOS中每个应用都有一个音频会话,这个会话就可以通过AVAudioSessiion来表示
      • AVAudioSession同样存在于AVFoundation框架中,它是单例模式设计,通过sharedInstance进行访问
      • 音频会话类型简介
        • AVAudioSessionCategoryAmbient

          • 混音播放,可以与其他音频应用同时播放
        • AVAudioSessionCategorySoloAmbient
          • 独占播放
        • AVAudioSessionCategoryPlayback
          • 后台播放,也是独占的
        • AVAudioSessionCategoryRecord
          • 录音模式,用于录音时使用
        • AVAudioSessionCategoryPlayAndRecord
          • 播放和录音,此时可以录音也可以播放
        • AVAudioSessionCategoryProcessing
          • 硬件解码音频,此时不能播放和录制
        • AVAudioSessionCategoryMultiRoute
          • 多种输入输出,例如可以耳机/USB设备同时播放
    • 代码实现
      • 获取音频会话

        • AVAudioSession *session = [AVAudioSession sharedInstace];
      • 设置会话分类
        • [session setCategory: AVAudioSessionCategoryPlayback error:nil];
      • 激活会话
        • [session setActive:YES error:nil];
  5. 代码封装重构(注意容错处理)
    • 结合QQ音乐案例进行封装
  6. 使用须知
    • 每一个AVPlayer对象对应一个音频播放,如果想播放多个音频,就需要创建多个AVPlayer
    • 使用AVAudioPlayer类,只能播放本地资源,不能播放远程音乐
  7. 测试环境
    • 后台播放,需要使用真机进行测试,模拟器测试不准确

2.模仿QQ音乐

  1. 搭建项目结构

    • 划分项目功能模块,创建文件夹结构

      • 音乐列表

        • 主要负责展示音乐列表,当点击某一个音乐时,就播放对应音乐,停止其他音乐播放
      • 音乐详情
        • 主要负责展示音乐详情,包含音乐名称/歌手/专辑图片/歌词/进度以及控制逻辑
    • 拖入必要的资源和工具类,以及第三方框架(可以使用时再拖入)
    • 根据界面跳转逻辑,搭建Storyboard,并创建好对应的控制器
      • 导航控制器为初始控制器,其根控制器为UITableViewController(QQ音乐列表控制器)
      • 当点击QQ音乐列表控制器某一行时,跳转到详情控制爱UIViewController
  2. 实现音乐列表功能
    • 界面基本设置

      • 背景图片
      • 隐藏导航栏
      • 状态栏设置为白色
    • 加载QQ列表数据
      • 经验:千万不要把获取数据的实现逻辑写在控制器中,不利于维护和重用,也不利于后期扩展
      • 创建数据模型
        • 根据音乐列表plist文件内容,创建对应的音乐数据模型xxxMusicModel
      • 创建数据操作工具类
        • 主要负责数据的获取,和以后数据的操作
        • 此处提供,供外界调用的获取数据的接口
        • 请使用block将数据传递出去,不要直接返回一个数组(因为后期如果改为从网络获取列表,因为网络获取数据是异步的,所以返回的结果可能为nil)
        • 获取所有音乐列表的接口如下:
          • getMusicModelsWithResultBlock:block
      • 在表格控制器内,调用数据操作类提供的接口,加载数据并显示
    • 音乐列表界面展示
      • 使用自定义cell,以便后期扩充
    • 预留好对接接口
      • 经验:知道到时候在哪里调用真正的外接播放接口/停止接口,为了统一管理
      • 播放接口
      • 停止播放接口
    • 实现音乐播放功能
      • 经验:千万不要把播放的业务实现逻辑直接写在控制器里面,应当抽取一个工具类
      • 高级经验:针对于音乐播放功能,建议分为两层
        • 最底层负责单个音乐的播放/暂停/停止等操作
        • 上层则负责播放的业务逻辑,比如上一首/下一首/随机播放/顺序播放等
        • 这样易于维护,重用和扩展
      • 封装单个音乐文件操作的工具类(xxxAudioTool)
        • 接口1:根据音频名称播放音频

          • playAudioWithName:
        • 接口2:暂停音频
          • pauseCurrentAudio
        • 接口3:停止音频
          • stopCurrentAudio
      • 封装多个音乐文件操作的工具类(xxxMusicOperationTool)
        • 接口1:根据音乐数据模型,播放一首音乐

          • playMusicWithMusicModel:
        • 接口2:暂停当前音乐
          • pauseCurrentMusic
        • 接口3:停止当前音乐
          • stopCurrentMusic
      • 重要建议:
        • 将此工具类设计成为一个单例
        • 因为会有很多界面使用,而且多个界面操作的数据一致
    • 功能测试
      • 在预留接口中,调用工具类的对应接口,然后测试
      • 音乐列表功能开发结束
  3. 详情界面实现
    • 音乐详情界面搭建

      1. 分析界面结构,选择合适控件搭建界面
      2. 注意将同一组子控件使用一个父控件进行包装,方便添加约束布局
      3. 稍微不好构思的地方在于歌词界面和专辑界面的切换,需要借助UIScrollView
      4. 关联属性和方法到对应的详情控制器,方便后续的动画和赋值操作
    • 扩展音乐播放工具类接口,实现播放业务逻辑,并展示音乐详情
      1. 扩展多个音乐操作的工具类(xxxMusicOperationTool)的上一首/下一首等接口

        • 接口1:播放上一首音乐

          • preMusic
        • 接口2:播放下一首音乐
          • nextMusic
      2. 在控制器对应的关联方法中,调用不同的播放接口,进行测试
      3. 将需要展示的数据按"刷新频率"进行分类,分别提供"单次刷新"和"实时刷新"方法
        • 需要根据不同的数据刷新频率,采用不同的刷新策略
        • 如果实时刷新,就可以使用NSTimer,使用定时任务不断刷新,展示最新数据,比如播放进度,就需要不断刷新
        • 而歌曲图片和作者,只需要刷新一次
      4. 汇总所有需要刷新的字段,根据字段,创建歌曲播放信息数据模型(此数据模型由多个音乐操作的工具类同一提供)
        • 不要非常零散的单独获取,到处拼凑
        • 之所以由工具类统一提供歌曲播放信息数据模型,主要原因
          • 因为此功能,应该划分到此类的业务逻辑中
          • 只有这个类,最了解当前音乐的播放信息
      5. 直接从控制器预留的"单次刷新"和"实时刷新"刷新方法中,从多个音乐操作的工具类中获取最新的音乐播放数据
    • 实时更新歌词,并实现进度展示
      • 创建歌词数据模型(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);
  4. 后台播放实现
    • 勾选后台模式->音频播放
    • 激活音频播放会话
      • 获取音频会话
      • 设置会话分类
      • 激活会话
  5. 显示锁屏界面,并接收远程事件
    • 显示锁屏信息

      • 获取锁屏信息中心

        • 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
          • 快进停止(操作:按耳机线控中间按钮两下到了快进的位置松开)
  6. 锁屏界面显示歌词
    • 实现方案:利用锁屏显示图片设置项,实时的将歌词绘制到图片上,组成一个新的图片,设置为锁屏的图片
    • 绘制步骤
      1. 开启图形上下文
      2. 绘制背景图片
      3. 获取歌词信息,并绘制
      4. 从图形上下文中获取混合图片
      5. 关闭图形上下文
    • 注意:效率优化
  7. 功能完善,细节处理
    1. 通过进度条拖拽,控制播放进度
    2. 通过点击进度条某个位置,控制播放进度
    3. 自动播放下一首
    4. 列表歌词页的歌词进度展示
    5. iOS9.0新推出的Storyboard Reference

3.播放远程音乐

  • 使用AVPlayer来播放远程音乐
  • 方案1:
    • 根据URL,创建AVPlayer

      • self.player = [[AVPlayer alloc] initWithURL:remoteURL];
    • 播放
      • [self.player play];
  • 方案2:
    • 根据AVPlayerItem,创建AVPlayer

      • NSURL *remoteURL = [NSURL URLWithString:remoteURL];
      • AVPlayerItem *playerItem = [AVPlayerItem playerItemWihtURL:remoteURL];
      • self.player = [[AVPlayer alloc] initWithPlayerItem:playerItem];
    • 播放
      • [self.player play];
  • 方案对比
    • 如果通过方案1播放某个远程音频,那么后面如果想要更改音乐,则需要重新创建AVPlayer对象
    • 方案2就可以直接通过更改播放项来间接更换播放远程音乐

音频播放(iOS开发)的更多相关文章

  1. 聊聊iOS开发中耳机的那点事(监听耳机拔插、耳机线控)-b

    如果说一个项目出现的最重大的事故,那无疑就是开发人员使用了不可控的元素. 前言 iOS开发当中有关于视音频播放的开发不在少数,用户时常会使用到一种输出设备,那就是"耳机",这一篇博 ...

  2. 最简单的视音频播放示例9:SDL2播放PCM

    本文记录SDL播放音频的技术.在这里使用的版本是SDL2.实际上SDL本身并不提供视音频播放的功能,它只是封装了视音频播放的底层API.在Windows平台下,SDL封装了Direct3D这类的API ...

  3. 最简单的视音频播放示例7:SDL2播放RGB/YUV

    本文记录SDL播放视频的技术.在这里使用的版本是SDL2.实际上SDL本身并不提供视音频播放的功能,它只是封装了视音频播放的底层API.在Windows平台下,SDL封装了Direct3D这类的API ...

  4. 最简单的视音频播放演示样例7:SDL2播放RGB/YUV

    ===================================================== 最简单的视音频播放演示样例系列文章列表: 最简单的视音频播放演示样例1:总述 最简单的视音频 ...

  5. 视频和音频播放的演示最简单的例子9:SDL2广播PCM

    ===================================================== 最简单的视频和音频播放的演示样品系列列表: 最简单的视音频播放演示样例1:总述 最简单的视音 ...

  6. iOS开发系列--音频播放、录音、视频播放、拍照、视频录制

    --iOS多媒体 概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制, ...

  7. IOS开发之简单音频播放器

    今天第一次接触IOS开发的UI部分,之前学OC的时候一直在模拟的使用Target-Action回调模式,今天算是真正的用了一次.为了熟悉一下基本控件的使用方法,和UI部分的回调,下面开发了一个特别简易 ...

  8. iOS开发----音频播放、录音、视频播放、拍照、视频录制

    随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操 ...

  9. iOS开发拓展篇—封装音频文件播放工具类

    iOS开发拓展篇—封装音频文件播放工具类 一.简单说明 1.关于音乐播放的简单说明 (1)音乐播放用到一个叫做AVAudioPlayer的类 (2)AVAudioPlayer常用方法 加载音乐文件 - ...

随机推荐

  1. axure rp pro 6.5

    现在地址:http://www.xdowns.com/soft/1/95/2012/Soft_94434.html Axure6.5正式版推出了,大大改善了用户体验以及修复了很多6.0上的bug. 而 ...

  2. Seven Python Tools All Data Scientists Should Know How to Use

    Seven Python Tools All Data Scientists Should Know How to Use If you’re an aspiring data scientist, ...

  3. 被FBI点名的中国黑客-Lion

    网名:Lion(狮子) 真实姓名:林勇 QQ:21509     简介:红客联盟创始人(该组织在2001年5月的黑客大战中一举成名,会员人数最多时达到6万,很有影响力),现在安氏因特网安全系统(中国) ...

  4. Uva 12361 File Retrieval 后缀数组+并查集

    题意:有F个单词,1 <= F <=60 , 长度<=10^4, 每次可以输入一个字符串,所有包含该字串的单词会形成一个集合. 问最多能形成多少个不同的集合.集合不能为空. 分析:用 ...

  5. [jobdu]二叉树的镜像

    树的镜像,这里的做法就是先序遍历的反过来呗. #include <iostream> #include <vector> using namespace std; void p ...

  6. 155. Min Stack

    题目: Design a stack that supports push, pop, top, and retrieving the minimum element in constant time ...

  7. 转载爱哥自定义View系列--Canvas详解

    上面所罗列出来的各种drawXXX方法就是Canvas中定义好的能画什么的方法(drawPaint除外),除了各种基本型比如矩形圆形椭圆直曲线外Canvas也能直接让我们绘制各种图片以及颜色等等,但是 ...

  8. c++模板注意事项

    c++模板类 分类: C++2012-08-20 21:28 7108人阅读 评论(2) 收藏 举报 c++编译器instantiationiostreamlinker编程 c++模板类 分类: 数据 ...

  9. 多设备官方教程(6)控制多版本API

    Supporting Different Platform Versions While the latest versions of Android often provide great APIs ...

  10. hdu4705Y

    链接 这题可以算树形DP吧 树上的递推 对于树上的某个节点 反着算比较好做 就是算有多少有simple路径的 固定某个节点u 另两个节点 有两种取法 1.从不同子树里各选一个 2.从所有子树里选一个 ...