7 AMR-WB 编解码
AMR-WB 由 3GPP(第三代合作伙伴计划)制定10,是一种用于语音编码的音频压缩标准,广泛应用于移动通信领域,特别是在 3G 和 4G 网络中。 AMR-WB 支持的音频带宽范围为 50-7000 Hz,比 AMR-NB 更宽,语音更清晰、自然。 具备从 6.6 kbps 到 23.85 kbps 等多种码率,支持动态调整、优化语音质量和带宽占用。
AMR-WB 音频采样率为 16kHz,以 20ms 为一帧,即 320 个采样(AMR_WB_PCM_FRAME_16k
)。
7.1 使用方法
7.1.1 编码
初始化
使用
amr_wb_encoder_init
初始化编码器对象:struct amr_wb_encoder *amr_wb_encoder_init( int bit_stream_format, // 比特流格式 int allow_dtx, // 是否启用 DTX (1 或 0) int mode, // 默认模式(即码率) void *buf); // 用于存放上下文的内存
支持三种比特流格式,如表 7.1 所示。当用于语音数据压缩时, 应该使用 MIME 格式(
AMR_WB_BIT_STREAM_FORMAT_MIME_IETF
)。表 7.1: AMR-WB 比特流格式 格式 帧头长度(字节) 载荷格式 ETS 6 每 2 个字节表示一个比特 ITU 4 每 2 个字节表示一个比特 MIME 1 详见 RFC 3267 (5.1,5.3) 帧头长度也可以通过
amr_wb_get_frame_header_size(mode)
获得。allow_dtx
参数详见 AMR-WB 规范,可以填0
。模式参数
mode
与实际码率对应关系见表 7.2。表 7.2: AMR-WB 码率模式与帧长(MIME 格式) 模式 码率(kb/s) 每帧比特数 每帧载荷长度(字节) 0 6.6 132 17 1 8.85 177 23 2 12.65 253 32 3 14.25 285 36 4 15.85 317 40 5 18.25 365 40 6 19.85 397 50 7 23.05 461 58 8 23.85 477 60 调用
amr_wb_encoder_get_context_size()
可获取buf
所需大小。编码
调用
amr_wb_encoder_encode_frame
编码一个音频帧,其返回值为音频帧的帧头和载荷的总长度。int amr_wb_encoder_encode_frame( struct amr_wb_encoder *ctx, // 编码器对象 const int16_t *pcm_samples, // PCM 输入 uint8_t *output, // 编码输出 void *scratch); // 临时内存
编码输出
output
的大小根据选择的码率确定(见表 7.2), 例如,若码率为 6.6 kb/s,则output
的长度应该至少是 1 + 17 = 18 字节。调用
amr_wb_encoder_get_context_size()
可获取临时内存scratch
所需大小。需要切换模式时,调用
amr_wb_encoder_encode_frame2
,先切换模式,再编码。
下面的代码演示了如何编码一整段数据。
void *context = malloc(amr_wb_encoder_get_context_size());
void *scratch = malloc(amr_wb_encoder_get_scratch_mem_size());
static uint8_t output[模式所对应的载荷长度 + 1];
const uint16_t *in = ... // 音频采样
const int NUM_OF_SAMPLES = .... // 总采样数
struct amr_wb_encoder *enc =
(AMR_WB_BIT_STREAM_FORMAT_MIME_IETF,
amr_wb_encoder_init0, 模式, context);
for (i = 0;
< NUM_OF_SAMPLES - AMR_WB_PCM_FRAME_16k;
i += AMR_WB_PCM_FRAME_16k)
i {
int r = amr_wb_encoder_encode_frame(
, in + i, output, scratch);
enc
// 处理 pcm_output
....
}
7.1.2 解码
初始化
使用
amr_wb_decoder_init
初始化解码器对象:struct amr_wb_decoder *amr_wb_decoder_init( int bit_stream_format, // 比特流格式 void *buf); // 用于存放上下文的内存
调用
amr_wb_decoder_get_context_size()
可获取buf
所需大小。比特流格式仅支持
AMR_WB_BIT_STREAM_FORMAT_MIME_IETF
。解码帧头
使用
amr_wb_decoder_probe
解码帧头,获得音频帧基本参数:int amr_wb_decoder_probe( struct amr_wb_decoder *ctx, // 解码器对象 const uint8_t *stream); // 音频流
音频流
stream
应该指向一个音频帧的帧头。这个函数将返回这个音频帧的载荷的长度。 如果出现错误,将返回负值错误码。解码载荷
使用
amr_wb_decoder_decode_frame
解码载荷:int amr_wb_decoder_decode_frame( struct amr_wb_decoder *ctx, // 解码器对象 const uint8_t *payload, // 音频帧载荷 int16_t *synth_pcm, // PCM 输出 void *scratch); // 临时内存
这个函数返回输出的 PCM 采样的个数,即
AMR_WB_PCM_FRAME_16k
,synth_pcm
的长度也应为AMR_WB_PCM_FRAME_16k
。调用
amr_wb_decoder_get_scratch_mem_size()
可获取临时内存scratch
所需大小。
下面的代码演示了如何解码一段数据。
static uint8_t pcm_output[AMR_WB_PCM_FRAME_16k];
const uint8_t *in = ...; // 音频数据
int data_size = ...; // 音频数据总长度
void *context = malloc(amr_wb_decoder_get_context_size());
void *scratch = malloc(amr_wb_decoder_get_scratch_mem_size());
struct amr_wb_decoder *dec = amr_wb_decoder_init(
, context);
AMR_WB_BIT_STREAM_FORMAT_MIME_IETFconst int header_size = amr_wb_get_frame_header_size(
);
AMR_WB_BIT_STREAM_FORMAT_MIME_IETF
while (data_size > header_size)
{
int payload_len = amr_wb_decoder_probe(dec, in);
+= header_size;
in -= header_size;
data_size
if (payload_len > data_size) break;
if (payload_len < 0) break;
int r = amr_wb_decoder_decode_frame(
, in, pcm_output, scratch);
dec
+= payload_len;
in -= payload_len;
data_size
// 处理 pcm_output
....
}
7.2 资源消耗
以下数据仅供参考。实际表现受编译器、Cache、RTOS、中断、音频数据等因素影响。
7.2.1 ING916XX
功能 | context (字节) |
scratch (字节) |
---|---|---|
编码 | 2788 | 11898 |
解码 | 1552 | 3826 |
当 CPU 主频为 112 MHz 时,AMR-WB 编解码器的处理一个音频帧所消耗的时间见表 7.4。 从表中可以看出,需要进行实时编码时,只能使用 6.6 kbps,不可使用更高速率。
模式 | 编码 (ms) | 解码 (ms) |
---|---|---|
0 | 16.7 | 7.9 |
1 | 20.0 | 6.6 |
2 | 22.2 | 5.9 |
3 | 23.9 | 5.9 |
4 | 23.9 | 6.0 |
5 | 24.6 | 6.1 |
6 | 25.6 | 6.2 |
7 | 25.3 | 6.2 |
8 | 24.8 | 6.6 |
参见 TS 26.171 等↩︎