音高(pitch)是声音的三大属性(音量、音高、音色)之一。除去个别极端情况,音高是由声音的基频(fundamental frequency, 简记为[公式])决定的,因此在文献中「音高」与「基频」两个词常常混用。由有规律的振动发出的声音,一般都会有基频,这样的声音包括语音中的元音与浊辅音,以及能演奏旋律的乐器发出的声音。也有的声音没有基频,它们听起来就是噪声,这样的声音包括语音中的清辅音,以及打击乐器发出的声音。


语音的基频一般在 100 Hz ~ 400 Hz 之间,女声比男声的基频高,童声更高。歌声以及乐器发出的声音则会有更广的基频范围,低可以低到 50 Hz 甚至更低,高可以超过 1000 Hz。人对于基频的感知遵循对数律,也就是说,人们会感觉 100 Hz 到 200 Hz 的差距,与 200 Hz 到 400 Hz 的差距相同。因此,音高常常用基频的对数来表示。在音乐上,把相差一倍的两个基频的差距称为一个八度(octave);把一个八度 12 等分,每一份称为一个半音(semitone);把一个半音再 100 等分,每一份称为一个音分(cent)。音乐中常常用 midi number 来表示音高,它与基频[公式]的关系为:


即:把国际标准音 440 Hz 的 midi number 定为 69,然后每升高(或降低)一个八度,midi number 增(或减)12。由此可见 midi number 的单位为半音。


图 1:张靓颖歌曲《画心》中的海豚音,最高基频达到了 1320 Hz(音名 E6,midi number 88)

.基频提取(pitch estimation, pitch tracking)在声音处理中有广泛的应用。它最直接的应用,是用来识别音乐的旋律。它也可以用于语音处理,比如辅助带声调语言(如汉语)的语音识别,以及识别语音中的情感。

由于声音的基频往往随时间而变化,所以基频提取通常会先把信号分帧(帧长通常为几十毫秒),再逐帧提取基频。提取一帧声音基频的方法,大致可以分为时域法和频域法。时域法以声音的波形为输入,其基本原理是寻找波形的最小正周期。当然,实际信号的周期性只能是近似的。频域法则会先对信号做傅里叶变换,得到频谱(仅取幅度谱,舍弃相位谱)。频谱上在基频的整数倍处会有尖峰,频域法的基本原理就是要求出这些尖峰频率的最大公约数。


图 2:一段基频约为 120 Hz(周期约为 8.3 ms)的语音波形及其频谱

考虑到基频并不是每一帧都会有,在提取基频之前、之后或同时,往往要判断一下基频的有无,这称为清浊音判别(unvoiced / voiced decision,简称 U/V decision)。逐帧提取的基频常常含有错误,其中最常见的错误是「倍频错误」和「半频错误」,即提取出的基频是真实基频的两倍或者一半。为了纠正这些错误,通常会再对结果进行平滑(smoothing)处理,得到光滑的基音轨迹(pitch contour)。

基频提取长期以来都是用纯信号处理的方法进行的,属于基于规则(rule-based)的方法。这是由于基频的概念在信号层面上就比较清晰,不像语音识别中的「音素」等概念那样抽象。不过,用纯信号处理方法,很难同时降低「倍频错误」和「半频错误」的发生率:在算法中努力降低一者,往往会造成另一者升高,呈现「按下葫芦起来瓢」的态势。因此,最近几年出现了一些使用机器学习方法提取基频的研究,它们通过数据驱动(data-driven)的方式,超越了纯信号处理方法的性能。

从上世纪末到现在,基频提取方法一共出现了几十乃至上百种。这篇文章不求全面,而只是挑选其中有代表性的四种方法(YIN、SWIPE、CREPE、SPICE)来综述一下。这些方法的使用都比较广泛,性能也都在一段时期内保持领先;它们恰好也涵盖了信号处理与机器学习、时域法与频域法的所有类别。四种方法都只能处理单个声源;至于有多个声源的声音叠加时,如何同时提取各自的基频,本文暂不涉及。


一、YIN[1](信号处理、时域法)

前面说过,时域法的基本原理是寻找波形的最小正周期。换句话说,就是看信号平移多少后,与原信号的重合度最高。「重合度」有两种定量衡量的方法:

● 一是乘法,即把平移后的信号与原信号相乘,再在一帧之内求和。这就是自相关函数(auto-correlation function, ACF):


