iOS音频播放(一)

转载: http://msching.github.io/blog/2014/07/07/audio-in-ios/

从事音乐相关的app开发也已经有一段时日了,在这过程中app的播放器几经修改我也因此对于iOS下的音频播放实现有了一定的研究。写这个系列的博客目的一方面希望能够抛砖引玉,另一方面也是希望能帮助国内其他的iOS开发者和爱好者少走弯路(我自己就遇到了不少的坑=。=)。

本篇为《iOS音频播放》系列的第一篇,主要将对iOS下实现音频播放的方法进行概述。

基础

先来简单了解一下一些基础的音频知识。 目前我们在计算机上进行音频播放都需要依赖于音频文件,音频文件的生成过程是将声音信息采样、量化和编码产生的数字信号的过程,人耳所能听到的声音,最低的频率是从20Hz起一直到最高频率20KHZ,因此音频文件格式的最大带宽是20KHZ。根据奈奎斯特的理论,只有采样频率高于声音信号最高频率的两倍时,才能把数字信号表示的声音还原成为原来的声音,所以音频文件的采样率一般在40~50KHZ,比如最常见的CD音质采样率44.1KHZ。

对声音进行采样、量化过程被称为脉冲编码调制(Pulse Code Modulation),简称PCM。PCM数据是最原始的音频数据完全无损,所以PCM数据虽然音质优秀但体积庞大,为了解决这个问题先后诞生了一系列的音频格式,这些音频格式运用不同的方法对音频数据进行压缩,其中有无损压缩(ALAC、APE、FLAC)和有损压缩(MP3、AAC、OGG、WMA)两种。

目前最为常用的音频格式是MP3,MP3是一种有损压缩的音频格式,设计这种格式的目的就是为了大幅度的减小音频的数据量,它舍弃PCM音频数据中人类听觉不敏感的部分,从下面的比较图我们可以明显的看到MP3数据相比PCM数据明显矮了一截(图片引自imp3论坛)。

上图为pcm数据

上图为mp3数据

MP3格式中的码率(BitRate)代表了MP3数据的压缩质量,现在常用的码率有128kbit/s、160kbit/s、320kbit/s等等,这个值越高声音质量也就越高。MP3编码方式常用的有两种固定码率(Constant bitrate,CBR)和可变码率(Variable bitrate,VBR)。

MP3格式中的数据通常由两部分组成,一部分为ID3用来存储歌名、演唱者、专辑、音轨数等信息,另一部分为音频数据。音频数据部分以帧(frame)为单位存储,每个音频都有自己的帧头,如图所示就是一个MP3文件帧结构图(图片同样来自互联网)。MP3中的每一个帧都有自己的帧头,其中存储了采样率等解码必须的信息,所以每一个帧都可以独立于文件存在和播放,这个特性加上高压缩比使得MP3文件成为了音频流播放的主流格式。帧头之后存储着音频数据,这些音频数据是若干个PCM数据帧经过压缩算法压缩得到的,对CBR的MP3数据来说每个帧中包含的PCM数据帧是固定的,而VBR是可变的。 [

]

iOS音频播放概述

了解了基础概念之后我们就可以列出一个经典的音频播放流程(以MP3为例):

  • 读取MP3文件
  • 解析采样率、码率、时长等信息,分离MP3中的音频帧
  • 对分离出来的音频帧解码得到PCM数据
  • 对PCM数据进行音效处理(均衡器、混响器等,非必须)
  • 把PCM数据解码成音频信号
  • 把音频信号交给硬件播放
  • 重复1-6步直到播放完成

在iOS系统中apple对上述的流程进行了封装并提供了不同层次的接口(图片引自官方文档)。

CoreAudio的接口层次

下面对其中的中高层接口进行功能说明:

  • Audio File Services:读写音频数据,可以完成播放流程中的第2步;
  • Audio File Stream Services:对音频进行解码,可以完成播放流程中的第2步;
  • Audio Converter services:音频数据转换,可以完成播放流程中的第3步;
  • Audio Processing Graph Services:音效处理模块,可以完成播放流程中的第4步;
  • Audio Unit Services:播放音频数据:可以完成播放流程中的第5步、第6步;
  • Extended Audio File Services:Audio File Services和Audio Converter services的结合体;
  • AVAudioPlayer/AVPlayer(AVFoundation):高级接口,可以完成整个音频播放的过程(包括本地文件和网络流播放,第4步除外);
  • Audio Queue Services:高级接口,可以进行录音和播放,可以完成播放流程中的第3、5、6步;
  • OpenAL:用于游戏音频播放,暂不讨论

