理解 iOS Core Audio 音频概念

在了解 iOS Core Audio 相关技术的时候,会遇到 bitrate、sample、frame 和 packet 等概念。由于业界在不同场合下使用 packet 和 frame 等词语会代表不同的含义,一不小心,很容易被绕进去。

本文讲述了 iOS Core Audio 中常用的音频概念定义,然后介绍一些容易造成概念混淆的场景以及一个实践 demo 案例,最后解答一些常见的问题。

(一) iOS Core Audio 音频概念定义

讨论 iOS Core Audio,就要按照苹果的定义对音频相关概念进行理解。

首先,重点理解 sample, frame 和 packet 三个概念。在 API 文档中中苹果明确定义了 audio stream, channel, sample, frame, packet 和 sample rate 这些概念:

  • A sample is single numerical value for a single audio channel in an audio stream.
  • A frame is a collection of time-coincident samples. For instance, a linear PCM stereo sound file has two samples per frame, one for the left channel and one for the right channel.
  • A packet is a collection of one or more contiguous frames. A packet defines the smallest meaningful set of frames for a given audio data format, and is the smallest data unit for which time can be measured. In linear PCM audio, a packet holds a single frame. In compressed formats, it typically holds more; in some formats, the number of frames per packet varies.

从上面文档定义,简单来说,可以这样理解:

  • sample 是一个声道的一个采样。
  • frame 是最小单位时间点包含的一个或多个声音采样,最小单位时间点取决于声音采样设备,是一个时间点多个采样的集合。譬如,双声道的音频文件,一个时间点有两个声道,一个frame就包括两个采样。
  • packet 是一个或多个 frame 的集合,一个 packet 包含多少个 frame,是由声音文件格式决定的。譬如 PCM 文件格式中一个 packet 包含 1 个frame。而 MP3 文件格式中一个 packet 包含 1152 个frames。

从上面定义来看这三个概念互相独立,定义清晰。

(二)这些概念为什么容易搞混?

然而在日常讨论中,会在多种场合下使用 framepacket 两个词,但是各种场合下它们代表的含义是不同的,所以比较容易搞混。

举下面不同场景的例子来说明:

  1. 在讨论 MPEG 格式的时候,如网上常见的MPEG文件格式介绍,把 MPEG 一个 header + payload (帧头 + 数据内容)的数据结构叫做一个 frame (MPEG数据帧),一个 MPEG 数据帧包含了多个音频帧。事实上这个东东在上述 iOS Core Audio 定义中,却又被称为一个 packet。所以两份文档中,分别使用了 packet 和 frame 两个词指代同一个概念
  2. 网络传输音频的时候,会把音频数据进行打包发送,这个时候也用到 packet 的概念,他有自己独立的 packet header 定义,又跟 iOS Core Audio 定义的 packet 不是同一个了。
  3. 在讨论计算机网络时,硬件数据帧称为 frame,而数据链路层将 frame 打包成 packet 之后提供给上层网络层使用。 这里 frame 和 packet 的概念又跟音频讨论中的含义不一样了。
  4. FFmpeg是一个音/视频编码解码及转换的开源软件。它定义了两个结构体,AVPacket 一份代表经过压缩的音频/视频数据,AVFrame 代表一份解压后的一个音频/视频数据。视频一个 AVPacket 通常只包含一个 AVFrame,经过压缩的音频 AVPacket 通常包括多个 AVFrame。可以看到 FFmpeg 在处理音频和视频时,对 packet 和 frame 概念的使用跟 iOS Core Audio 基本一致。

从上面例子可以看到,不同场景下都使用了 frame 和 packet 两个词语会代表不一样的含义。更糟糕的是,如果使用了中文“帧”,在某些语境下,到底是代表数据帧、音频帧、packet 还是 frame 呢,就更容易分不清楚了。

(三)DEMO:QQ音乐一首歌的音频数据帧

从上面的概念定义,我们搞清楚了 iOS Core Audio 中对 sample, frame 和 packet 的定义,其中 frame 和 packet 又很容易搞混。

下面我们通过分析QQ音乐一首歌的例子,在实践中理解 iOS Core Audio 中对 packet 的定义。

iOS Core Audio 在使用 AudioFileStreamOpen 解码音频文件时候,会要求我们注册 AudioFileStream_PropertyListenerProc 和 AudioFileStream_PacketsProc 两个回调,用于文件读取到属性和包的时候回调。

以QQ音乐中,《最长的电影》这首歌的MP3文件为例,我们每次传入 1000 个字节调用 AudioFileStreamParseBytes 方法,可以得到下面结果(已知音频帧从第 496 个字节开始)。

第1次传入 1000 个字节: 首先回调多次 AudioFileStream_PropertyListenerProc,证明文件前面496个字节是属性。 之后回调一次 AudioFileStream_PacketsProc,回调方法有1个packet,417个字节;二进制内容就是音频数据帧 fffb9044 0008024e…(文件位置:496),没有任何跟文件不一样的多余信息。 然后就没回调了,这时候处理了 496+417 = 913 个字节。传进去的1000个字节,剩下 1000 - 913 = 87 个没处理,因为不能构成一个完整的音频数据帧。

然后传入第2次 1000 个字节: 首先回调 AudioFileStream_PacketsProc,回调418个字节,1个 packet,二进制内容是 fffb9264 29000153…(文件位置913)。 之后第二次继续回调 AudioFileStream_PacketsProc,回调418个字节,1个 packet,二进制内容是 fffb9264 510d0260…(文件位置 913+418=1331)。

