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