正如我们在评论中讨论的那样,Goertzel 算法是检测噪声音调的常用方法。讨论之后,我不确定它是否完全符合您的要求(您想要开始时间),但是对于如何将 Goertzel 算法应用于您的问题似乎存在混淆,所以我想我会写下来这里。
格策尔算法
如果您知道要查找的音调的频率(称之为fg),如果您对噪声水平有一个合理的了解,以便您可以选择合适的检测阈值。
可以认为 Goertzel 算法总是计算 ONE FFT bin 的输出:
y(n)=eȷ2πfgn∑k=0nx(n)e−ȷ2πfgk
在哪里fg是您正在寻找的频率。
维基百科页面有更好的计算方法。
这是Scilab实施它的一个(微弱的)尝试:
function [y,resultr,resulti] = goertzel(f_goertzel,x)
realW = 2.0*cos(2.0*%pi*f_goertzel);
imagW = sin(2.0*%pi*f_goertzel);
d1 = 0;
d2 = 0;
for n = 0:length(x)-1,
y(n+1) = x(n+1) + realW*d1 - d2;
d2 = d1;
d1 = y(n+1);
resultr(n+1) = 0.5*realW*d1 - d2;
resulti(n+1) = imagW*d1;
end
endfunction
考虑信号f=0.0239074和ϕ=4.4318752:
x=sin(2πfn+ϕ)+ϵ(n)
在哪里ϵ(n)是零均值、单位方差的高斯白噪声。
在此示例中,音调从索引 1001 处信号的三分之一处开始。
如果我们在其上运行 Goertzel 算法fg=f−0.001然后我们得到图形的顶部两条迹线。
如果我们在其上运行 Goertzel 算法fg=f然后我们得到图形底部的两条痕迹。
这四个痕迹是:
- x(蓝色)和y(红色)为fg=0.0229074
- 所结果的resultr2+resulti2−−−−−−−−−−−−−−−√
- x(蓝色)和y(红色)为fg=0.0239074
- 所结果的resultr2+resulti2−−−−−−−−−−−−−−−√(实线)和第一个结果(虚线)。
如您所见,我们感兴趣的音调出现在大约 250 处的峰值。如果我们将检测阈值设置为该值的一半左右(125),那么就会发生检测(平方根值大于 125 ) 在音调开始后大约索引 1450 --- 450 个样本。
这个阈值 (125) 在其他情况下不会导致检测(无论如何,对于这次运行),但是该输出的最大值是 115.24,我们不能过多地降低阈值而不会得到错误检测。
将阈值降低到 116 将导致在索引 1401 处检测到真实情况(对于本次运行)......但我们冒着更多误报的风险。
