mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 17:58:43 -05:00
Added a FFT based RRC filter
This commit is contained in:
parent
35c4d5a325
commit
74286a5767
@ -28,6 +28,7 @@
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@ -130,7 +131,7 @@ void fftfilt::create_filter(float f1, float f2)
|
|||||||
for (int i = 0; i < flen2; i++)
|
for (int i = 0; i < flen2; i++)
|
||||||
filter[i] *= _blackman(i, flen2);
|
filter[i] *= _blackman(i, flen2);
|
||||||
|
|
||||||
fft->ComplexFFT(filter);
|
fft->ComplexFFT(filter); // filter was expressed in the time domain (impulse response)
|
||||||
|
|
||||||
// normalize the output filter for unity gain
|
// normalize the output filter for unity gain
|
||||||
float scale = 0, mag;
|
float scale = 0, mag;
|
||||||
@ -155,7 +156,7 @@ void fftfilt::create_dsb_filter(float f2)
|
|||||||
filter[i] *= _blackman(i, flen2);
|
filter[i] *= _blackman(i, flen2);
|
||||||
}
|
}
|
||||||
|
|
||||||
fft->ComplexFFT(filter);
|
fft->ComplexFFT(filter); // filter was expressed in the time domain (impulse response)
|
||||||
|
|
||||||
// normalize the output filter for unity gain
|
// normalize the output filter for unity gain
|
||||||
float scale = 0, mag;
|
float scale = 0, mag;
|
||||||
@ -182,7 +183,7 @@ void fftfilt::create_asym_filter(float fopp, float fin)
|
|||||||
filter[i] *= _blackman(i, flen2);
|
filter[i] *= _blackman(i, flen2);
|
||||||
}
|
}
|
||||||
|
|
||||||
fft->ComplexFFT(filter);
|
fft->ComplexFFT(filter); // filter was expressed in the time domain (impulse response)
|
||||||
|
|
||||||
// normalize the output filter for unity gain
|
// normalize the output filter for unity gain
|
||||||
float scale = 0, mag;
|
float scale = 0, mag;
|
||||||
@ -204,7 +205,7 @@ void fftfilt::create_asym_filter(float fopp, float fin)
|
|||||||
filterOpp[i] *= _blackman(i, flen2);
|
filterOpp[i] *= _blackman(i, flen2);
|
||||||
}
|
}
|
||||||
|
|
||||||
fft->ComplexFFT(filterOpp);
|
fft->ComplexFFT(filterOpp); // filter was expressed in the time domain (impulse response)
|
||||||
|
|
||||||
// normalize the output filter for unity gain
|
// normalize the output filter for unity gain
|
||||||
scale = 0;
|
scale = 0;
|
||||||
@ -218,6 +219,32 @@ void fftfilt::create_asym_filter(float fopp, float fin)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This filter is constructed directly from frequency domain response. Run with runFilt.
|
||||||
|
void fftfilt::create_rrc_filter(float fb, float a)
|
||||||
|
{
|
||||||
|
std::fill(filter, filter+flen, 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < flen; i++) {
|
||||||
|
filter[i] = frrc(fb, a, i, flen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalize the output filter for unity gain
|
||||||
|
float scale = 0, mag;
|
||||||
|
for (int i = 0; i < flen; i++)
|
||||||
|
{
|
||||||
|
mag = abs(filter[i]);
|
||||||
|
if (mag > scale) {
|
||||||
|
scale = mag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (scale != 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < flen; i++) {
|
||||||
|
filter[i] /= scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// test bypass
|
// test bypass
|
||||||
int fftfilt::noFilt(const cmplx & in, cmplx **out)
|
int fftfilt::noFilt(const cmplx & in, cmplx **out)
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,7 @@ public:
|
|||||||
void create_filter(float f1, float f2);
|
void create_filter(float f1, float f2);
|
||||||
void create_dsb_filter(float f2);
|
void create_dsb_filter(float f2);
|
||||||
void create_asym_filter(float fopp, float fin); //!< two different filters for in band and opposite band
|
void create_asym_filter(float fopp, float fin); //!< two different filters for in band and opposite band
|
||||||
|
void create_rrc_filter(float fb, float a); //!< root raised cosine. fb is half the band pass
|
||||||
|
|
||||||
int noFilt(const cmplx& in, cmplx **out);
|
int noFilt(const cmplx& in, cmplx **out);
|
||||||
int runFilt(const cmplx& in, cmplx **out);
|
int runFilt(const cmplx& in, cmplx **out);
|
||||||
@ -48,18 +49,43 @@ protected:
|
|||||||
int pass;
|
int pass;
|
||||||
int window;
|
int window;
|
||||||
|
|
||||||
inline float fsinc(float fc, int i, int len) {
|
inline float fsinc(float fc, int i, int len)
|
||||||
|
{
|
||||||
int len2 = len/2;
|
int len2 = len/2;
|
||||||
return (i == len2) ? 2.0 * fc:
|
return (i == len2) ? 2.0 * fc:
|
||||||
sin(2 * M_PI * fc * (i - len2)) / (M_PI * (i - len2));
|
sin(2 * M_PI * fc * (i - len2)) / (M_PI * (i - len2));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float _blackman(int i, int len) {
|
inline float _blackman(int i, int len)
|
||||||
|
{
|
||||||
return (0.42 -
|
return (0.42 -
|
||||||
0.50 * cos(2.0 * M_PI * i / len) +
|
0.50 * cos(2.0 * M_PI * i / len) +
|
||||||
0.08 * cos(4.0 * M_PI * i / len));
|
0.08 * cos(4.0 * M_PI * i / len));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** RRC function in the frequency domain. Zero frequency is on the sides with first half in positive frequencies
|
||||||
|
* and second half in negative frequencies */
|
||||||
|
inline cmplx frrc(float fb, float a, int i, int len)
|
||||||
|
{
|
||||||
|
float x = i/(float)len; // normalize to [0..1]
|
||||||
|
x = 0.5-fabs(x-0.5); // apply symmetry: now both halves overlap near 0
|
||||||
|
float tr = (fb*a)/2.0; // half the transition zone
|
||||||
|
|
||||||
|
if (x < fb-tr)
|
||||||
|
{
|
||||||
|
return 1.0; // in band
|
||||||
|
}
|
||||||
|
else if (x < fb+tr) // transition
|
||||||
|
{
|
||||||
|
float y = ((x-(fb-tr)) / (2.0*tr))*M_PI;
|
||||||
|
return (cos(y) + 1.0f)/2.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0.0; // out of band
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void init_filter();
|
void init_filter();
|
||||||
void init_dsb_filter();
|
void init_dsb_filter();
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user