可以看到apple提供的接口类型非常丰富,可以满足各种类别类需求:

  • 如果你只是想实现音频的播放,没有其他需求AVFoundation会很好的满足你的需求。它的接口使用简单、不用关心其中的细节;
  • 如果你的app需要对音频进行流播放并且同时存储,那么AudioFileStreamer加AudioQueue能够帮到你,你可以先把音频数据下载到本地,一边下载一边用NSFileHandler等接口读取本地音频文件并交给AudioFileStreamer或者AudioFile解析分离音频帧,分离出来的音频帧可以送给AudioQueue进行解码和播放。如果是本地文件直接读取文件解析即可。(这两个都是比较直接的做法,这类需求也可以用AVFoundation+本地server的方式实现,AVAudioPlayer会把请求发送给本地server,由本地server转发出去,获取数据后在本地server中存储并转送给AVAudioPlayer。另一个比较trick的做法是先把音频下载到文件中,在下载到一定量的数据后把文件路径给AVAudioPlayer播放,当然这种做法在音频seek后就回有问题了。);
  • 如果你正在开发一个专业的音乐播放软件,需要对音频施加音效(均衡器、混响器),那么除了数据的读取和解析以外还需要用到AudioConverter来把音频数据转换成PCM数据,再由AudioUnit+AUGraph来进行音效处理和播放(但目前多数带音效的app都是自己开发音效模块来坐PCM数据的处理,这部分功能自行开发在自定义性和扩展性上会比较强一些。PCM数据通过音效器处理完成后就可以使用AudioUnit播放了,当然AudioQueue也支持直接使对PCM数据进行播放。)。下图描述的就是使用AudioFile + AudioConverter + AudioUnit进行音频播放的流程(图片引自官方文档)。

下篇预告

下一篇将讲述iOS音频播放中必须面对的难(da)题(keng),AudioSession。

参考资料

音频文件格式 脉冲编码调制 采样率 奈奎斯特频率 MP3 ID3 Core Audio Essential Common Tasks in OS X

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 「SDL第七篇」PCM音频播放器的实现

    如果我们要播放一段声音,想当然的认为直接将播放的声音发送给声卡,这样扬声器就会将声音播放出来。只要我们不断的送数据,声音就会不停的输出。

    音视频_李超
  • RTMP播放流媒体过程

    服务器和客户端之间只能建立一个网络连接,但是基于该连接可以创建很多网络流。他们的关系如图所示:

    音视频_李超
  • 「转」javascript中的prototype

    在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例。但是在Javascript语言体系中,是不存在类(Cla...

    音视频_李超
  • 从JVM堆内存分析验证深浅拷贝

    在重写性能测试框架的过程中,遇到一个问题,每个线程都要收集一些统计数据,但是在我之前的框架Demo里面有一种情况:单一的threadbase线程任务,多线程并发...

    FunTester
  • “优”有突破|腾讯优图团队再创佳绩,刷新人脸识别世界纪录

    近日,在国际权威人脸识别数据库LFW上,腾讯优图团队提交了在无限制条件下人脸验证测(unrestrictedlabeledoutsidedata)中的最新成绩,...

    优图实验室
  • Centos8 - 图形界面和命令行切换

    小菠萝测试笔记
  • 哲思片段 | 设计中的变与不变

    古希腊哲学家巴门尼德认为:“人的思想和言语都有一个载体,如果你在这一时间和另外一个时间想到或者谈到同样一件东西,那就说明这件东西在这段时间内没有变化,如有变化的...

    张逸
  • 浅谈FPGA与音频处理器的结合

    FPGA通常是面向通信行业,尽管其主要开发者仍然专注于通信应用, 但他们越来越关注存储和服务器市场。

    半吊子全栈工匠
  • MySQL information_schema详解 FILES

    它提供InnoDB数据文件的信息,如果是NDB,它提供了有关存储了NDB集群磁盘数据表的文件的信息。

    bsbforever
  • GreenDao教程2

    可以多次使用where(),进行多次筛选,也可以使用whereOr()语句,进行或语句查找

    用户3030674

扫码关注云+社区

领取腾讯云代金券