这里主要是LPC声码器,这部分的内容绝大部分摘自我的专利《Opus编码器原理和工程实现详解》,对内部细致的实现,以及LPC声码器在音频编解码上如何使用的,可以参看该专栏
线性预测编码 (LPC) 是一种主要用于音频信号处理和语音处理的方法,用于使用线性预测模型的信息以压缩形式表示数字语音信号的频谱包络。
LPC 通过估计共振峰、从语音信号中去除它们的影响以及估计剩余“噪声”的强度和频率来分析语音信号。去除共振峰的过程称为逆滤波,减去滤波后的建模信号后剩余的信号称为残差。
LPC 是语音编码、语音合成以及歌声合成中使用最广泛的方法。它通常用于语音分析和重新合成。一些对算力和实时性要求较高的场景,仍然使用着LPC技术,但是对于语言合成以及歌声合成等质量要求较高的场景,基本都已采用端到端的大模型来实现了。
和第一章类似,如果合成的质量不好,该如何分析?或者说该如何评价TTS以及sing voice(假声、颤音、张力、气声等会比TTS复杂一些),那么基于LPC的谱包络就可以作为其中一个评价指标,当然结合第一章的相位校正和谱包络校正,可以修复大模型合成的一些明显瑕疵。
第二章 线性预测编码(LPC)
人的发生过程是一个source-filter模型,人类发声涉及肌肉、肺、舌和声道等器官位置变化,这些器官在发音时变化速度是有限度的,其中声带和声道的形状相对平稳,这使得语音具有短时平稳特性,短时平稳性是很多语音算法的先决条件之一。语音发音可以分为浊音和清音两类,发浊音时大部分能量集中在低频段,且在时域上具有周期性,在频域上频谱分布具有共振峰结构,清音和白噪声类似,没有明显的时域和频域特征。
基频
Pitch 音高/音调,人耳对声音调子高低的主观感受,音高的大小主要取决于声波基频F0的高低,频率高则音调高,反之则低,用Hz表示。
tone音色/音品,由声音波形的谐波频谱和包络决定。双二阶滤波器,其传递函数,是二阶IIR滤波器,含两个零点和两个极点,高阶滤波器对系数更为敏感,12dB/octave双二阶滤波器可用于音调tone控制;
LPC(部分摘取)
精确重构短时功率谱包络对于音质和清晰度是非常重要的,谱峰对于感知质量更为关键,而LPC参数的包络谱(反应了短时内的共振峰信息)更有益于谱峰的表示,对于低比特率语音编码器,LPC广泛用于谱包络编码,语音编码中LPC是逐帧获取的,通常50帧/秒,LPC通常10~20阶,为压缩比特率通常会对LPC进行量化压缩,由于LPC系数是逐帧获取的,因而有两种方式对齐进行量化,分别是标量量化和矢量量化,标量量化是逐点量化,点与点之间是独立的,而矢量量化是对每帧提取的一组LPC系数量化,其目标是最小化各组失真,这使得矢量量化在各量化比特率下失真都比标量量化小。
语音的相关性有短时和长时两种,短时相关性的滞后小于2ms,而长时相关滞后时间通常大于2ms,这是因为长时相关性基于语音信号的周期性特征,短时相关性确定了功率谱包络,长时相关性确定了功率谱的精细结构,这里的LPC系数是由短时相关性获取的,短时相关性是声道形状的函数。
语音是连续信号,如下图所示,短时采样点之间是相关的,
根据这一相关性,由前一个采样点
x
[
n
−
1
]
x[n-1]
x[n−1]可以预估当前采样点
x
^
[
n
]
\hat {x}[n]
x^[n],当前点的真实值可以用下式计算:
x
[
n
]
≈
x
^
[
n
]
=
x
[
n
−
1
]
x[n] \approx \hat x[n] = x[n-1]
x[n]≈x^[n]=x[n−1]
使用越多(对于语音多达50个左右)的历史采样点真实值,估计当前点真实的有效信息越多,准确性越高,可以用p个点估计当前点的值:
x
^
[
n
]
=
−
∑
k
=
1
P
a
k
(
P
)
x
[
n
−
k
]
\hat x[n]=-\sum \limits_{k=1}^P a_k^{(P)}x[n-k]
x^[n]=−k=1∑Pak(P)x[n−k]
这是一个标准的线性预测器,是自回归模型,预测器的误差(预测残差)定义为:
e
[
n
]
=
x
[
n
]
−
x
^
[
n
]
=
x
[
n
]
+
∑
k
=
1
P
a
k
(
P
)
x
[
n
−
k
]
=
∑
k
=
0
P
a
k
(
P
)
x
[
n
−
k
]
,
a
0
=
1
e[n] = x[n] - \hat x[n] = x[n] + \sum \limits_{k=1}^Pa_k^{(P)}x[n-k] = \sum \limits_{k=0}^P a_k^{(P)}x[n-k],a_0=1
e[n]=x[n]−x^[n]=x[n]+k=1∑Pak(P)x[n−k]=k=0∑Pak(P)x[n−k],a0=1
线性预测器的P个系数(因符合自回归滤波模型,故这里P也称为阶数,即LPC系数的阶数),
a
1
,
a
2
,
⋯
,
a
p
{a_1, a_2,\cdots, a_p}
a1,a2,⋯,ap是LPC系数,P值通常是10~20,
e
[
n
]
{e[n]}
e[n]被称为残差信号,由于两个相关信号相减之后的残差信号自身相关性很弱,因而残差信号谱包络是近乎平坦的,将残差信号用Z域表示为:
E
[
z
]
=
A
[
z
]
S
[
z
]
E[z] = A[z]S[z]
E[z]=A[z]S[z]
其中
A
[
z
]
=
1
−
∑
k
=
1
P
a
k
z
−
k
A[z]=1 - \sum \limits_{k=1}^Pa_kz^{-k}
A[z]=1−k=1∑Pakz−k,滤波器
A
[
z
]
A[z]
A[z]被称为“白化”滤波器,因为信号经过该滤波器之后信号的短时相关性被去掉了,因而使得谱包络更平坦,由于
E
(
z
)
E(z)
E(z)的谱近似平坦,LPC分析中语音短时谱包络可用自回归模型表示:
H
(
z
)
=
1
/
A
(
z
)
H(z)=1/A(z)
H(z)=1/A(z)
预测和真实值之差最小时(最小均方误差准则),可以得到一组最优解,因而系数可以使用最小均方误差准则求解得到:
ξ
2
=
E
[
e
2
[
n
]
]
=
E
[
(
x
^
[
n
]
−
x
[
n
]
)
2
]
=
E
[
(
∑
k
=
1
P
a
k
(
P
)
x
[
n
−
k
]
+
x
[
n
]
)
2
]
\xi^2 = E[e^2[n]]=E[(\hat x[n] -x[n])^2]=E[(\sum_{k=1}^{P}a_k^{(P)}x[n-k]+x[n])^2]
ξ2=E[e2[n]]=E[(x^[n]−x[n])2]=E[(k=1∑Pak(P)x[n−k]+x[n])2]
其中
a
k
(
P
)
a_k^{(P)}
ak(P)的角标P表示的是阶数,通过对上式
a
k
a_k
ak求偏微分,并令其等于零求解系数。
d
ξ
2
d
a
k
=
E
[
(
∑
l
=
1
P
a
l
(
P
)
x
[
n
−
l
]
+
x
[
n
]
)
x
[
n
−
k
]
=
0
\frac{d\xi^2}{da_k}=E[(\sum \limits{l=1}^Pa_l^{(P)}x[n-l]+x[n])x[n-k] = 0
dakdξ2=E[(∑l=1Pal(P)x[n−l]+x[n])x[n−k]=0
E
[
∑
l
=
1
P
a
l
(
P
)
x
[
n
−
l
]
x
[
n
−
k
]
=
−
E
[
x
[
n
]
x
[
n
−
k
]
E[\sum \limits{l=1}^Pa_l^{(P)}x[n-l]x[n-k] = -E[x[n]x[n-k]
E[∑l=1Pal(P)x[n−l]x[n−k]=−E[x[n]x[n−k]
用协方差矩阵将上式重写如下:
∑
l
=
1
P
a
l
P
r
x
x
[
k
−
l
]
=
−
r
x
x
[
k
]
,
k
=
1
,
⋯
,
P
\sum_{l=1}^Pa_l^Pr_{xx}[k-l]=-r_{xx}[k], k=1,\cdots,P
l=1∑PalPrxx[k−l]=−rxx[k],k=1,⋯,P
[
a
1
(
P
)
r
x
x
[
1
−
1
]
a
2
(
P
)
r
x
x
[
1
−
2
]
⋯
a
P
(
P
)
r
x
x
[
1
−
P
]
a
1
(
P
)
r
x
x
[
2
−
1
]
a
2
(
P
)
r
x
x
[
2
−
2
]
⋯
a
P
(
P
)
r
x
x
[
2
−
P
]
⋮
a
1
(
P
)
r
x
x
[
P
−
1
]
a
2
(
P
)
r
x
x
[
P
−
2
]
…
a
P
(
P
)
r
x
x
[
P
−
P
]
]
=
[
−
r
x
x
[
1
]
−
r
x
x
[
2
]
⋮
−
r
x
x
[
P
]
]
\begin {bmatrix}a^{(P)}_1r_{xx}[1-1] & a^{(P)}_2r_{xx}[1-2] & \cdots & a^{(P)}_Pr_{xx}[1-P] \\ a^{(P)}_1r_{xx}[2-1] & a^{(P)}_2r_{xx}[2-2] & \cdots & a^{(P)}_Pr_{xx}[2-P] \\ \vdots \\a^{(P)}_1 r_{xx}[P-1] &a^{(P)}_2r_{xx}[P-2]& \dots &a^{(P)}_Pr_{xx}[P-P]\end{bmatrix} = \begin {bmatrix}-r_{xx}[1] \\ -r_{xx}[2] \\ \vdots \\ -r_{xx}[P]\end{bmatrix}
a1(P)rxx[1−1]a1(P)rxx[2−1]⋮a1(P)rxx[P−1]a2(P)rxx[1−2]a2(P)rxx[2−2]a2(P)rxx[P−2]⋯⋯…aP(P)rxx[1−P]aP(P)rxx[2−P]aP(P)rxx[P−P]
=
−rxx[1]−rxx[2]⋮−rxx[P]
由于互相关矩阵可知,
r
x
x
[
1
]
=
r
x
x
[
−
1
]
r_{xx}[1]=r_{xx}[-1]
rxx[1]=rxx[−1],则上述矩阵可以写为:
[
r
x
x
[
0
]
r
x
x
[
1
]
⋯
r
x
x
[
P
−
1
]
r
x
x
(
1
)
r
x
x
[
0
]
⋯
r
x
x
[
P
−
2
]
⋮
r
x
x
[
P
−
1
]
r
x
x
[
P
−
2
]
…
r
x
x
[
0
]
]
⋅
[
a
1
(
P
)
a
2
(
P
)
⋮
a
P
(
P
)
]
=
[
−
r
x
x
[
1
]
−
r
x
x
[
2
]
⋮
−
r
x
x
[
P
]
]
\begin {bmatrix}r_{xx}[0] & r_{xx}[1] & \cdots & r_{xx}[P-1] \\ r_{xx}(1) & r_{xx}[0] & \cdots & r_{xx}[P-2] \\ \vdots \\ r_{xx}[P-1] &r_{xx}[P-2]& \dots &r_{xx}[0]\end{bmatrix} \cdot \begin {bmatrix}a^{(P)}_1 \\ a^{(P)}_2 \\ \vdots \\ a^{(P)}_P\end{bmatrix} = \begin {bmatrix} -r_{xx}[1] \\ -r_{xx}[2] \\ \vdots \\ -r_{xx}[P]\end{bmatrix}
rxx[0]rxx(1)⋮rxx[P−1]rxx[1]rxx[0]rxx[P−2]⋯⋯…rxx[P−1]rxx[P−2]rxx[0]
⋅
a1(P)a2(P)⋮aP(P)
=
−rxx[1]−rxx[2]⋮−rxx[P]
上式的矩阵表示是:
R
a
=
P
\mathbf R \mathbf a= \mathbf P
Ra=P
其中
R
\mathbf R
R是PXP自相关系数矩阵,
a
\mathbf a
a是线性预测系数,
P
\mathbf P
P是Px1自相关向量。其是维纳霍夫方程,其解可用
a
=
R
−
1
P
\mathbf a =\mathbf R^{-1} \mathbf P
a=R−1P,矩阵求逆的运算复杂度是
O
(
N
3
)
O(N^3)
O(N3),由于自相关系数矩阵是对称的Toeplitz(托普利兹)矩阵,主对角线对称的正定矩阵,因而可以用复杂度为
O
(
N
2
)
O(N^2)
O(N2)的Levinson-Durbin递归算法求解。
由于LPC方法假设语音可以使用全零点滤波器建模,滤波器其的激励对于语音是单脉冲,对于非语言信号用随机白噪声,而这一激励模型对于语音并不是特别适用,有些语音本身就和非语言类似,因而重构信号有一定程度失真,另外全零点分析法的稳定性要求所有零点位于单位元内,定点计算和量化误差也会引入失真和稳定性问题,因而工程上常使用LSF系数代替LPC系数。
真实值和估算值之间的误差随着阶数的增大而减小,这是因为阶数越高,利用的历史信息越充分,理所应当误差越小,由于不同阶的系数都是基于互相关值计算得到的,因而可以根据低阶系数推导高阶系数值,这样就避免了矩阵求逆的运算,通常LPC系数算法中的系数可以达16阶,Levinson-Durbin递归算法求解系数方法的核心思想是通过低阶算高阶,这里以P为4为例阐述其计算过程。
LPCNet[1]
LPCNet的的作者也是Opus编码器的作者,在WavNet开源之后,将模型的方法融入到编解码中,进一步提升了压缩效率和质量。
WaveNet是DeepMind 2016提出的方法,其不对语音做任何先验假设,用神经网络从数据中学习分布,其不直接预测语音样本值,而是通过一个采样过程来生成语音,其语音质量比之前的所有基于参数声码器多要好,但是其生成语音太慢,主要是因为为了或得足够大的感受野使得卷积层太深太复杂,这使得计算量有几十GFLOPS,因此DeepMind和GoogleBrain提出了WaveRNN,用RNN提示计算效率并采用权重稀疏化方法进一步降低计算量,但其计算量仍然需要10GFLOPS,相对于不需要1GFLOPS的基于信号处理的编码器而言,这仍然高了近两个数量级。自然而然将信号处理和深度学习方法结合以达到实时计算和性能提升的目的,LPCNet正式在这一想法下诞生的编码器。
WaveRNN主要由一层GRU、两层全连接以及softmax激励层组成。
LPCNet是基于WaveRNN的低复杂度语音编码器,通过将线性预测技(对声道建模)和WaveRNN相结合以达到低复杂度语音合成和压缩,其计算复杂度在3GFLOPS以下,许多带支持SIMD指令低功耗移动端处理器(手机和嵌入式系统)都可以支持这一计算复杂度,Jean-Marc Valin是LPCNet和Opus编码器的主要贡献者之一,因而LPCNet信号处理部分使用Opus部分实现方法,开源代码中包含了推理和基于Keras的训练代码。
线性预测是一种简单高效的谱包络建模方法,但是激励信号却没有如此简单高效的方法,LPCNet的谱包络建模还是使用线性预测方法实现,谱特性平坦的激励使用神经网络建模。下图是LPCNet的基本结构,它包括一个工作频率为16 kHz的采样率网络和一个处理10 ms帧(160个采样)的帧率网络,帧率网络为采样率网络提供一个条件向量输入,这个条件向量一帧计算一次,并在该帧时间内保持不变。提取的特征是18个Bark倒谱系数和两个基频参数(周期和相关性),对于低比特率编码应用场景,接收端收到的倒谱系数和基频参数通常经过量化压缩,网络的左侧部分(黄色)每帧计算一次,其结果在整个帧中对于右侧的采样率网络保持不变,compute prediction 模块基于t时刻之前的采样点根据线性预测方法估计的当前采样点值,对输出的采样点
s
t
s_t
st使用去加重滤波后输出。
图 LPCNet框架结构
CLPCNet [2](Controllable LPCNet)
CLPCNet的主要功能是和第一章的Phase Vocoder一样的,提供对时间缩放以及音高变换。该方法的突出贡献是使用LPCNet神经网络声码器,这取得了以前的DSP方法,这使得效果上大大优于以前的。
神经声码器是利用深度神经网络从声学特征(例如梅尔频谱图)生成波形的技术。通过这种技术,我们可以通过编码音频为声学特征、修改这些特征,然后通过声码器产生新的波形来操作语音。
采样率网络和帧率网络的时间分辨率通过一个称为上采样因子k的参数相关联。这意味着,对于帧率网络处理的每一帧,采样率网络将产生k个样本。这些样本之间没有重叠。假设一个音素(phoneme,发音单位)的发音持续了100毫秒,这段时间内包含了10帧数据。如果我们希望将这个音素伸展到200毫秒,就需要对每一帧解码出双倍数量的样本。通过这种方式,每帧原来产生的样本数通过调整为原来的两倍,实现了时间上的伸展。例如,如果原本每个帧产生k个样本,现在每个帧将产生2k个样本,从而将整个音素的播放时间增加到原来的两倍。
对输入特征音高的改进:
在LPCNet中,音高值是按每周期采样数编码的。这种设计导致pitch bins在感知上不均匀;高频率被粗略采样,一些音高bin宽度超过50 cents(音分)。在16 kHz的采样率和8位量化下,最低可表示频率为63 Hz,这限制了低音音色的建模能力。提议对50-550 Hz的频率范围进行量化,量化方式在以2为底的对数尺度上等间隔,使每个音高桶宽度为16.3 cents。
YIN算法在音高和周期性的提取上表现出显著的噪声,这影响了LPCNet的性能。CLPCNet使用CREPE(特别是torchcrepe)来提取音高和周期性。CREPE输出随时间变化的量化音高值的分布。应用Viterbi解码来提取平滑的音高轨迹,减少半频和倍频误差。对提取的音高添加以零为中心、宽度为两个CREPE音高桶(即40 cents)的三角分布随机噪声,减小量化误差而不提高噪声水平。CREPE的周期性测量是与Viterbi解码选定的pitch bins相关联的概率序列。CREPE将输入音频的每一帧标准化,使其对幅度变化不敏感。这会导致在静默区域期间低比特噪声被标记为周期性。为避免此问题,当A-加权响度小于-60 dB(相对参考值20 dB)时,将周期性设置为零。我们的周期性测量与YIN的周期性测量相关性为0.82,显示噪声变小。
参考文献
[1] https://jmvalin.ca/papers/lpcnet_icassp2019.pdf
[2]arXiv:1810.11846v2 [eess.AS] 19 Feb 2019