基音周期估计的现有方法
到目前为止,基音检测的方法大致上可以分为三类:
1)时域估计法,直接由语音波形来估计基音周期,常见的有:自相关法、并行处理法、平均幅度差法、数据减少法等;
2)变换法,它是一种将语音信号变换到频域或者时域来估计基音周期的方法,首先利用同态分析方法将声道的影响消除,得到属于激励部分的信息,然后求取基音周期,最常用的就是倒谱法,这种方法的缺点就是算法比较复杂,但是基音估计的效果却很好;
3)混合法,先提取信号声道模型参数,然后利用它对信号进行滤波,得到音源序列,最后再利用自相关法或者平均幅度差法求得基因音周期。
自相关函数
能量有限的语音信号x(n)的短时自相关函数定义为:
此公式表示一个信号和延迟m点后该信号本身的相似性。
如果信号x(n)具有周期性,那么它的自相关函数也具有周期性,而且周期与信号x(n)的周期性相同。
自相关函数提供了一种获取周期信号周期的方法:在周期信号周期的整数倍上,它的自相关函数可以达到最大值,因此可以不考虑起始时间,而从自相关函数的第一个最大值的位置估计出信号的基音周期,这使自相关函数成为信号基音周期估计的一种工具。
短时自相关函数法
语音信号是非稳态信号它的特征是随时间变化的,但在一个很短的时间段内可以认为具有相对稳定的特征即短时平稳性。因此语音具有短时自相关性。这个时间段约5ms-50ms。其统计特性和频谱特性都是对短时段而言的。这使得要对语音信号作数字处理必须先按短时段对语音信号分帧。这样每一帧信号都具有短时平稳性,从而能够进行短时相关分析。
能量有限的语音信号s(n)的短时自相关函数定义为:
一般要求一帧至少包含2个以上的周期。一般,基频最低50Hz,故周期最长为20ms。而且相邻帧之间要有足够的重叠。具体应用时,窗口长度根据采样率确定帧长。
算法实现
将算法翻译成C++语言如下:
short calOneFrameACF(vector<short> wavFrame, int sampleRate)
{
vector<float> acf;
acf.empty();
// calculate ACF
for (int k = 0; k < wavFrame.size(); k++)
{
float sum = 0.0;
for (int i = 0; i < wavFrame.size() - k; i++)
{
sum = sum + wavFrame[i] * wavFrame[ i + k ];
}
acf.push_back(sum);
}
// find the max one
float max(-999);
int index = 0;
for (int k = 0; k < wavFrame.size(); k++)
{
if (k > 25 && acf[k] > max)
{
max = acf[k];
index = k;
}
}
return (short)sampleRate / index;
}
有了基频估计就可以针对不同频率判断音频来源,作出相关针对性处理。
项目工程源码可参照工程AudioClippingDetect
封装了该算法与音频短时能量的计算