我正在读取来自麦克风的原始波流。
(这个部分起作用,因为我可以把它发送到扬声器并得到一个很好的回声。)
为简单起见,我想要检测波形数据中的DTMF音调。实际上我想检测任何频率,而不仅仅是DTMF中的频率。但我总是知道我要找的频率。
我已经尝试通过FFT运行它,但如果我想要高精度的检测(例如它只有20毫秒),它似乎不是很有效。我可以将其检测到大约200毫秒的精度。
关于算法,我有哪些选择? 是否有任何.Net库?
答案 0 :(得分:13)
如果您尝试检测特定频率(如DTMF输入),则可能需要查看Goertzel algorithm。 Sourceforge上有一个基于此算法的C# DTMF generator/detector库。
答案 1 :(得分:5)
Goertzel非常好的实现是there。 C#修改:
private double GoertzelFilter(float[] samples, double freq, int start, int end)
{
double sPrev = 0.0;
double sPrev2 = 0.0;
int i;
double normalizedfreq = freq / SIGNAL_SAMPLE_RATE;
double coeff = 2 * Math.Cos(2 * Math.PI * normalizedfreq);
for (i = start; i < end; i++)
{
double s = samples[i] + coeff * sPrev - sPrev2;
sPrev2 = sPrev;
sPrev = s;
}
double power = sPrev2 * sPrev2 + sPrev * sPrev - coeff * sPrev * sPrev2;
return power;
}
非常适合我。
答案 2 :(得分:1)
我发现这是Goertzel的一个简单实现。还没有让它工作(寻找错误的频率?),但我想我会分享它。它是从this site复制的。
public static double CalculateGoertzel(byte[] sample, double frequency, int samplerate)
{
double Skn, Skn1, Skn2;
Skn = Skn1 = Skn2 = 0;
for (int i = 0; i < sample.Length; i++)
{
Skn2 = Skn1;
Skn1 = Skn;
Skn = 2 * Math.Cos(2 * Math.PI * frequency / samplerate) * Skn1 - Skn2 + sample[i];
}
double WNk = Math.Exp(-2 * Math.PI * frequency / samplerate);
return 20 * Math.Log10(Math.Abs((Skn - WNk * Skn1)));
}
答案 3 :(得分:0)
假设典型的DTMF频率为200Hz-1000Hz。然后你必须检测基于4到20个周期的信号。因为你只能检测50Hz频率的倍数,所以FFT不会让你到达任何地方:这是FFT的内置功能,增加样本数不解决你的问题。你必须做一些更聪明的事。
您的最佳镜头是线性最小二乘拟合您的数据
h(t) = A cos (omega t) + B sin (omega t)
给定的omega(DTMF频率之一)。有关详细信息,请参阅this(特别是如何设置统计显着性水平)以及指向文献的链接。
答案 4 :(得分:0)
对于执行此操作的任何.NET库,请尝试TAPIEx ToneDecoder.Net Component。我用它来检测DTMF,但它也可以做自定义音调。
我知道这个问题已经过时了,但也许它可以节省其他人几天的搜索和尝试不起作用的代码示例和库。
答案 5 :(得分:-2)
<强> Spectral Analysis 即可。
从信号中提取频率的所有应用都在场光谱分析下进行。