opencore-amr是用C和C++编写的AMR音频编解码库,可以对AMR-NB和AMR-WB格式的音频进行编解码。
要移植opencore-amr我们只需用对应的工具链编译出静态链接库即可。

opencore-amr源码下载地址:

https://sourceforge.net/projects/opencore-amr/files/opencore-amr/x86 Linux下编译

1.下载并解压opencore-amr源码

opencoreamrphpopencoreamr移植至嵌入式装备 RESTful API

tar -xvf opencore-amr-0.1.3.tar.gz

2. opencore-amr利用configure脚本配置不同的参数。
x86平台下,只须要指定‘--prefix’参数即可,这个参数指定了完成编译后的头文件和库的保存位置,必须是绝对路径。
如需理解其他参数,可以利用 ./configure --help 命令查看。

./configure --prefix='/home/joshua/opencore-amr/x86'

3.配置好后,利用make进行编译和安装

make && make install

之后就可以到”--prefix“设定的目录中查看编译好的库文件了。

嵌入式交叉编译

1.比较于x86,嵌入式平台须要指定交叉编译器进行配置。
请确保环境变量中有交叉编译器的路径。

./configure --host=arm-none-eabi --prefix='/home/joshua/opencore-amr/arm'

如果有“configure: error: C++ compiler cannot create executables”的缺点提示,并且config.log中的报错信息为 ‘exit.c:(.text.exit+0x2c): undefined reference to `_exit'’,该缺点的缘故原由可能是g++编译器的版本不匹配,办理办法为在configure前增加编译参数'--specs=nosys.specs'。

2.还需把稳的是,编译器参数最好和要利用该库的代码保持同等,否则可能涌现浮点打算办法不同而不能正常链接的缺点。

export OTHER_LINK_OPTIONS="--specs=nosys.specs"export GCC_FLAGS="-std=gnu11 -mcpu=cortex-a5 -mtune=generic-armv7-a -mthumb -mfpu=neon-vfpv4 -mfloat-abi=hard -mno-unaligned-access -Os"LDFLAGS=$OTHER_LINK_OPTIONS CFLAGS=$GCC_FLAGS CXXFLAGS=$GCC_FLAGS ./configure --host=arm-none-eabi --prefix='/f/sc02/opencore-amr-0.1.3/openCPU'PCM转AMR程序

#include <stdio.h>#include <stdlib.h>#include "interf_enc.h"/ PCM参数 /#define PCM_SAMPLERATE (8000) / 只能编码 8 khz /#define PCM_SAMPLEBITS (16) / 只支持16位 /#define PCM_CHANNELS (1) / 不管PCM输入是单声道还是双声道,这里输出的amr都是单声道的 // amr一帧数据是20ms,一秒50帧。
8000,16,1 ==> 320 Bytes /#define PCM_ONE_FRAME_SIZE (PCM_SAMPLERATE/50 PCM_SAMPLEBITS/8 PCM_CHANNELS)/ AMR参数 /#define AMR_ENCODE_MODE MR122#define AMR_ONE_FRAME_SIZE (32) / MR122格式是32字节一帧 // 是否使能背景噪声编码模式 /#define DTX_DECODE_ENABLE 1#define DTX_DECODE_DISABLE 0int main(int argc, char argv[]){int dtx = DTX_DECODE_ENABLE;void vpAmr = NULL;FILE fpAmr = NULL;FILE fpPcm = NULL;/ 检讨参数 /if(argc != 3){printf("Usage: \n" "\t %s ./audio/test_8000_16_1.pcm out.amr\n", argv[0]);return -1;}printf("It will encode a PCM file as [sample rate: %d] - [sample bits: %d] - [channels: %d] !\n", PCM_SAMPLERATE, PCM_SAMPLEBITS, PCM_CHANNELS);/ 初始化编码器 /vpAmr = Encoder_Interface_init(dtx);if(vpAmr == NULL){printf("Encoder_Interface_init error!\n");return -1;}/ 打开pcm文件 /fpPcm = fopen(argv[1], "rb");if(fpPcm == NULL) { perror("argv[1]");return -1;}/ 打开amr文件 /fpAmr = fopen(argv[2], "wb");if(fpAmr == NULL){perror("argv[2]");return -1;}/ 先写入amr头部 /fwrite("#!AMR\n", 1, 6, fpAmr);/ 循环编码 /while(1){unsigned char acPcmBuf[PCM_ONE_FRAME_SIZE] = {0}; / 保存在文件中一帧(20ms)PCM数据,8bit为单位,这里是unsigned /short asEncInBuf[PCM_ONE_FRAME_SIZE/2] = {0}; / 编码须要的一帧(20ms)PCM数据,16bit为单位 /char acEncOutBuf[AMR_ONE_FRAME_SIZE] = {0};/ 编码出来的一帧(20ms)AMR数据 /int iReadPcmBytes = 0; / 从PCM文件中读取出的数据大小,单位:字节 /int iEncAmrBytes = 0; / 编码出的AMR数据大小,单位:字节 // 读出一帧PCM数据 /iReadPcmBytes = fread(acPcmBuf, 1, PCM_ONE_FRAME_SIZE, fpPcm);if(iReadPcmBytes <= 0){break;}//printf("iReadPcmBytes = %d\n", iReadPcmBytes);#if 0/ 编码办法 1:像官方测试程序一样转换为short类型再进行编码 /for(int i = 0; i < PCM_ONE_FRAME_SIZE/2; i++){unsigned char p = &acPcmBuf[2PCM_CHANNELSi];asEncInBuf[i] = (p[1] << 8) | p[0];}/ 编码 /iEncAmrBytes = Encoder_Interface_Encode(vpAmr, AMR_ENCODE_MODE, asEncInBuf, acEncOutBuf, 0/ 参数未利用 /);#else/ 编码办法 2:传参时直接类型逼迫转换即可 // 编码 /iEncAmrBytes = Encoder_Interface_Encode(vpAmr, AMR_ENCODE_MODE, (short )acPcmBuf, acEncOutBuf, 0/ 参数未利用 /);#endif//printf("iEncAmrBytes = %d\n", iEncAmrBytes);/ 写入到AMR文件中 /fwrite(acEncOutBuf, 1, iEncAmrBytes, fpAmr);}/ 关闭文件 /fclose(fpAmr);fclose(fpPcm);/ 关闭编码器 /Encoder_Interface_exit(vpAmr);printf("%s -> %s: Success!\n", argv[1], argv[2]);return 0;}