AMR文件结构解析——时长解析

分类: 365bet指数 时间: 2025-10-03 14:15:07 作者: admin

一、AMR简介

基于新的网络和新的要求,无论是从节省传输频带资源,还是保持线路通信的高效率等方面来看,研究采用各种可变速率语音编码技术的系统都有重要意义。目前为了适应此需要提出了AMR(Adaptive Multi-rate) 的概念,即自适应多速率语音编码器,主要用于移动设备的音频,压缩比比较大,但相对其他的压缩格式质量比较差,由于多用于人声通话。AMR又分为两种,一种是AMR-NB(AMR-NarrowBind),语音带宽范围:300-3700Hz,8KHz采样频率;另外一种是AMR-WB(AMR WideBand),语音带宽范围50-7000Hz,16KHz采样频率。但考虑语音的短时相关性,每帧长度均为20ms。这两种编码器根据带宽的要求虽然选用了不同的速率,但有异曲同工之处.

总之,知道AMR是一种压缩比较大的、多用于人声通话的语音编码技术就好了。关于AMR-NB和AMR-WB网上有较多的介绍此处也不在重复。另一个比较重要的点是“每帧长度均为20ms”,这对我们接下来解析时长比较有用。

二、AMR文件结构解析

AMR文件由文件头和数据帧组成,文件头标识占6个字节,后面紧接着的就是音频帧了,如下:

文件头(6字节)语音帧1语音帧2......语音帧n

1、文件头。关于文件头单声道和多声道情况下文件的头部是不一致的,单声道情况下的文件头只包括一个Magic number,而多声道情况下文件头既包含Magic number,在其之后还包含一个32位的Chanel description field。多声道情况下的32位通道描述字符,前28位都是保留字符,必须设置成0,最后4位说明使用的声道个数。此处我们知道占6个字节就好了。

2、语音数据。

(1)语音帧块。文件头之后就是时间连续的语音帧块了,也就是说语音帧还存在以帧块为维度的划分。每个帧块包含8位组对齐的语音帧,相对于若干个声道,从第一个声道开始一次排列。

(2)语音帧。语音帧的组成包括两部分:帧头和帧内容。每个帧都是8位组对齐的。其实语音帧就可以理解为视频的一帧一帧的画面,语音帧的概念与之相同。

1)帧头:每一帧都是从一个8位的帧头开始,而且其中的P为填充位必须设为0(感觉就是第一个bit必为0的意思)。

帧头(8bit)帧内容(字节数因编码模式而不同)

2)语音帧的编码模式有如下八种,他们的音频帧的大小是不同的,比特率也是不同的。

注意,这些模式会在同一个文件amr文件中共存,这也就是Adaptive Multi-rate的真实含义吧。

模式

规格

比特率(kbps)

音频帧大小(字节)

帧头(字节)

FT

0

AMR 4.75

4.75

13

04 00000100

0000

1

AMR 5.15

5.15

14

0C 00001100

0001

2

AMR 5.9

5.90

16

14 00010100

0010

3

AMR 6.7

6.70

18

1C 00011100

0011

4

AMR 7.4

7.40

20

24 00100100

0100

5

AMR 7.95

7.95

21

2C 00101100

0101

6

AMR 10.2

10.20

27

34 00110100

0110

7

AMR 12.2

12.20

32

3C 00111100

0111

由以上表格可知,八种模式的是可以根据帧头进行区分的。这个在后续的解析amr文件获取语音时长的代码中会体现出来。

3、音频数据帧大小的计算:AMR 一帧对应20ms,那么一秒有50帧的音频数据。由于比特率不同,每帧的数据大小也不同。如果比特率是12.2kbs,那么每秒采样的音频数据位数为:

12200 / 50 = 244bit = 30.5byte,取整为31字节。

再加上一个字节的帧头,这样数据帧的大小为32字节。

三、解析AMR文件的时长

根据以上介绍我们此处给出解析AMR文件获取语音时长的C++代码。

uint64_t getDuration(std::string fileContent)

{

uint64_t duration=0;//语音持续时长

//音频帧在八种编码模式下的帧内容占用字节数

int AMR_FRAME_SIZE[8] = { 13, 14, 16, 18, 20, 21, 27, 32};

size_t pos=0;//pos用来指示位置

size_t length=fileContent.length();

char toc;//toc每次代表帧头,通过运算可以知道属于哪种编码模式

pos+=6;//跳过文件头的6个字节

while(pos

{

toc=fileContent[pos];//toc赋值帧头

toc=toc & 0x78;//对照表格帧头的编码一目了然

toc=toc>>3;//对照表格帧头的编码一目了然

if(toc>=8)

toc=0;

duration+=20;//每一个数据帧对应20ms

pos+=AMR_FRAME_SIZE[(int)toc];

}

duration+=500;//四舍五入

duration/=1000;//转换为秒

return duration;

}

关于时长读取提供如下具体测试代码,见本人上传资源【解析amr文件时长c++实例代码(包含arm示例文件)】。