Обнаружение определенной частоты / тона из необработанных волновых данных - PullRequest
12 голосов
/ 26 января 2011

Я читаю необработанный волновой поток, исходящий из микрофона.(Эта часть работает так, как я могу отправить ее на динамик и получить хорошее эхо.)

Для простоты, скажем, я хочу обнаружить DTMF-тон в данных волны.На самом деле я хочу обнаружить любую частоту, а не только частоту в DTMF.Но я всегда знаю, какую частоту я ищу.

Я пытался запустить его через БПФ, но это не кажется очень эффективным, если я хочу высокую точность в обнаружении (скажем, она там всего 20 мс).Я могу определить его с точностью до 200 мс.

Какие у меня варианты в отношении алгоритмов?Есть ли .Net-библиотеки для этого?

Ответы [ 6 ]

13 голосов
/ 26 января 2011

Возможно, вы захотите взглянуть на алгоритм Goertzel , если вы пытаетесь обнаружить определенные частоты, такие как вход DTMF.На Sourceforge есть библиотека C # DTMF генератор / детектор , основанная на этом алгоритме.

5 голосов
/ 16 апреля 2014

Очень хорошая реализация 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;
    }

Прекрасно работает для меня.

1 голос
/ 27 января 2011

Я нашел это как простую реализацию Гертцеля. Вы еще не получили его на работу (ищите неправильную частоту?), Но я решил поделиться этим. Скопировано с этого сайта .

        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)));
        }
0 голосов
/ 09 декабря 2011

Что касается любых библиотек .NET, которые делают это, попробуйте TAPIEx ToneDecoder.Net Component . Я использую его для обнаружения DTMF, но он также может выполнять пользовательские тоны.

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

0 голосов
/ 26 января 2011

Допустим, типичная частота DTMF составляет 200 Гц - 1000 Гц.Тогда вам нужно будет обнаружить сигнал на основе от 4 до 20 циклов.Полагаю, что FFT вас никуда не приведет, поскольку вы будете обнаруживать только кратные частоты 50 Гц: это встроенная функция *1002* в FFT, увеличение числа выборок не решит вашу проблему.проблема.Вы должны будете сделать что-то более умное.

Ваш лучший снимок - линейное приближение наименьших квадратов ваши данные -

h(t) = A cos (omega t) + B sin (omega t)

для данного омегачастот DTMF).Подробнее см. this (в частности, как установить уровень статистической значимости) и ссылки на литературу.

0 голосов
/ 26 января 2011

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

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

...