Calculation of FIR coefficients

Status
Not open for further replies.

koen

Member
Library for calculation of FIR coefficients

Those who use FIR filters may be interested in a very early version of a library to calculate FIR coefficients which I created. It is a translation of the firwin Python code in the scipy library. Scipy does a fantastic job at calculating these coefficients. In my library (fir_filters) I implemented only a subset of firwin, only the code to calculate a (single) bandpass filter, and only using the Kaiser window. Expanding the library to include other filters should not be too difficult. I do not know about using other window types. That may be a bit harder.

The library has been (lightly) tested in my SDR running on a Teensy 3.6. It is very fast, and allows runtime calculation of the coefficients. Calculating the FIR coefficients at development time is not necessary anymore!

The code for this library is available at https://github.com/kvdijken/fir_filters. Let me know what you think. I am neither an expert in DSP, nor in Python, so there may (will) still be bugs in the code.

Have fun!
 
Last edited:
Thanks for sharing. I have bookmarked your lib for future reference.
Do you have a youtube video of your SDR in action?

I played with some DSP coding a long time ago. I wonder if you would consider code for a low pass filter. I remember that low pass filter constants could be changed into high pass and bandpass fairly easily.

Ok. I have located my old code. And here are the functions I wrote back then ( DOS Mix Power C ).

Code:
void modtohigh(){  
int i;

  for( i= 1; i < order; i+= 2 ) a[i]= -a[i];  /* pretty simple heh? */

}

void mod( int freq, int sample ){     // where freq is center freq and sample is the sample rate
double update, phase;
int i,j,k;
extern int order;

 if( freq ){
    update= (double)sample/(double)freq;   /* # of samples in 360 deg */
    update= 6.2831852/update;               /* update in radians */
    phase= 0; 

/* try starting in the middle so we keep the linear phase characteristic */
/* preset the phase so can go from start to finish */    

    j= order/2;
    k= 2*j;
    if( k == order ) {         /* even order */
       phase+= update/2.0;   /* split the diff */
       }
    while( --j >= 0 ) phase-= update;   /* find starting phase */

    for( i= 0; i < order; ++i ){
       a[i]= cos( phase ) * a[i] * 2;   /* mod constants to new freq */
       phase += update;
       }
    }
}
 
No, unfortunately I do not have a video of my SDR running.

Thanks for sharing your code. I will study it. But as the original Python sources encompass all type of filters (LP, HP, BP, notch, ...), I will translate that code into C when there is a need. This is not so difficult now the foundation is there in C.
 
Hi!

there is a function providing FIR coeffs for lowpass, highpass, bandpass, notch and Hilbert transform written by Walter for the Teensy (in the context of Fast Convolution filtering, but the coefficients are identical whether you perform filtering in the time or frequency domain):

https://github.com/WMXZ-EU/SDR/blob/master/src/fft_filt.c

look for:
Code:
void calc_FIR_coeffs (float * coeffs, int numCoeffs, float32_t fc, float32_t Astop, int type, float dfc)

It was discussed here:

https://forum.pjrc.com/threads/40188-Fast-Convolution-filtering-in-floating-point-with-Teensy-3-6

Maybe that helps!

All the best, have fun,

Frank DD4WH
 
Hi all,

Do you have any idea how to convert coefficients from rePhase , from float to short 16bit?

Code:
float 12db_1st[200] = {
	 0,                      1.10891522634917e-007,  5.20750726048583e-007,  1.39298583988212e-006,
	 2.83614717620591e-006,  4.84860312907574e-006,  7.53891252034105e-006,  1.11179190189895e-005,
	 1.54341691426823e-005,  1.98300720833476e-005,  2.40116221889069e-005,  2.83895979919993e-005,
	 3.25884270650686e-005,  3.49390167481398e-005,  3.4425623615678e-005,   3.19100130852722e-005,
	 2.81725813899766e-005,  2.11653903325906e-005,  8.48602399694238e-006, -7.75539775655138e-006,
	-2.38603989319117e-005, -4.06708531361502e-005, -6.16053900149558e-005, -8.50459246497118e-005,
	-0.000102942982449628,  -0.00011172363412284,   -0.000117463608796667,  -0.000121486667661444,
	-0.00011286099403735,   -8.30529356305578e-005, -3.83784695871632e-005,  1.04420420010946e-005,
	 7.0404784722222e-005,   0.000158484309459244,   0.000268290364751084,   0.000376091284200593,
	 0.000478512714568412,   0.000595099810040718,   0.000730240529522082,   0.00085013667082478,
	 0.000926952794479874,   0.000984695419384831,   0.0010475704958065,     0.0010815481724572,
	 0.00103837938933176,    0.000928710694901237,   0.000809225840703402,   0.000678829347118329,
	 0.000460459620947257,   0.000142199576294647,  -0.000183649289973653,  -0.000468325798842051,
	-0.000782746438177988,  -0.00119536929042976,   -0.00161383187619801,   -0.00188918119532174,
...
I tried to scale coefficients from rePhase across +- &H7FFF, but it does not work.

Results:
Code:
static short filter_taps[200] = PROGMEM {
  (short)0x0000,  (short)0x0000,  (short)0x0000,  (short)0x0000,  (short)0x0000,  (short)0x0000,  (short)0x0000,
  (short)0x0000,  (short)0x0001,  (short)0x0001,  (short)0x0001,  (short)0x0001,  (short)0x0001,  (short)0x0001,
  (short)0x0001,  (short)0x0001,  (short)0x0001,  (short)0x0001,  (short)0x0000,  (short)0x0000,  (short)0xFFFF,
  (short)0xFFFF,  (short)0xFFFE,  (short)0xFFFD,  (short)0xFFFD,  (short)0xFFFC,  (short)0xFFFC,  (short)0xFFFC,
  (short)0xFFFC,  (short)0xFFFD,  (short)0xFFFF,  (short)0x0000,  (short)0x0002,  (short)0x0005,  (short)0x0009,
  (short)0x000C,  (short)0x0010,  (short)0x0013,  (short)0x0018,  (short)0x001C,  (short)0x001E,  (short)0x0020,
  (short)0x0022,  (short)0x0023,  (short)0x0022,  (short)0x001E,  (short)0x001B,  (short)0x0016,  (short)0x000F,
  (short)0x0005,  (short)0xFFFA,  (short)0xFFF1,  (short)0xFFE6,  (short)0xFFD9,  (short)0xFFCB,  (short)0xFFC2,
  (short)0xFFBC,  (short)0xFFB4,  (short)0xFFAC,  (short)0xFFAB, ...
Generally I want to design few filters like below one
12db.png

Regards,
Radek
 
Last edited:
Hi Radek,

if I interpret it correctly, you want to implement an audio high shelf filter.

For that purpose you could use the biquad filter from the audio library and choose the highshelf option. That is very easy and gives excellent performance!

Designing a highshelf filter as a FIR filter with 200 coefficients is in my view total overkill, just my two cents.

Some information on calculating/converting coefficients can also be found in this thread:

https://forum.pjrc.com/threads/45620-Design-filter-coefficients-of-FIR-and-Biquad

All the best!

Frank DD4WH
 
Status
Not open for further replies.
Back
Top