ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Воскресенье
5 мая
1343345 Топик полностью
Связанные сообщения
FirБих
Спасибо, то что нужно. Простейшее понятное объяснение расчёта FIR без МАТКАДа. Допишу что ещё узнал. Конечно интересно по...2023-08-23
Если требования к потреблению не более 30-50 мВт, то возможно ли реализовать на МК полосовой фильтр высокой добростнойстью? АЧХ ...2011-06-05
RxTx (23.08.2023 01:25, просмотров: 423) ответил General на Программная фильтрация. Чаще всего для фильтрации используется апериодическое звено - аналог RC-цепочки.
Рассчитывается КИХ фильтр так. Отклик в частотной области представляет ступеньку, во временной области представляет sinc-функцию. И если надо то наоборот. Значит наша задача не более чем сгенерировать sinc-функцию. Коэффициенты КИХ фильтра её и представляют. И вся фильтрация, т.е. фильтр будет представлять собой банальную свертку с ней, т.е. к коэффициентами). Налабал демо-код в дикой спешке, у меня нет времени писать красиво, завтра с утра ехать запускать проект и я 

самозабанюсь на сахаре.


#include <math.h>

#define PI 3.14159265

#define KernelLen 51       // Длина ядра фильтра
float KERNEL[KernelLen];   // коэфф. фильтра, оно ж ядро

#define SignalLen 2000         // Длина сигнала
float InputSignal[SignalLen];   // Сигнал

float Output[SignalLen];       // Выходной сигнал


float Fcutoff = 0.003;     // F среза, задается в диапазоне от 0  до 0.5 от F сэмплирования исх. сигнала

// Расчет ядра фильтра aka sinc-фунции void CalcFIR(void) {

// Расчет коэфф. фильтра. for (int i = 0 ; i < KernelLen ; i++) { if ((i-KernelLen/2) == 0) { KERNEL[i] = 2*PI*Fcutoff; } else if ((i-KernelLen/2) != 0) { KERNEL[i] = sinf(2*PI*Fcutoff * (i-KernelLen/2)) / (i-KernelLen/2); }
KERNEL[i] = KERNEL[i] * (0.42f - 0.5f*cosf(2*PI*i/KernelLen) + 0.08f*cosf(4*PI*i/KernelLen)); }
// Банальная нормализация полученного float sum = 0.0f; for (int i = 0; i<KernelLen; i++) { sum = sum + KERNEL[i]; } for (int i = 0; i<KernelLen; i++) { KERNEL[i] = KERNEL[i] / sum; } }

Примитивная и медленная КИХ фильтрация предсталяет собой свертку "в лоб" с расчитанной sinc-функцией.


for( int j = KernelLen ; j <  SignalLen-1; j++)
{
  Output[j] = 0.0;                
  for (int i = 0; i < KernelLen; i++) 
   {
     Output[j] = Output[j] + InputSignal[j-i] * KERNEL[i];
   }
}


Но учти, так как sinc-функция обрезана (короткая), она даст вследствие эффекта Гиббса некоторую рябь.

Поэтому реально ядро фильтра представляет собой обрезанную SINC функцию просто поэлементно умноженную на оконные функции, ф-лы:

HAMMING[i] = 0.54 - 0.46 *cosf(2*PI * i / LENGTH );

BLACKMAN[i] = 0.42 - 0.5 cosf(2 * PI * i / LENGTH ) + 0.08 * cosf(4 * PI * i / LENGTH );



Фазовый отклик линейный.

https://en.wikipedia.org/wiki/Sinc_filter


Да, и судя по тому что ты писал выше, попробуй несколько раз фильтровать по сигналу одним и тем же фильтром, втч и БИХ что приводил выше.