zoukankan      html  css  js  c++  java
  • 音频播放(iOS开发)

    音频处理

    一.录音

    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就可以直接通过更改播放项来间接更换播放远程音乐
  • 相关阅读:
    SAP PI 如何实现消息定义查询
    EWM与ERP交互程序
    ITS Mobile Template interpretation failed. Template does not exist
    SAP Material Flow System (MFS) 物料流系统简介
    SAP EWM Table list
    EWM RF 屏幕增强
    SAP EWM TCODE list
    SAP扩展仓库管理(SAPEWM)在线研讨会笔记
    ERP与EWM集成配置ERP端组织架构(二)
    EWM RF(Radio Frequency)简介
  • 原文地址:https://www.cnblogs.com/coderwjq/p/6236265.html
Copyright © 2011-2022 走看看