Обнаружение определенной частоты / тона из 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, но он также может делать пользовательские тона.

Я знаю, что этот вопрос старый, но, возможно, это сэкономит кому-то еще несколько дней поиска и тестирования образцов кода и библиотек, которые просто не работают.


Спектральный Анализ.

все приложения, где вы извлекаете частоты из сигналов, проходят полевой спектральный анализ.