可以验证到,AudioStreamPacketDescription 说的 packet ,是指传入数据之后,分离出来的MP3 音频数据帧。注意的链接说这是 MPEG Audio Layer I/II/III frame header,而 iOS Core Audio 使用了 AudioStreamPacketDescription,这里就很容易把 frame 和 packet 的概念搞混。事实上他们是指同一样东西。

看一下 AudioStreamPacketDescription 的代码定义,可以看到它就是一个数据帧 packet,包含了多个音频帧 frame。

(四)答疑

因此,在讨论 iOS Core Audio 相关概念的时候,遇到过的下列疑问都可以解答:

Q: iOS Core Audio 对于 packet 的明确定义是什么? A: 见上述讨论第(一)点。

Q: 为什么经常搞不清楚 packet 和 frame 的区别? A: 见上述讨论第(二)点、(三)实验,因为这两个概念在不同场景下代表不同的含义。

Q: 一个 packet 可以包含半个 frame 吗? A: 从上述(三)实验可以看到,iOS Core Audio 的 packet 至少包含一个 frame,譬如 PCM 就是一个 packet 一个 frame;数据传输的时候的 packet 跟 iOS Core Audio 讨论的概念不一样,有多种不同的协议,相信有些协议可以自己定义传输大小,传送半个帧然后组装成一个帧。

Q: AudioFileStreamParseBytes 每次解析多少个数据帧?可以控制吗? A: 可以控制,对于 CBR 音频格式,基本上你传入多少个字节的数据,就会回调分离多少个数据帧,除非是最后一个不包含完整的 frame;对于 VBR 音频格式,传入一次数据,可能会回调多次分类帧回调。相关说明见AudioFileStream_PacketsProc API 文档最下方。

文中链接 1: https://developer.apple.com/reference/coreaudio/audiostreambasicdescription “苹果 AudioStreamBasicDescription API 文档” 2: http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm “MPEG文件格式介绍” 3: https://en.wikipedia.org/wiki/MPEG_transport_stream “MPEG transport stream” 4: http://ffmpeg.org/ “FFmpeg官网” 5: http://www.ffmpeg.org/doxygen/2.7/structAVPacket.html “FFmpeg AVPacket 文档” 6: http://www.ffmpeg.org/doxygen/2.7/structAVFrame.html “FFmpeg AVFrame 文档” 7: https://developer.apple.com/reference/audiotoolbox/audiofilestream_packetsproc “AudioFileStream_PacketsProc API 文档”

(全文完)

原文发布于微信公众号 - QQ音乐技术团队(gh_287053a877e6)

原文发表时间:2017-05-05

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

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小白课代表

[Android/IOS] | 把微博秒拍Twitter的视频装进口袋里的...

12120
来自专栏PPV课数据科学社区

从 R 迁移到 Python 过程中你需要知道的几个软件库

为什么要用 Python 呢? 我喜欢用 Python 来处理机器学习问题的一个重要原因是 Python 吸取了 R 社区的优点,同时还将其进行了优化打包。我一...

32370
来自专栏哲学驱动设计

090609 T 领域建模

领域建模的重要性     以数据为中心的应用程序开发,面向过程分析方法的核心在于对数据库的设计。     而现在以面向对象的方式进行分析(OOA,OOD)时,领...

20080
来自专栏IT派

你以为越复杂的密码越安全?小心那些错误认知

如何在网络社会中保护自己的个人隐私,长久以来都是一个让人挥之不去的现实问题。几十年的积累,现代人已经完全掌握了密码的“构造”方法,自认为从此便可以真的高枕无忧,...

16320
来自专栏tkokof 的技术,小趣及杂念

“连连看”小析

近段日子与几位同事聊到了“连连看”这个小游戏,感觉还颇有些趣味,虽然其本身规则并不繁琐,但玩起来确实很能让人投入。出于自己的一点追究癖,自己这几天还认真考虑了...

6410
来自专栏WOLFRAM

强大的 Wolfram 11.0(下)

14640
来自专栏PPV课数据科学社区

【学习】《R实战》读书笔记(第一章)

第一章 R简介 本章概要 1安装R 2理解R语言 3运行R程序 本章所介绍的内容概括如下。 一个典型的数据分析步骤如图1所示。 图1:典型数据分析步骤 简而言之...

33580
来自专栏软件成本造价评估

国际上的5大ISO功能点方法标准是哪5种?

在功能点方法的发展演进中,共有5种功能点方法被ISO国际标准组织接受成为了ISO国际功能点标准。这五种方法分别为IFPUG、MARK Ⅱ、COSMIC、NES...

23100
来自专栏AI科技大本营的专栏

浮点峰值那些事儿

本文作者高洋,目前在商汤科技高性能计算组担任总监,对于并行计算颇有心得。本篇为高洋写给高性能并行计算的初学者,核心内容是教初学者用科学手段测量硬件的理论指标。有...

31850
来自专栏数据派THU

独家 | Python数据分析入门指南

作者:Zack Jost 翻译:梁傅淇 校对:丁楠雅 本文长度为1500字,建议阅读3分钟 Zack Jost是美国第一资本投资国际集团的首席数据科学家,这是他...

21960

扫码关注云+社区

领取腾讯云代金券