目的
最近在公司开发一个amrnb/amrwb的转码工具,在网上看了很多资料,主要是这篇AMR在IP域中的编码(rfc3267,4867) 对我帮助很大。 这里补充一下缺少和我自己的理解。
AMR编码介绍
AMR是3GPP组织的一个音频编码规范,目前的手机都使用AMR, 比如公司的测试机华为、小米只支持amrnb/amrwb。amrnb是对窄带信号进行编码(200–3400 Hz),amrwb是对更宽的频率范围进行编码(50–7000 Hz)。
根据香农理论,采样频率要是目标频率的两倍,所以向上取整的amrnb的采样频率是8000Hz, amrwb的采样频率是16000Hz。
bitrate
amrnb和amrwb有多种编码速率(bitrate),并支持在通话过程中通过CMR(codec mode request)协商来变化编码速率,不同于一般的编码器固定一种比特率。除此之外,还有没有人声时的SID(舒适噪音)模式。这时只需要发送一个Mode而不是发送无声的包,从而来降低带宽占用。
amrnb 不同比特率时的语音帧大小
Index | Mode | Class A bits | total speech bits |
---|---|---|---|
0 | 4.75 | 42 | 95 |
1 | 5.15 | 49 | 103 |
2 | 5.9 | 55 | 118 |
3 | 6.7 | 58 | 134 |
4 | 7.4 | 61 | 148 |
5 | 7.95 | 75 | 159 |
6 | 10.2 | 65 | 204 |
7 | 12.2 | 81 | 244 |
amrwb 不同比特率的语音帧大小
Index | AMR-WB codec mode | Total number of bits | Class A Class B Class C |
---|---|---|---|
0 | 6.60 | 132 | 54 78 0 |
1 | 8.85 | 177 | 64 113 0 |
2 | 12.65 | 253 | 72 181 0 |
3 | 14.25 | 285 | 72 213 0 |
4 | 15.85 | 317 | 72 245 0 |
5 | 18.25 | 365 | 72 293 0 |
6 | 19.85 | 397 | 72 325 0 |
7 | 23.05 | 461 | 72 389 0 |
8 | 23.85 | 477 | 72 405 0 |
payload type
amrnb和amrwb使用的动态payload type, 所以在用wireshark分析时,需要经常调整payload-type值
align mode
amrnb和amrwb在SIP协商中有两种align mode,对齐模式和节省带快模式。总结有几个区别
- 对齐模式下CMR占8位,每个TOC占8位,然后每个语音帧补齐为整字节。
- 节省带宽模式下,CMR占4位,每个TOC占6位,然后CMR + TOC + 所有语音帧加起来,最后补齐为整字节。
以单帧的12.2kbps为例
- 语音帧为244位,对齐之后为
(244 + 8 - 1)/8 = 31
字节。加上1字节的CMR和1字节的TOC, 一共33字节。 - 语音帧为244位,加上4位CMR和6位TOC,一共为254位,对齐后为
(254 + 8-1)/8
,一种32字节字节。
以两帧的12.2kbps为例
- 两个语音帧分别占用31字节,加上1字节的CMR和2字节的TOC, 一共 65字节。
- 两个语音帧分别占用244位, 加上4位的CMR和6 * 2位的TOC, 对齐后为
( 488 + 4 + 12 + 8 - 1)/8
,一共63字节。
总之,对齐模式是先对齐成字节再求和,节省带宽模式是先计算位和
再对齐成字节。特别是多帧的时候,节省带宽模式算起来更复杂。好在实际情况都是1帧。
基于opencore-amr的编解码
开始用FFmpeg的库来做转码和推流,后来发现不支持节省带宽模式,而且还有个BUG,所以后面自己基于opencore的库写的转码功能。