Обнаружение определенной частоты / тона из необработанных волновых данных
Я читаю поток сырой волны, идущий от микрофона.
(Эта часть работает так, как я могу отправить ее оратору и получить хорошее эхо.)
Для простоты, скажем, я хочу обнаружить DTMF-тон в волновых данных. На самом деле я хочу обнаружить любую частоту, а не только частоту в DTMF. Но я всегда знаю, какую частоту я ищу.
Я попытался запустить его через FFT, но он не кажется очень эффективным, если я хочу высокую точность в обнаружении (скажем, это там только в течение 20 мс). Я могу обнаружить его с точностью до 200 мс.
Какие у меня варианты в отношении алгоритмов? Есть ли.Net libs для этого?
6 ответов
Возможно, вы захотите взглянуть на алгоритм Гёртцела, если вы пытаетесь обнаружить определенные частоты, такие как вход DTMF. На Sourceforge есть библиотека генератора / детектора C# DTMF, основанная на этом алгоритме.
Очень хорошая реализация Goertzel есть. 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;
}
Прекрасно работает для меня.
Я нашел это как простую реализацию Goertzel. Вы еще не получили его на работу (ищите неправильную частоту?), Но я решил поделиться этим. Он скопирован с этого сайта.
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)));
}
Допустим, типичная частота DTMF составляет 200 Гц - 1000 Гц. Тогда вам нужно будет обнаружить сигнал на основе от 4 до 20 циклов. Я полагаю, что FFT никуда вас не приведет, поскольку вы будете обнаруживать только кратные частоты 50 Гц: это встроенная функция FFT, увеличение количества выборок не решит вашу проблему. Вам придется сделать что-то более умное.
Ваш лучший снимок - это линейное наименьшее соответствие ваших данных
h(t) = A cos (omega t) + B sin (omega t)
для данного омега (одна из частот DTMF). Смотрите это для деталей (в частности, как установить уровень статистической значимости) и ссылки на литературу.
Что касается любых библиотек.NET, которые делают это, попробуйте TAPIEx ToneDecoder.Net Component. Я использую его для обнаружения DTMF, но он также может выполнять пользовательские тоны.
Я знаю, что этот вопрос старый, но, возможно, он сэкономит кому-то еще несколько дней поиска и опробования примеров кода и библиотек, которые просто не работают.
Все приложения, где вы извлекаете частоты из сигналов, проходят полевой спектральный анализ.