自相关函数的峰值对应的平移量[公式],可以代表信号在[公式]处的周期。式中[公式]为一帧内的采样点数。

● 二是减法,即把平移后的信号与原信号相减。对于相减的结果,可以求绝对值再积分,这就是平均幅度差函数(average magnitude difference function, AMDF)[2]

[公式]

也可以像 YIN 一样,求平方再积分,YIN 的论文把这样做的结果简称为差函数(difference function):[公式]差函数的谷值对应的平移量[公式],可以代表信号在[公式]处的周期。

YIN 的论文指出,做减法优于做乘法。这是因为,如果信号幅度在逐渐增大,那么把信号往后平移得越多,与原信号相乘再积分的结果就会越大。这将造成估计出的周期过大,基频过低,产生「半频错误」。做减法则没有这个问题。

YIN 算法的名称取自「阴阳」之「阴」,它表明算法的核心思想是在差函数上寻找「谷值」,而不是在自相关函数上寻找「峰值」。之所以想到用「阴阳相生」来形容差函数与自相关函数的关系,是因为差函数可以用自相关函数表示出来:

[公式]


图 3:一段周期约 150 个采样点的语音信号(上)及其差函数(中)与 CMNDF(下),取自 YIN 论文中的图 1、3

一个典型信号的差函数如图 3(中)所示,我们要找的是它尽量靠左,又比较深的谷。然而,差函数在原点(平移量为 0)时会取得最小值 0,这个谷会产生干扰,应该避开它。一种方法是设定周期的最小允许值,只在这个阈值右边寻找谷。然而问题是,原点处的谷的宽度并不固定,导致阈值难以设置。YIN 提出的解决办法是,在差函数的基础上,定义一种累积均值归一化差函数(cumulative mean normalized difference function, CMNDF):

[公式]

这相当于说,把差函数在[公式]处的值,用差函数在[公式]左边的平均值去归一化。CMNDF 有两个好处:

● 从图 3 可以看到,CMNDF 去除了差函数在原点处的谷,避免了它的干扰;● CMNDF 的纵坐标是归一化的,不再依赖于信号本身的幅度。

若在 CMNDF 上直接求最小值,容易产生一个问题:由于信号的周期性并不理想,最小值可能并不是最左边的深谷,而是第二个甚至第三个。这会导致「半频错误」。YIN 的解决办法是,设置一个谷深阈值(如 0.1,图 3(下)里的虚线),取比此阈值更深的第一个谷的位置作为周期。CMNDF 「归一化」的特点使得选取谷深阈值成为可能。谷深阈值的选取带有任意性,不过 YIN 的作者用实验表明,YIN 的性能对此阈值并不敏感。若没有比阈值更深的谷,则选择最深的谷的位置作为基频,也可以认为这一帧没有基频。

以上就是 YIN 的核心方法。在此基础上还有一些非核心的改进,比如在 CMNDF 的每个谷处进行二次插值,以确定谷底的精确位置。

YIN 算法还有一种改进,称为概率 YIN 算法(probabilistic YIN,简称 pYIN)[3],它主要针对的是基音轨迹的平滑性。原始的 YIN 算法对每一帧只给出周期的一个估计值,一旦产生了倍频或半频错误,就很难恢复。pYIN 算法对每一帧挑选多个谷作为候选,并用 HMM 建模基频的转移规律,使得基音轨迹尽可能平滑,并消除个别帧产生的倍频或半频错误。同时,HMM 中设置了「无基频」状态,可以借此实现清浊音判别。


二、SWIPE[4](信号处理、频域法)

用频域法提取基频的一般套路是:对每一个候选频率[公式],设计一个函数来表达[公式]是基频的可能性,称为显著度函数(salience function);使得显著度函数取得最大值的频率[公式]就当作基频。

考虑到信号的幅度谱[公式]在基频[公式]的整数倍处会有峰值,于是可以用幅度谱在[公式]的各个倍数处的值的总和来代表[公式]的显著度:[公式]这称为谐波相加法(harmonic summation)[5],它构成了大部分频域法的骨架。在具体的算法中,求和可能只取固定的项数,也可能一直取到信号所能表示的频率上限(即采样率的一半,称为奈奎斯特频率);求和的各项也可能乘以不同的权重[公式],一般[公式]越小,权重越大。

