下面内容是将我自己在实际开拓事情中打仗到的音频干系的知识进行了一个大略整理归纳,仅供参考。
(一)音频处理流程先容(1)空想处理流程比较空想的音频运用场置流程,大概入下图所示:
MIC 将声音震撼旗子暗记转换为电(数字/仿照)旗子暗记,将其输入到SOC的AI(音频输入模块)AI模块对输入的旗子暗记进行转换(ADC转换采样),输出为PCM格式的音频数据将PCM音频数据进行压缩、转换、封装成各种格式,比如常见的AAC、MP3等将压缩过的音频文件,与视频文件一起封装成音视频文件,比如MP4文件(2)实际处理流程
在嵌入式运用中,考虑到系统资源限定、运用处景的不同,实际利用会比较的繁芜,紧张的受限是:既要支持本地音频存储、又要支持网络传输。
PCM是原始音频数据,一样平常嵌入式芯片的音频编码是可以将PCM数据编码成G711、G726等格式,但基本上不会支持AAC编码,紧张可能是涉及到版权问题。君正和海思系列的SOC都不能直接支持AAC编码。
但是从编码压缩比例来看,ACC编码的压缩比例是比G711、G726的要高的,也便是说在相同条件下,AAC编码可以存储韶光更加长的音频信息。其余,很多视频封装库,对AAC的支持都是比较友好。
基于上面这些情形,就会导致在同一个体统中,可能会存在几种格式的音频格式数据。比如下图:
上图中,紧张的运用处景,一个是音频网络传输,一个是音频本地存储。
路线1:
将AI模块采集到的PCM直接通过网络传输给IOT平台这种办法耗费资源少,但是占用网络带宽大适用于没有音频编码模块的SOC路线2:
将PCM格式数据,编码成G711、G726等格式之后再通过网络传输出去耗费资源少,网络带宽占用的也少,是最优的一个选项适用于带音频编码的SOC路线3:
将PCM格式数据,通过软件编码的办法编码成AAC格式,然后再封装成MP4、AVI等格式这种办法会占用CPU资源,运行内存RAM,以及Flash空间(AAC编码库比较大)适用于一定须要AAC编码的场景路线4:
涌现这种利用办法的紧张缘故原由是,SOC同一韶光只支持一个音频格式输出,比如如果要输出PCM格式,就不能再编码输出G711、G726等格式将编码输出的G711、G726格式,进行软件解码成PCM格式,在通过软件压缩成AAC格式,末了才封装成mp4格式这种办法适用于一定要利用AAC格式,但是SOC又不能同时输出两种类型音频格式的场景耗费的各种资源都是最多的(二)音频格式转换(1)PCM 与 G711A、G711UPCM:
设备通过MIC采集音频旗子暗记,MIC分为两大类,数字MIC和仿照MIC,数字MIC输出的是已经转换过的数字旗子暗记,但消费类设备中比较常用的是仿照MIC。PCM数据 是将仿照MIC输入的仿照音频旗子暗记通过ADC转换为数字旗子暗记的二进制序列,它没有文件头也没有结束标志,是一种未压缩的数据格式。PCM文件 可以通过Audacity Beta (Unicode) 以文件->导入->裸数据 的办法打开,可以进行播放,剪辑,查看等操作紧张的参数有:声道,采样频率,采样位数下图打开的是一个:2声道,48KHz 采样频率,16位深度的PCM文件
G711A与G711U
G711 分为a-law和u-law,通过查表的办法将16位的PCM数据压缩成8位G711 它的压缩率为1:2,1个1M 的PCM文件转换为G711格式后只有0.5MG711 中的u-law 即g711u,紧张利用在北美和日本G711 中的a-law 即g711a,紧张利用在欧洲及其它地区如果要直接播放G711 文件音频,在Linux系统中可以直策应用 ffplay 命令来播放ffplay -i test.pcm -f s16le -ac 2 -ar 48000ffplay -i test.g711a -f alaw -ac 2 -ar 48000ffplay -i test.g711u -f mulaw -ac 2 -ar 48000
-ac: 音频通道数 -ar:音频采样率 -f:文件格式
G711与PCM之间的转换先对来说是比较大略的,上面我是将一个 48K 16bit 2通道PCM 与G711 格式相互转换的大略工程
(三) AAC格式与编码AAC 比较于G711 要繁芜很多,AAC它有很多的版本,编码器也有很多种,利用比较多的是FAAC(Freeware Advanced Audio Coder),由于它是免费的。
(1)AAC的各种格式AAC的文件格式有:
ADIF (Audio Data Interchange Format) 只有在文件开头的位置才有音频的头部信息ADTS (Audio Data Transport Stream) 紧张特点是每一帧都带有头部信息文件格式是指紧张以文件类型来保存的音频数据AAC的流格式:
流格式紧张是指用于流媒体传输的格式,紧张有:AAC_RAW 是指未经由封装AAC裸数据AAC_ADTS 与文件格式中的ADTS格式相同AAC_LATM (Low-Overhead Audio Transport Multiplex)AAC音频的一种传输协议。比较常用的是ADTS格式,由于它在音频数据文件存储和流传输中都可以利用
(2)ATDS格式先容我们看fdk-aac中对ADTS构造的定义
typedefstruct { / ADTS header fields / UCHAR mpeg_id; UCHAR layer; UCHAR protection_absent; UCHAR profile; UCHAR sample_freq_index; UCHAR private_bit; UCHAR channel_config; UCHAR original; UCHAR home; UCHAR copyright_id; UCHAR copyright_start; USHORT frame_length; USHORT adts_fullness; UCHAR num_raw_blocks; UCHAR num_pce_bits;} STRUCT_ADTS_BS;
这里只是把构造头部的项列出来了,这里列出来的有15项,全体构造头的长度有17个字节。
实际ADTS头构造有两种长度,包含CRC校验的是9个字节的长度,没有CRC校验的是7个字节,每项的浸染与实际长度可以看wiki上的一个定义:https://wiki.multimedia.cx/index.php/ADTS
我们利用Elecard Stream Analyzer 工具打开一个ADTS格式的AAC文件进行查看会更加的清晰:
标签1随意点的第四帧,它的偏移地址是0x54a标签2处是ADTS 的同步字Syncword,12位,0xFFF右上的方框,是ADTS各项参数的解析标签3处是单前帧(第4帧)的长度,403标签4是下一帧的偏移地址0x6dd,恰好是上一帧的偏移地址+上一帧的长度 = 0x54a + 403 = 0x6dd
如果是须要自己手动解析AAC的ADTS格式文件,也可以通过上面办法进行解析,先找到帧头标签,再逐项的解析各个参数,末了在根据帧长度跳转到下一帧进行数据解析。
(3)AAC格式编码紧张的AAC编码器有:FhG、Nero AAC、QuickTime/iTunes、FAAC、DivX AAC ,在嵌入式中比较常用的是FAAC。
基于FAAC的编码工具和库,比较常用的有:
FFMPEG: 它可以集成多种编码器fdk-aac: 同时集成了faac编解码faac: aac 编码库faad: aac 解码库上面先容的几种AAC封装库,都可以在github高下载到源码:
https://github.com/mstorsjo/fdk-aac https://github.com/knik0/faac https://github.com/knik0/faad2
(4) fdk-aac移植github 高下载源码https://github.com/mstorsjo/fdk-aac
可以通过tag选择不同版本进行下载,tag中的一样平常都是比较稳定的发布版本
如果要将fdk-aac移植到君正的T31设备上,可以按下面命令进行交叉编译:
mkdir _install_uclibc./autogen.shCFLAGS+=-muclibc LDFLAGS+=-muclibc CPPFLAGS+=-muclibc CXXFLAGS+=-muclibc ./configure --prefix=$PWD/_install_uclibc --host=mips-linux-gnumake -j4make install
交叉编译的文件放置在_install_uclibc文件夹下,可以通过下面命令确定编译利用的编译工具链:file libfdk-aac.so.2.0.2
biao@ubuntu:~/test/fdk-aac-master/_install_uclibc/lib$ file libfdk-aac.so.2.0.2libfdk-aac.so.2.0.2: ELF 32-bit LSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, not stripped
如果要直接在PC上编译测试,可以利用下面命令:
mkdir _install_linux_x86./autogen.sh./configure --prefix=$PWD/_install_linux_x86 make -j4make install
(5) fdk-aac运用
这里大略先容如何利用fdk-aac将PCM文件编码成AAC格式文件,然后再通过fdk-aac将AAC解码成PCM格式数据。
fdk-aac 源码下有个 test-encode-decode.c 文件,它因此wav格式的文件为根本的一个demo,如果PCM和AAC数据因此wav的格式存储的,可以直接参考官方demo。
我这里利用的是上面有先容的PCM裸流进行编码和解码。
(a) PCM编码成AAC
由于我们利用的是PCM裸流,从文件中是无法读取出流的任何信息,以是PCM流的信息是须要我们自己填写的:
int aot, afterburner, eld_sbr, vbr, bitrate, adts, sample_rate, channels,mode; /参数设置/ aot = 2; /Audio object type 2 MPEG-4 AAC Low Complexity./ afterburner = 0; /是否启用剖析合成算法,可提高编码质量,但是会耗资源/ eld_sbr = 0 ; /Spectral Band Replication 频谱显示/ vbr = 0; /可变码率配置/ bitrate = 48000; /编码码率/ adts = 1; /是否可传输/ sample_rate = 48000; /采样率/ channels = 2; /通道/
通过aacEncoder_SetParam(encoder, AACENC_TRANSMUX, 2) 可以设定须要编码成的AAC格式,它支持的格式有:
- 0: raw access units- 1: ADIF bitstream format- 2: ADTS bitstream format- 6: Audio Mux Elements (LATM) withmuxConfigPresent = 1- 7: Audio Mux Elements (LATM) withmuxConfigPresent = 0, out of band StreamMuxConfig- 10: Audio Sync Stream (LOAS) /
(b) AAC解码成PCM
我们这里先容将ADTS格式编码的AAC文件解压成PCM
要解码AAC文件,首先须要能够检测到AAC文件中音频帧的位置及长度,以是我们首先须要解析AAC 的ADTS头信息,头构造定义如下:
typedefstruct adts_fixed_header { unsigned short syncword:12; unsignedchar id: 1; unsignedchar layer:2; unsignedchar protection_absent: 1; unsignedchar profile: 2; unsignedchar sampling_frequency_index: 4; unsignedchar private_bit: 1; unsignedchar channel_configuration:3; unsignedchar original_copy:1; unsignedchar home: 1;} adts_fixed_header; // length : 28 bitstypedefstruct adts_variable_header { unsignedchar copyright_identification_bit:1; unsignedchar copyright_identification_start:1; unsigned short aac_frame_length:13; unsigned short adts_buffer_fullness:11; unsignedchar number_of_raw_data_blocks_in_frame:2;} adts_variable_header; // length : 28 bits
解析方法如下:
memset(&fixed_header, 0, sizeof(adts_fixed_header)); memset(&variable_header, 0, sizeof(adts_variable_header)); get_fixed_header(headerBuff, &fixed_header); get_variable_header(headerBuff, &variable_header);
解码的时候,还须要把稳须要利用aacDecoder_ConfigRaw 配置PCM的信息,demo 是通过info.confBuf来获取,这个值是在编码的时候才会有,以是这个值须要根据实际参数来设置:
unsignedchar conf[] = {0x11, 0x90}; //AAL-LC 48kHz 2 channle unsignedchar conf_array[1] = { conf }; unsignedint length = 2; if (AAC_DEC_OK != aacDecoder_ConfigRaw(decoder, conf_array, &length)) { printf("error: aac config fail\n"); exit(1); }
完全工程文件如下:
biao@ubuntu:~/test/faac/fdk-aac-x86$ tree.├── 48000_16bits_2ch.pcm├── adts.c├── adts.h├── decode_48000_16bits_2ch.pcm├── include│ └── fdk-aac│ ├── aacdecoder_lib.h│ ├── aacenc_lib.h│ ├── FDK_audio.h│ ├── genericStds.h│ ├── machine_type.h│ └── syslib_channelMapDescr.h├── lib│ ├── libfdk-aac.a│ ├── libfdk-aac.la│ ├── libfdk-aac.so -> libfdk-aac.so.2.0.2│ ├── libfdk-aac.so.2 -> libfdk-aac.so.2.0.2│ ├── libfdk-aac.so.2.0.2│ └── pkgconfig│ └── fdk-aac.pc├── Makefile├── out.aac├── out_ADIF.aac├── out_adts.aac├── out_RAW.aac└── test_faac.c4 directories, 22 filesbiao@ubuntu:~/test/faac/fdk-aac-x86$
(四)工程资料下载
如需上面先容的工程,测试文件,以及查看工具,可以在"大众年夜众号中回答 资源 获取,内容在音视频连接中。
结尾嵌入式音频开拓涉及到的内允许多,每个功能单独拉出来都会涉及到很多的知识点。
上面只是大略的先容了一下它们的观点,以大略利用。如有缺点,欢迎批评示正。
---------------------------End---------------------------
如需获取更多内容
请关注liwen01公众年夜众号