音频和OPUS开源库简介

1、音频简介

传感器采集音频信号是模拟量,而我们实际传输过程中使用的是数字量。而这就涉及到模拟转数字的过程。而模拟信号数字化必须经过三个过程,即抽样、量化和编码,以实现话音数字化的脉冲编码调制(PCM,Pulse Coding Modulation)技术
在这里插入图片描述

1.1采样

采样是把模拟信号以其信号带宽2倍以上的频率提取样值,变为在时间轴上离散的抽样信号的过程。采样率 (sample):每秒从连续信号中提取并组成离散信号的采样个数,用赫兹(Hz)来表示。采样频率必须至少是信号中最大频率分量频率的两倍,否则就不能从信号采样中恢复原始信号,这其实就是著名的奈奎斯特采样定律。例如,要表示人类听觉范围 (20-20000 Hz) 内的音频,数字音频格式必须至少每秒采样 40000 次(CD 音频使用 44100 Hz 的采样率,部分原因也在于此)。

1.2量化

采样信号虽然是时间轴上离散的信号,但仍然是模拟信号,其采样值在一定的取值范围内,但却有无限多个值。对无限个采样值一一给出数字码组来对应是不可能的。为了实现以数字码表示样值,必须采用“四舍五入”的方法把采样值分级“取整”,使一定取值范围内的采样值由无限多个值变为有限个值。这一过程称为量化。
量化后的抽样信号与量化前的采样信号相比较,当然有所失真,且不再是模拟信号。这种量化失真在接收端还原模拟信号时表现为噪声,并称为量化噪声。量化噪声的大小取决于把采样值分级“取整”的方式,分的级数越多,即量化级差或间隔越小,量化噪声也越小。
采样位数:指的是描述数字信号所使用的位数。8位(8bit)代表2的8次方=256,16 位(16bit)则代表2的16次方=65536; 采样位数越高,精度越高。
8-bit:2^8 = 256 levels,有256个等级可以用于衡量真实的模拟信号。
16-bit:2^16 = 65,536 levels,有65,536个等级可以用于衡量真实的模拟信号。
24-bit:2^24 = 16,666,216 levels,有16,666,216个等级可以用于衡量真实的模拟信号。

量化会将波形分成多个等份,值越大对模拟信号描述越真实。采样率是1秒钟采样的次数,值越大对声音的还原程度越高。所以,声音的质量很大程度被量化和采样率所影响。

1.3编码

量化后的采样信号就转化为按采样时序排列的一串十进制数字码流,即十进制数字信号。简单高效的数据系统是二进制码系统,因此,应将十进制数字代码变换成二进制编码,根据十进制数字代码的总个数,可以确定所需二进制编码的位数,即字长(采样位数)这种把量化的抽样信号变换成给定字长的二进制码流的 过程称为编码。
PCM是原始数据原封不动地量化编码,这种量化位宽大,在wav的音频文件中通常采用a律13编码PCM或者是u律13编码PCM,中国、欧洲采用A律13折线编码,北美和日本采用u律15折线编码(这和PAL电视标准用于中国、欧洲等国家,NTSC电视标准用于美、日等国家和地区有点相似)。
A律13折线PCM 编码中实现的是非均匀量化。为什么使用非均匀量化呢? —— 这是因为在实际的通信系统中,信号幅度可能会在一个很大的范围内变化。以电话通信为例:经过实验证明,幅度较低的信号出现的频率非常高,而幅度特别大的信号出现的概率就比较小。这样一来,如果采用均匀量化,那么小信号的量化就显得十分粗糙了。而换一种思路:如果我们对出现概率很大的小信号,采用更为精细的量化方式;对于出现频率不那么高的大信号,采用略微粗糙的量化方法,可以预见的是这样做对通话质量是有保障的。
在这里插入图片描述

1.4 PCM的存放方式

PCM音频数据排列格式为左右声道每个样本点数据交错排列。
在这里插入图片描述
知道pcm存储格式后,获取pcm数据可以对pcm做音量调节等操作,这里不再去详细说,附上大佬连接,感兴趣可以了解下:http://blog.jianchihu.net/pcm-vol-control-advance.html
http://blog.jianchihu.net/pcm-volume-control.html

2、OPUS简介