如果采用不加权的谐波相加法,并在求和时取到频率上限,就容易产生半频错误:这是因为[公式]的整数倍,也都是[公式]的整数倍,这会使得[公式]取得更大的显著度。若是在求和时施加随[公式]递减的权重,则又容易产生倍频错误,因为[公式]的[公式]次谐波对于[公式]来说只是[公式]次谐波,权重更大,这会使得[公式]取得更大的显著度。

SWIPE 的论文提出了如下的核心论点:一个频率[公式]若是好的基频候选值,那么幅度谱不仅要在[公式]的整数倍处取得峰值,还要在[公式]的半整数倍处取得谷值。SWIPE 用如下的函数衡量幅度谱在[公式]处的峰值相对于紧邻它的两个谷值有多显著,称为峰谷距(peak-to-valley distance,PVD):[公式]各次谐波的平均峰谷距(average PVD, APVD),就可以代表[公式]的显著度:[公式]

平均峰谷距可以表达成幅度谱与一个核函数的内积,这个核函数在[公式]的整数倍处有向上的冲激,在[公式]的半整数倍处有向下的冲激,如图 4 所示。为了表达「平均」峰谷距而不是「总」峰谷距,核函数需要经过某种归一化。


图 4:信号的幅度谱(虚线)与核函数(实线)做内积,取自 SWIPE 论文中的图 1

平均峰谷距对于对抗倍频错误有奇效:当候选基频[公式]等于真实基频[公式]的两倍时,[公式]的奇次谐波将与核函数中向下的冲激对齐,这会减小显著度。它也能对抗半频错误:如果[公式],那么核函数中第奇数个向上的冲激将无法对应到频谱上的峰值,从而被「浪费」掉,这也会减小显著度。

SWIPE 算法在平均峰谷距的基础上,考虑了许多细节,让算法的性能精益求精。这些细节包括:

1. 频谱的横轴采用 ERB 刻度,以展宽低频带、缩窄高频带(原文 II.F 节)。2. 频谱的纵轴取了平方根(原文 II.B 节)。3. 求和时考虑奈奎斯特频率以内的所有谐波(原文 II.E 节),并对[公式]次谐波施加[公式]的权重(原文 II.C 节)。4. 把核函数中的冲激换成了半个周期的余弦波形(原文 II.D 节)。5. 对核函数进行 2-范数归一化,并在计算范数时仅考虑正值部分,不考虑负值部分(原文 II.G 节)。之所以这样做,是因为频谱就只有正值,没有负值。6. 对不同的候选基频[公式],采用不同的窗长来计算幅度谱,以使得幅度谱上各个峰的宽度与核函数的余弦波形的宽度吻合(仍为原文 II.G 节)。具体来说,使用的是长度为[公式](即 8 个周期)的汉宁窗。

在第 3 条中,之所以把权重取为[公式],是因为语音中元音的幅度谱常常呈现[公式]的衰减规律,经过了第 2 条的平方根压缩后,就是按[公式]衰减了。让核函数与幅度谱按相同的速率衰减,可以让元音取得最大的平均峰谷距。综合考虑 2、3 两条细节,可以得到各次谐波在求和时的贡献按[公式]规律衰减,实验发现这个衰减速率不快不慢正合适。

在典型信号中,锯齿波(sawtooth wave)的幅度谱与元音一样,都呈现[公式]的衰减规律,这正是 SWIPE 算法全名(sawtooth wave inspired pitch estimator)的来源。不过,与其说是受到了「锯齿波」的启发,不如说算法是针对「语音中的元音」而设计的。

考虑了上述 6 条细节的 SWIPE 算法,可以表示成下面图 5 中的幅度谱与核函数的内积:


图 5:SWIPE 算法中实际使用的、经过弯折的幅度谱(虚线)与核函数(实线),取自 SWIPE 论文的图 7

为了进一步减少「半频错误」,SWIPE 算法的作者又提出了这样一条改进(原文 II.I 节):在计算平均峰谷距中的求和时,只考虑候选频率及其素数倍频率。改进后的算法称为 SWIPE',撇号在英语中读作 prime,正是「素数」的意思。SWIPE' 算法相当于把核函数改成了下面图 6 的样子。这样,如果候选频率[公式]是真实基频的整数分之一,那么幅度谱上的各次谐波的峰(基波除外)都将位于[公式]的合数倍处,与核函数的峰完美错开,只能得到很小的显著度。

