ФНЧ Баттерворта
ФНЧ Баттерворта
Здравствуйте. Я пытаюсь создавать программы для музыкальных инструментов (в основном для гитары). Демонстрацию рабочей версии можете посмотреть тут - https://www.youtube.com/watch?v=D-F2KHjamFg
Пришел попросить помощи для выбора фильтра. Частота стандартная 44100 Гц. Размер захватываемого буфера 1024 семпла. Частота высокой ноты на 1 струне 12 ладу примерно 660 Гц. (На самом деле бывает и выше, но для обучения достаточно такого диапазона). Сейчас после захвата (на скрине верхний график) применяется скользящее среднее (нижний график), но это плохой вариант.
Как я понял, фильтр Баттерворта оставляет низкие частоты практически не тронутыми и заглушает высокие частоты. Я бы хотел с вашей помощью применить его к своим программам. Пока изучаю теорию, потом приду с кодом на проверку.
Пришел попросить помощи для выбора фильтра. Частота стандартная 44100 Гц. Размер захватываемого буфера 1024 семпла. Частота высокой ноты на 1 струне 12 ладу примерно 660 Гц. (На самом деле бывает и выше, но для обучения достаточно такого диапазона). Сейчас после захвата (на скрине верхний график) применяется скользящее среднее (нижний график), но это плохой вариант.
Как я понял, фильтр Баттерворта оставляет низкие частоты практически не тронутыми и заглушает высокие частоты. Я бы хотел с вашей помощью применить его к своим программам. Пока изучаю теорию, потом приду с кодом на проверку.
- Вложения
-
- 2015-01-28 00 52 50.png (6.49 КБ) 9389 просмотров
Re: ФНЧ Баттерворта
Для изучения фильтра решил накидать генератор синусоиды. Потом можно будет генерировать разные частоты, длительности, и отправлять массив на фильтрацию с разными параметрами.
RND сделал чтоб смещение фазы было. M_PI может быть вам придется писать по другому, или число вставить.
RND сделал чтоб смещение фазы было. M_PI может быть вам придется писать по другому, или число вставить.
Код: Выделить всё
#include <stdio.h>
#include <math.h>
#define FREQ 44100
#define BUFER_SIZE 512
#define RAND 346
int main(void) {
int i;
float freq=440;
float sin_array [BUFER_SIZE];
for(i=0; i<=BUFER_SIZE; i++){
sin_array[i]= sin ((i+RAND) * 2 * M_PI *freq / FREQ);
printf ("%i %f\n", i, sin_array[i]);
}
return 0;
}
- Santik
- Сообщения: 609
- Зарегистрирован: 28 дек 2010, 08:04
- Откуда: Мирный (Якутия)
- Контактная информация:
Re: ФНЧ Баттерворта
Какая-то совсем неправильная программа
Если я Вас правильно понял, Вы хотели написать:
Теперь посмотрим, что у Вас:
t=(i+RAND)/FREQ - это вообще непонятно.
1. начальную фазу надо вычислять вне цикла
2. 2 * M_PI *freq / FREQ- надо вычислять вне цикла
и вообще что это freq / FREQ???
Советую написать генератор сигнала, который бы автоматически генерировал гармоники.
Если я Вас правильно понял, Вы хотели написать:
Теперь посмотрим, что у Вас:
t=(i+RAND)/FREQ - это вообще непонятно.
1. начальную фазу надо вычислять вне цикла
2. 2 * M_PI *freq / FREQ- надо вычислять вне цикла
и вообще что это freq / FREQ???
Код: Выделить всё
int main(void) {
int i;
float freq=440;
float freq_d=44100;
float Pi=3.14159265358;
float sin_array [BUFER_SIZE];
float faza,z;
faza=2*Pi*RAND;// подразумевается что функция RAND возвращает случайное число от 0.0 до 1.0
z=2*Pi*freq/freq_d;
for(i=0; i<=BUFER_SIZE; i++){
sin_array[i]= sin (i*z+faza);
printf ("%i %f\n", i, sin_array[i]);
}
return 0;
}
Re: ФНЧ Баттерворта
Можно изменить для понятности
Я амплитуду рассчитываю от номера семпла, а не от значения времени. И RAND смещается на произвольный семпл. В том месте начальная амплитуда не равна нулю.
Для объективности приведу несколько значений. Начало синусоиды:
0 0.000000
1 0.062648
2 0.125051
3 0.186961
Конец первой волны и начало второй происходит около сотого семпла.
99 -0.076861
100 -0.014247
101 0.048423
102 0.110903
Давайте сравним с вашими расчётами и убедимся, что всё верно.
Пожалуй надо будет генерацию в отдельную функцию вынести, чтоб можно было в один массив примешивать произвольное количество синусин с произвольными частотой и амплитудой. Но сначала надо разобраться с одной.
Код: Выделить всё
#define SAMPLE_RATE 44100
#define BUFER_SIZE 512
#define RAND 0
Для объективности приведу несколько значений. Начало синусоиды:
0 0.000000
1 0.062648
2 0.125051
3 0.186961
Конец первой волны и начало второй происходит около сотого семпла.
99 -0.076861
100 -0.014247
101 0.048423
102 0.110903
Давайте сравним с вашими расчётами и убедимся, что всё верно.
Пожалуй надо будет генерацию в отдельную функцию вынести, чтоб можно было в один массив примешивать произвольное количество синусин с произвольными частотой и амплитудой. Но сначала надо разобраться с одной.
Re: ФНЧ Баттерворта
Ещё я с частотой не могу определиться
Гарантировано должно передаваться без искажений до ноты МИ второй октавы = 659.26 Гц
Диапазон гитары примерно до 20 лада, до ноты ДО третьей октавы = 1046.5 Гц
Если тренажер переделать под стандартные инструменты (клавишные) то он может задавать ноты до ноты МИ третьей октавы (1318.5 Гц)
Как рассчитать коэффициенты для этих частот? Можно округлить, например 700, 1000, 1300.
Статьи для себя, чтоб не потерять.
Расчет аналогового нормированного фильтра нижних частот Баттерворта
Пример расчета цифрового фильтра нижних частот Баттерворта
Гарантировано должно передаваться без искажений до ноты МИ второй октавы = 659.26 Гц
Диапазон гитары примерно до 20 лада, до ноты ДО третьей октавы = 1046.5 Гц
Если тренажер переделать под стандартные инструменты (клавишные) то он может задавать ноты до ноты МИ третьей октавы (1318.5 Гц)
Как рассчитать коэффициенты для этих частот? Можно округлить, например 700, 1000, 1300.
Статьи для себя, чтоб не потерять.
Расчет аналогового нормированного фильтра нижних частот Баттерворта
Пример расчета цифрового фильтра нижних частот Баттерворта
- Santik
- Сообщения: 609
- Зарегистрирован: 28 дек 2010, 08:04
- Откуда: Мирный (Якутия)
- Контактная информация:
Re: ФНЧ Баттерворта
Можно проще сделать. Взять одну синусоиду и ограничить ее по амплитуде. Наличие гармоник будет гарантировано! Если ограничить симметрично то будут отсутствовать чётные гармоники.Rem писал(а): Пожалуй надо будет генерацию в отдельную функцию вынести, чтоб можно было в один массив примешивать произвольное количество синусин с произвольными частотой и амплитудой. Но сначала надо разобраться с одной.
О частотах (может я не совсем правильно понял вопрос?):
https://ru.wikipedia.org/ :
Можно математически вычислить частоты для всего звукоряда, пользуясь формулой:
где f0 — частота камертона (например Ля 440 Hz), а i — количество полутонов в интервале от искомого звука к эталону f0.
Последовательность вычисленных таким образом частот образует геометрическую прогрессию:
например, можно вычислить частоту звука на тон (2 полутона) ниже от камертона Ля — ноты соль:
i=-2
если нам надо вычислить ноту Соль, но на октаву (12 полутонов) выше:
i=12-2=10
Частоты двух полученных нот Соль отличаются в два раза, что дает чистую октаву. Преимущества равномерной темперации также в том, что можно произвольно транспонировать пьесу на произвольный интервал вверх или вниз.
Последний раз редактировалось Santik 15 фев 2015, 08:14, всего редактировалось 1 раз.
- Santik
- Сообщения: 609
- Зарегистрирован: 28 дек 2010, 08:04
- Откуда: Мирный (Якутия)
- Контактная информация:
Re: ФНЧ Баттерворта
Дело в том что RAND вычисляется внутри цикла! И это неправильно! Получилась синусоида с частотной модуляцией!Rem писал(а): Я амплитуду рассчитываю от номера семпла, а не от значения времени. И RAND смещается на произвольный семпл. В том месте начальная амплитуда не равна нулю.
Код: Выделить всё
Dt=RAND;
for(i=0; i<=BUFER_SIZE; i++){
sin_array[i]= sin ((i+Dt) * 2 * M_PI *freq / FREQ);
printf ("%i %f\n", i, sin_array[i]);
}
return 0;
}
#define SAMPLE_RATE 44100 ????
SAMPLE_RATE по определению = 1/Fd=1/44100!
Re: ФНЧ Баттерворта
Если фильтр второго порядка, и частота среза 1300Гц - такие условия достаточны для расчёта?
- Santik
- Сообщения: 609
- Зарегистрирован: 28 дек 2010, 08:04
- Откуда: Мирный (Якутия)
- Контактная информация:
Re: ФНЧ Баттерворта
Да, достаточно.
Re: ФНЧ Баттерворта
Ух как хорошо получилось
В данном примере я генерирую несколько синусоид. Измеряю максимальную амплитуду. Потом отправляю на фильтрацию. Измеряю новую амплитуду. На скрине видно, как уменьшаются итоговые значения от увеличения частоты.
Единственный вопрос. В итоговом массиве Y первые два значения присвоил нулю. Правильно сделал?
Весь код на си:
В данном примере я генерирую несколько синусоид. Измеряю максимальную амплитуду. Потом отправляю на фильтрацию. Измеряю новую амплитуду. На скрине видно, как уменьшаются итоговые значения от увеличения частоты.
Единственный вопрос. В итоговом массиве Y первые два значения присвоил нулю. Правильно сделал?
Весь код на си:
Код: Выделить всё
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define SAMPLE_RATE 44100
#define BUFER_SIZE 10000
void SinGen( float freq, int bufersize, int samplrate, float * sampleblock);
float FindMaxAmpl( float * sampleblock , int bufersize);
void Butterworth (float * sampleblock , int bufersize);
int main()
{
printf("Butterworth filter\n");
float FreqArr[]={250, 500, 1000, 2000, 4000, 8000, 16000, 22000};
float sin_array [BUFER_SIZE];
int i;
float MaxAmpl=0, MaxAmplFilter=0;
for (i=0; i<8; i++){
//генерируем разные синусоиды
SinGen(FreqArr[i], BUFER_SIZE, SAMPLE_RATE, sin_array);
//находим макисмальную амплитуду
MaxAmpl = FindMaxAmpl (sin_array, BUFER_SIZE);
//отправляем на фильтрацию по Баттерворту
Butterworth (sin_array, BUFER_SIZE);
//находим макс амплитуту после фильтрации
MaxAmplFilter = FindMaxAmpl (sin_array, BUFER_SIZE);
//выводим результаты
printf ("f=%f max=%f max_filter=%f\n", FreqArr[i], MaxAmpl, MaxAmplFilter);
}
return 0;
}
void SinGen( float freq, int bufersize, int samplrate, float * sin_array)
{
// генерируем массив семплов для синусоиды
int i;
int random = rand()%10000;
for ( i=0; i<bufersize ; i++){
sin_array[i]= sin ((i+random) * 2 * M_PI *freq / samplrate); // вместо 0 можно поставить rand();
}
return;
}
float FindMaxAmpl( float * sampleblock , int bufersize)
{
int i;
float Max=0;
for ( i=0; i<bufersize ; i++){
// printf("buf[i]=%f \n", sampleblock[i] );
if ( fabs(sampleblock[i]) > Max) Max = fabs (sampleblock[i]);
}
return Max;
}
void Butterworth(float * X , int bufersize)
{
//коэффициенты фильтра Баттерворта второго порядка
float b1 = 0.01413248273498;
float b2 = 0.02826496546996;
float b3 = 0.01413248273498;
float a1 = 1.0;
float a2 = -1.636681376728;
float a3 = 0.693211307667;
float Y[bufersize]; // для фильтрованного сигнала
Y[0] = 0;
Y[1] = 0;
int k;
for ( k=2; k<bufersize; k++){
Y[k] = b1*X[k] + b2*X[k-1] + b3*X[k-2] - a2*Y[k-1] - a3*Y[k-2];
}
// переносим в исходный массив
for ( k=0; k<bufersize; k++) X[k] = Y[k];
return;
}