上面说的PCM编码仅是将数据转化成2进制,接下来需要说的是音频的压缩编码。,音频编码的主要作用是将音频采样数据(PCM等)压缩成为音频码流,从而降低音频的数据量,偏于存储和传输。
常见的音频编码器:OPUS,AAC,Ogg,Speex,iLBC,AMR,G.711等。常见的音频编码器特性:
OPUS:延迟小,压缩率高,适合实时通讯,WebRTC默认使用OPUS。
AAC:应用最广泛的一款解码器。
Ogg:收费的,应用不如前面2个应用广泛
Speex:在前面3个之前是应用广泛的,因为它包含了回音消除这个功能。在之前是很多编解码器不支持的。
G.711系列:通常用于固话。
编码器性能比较:OPUS > AAC > Ogg
在这里插入图片描述
这里主要介绍OPUS编码:Opus编码是一个有损声音编码的格式,由互联网工程任务组(IETF)进来开发,适用于网络上的实时声音传输,标准格式为RFC 6716。Opus格式是一个开放格式,使用上没有任何专利或限制。
Opus的前身是celt编码器。在当今的有损音频格式争夺上,拥有众多不同编码器的AAC格式打败了同样颇有潜力的Musepack、Vorbis等格式,而在Opus格式诞生后,情况似乎不同了。通过诸多的对比测试,低码率下Opsu完胜曾经优势明显的HE AAC,中码率就已经可以媲敌码率高出30%左右的AAC格式,而高码率下更接近原始音频。
opus可以处理各种音频应用,包括IP语音,视频会议,游戏内聊天,甚至远程现场音乐表演。支持的特性包括:
1、比特率从6 kb/s到510 kb/s
2、采样率从8 kHz(窄带)到48 kHz(全频段)
3、帧大小从2.5 ms到60 ms
4、支持恒定比特率(CBR)和可变比特率(VBR)
5、从窄带到全频段的音频带宽
6、支持演讲和音乐
7、支持单声道和立体声
8、最多支持255个频道(多流帧)
9、可动态调整比特率、音频带宽和帧大小
10、良好的丢失鲁棒性和丢包隐蔽性(PLC)
11、浮点和定点实现

3、OPUS开源库

3.1 OPUS工具安装编译和命令行使用

官网:https://www.opus-codec.org/
wget https://archive.mozilla.org/pub/opus/opus-1.3.1.tar.gz
tar -xzvf opus-1.3.1.tar.gz
cd opus-1.3.1/
mkdir opus_lib
./configure --prefix=/home/wyj/Downloads/opus-1.3.1/opus_lib
make
make install
安装好后在目录下面就会有opus_demo工具,用法如下:

Usage: opus_demo [-e] <application> <sampling rate (Hz)> <channels (1/2)>
         <bits per second> [options] <input> <output>
       opus_demo -d <sampling rate (Hz)> <channels (1/2)> [options]
         <input> <output>
 
mode: voip | audio | restricted-lowdelay
options:
  -e                : only runs the encoder (output the bit-stream)
  -d                : only runs the decoder (reads the bit-stream as input)
  -cbr              : enable constant bitrate; default: variable bitrate
  -cvbr             : enable constrained variable bitrate; default:
                      unconstrained
  -bandwidth <NB|MB|WB|SWB|FB>
                    : audio bandwidth (from narrowband to fullband);
                      default: sampling rate
  -framesize <2.5|5|10|20|40|60>
                    : frame size in ms; default: 20
  -max_payload <bytes>
                    : maximum payload size in bytes, default: 1024
  -complexity <comp>
                    : complexity, 0 (lowest) ... 10 (highest); default: 10
  -inbandfec        : enable SILK inband FEC
  -forcemono        : force mono encoding, even for stereo input
  -dtx              : enable SILK DTX
  -loss <perc>      : simulate packet loss, in percent (0-100); default: 0
 
input and output are little-endian signed 16-bit PCM files or opus
bitstreams with simple opus_demo proprietary framing.

注意最后这个说明,输入和输出都是小端带符号16bit的PCM文件,或者用示例opus_demo编码出来的opus码流:

input and output are little-endian signed 16-bit PCM files or opusbitstreams with simple opus_demo proprietary framing

这里用ffmpeg命令mp3文件将生成pcm文件,正常的pcm也可以从设备采集到,重采样后保存pcm文件出来用。

ffmpeg -i ‘周杰伦-反方向的钟.mp3’ -f s16le -ar 48000 -ac 2 -acodec pcm_s16le reverseClock.pcm

说明:-acodec pcm_s16be:输出pcm格式,采用signed 16编码,字节序为大尾端be/小尾端为le;-ar 48000: 采样率为48000-ac 2: 声道数为2,这里生成小端16bit带符号的pcm文件。

使用opus_demo编码:
./opus_demo -e audio 48000 2 64000 reverseClock.pcm reverseClock.opus
libopus 1.3.1
Encoding 48000 Hz input at 64.000 kb/s in auto bandwidth with 960-sample frames.
average bitrate: 63.133 kb/s
maximum bitrate: 129.600 kb/s
active bitrate: 63.671 kb/s
bitrate standard deviation: 12.626 kb/s

这里用最简单的命令去进行opus编码,其他参数没用到,用法比较简单 -e 表示编码,audio指定编码音频,48000采样率,2声道,64000比特率

使用opus_demo解码:
./opus_demo -d 48000 2 reverseClock.opus reverseClock_Opus.pcm
libopus 1.3.1
Decoding with 48000 Hz output (2 channels)
average bitrate: 63.133 kb/s
maximum bitrate: 129.600 kb/s
bitrate standard deviation: 12.626 kb/s