图 6:SWIPE' 算法的核函数(实线),只保留了第一个和第素数个峰。取自 SWIPE 论文中的图 9

SWIPE 和 SWIPE' 算法还有一些用来减少运算量的改进,在此就不赘述了。


三、CREPE[6](机器学习、时域法、有监督)

用纯信号处理方法来提取基频有两个优点:一是不需要训练数据,二是原理容易解释。但这些方法同样有一些明显的缺点:一是算法中总有许多成分显得很人为,二是实际数据中总会有设计算法时没有考虑到的情况,导致提取结果不准确。近几年出现了几种使用机器学习的基频提取方法,它们牺牲了可解释性,但换取了性能的进一步飞跃。

用机器学习来提取基频,同样可以分为时域法和频域法。这一节来介绍时域法的代表 CREPE。CREPE 的全名为 convolutional representation for pitch estimation,顾名思义,它采用的是卷积神经网络。网络结构如图 7 所示:


图 7:CREPE 的卷积神经网络结构,取自 CREPE 论文中的图 1

网络的输入是一段音频信号,其长度为 1024 个采样点,在 16 kHz 的采样率下相当于 64 毫秒。网络含有 6 个卷积层和一个全连接层。网络的输出是一个 360 维的向量,每一维对应着一个候选基频的概率[公式]。基频的范围为 32.70 Hz ~ 1975.5 Hz(对应音名 C1 ~ B7,midi number 24 ~ 95),在对数刻度上均匀分布,每隔 20 音分取一个值(嘛,这其实只有 356 个值);第[公式]个候选基频的对数值记为[公式]。输出层并没有整体使用一个 softmax 激活函数,而是逐维使用了 sigmoid 激活函数,以使输出位于 0 ~ 1 之间。这种设计使得网络具有提取多个基频的潜力,但论文中并没有利用这种潜力。

在训练时,网络的目标输出[公式],是把真实基频(对数值为[公式])经过高斯模糊产生的,就像图 7 最右侧所画的那样。高斯模糊的峰值为 1,标准差为 25 音分:[公式]由于目标输出并非 one-hot 形式,输出层使用的又是 sigmoid 激活函数,所以损失函数选用 binary cross entropy 而非 categorical cross entropy:[公式]在测试时,网络最终给出的(对数)基频估计值,是由网络输出层的 360 个单元所代表的(对数)基频加权平均而得的,权重就是网络的输出:[公式]

CREPE 论文中的系统,是在合成数据集上训练和测试的。测试结果表明,无论是基频估计准确率,还是抵抗多种噪声的能力,CREPE 都优于 pYIN 和 SWIPE。之所以选用合成而非真实数据集进行测试,是因为真实数据集需要人工标注真实基频,而人工标注的错误率会高于 CREPE 算法本身的错误率,于是就无法测出 CREPE 算法的真实性能。而「合成数据集」是根据预先确定的音高、音量和音色,用程序自动合成出来的,因此可以保证标准答案 100% 准确。但正因为如此,我有些怀疑 CREPE 的良好表现能否推广到音色更复杂、噪声更不可预料的真实数据上去。推特上有人表达了相同的疑虑[7]:


图 8:推特上一条对 CREPE 的评价

四、SPICE[8](机器学习、频域法、自监督)

SPICE 是使用机器学习方法在频域中提取基频的代表方法。不过,与 CREPE 相比,SPICE 最大的特点倒不在「频域」,而在于「自监督」—— SPICE 的全名 Self-supervised PItCh Estimation 也强调了这一点。所谓的「自监督」,就是不需要人工为训练数据标注标准答案,而是可以从训练数据中「自己出题自己做」。SPICE 是怎么给自己出题呢?


图 9:SPICE 算法的主要模块,取自介绍 SPICE 的博文

Google AI 有一篇介绍 SPICE 的博文[9],其中画出了 SPICE 的主要模块,如图 9。SPICE 首先把信号转换到频域,作为网络的输入;但这里使用的不是傅里叶变换,而是constant Q transform(CQT)。图 9 的下方是 CQT 得到的语谱图,它的纵轴直接就是对数频率;把一段声音的基频提高或者降低,在 CQT 语谱图上的表现就是向上或向下平移。在语谱图上的同一时刻、但不同频段处取两段频谱[公式],并假装它们来自同一频段,那么它们代表的就应该是两个基频不同的信号[公式];两个频段错开了多少,[公式]的(对数)基频就也应该相差多少。由此就可以「自己出题自己做」了:把两段频谱[公式]分别送进同一个卷积神经网络(图 9 中的编码器 Encoder),让它估计出两段频谱所代表的信号的(对数)基频,并相减。两个(对数)基频之差的标准答案是已知的,由此就可以构建损失函数[公式],并训练网络了。

