Первый FIR фильтр на Си

Давным давно я писал о как синтезировать и рассмотреть характеристики КИХ (он же FIR) фильтра.

Структура фильтра с конечной характеристикой выглядит таким образом:

Структура КИХ фильтра

Сам процесс фильтрации можно выразить так:

y \left( n \right) = \sum_{i=0}^{P} b_i x \left( n-i \right)

Фильтрация чаще всего происходит при помощи операций с фиксированной точкой. Но мы не будем затрагивать эту ипостась. Рассмотрим простой фильтр с использованием double переменных.
Допустим имеем массив входных величин x, массив коэффициентов фильтра h и массив отфильтрованных величин y.
В качестве коэффициентов фильтра используем такие:

-0.0416, -0.0865, 0.0000, 0.2018, 0.3742, 0.3742, 0.2018, 0.0000, -0.0865, -0.0416

Входной сигнал будет состоять из двух cos.

double x[500];
double y[500];
double h[] = { -0.0416, -0.0865, 0.0000, 0.2018, 0.3742, 0.3742, 0.2018, 0.0000, -0.0865, -0.0416 };

double angle = 0;
for (int i = 0;i < 500; i++)
{
	x[i] = 10 * cos(2 * M_PI*angle) + 2 * cos(100 * M_PI*angle + M_PI / 4);
	angle += 0.005;
}

Выглядит входной (зашумленный) сигнал так:

Входной сигнал

Теперь рассмотрим функцию FIR фильтра.

void fir(double *x, double *y, double *h, int nSamples)
{
	double acc = 0;
	static double history[FIR_LENGTH] = { 0 };

	for (int i = 0; i < nSamples; i++)
	{
		//shift history pipeline
		for (int k = FIR_LENGTH - 1; k >= 0; k--)
		{
			history[k] = history[k - 1];
		}
		history[0] = x[i];

		acc = 0;
		for (int j = 0; j < FIR_LENGTH; j++)
		{
			acc = acc + history[j] * h[j];
		}
		y[i] = acc;
	}
}

В данной функции имеем массив истории. Который служит нам цепочкой задержки. Его удобно сделать используя циклические буфера. Тут для простоты мы просто сдвигаем отсчеты при помощи цикла и копируем текущий отсчет в начало цепочки.
Далее создаем переменную аккумулятор acc и производим операции умножения с накоплением. По окончании цикла копируем значение в выходной массив.

Фильтрованный сигнал

Так выглядит результат ;)

UPD:
Как справедливо было замечено при такой реализации функцию нельзя будет использовать для разных каналов из-за static массива истории.
Для устранения этой беды можно передать в функцию указатель на массив, объявленный вне fir().

Просмотров:   1513

Комментарии

Добавить комментарий

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.
CAPTCHA
Введи эти символы. Ато роботы одолели!