解码的用法更加简单了,-d表示解码,48000采样率,2声道

以下是这几个音频的对比:
mp3文件
在这里插入图片描述

pcm文件
在这里插入图片描述

opus编码后,解码的pcm文件
在这里插入图片描述
有些细微的差别,毕竟是有损编码,原本mp3文件9.84MB,pcm文件47.2MB,而opus编码文件才2.04MB,所以才需要足以看出编码的重要性以及OPUS编码的压缩率。
在这里插入图片描述

3.2 OPUS编码API介绍

opus编解码器接口的定义主要在opus工程源码中的opus.h文件中。以C语言的方式提供。

编码器接口中有一个重要的结构体变量 struct OpusEncoder,它表示编码器状态,结构体中包含很多变量用来统计opus编码器的状态,typedef struct OpusEncoder OpusEncoder;

使用时用先创建编码器:
opus接口中创建编码器的方式有两种,因此与之对应的释放编码器的方式也有两种,创建编码器时可以选用

OpusEncoder* enc;
OpusEncoder* opus_encoder_create(opus_int32 Fs, int channels, int application, int* error);
举例:enc = opus_encoder_create(16000, 1,  OPUS_APPLICATION_VOIP, &err_num);
参数:采样率、通道数、应用类型、错误码

OpusEncoder* enc;
size = opus_encoder_get_size(channels);
enc = malloc(size);
err_num = opus_encoder_init(enc, Fs, channels, application);
参数:同上

两种创建编码器的方式差异在于表示编码器状态的结构体内存申请方式不一样,第一种内存的申请方式为opus_encoder_create函数申请内存后返回一个首地址指针,第二种是自己申请一块内存后用opus_encoder_init函数填充。

编码音频数据:
编码音频数据也分为两种方式,一种是float型,一种是int型。

opus_int32 opus_encode(OpusEncoder* st, const opus_int16* pcm, int frame_size, unsigned char* data, opus_int32 max_data_bytes);
举例:opus_int32 len = opus_encode(enc, pcm, 960, out, 4000);
参数:解码器状态指针、音频原始数据、以样本个数为单位的帧长度、编码完成的数据、最大的编码后数据长度可以用作固定比特率的最大上限

或者

opus_int32 opus_encode_float(OpusEncoder* st, const float* pcm, int frame_size, unsigned char* data, opus_int32 max_data_bytes);
举例:opus_int32 len = opus_encode(enc, pcm, 960, out, 4000);
参数:同上

在这两种编码方式中,浮点型编码是更加损耗CPU,但是因此获得的编码精度更高,所以音质更加精准,而16位in整型编码是更多机器支持的,编码精度稍低,对CPU的损耗也小一点。

释放编码器:

当采用opus_encoder_create创建编码器时,需要用opus_encoder_destroy释放。
opus_encoder_destroy(OpusEncoder* st);
举例:opus_encoder_destroy(enc);
参数:编码器状态结构指针

当采用opus_encoder_init创建编码器时,需要用free释放。
举例:free(enc); //由于前面是使用malloc申请的内存
参数:编码器状态结构指针

修改编码参数:
opus支持编码器运行时的参数修改。

int opus_encoder_ctl(OpusEncoder* st, int request, ...);
举例:opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate));
参数:编码器状态结构指针、设置的参数

解码用到的函数都是对称的,例如opus_encoder_create就变成对应的opus_decoder_create,这样的接口设计就很值得学习,解码对应的API下面就不再介绍了。

用opus库的API接口编码时候,如果想要用opus_demo解码,需要按照它要求的格式存储数据,前8个字节存储长度,后面跟着编码出来的数据,否则用opus_demo -d解码的时候会解不出来,下面对opus_demo工具代码简单分析。

3.3 OPUS_DEMO代码简单分析

编码器创建和编码控制,根据命令行参数赋值:
在这里插入图片描述
编码,读取带符号小端16位PCM文件用于编码,此处对应工具说明,需要输入带符号的小端16位PCM文件:
在这里插入图片描述

编码后的数据存文件,做个简单封装将长度和final range封装在数据前,便于解码,此处也对应工具说明需要opus_demo编码的流才能解码:
在这里插入图片描述opus库都是开源的,里面还有很多内容值得分析,后续有时间可以详细了解下opus编码和解码的原理和具体的实现。

参考:
1、【通信原理 入坑之路】—— 模拟信号的数字编码 之 PCM编码(A律13折线和μ律15折线的编译码剖析)https://eezzh.blog.csdn.net/article/details/109250794?utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-12.nolandingword2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-12.nolandingword2
2、I2S传输PCM音频数据分析总结https://blog.csdn.net/ZHONGCAI0901/article/details/116131776?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-1.searchformbaiduhighlight&spm=1001.2101.3001.4242

  • 7
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值