Как мне реализовать полосовой фильтр в C (Цель: обнаружение высоты тона)?

Недавно я задал этот вопрос:

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

Немного продвинутый алгоритм может сделать что-то вроде этого:

  1. Примерно определить частоту основного тона (можно сделать с помощью ДПФ).
  2. Полосовой сигнал для фильтрации частоты основного тона.
  3. Подсчитайте количество выборок между двумя пиками в отфильтрованных сигналах.

Теперь я могу сделать первый шаг в порядке (я пишу код для iOS, а у Apple есть фреймворк (фреймворк ускорения) для выполнения БПФ и т. д.

Я начал здесь: но я могу видите проблему: БПФ, который бы различал все возможные ноты, которые можно было бы спеть, потребовал бы большого количества сэмплов, и я не хочу выполнять слишком много ненужных вычислений, поскольку я нацелен на мобильное устройство.

Итак, я пытаюсь понять этот ответ выше, но я не понимаю, как я могу применить концепцию полосового фильтра к коду.

Кто-нибудь может помочь?


person P i    schedule 05.11.2010    source источник
comment
Вы уже задали много вопросов на SO об обнаружении высоты тона, но кажется, что вы все еще не совсем понимаете (a) разницу между высотой и частотой или ( б) необходимость выбора алгоритма определения высоты тона, подходящего для типа звука, который вы пытаетесь проанализировать (например, речь, музыка и т. д.). Я предлагаю вам немного больше прочитать об основах, прежде чем пытаться что-то реализовать, иначе вы можете потратить много ненужных усилий, выбрав неправильный путь.   -  person Paul R    schedule 05.11.2010
comment
Вот почему я задаю так много вопросов — я пытаюсь понять, что практично, а что нет, прежде чем что-то предпринять. Я медленно получаю некоторое представление о проблеме.   -  person P i    schedule 05.11.2010
comment
@Ohmu: возможно, вы захотите вернуться и перечитать некоторые из предыдущих ответов, а также предоставленные ссылки. У меня такое ощущение, что вы пытаетесь перейти к реализации, не поняв сначала основ. Удачи.   -  person Paul R    schedule 05.11.2010
comment
@Paul R: Насколько я понимаю, голос состоит из основной частоты и ее гармоник. Я прошел через математику преобразований Фурье, ДПФ, БПФ и столкнулся с практическими ограничениями; чтобы определить, немного ли отличается спетый тон, но фактическая нота требует низкой основной частоты, что требует большого окна выборки, что требует либо мощного процессора, либо резкого снижения частоты дискретизации микрофона. Следовательно, я собираюсь выполнить базовое БПФ, чтобы получить общие области интереса в частотной области и каким-то образом улучшить результат.   -  person P i    schedule 05.11.2010
comment
@Paul R: Отсюда мой интерес к данному мне ответу, предлагающему использовать полосовой фильтр на данном этапе. Однако я не могу определить, является ли это практическим предложением. Я также рассмотрел другие предложения; автокорреляция фактически аналогична умножению исходного сигнала на синусоиду желаемой частоты и интегрированию по целому числу длин волн, это может работать, но потребуется некоторая работа, чтобы расшифровать частоты, немного отличающиеся от выходных. Я действительно все еще пытаюсь подтолкнуть его со всех сторон.   -  person P i    schedule 05.11.2010
comment
@Ohmu: если вас интересует высота человеческого голоса, возможно, вы захотите взглянуть на кепстральный анализ: en.wikipedia.org/wiki/Кепструм   -  person Paul R    schedule 06.11.2010


Ответы (3)


Конструкция фильтра довольно сложная. Есть много техник. Сначала вы должны решить, какой фильтр вы хотите создать. Конечная импульсная характеристика (КИХ)? Бесконечная импульсная характеристика (IIR)? Затем вы выбираете алгоритм для разработки фильтра этого типа. Алгоритм Ремеза часто используется для проектирования КИХ-фильтров. Перейдите сюда, чтобы увидеть сложность, о которой я говорил: http://en.wikipedia.org/wiki/Remez_algorithm

Лучше всего для создания фильтра использовать существующую библиотеку обработки сигналов. Быстрый поиск в Google привел меня сюда: http://spuc.sourceforge.net/

Учитывая ваше приложение, вы можете прочитать о согласованных фильтрах. Я не уверен, что они уместны здесь, но они могут быть. http://en.wikipedia.org/wiki/Matched_filter

person Fantius    schedule 04.02.2011

хорошо в Википедии, проверьте фильтр нижних частот и высоких частот, затем объедините их, чтобы сделать полосовой фильтр. В Википедии есть реализации кода для этих двух фильтров.

http://en.wikipedia.org/wiki/Low-pass_filter http://en.wikipedia.org/wiki/High-pass_filter

person TechEffigy    schedule 16.09.2014
comment
В данный момент я занят нейронной сетью и перевешиваю использование полосовых фильтров или БПФ. Вот так я наткнулся на ваш вопрос :) - person TechEffigy; 16.09.2014

Поскольку вы хотите обнаружить только одну частоту, было бы излишним выполнять ДПФ, чтобы затем использовать только одно из значений.

Вы можете реализовать алгоритм Герцеля. Подобно этой реализации C, используемой для обнаружения DTMF тональные сигналы по телефонной линии из исходного кода FreePBX:

float goertzel(short x[], int nmax, float coeff) {
    float s, power;
    float sprev, sprev2;
    int   n;

    sprev = 0;
    sprev2 = 0;
    for(n=0; n<nmax; n++) {
        s = x[n] + coeff * sprev - sprev2;
        sprev2 = sprev;
        sprev = s;
    }

    power = sprev2*sprev2 + sprev*sprev - coeff*sprev*sprev2;

    return power;
}

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

person istepaniuk    schedule 17.11.2020