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


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

Спасибо, князь. Вы настоящий дворянин. И программист.