SPICE 采用 Huber loss 作为[公式],它的函数图象如图 10 中的实线所示。在原点附近的一个区间内,Huber loss 的图象是一段抛物线,相当于 L2 loss;超出这个区间后,Huber loss 的图象就变成了直线,相当于 L1 loss。对于「估计基频差」这个任务来说,原点附近的损失很小,代表可以容忍较小的估计误差。在离开原点较远的地方用 L1 loss 来代替 L2 loss,又可以避免特别大的估计误差带来过高的损失,导致喧宾夺主。


图 10:Huber loss,图取自:http://hua-zhou.github.io/teaching/biostatm280-2019spring/slides/26-qp/qp.html

SPICE 的「自监督」方法只能让编码器输出的差值代表(对数)基频差,却不能让输出本身具有「对数基频」本身的意义。因此,在 SPICE 系统训练好之后,需要对其输出进行校准(calibration),即拟合一个线性变换,把编码器的输出转换成(对数)基频。这一步需要少量的、基频已知的输入信号,这样的信号可以编程合成。实验发现,只需要 5 条校准信号,就能达到令人满意的校准效果。

博文[9]并没有介绍整个 SPICE 系统的全貌。事实上,SPICE 系统中还有一个重要的部分,就是根据估计出的基频重建 CQT 频谱的解码器。SPICE 系统的全貌如图 11 所示,其中的解码器(Decoder)是一个解卷积神经网络(deconvolutional neural network),其结构与编码器(Encoder)对称。在训练网络时,损失函数中除了衡量基频差的[公式],还有一项就是衡量重建频谱的[公式],它等于重建出的频谱与输出频谱之差的 L2 范数。重建频谱看起来是一个不可能的任务,因为编码器的输出只是一个数,它只携带了基频的信息,从中无法得知各次谐波的强度之比。然而实验却发现,这个重建损失[公式]对于系统性能至关重要。如果没有这个损失项,系统的 raw pitch accuracy(估计基频与真实基频之差小于 0.5 个半音的概率)就从 90% 立马下降到 56%,惨不忍睹了。


图 11:SPICE 系统的完整框图,取自 SPICE 论文中的图 2

完整的 SPICE 系统还可以给出基频估计值的置信度(confidence),对置信度设置一个阈值,就可以实现清浊音判别。置信度的训练方法,是让 1 减去置信度的结果,尽可能去逼近基频差的估计误差,这一损失项就是图 11 中的[公式]。


参考

  1. ^A. de Cheveigné and H. Kawahara, "YIN, a fundamental frequency estimator for speech and music", Journal of the Acoustical Society of America, 2002.
  2. ^M. J. Ross, et al., "Average magnitude difference function pitch estimator", IEEE Transactions on Acoustics, Speech, and Signal Processing, 1974.
  3. ^M. Mauch and S. Dixon, "pYIN: A fundamental frequency estimator using probabilistic threshold distributions", ICASSP, 2014.
  4. ^A. Camacho and J. G. Harris, "A sawtooth waveform inspired pitch estimator for speech and music", Journal of the Acoustical Society of America, 2008.
  5. ^D. J. Hermes, "Measurement of pitch by subharmonic summation", Journal of the Acoustical Society of America, 1988.
  6. ^J. W. Kim, et al., "CREPE: A convolutional representation for pitch estimation", ICASSP, 2018.
  7. ^https://twitter.com/khuasw/status/993492019594088449
  8. ^B. Gfeller, et al., "SPICE: Self-supervised pitch estimation", IEEE Transactions on Audio, Speech and Language Processing, 2020.
  9. ^abM. Tagliasacchi, "SPICE: Self-supervised pitch estimation", Google AI Blog, 2019. Online:https://ai.googleblog.com/2019/11/spice-self-supervised-pitch-estimation.html

文章来源知乎,文章作者:王赟 Maigo