A率PCM编码

开始接触一点音频内容了,许多知识要从头补起来。

花了一天时间了解了音频PCM的A率编码,这篇算是整理的笔记文。

我们都知道,数字脉冲编码调制,也就是PCM是目前模拟信号数字化的基本方法,PCM包括采样、量化和编码三个步骤。

抽样是对模拟信号进行周期性扫描,把时间上连续的模拟信号变为时间上离散信号的过程。要求经过抽样的信号应包含原始信号的所有信息,即能够无失真地恢复出原始信号。这部分是数字信号处理最最基础的内容,此处不展开赘述。

量化

对抽样后的序列幅度进行离散处理的过程称为量化,量化按照量化间隔是否均匀又分为均匀量化和非均匀量化。量化间隔相等的量化称为均匀量化,量化间隔不相等的量化称为非均匀量化。从理论角度分析,非均匀量化可以认为是对信号非线性变换后再进行均匀量化的结果。基于对语音信号的大量统计和研究,现有两种压缩特性:A率对数压缩特性、u率对数压缩特性,中国和欧洲用的是A率编码,因此这里只讨论A率对数特性。

A率对数压缩特性

令量化器的满载电压为归一化值±1,即若最大量化电平为V,那么对输入信号xi,归一化值为x = xi/V。A率对数压缩特性定义为:


其中,A为压缩系数,x为归一化输入,f(x)为归一化输出。

A率13折线是不均匀量化的方法,设法用13段折线逼近A=87.6的A率压缩特性。实现方法如下:

输入信号的归一化幅度为0~1,将其不均匀地划分为8个,每个区间长度以1/2倍递减,即划分点分别取1的1/2为1/2,1/2的1/2为1/4,以此类推,直到取1/64的1/2得到1/128。而输出信号幅度0~1则均匀划分为8个区间,每个区间长度为1/8,输入信号和输出信号按照对应顺序形成8个线段,正负方向各有8段,一共16段。将此16段线段相连成一条折线,下图表示的是正方向上的8个线段。由于正负方向的第一段和第二段因斜率相同而合成一条线段,因此实际上有13段折线,因此称为A率13折线。


A率13折线量化相对于均匀量化,在信号比较小的地方,划分比较密集,而在信号较大处,划分比较稀疏,因而量化小信号时不会出现大刻度量化,量化大信号时不会量程不够。

编码

编码就是把量化后的信号电平转化成二进制码组的过程,其逆过程称为解码。

常用的二进制码组有自然二进制码组(NBC)、折叠二进制码组(FBC)、格雷二进制码组(RBC),常见的二进制编码如下图所示。PCM采用折叠码。


A率13折线PCM编码即A率PCM编码。在A率13折线编码中,正负方向共16个线段,在每一段落内有16个均匀分布的量化电平,因此总的量化电平数为L=256,编码位数n=8。8位码的排列如下:

M0  M1 M2  M3  M4 M5  M6  M7

M0为极性码,0代表正极性,1代表负极性。M1~ M3为段落码,表示信号绝对值处在哪个段落,3位码可表示8个段落,代表了8个段落的起始电平值。M4~ M7表示同一个段落内的16个量化电平值。如此,8个段落被划分成128个量化级,段落码和8个段落之间的关系如下表所示:



由编码表可知,编码实际上是对输入信号所对应的电平xk进行编码,对于处在同一层的电平值,xk≤x ≤ xk+1,编码的结果是相同的。由编码码组直接接触的电平都是xk。为了使编码造成的量化误差小于量化间隔Δk的1/2,在解码时需要做一些补偿,即令解码输出x_out = xk + Δk/2。





MATLAB中可以使用`audioread`和`audiowrite`函数来完成PCM编码和解码。PCM编码是将模拟信号转换成数字信号的过程,而PCM解码则是将数字信号转换回模拟信号的过程。 首先,使用`audioread`函数读取音频文件,得到音频数据和采样。例如: ``` [data, Fs] = audioread('test.wav'); ``` 其中,`data`是音频数据,`Fs`是采样。 然后,将音频数据进行PCM编码PCM编码通常包括以下几个步骤: 1. 将音频数据转换为数字信号 2. 对数字信号进行量化,将其分成若干个离散的级别 3. 将量化后的数字信号转换为二进制码 在MATLAB中,可以使用`int16`函数将音频数据转换为16位有符号整数。例如: ``` data_int = int16(data * 32767); ``` 其中,`data`是音频数据,`32767`是16位有符号整数的最大值。 然后,对数字信号进行量化。可以使用`quantiz`函数将数字信号分成若干个离散的级别。例如: ``` L = 256; % 量化级别数 partition = linspace(-32768, 32767, L-1); codebook = linspace(-32767, 32767, L); [index, quantized_data] = quantiz(data_int, partition, codebook); ``` 其中,`L`是量化级别数,`partition`是分割点,`codebook`是码本,`index`是每个样本所属的量化区间,`quantized_data`是量化后的数据。 最后,将量化后的数字信号转换为二进制码。可以使用`dec2bin`函数将十进制数字转换为二进制码。例如: ``` N = 16; % 每个样本的位数 binary_data = dec2bin(quantized_data + 32768, N); ``` 其中,`N`是每个样本的位数,`+32768`是为了将量化后的数据转换为非负数。 解码的过程与编码的过程相反。首先,将二进制码转换为数字信号。可以使用`bin2dec`函数将二进制码转换为十进制数字。例如: ``` decoded_data = bin2dec(binary_data) - 32768; ``` 然后,进行逆量化。可以使用`codebook(index+1)`将每个样本所属的量化区间转换为量化后的数字信号。例如: ``` decoded_data_int = codebook(index+1); ``` 最后,将量化后的数字信号转换为模拟信号。可以使用`double`函数将16位有符号整数转换为浮点数,并除以最大值`32767`。例如: ``` decoded_data_float = double(decoded_data_int) / 32767; ``` 其中,`decoded_data_float`就是PCM解码后的模拟信号。 完整的PCM编码和解码代码如下: ``` [data, Fs] = audioread('test.wav'); data_int = int16(data * 32767); L = 256; % 量化级别数 partition = linspace(-32768, 32767, L-1); codebook = linspace(-32767, 32767, L); [index, quantized_data] = quantiz(data_int, partition, codebook); N = 16; % 每个样本的位数 binary_data = dec2bin(quantized_data + 32768, N); decoded_data = bin2dec(binary_data) - 32768; decoded_data_int = codebook(index+1); decoded_data_float = double(decoded_data_int) / 32767; ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值