1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-10 10:33:29 -05:00

Added 3 term Blackman window to FFTWindow and use it as default in FFT filter

This commit is contained in:
f4exb 2022-05-18 01:30:32 +02:00
parent d79d121a6b
commit 5447a8caef
6 changed files with 47 additions and 13 deletions

View File

@ -331,6 +331,11 @@
<string>Kai</string> <string>Kai</string>
</property> </property>
</item> </item>
<item>
<property name="text">
<string>Black</string>
</property>
</item>
</widget> </widget>
</item> </item>
<item> <item>

View File

@ -112,7 +112,7 @@ fftfilt::~fftfilt()
if (ovlbuf) delete [] ovlbuf; if (ovlbuf) delete [] ovlbuf;
} }
void fftfilt::create_filter(float f1, float f2) void fftfilt::create_filter(float f1, float f2, FFTWindow::Function wf)
{ {
// initialize the filter to zero // initialize the filter to zero
std::fill(filter, filter + flen, cmplx{0, 0}); std::fill(filter, filter + flen, cmplx{0, 0});
@ -135,8 +135,12 @@ void fftfilt::create_filter(float f1, float f2)
if (b_highpass && f2 < f1) if (b_highpass && f2 < f1)
filter[flen2 / 2] += 1; filter[flen2 / 2] += 1;
for (int i = 0; i < flen2; i++) FFTWindow fwin;
filter[i] *= _blackman(i, flen2); fwin.create(wf, flen2);
fwin.apply(filter);
// for (int i = 0; i < flen2; i++)
// filter[i] *= _blackman(i, flen2);
fft->ComplexFFT(filter); // filter was expressed in the time domain (impulse response) fft->ComplexFFT(filter); // filter was expressed in the time domain (impulse response)
@ -153,16 +157,20 @@ void fftfilt::create_filter(float f1, float f2)
} }
// Double the size of FFT used for equivalent SSB filter or assume FFT is half the size of the one used for SSB // Double the size of FFT used for equivalent SSB filter or assume FFT is half the size of the one used for SSB
void fftfilt::create_dsb_filter(float f2) void fftfilt::create_dsb_filter(float f2, FFTWindow::Function wf)
{ {
// initialize the filter to zero // initialize the filter to zero
std::fill(filter, filter + flen, cmplx{0, 0}); std::fill(filter, filter + flen, cmplx{0, 0});
for (int i = 0; i < flen2; i++) { for (int i = 0; i < flen2; i++) {
filter[i] = fsinc(f2, i, flen2); filter[i] = fsinc(f2, i, flen2);
filter[i] *= _blackman(i, flen2); // filter[i] *= _blackman(i, flen2);
} }
FFTWindow fwin;
fwin.create(wf, flen2);
fwin.apply(filter);
fft->ComplexFFT(filter); // filter was expressed in the time domain (impulse response) 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
@ -179,7 +187,7 @@ void fftfilt::create_dsb_filter(float f2)
// Double the size of FFT used for equivalent SSB filter or assume FFT is half the size of the one used for SSB // Double the size of FFT used for equivalent SSB filter or assume FFT is half the size of the one used for SSB
// used with runAsym for in band / opposite band asymmetrical filtering. Can be used for vestigial sideband modulation. // used with runAsym for in band / opposite band asymmetrical filtering. Can be used for vestigial sideband modulation.
void fftfilt::create_asym_filter(float fopp, float fin) void fftfilt::create_asym_filter(float fopp, float fin, FFTWindow::Function wf)
{ {
// in band // in band
// initialize the filter to zero // initialize the filter to zero
@ -187,9 +195,13 @@ void fftfilt::create_asym_filter(float fopp, float fin)
for (int i = 0; i < flen2; i++) { for (int i = 0; i < flen2; i++) {
filter[i] = fsinc(fin, i, flen2); filter[i] = fsinc(fin, i, flen2);
filter[i] *= _blackman(i, flen2); // filter[i] *= _blackman(i, flen2);
} }
FFTWindow fwin;
fwin.create(wf, flen2);
fwin.apply(filter);
fft->ComplexFFT(filter); // filter was expressed in the time domain (impulse response) 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
@ -209,9 +221,10 @@ void fftfilt::create_asym_filter(float fopp, float fin)
for (int i = 0; i < flen2; i++) { for (int i = 0; i < flen2; i++) {
filterOpp[i] = fsinc(fopp, i, flen2); filterOpp[i] = fsinc(fopp, i, flen2);
filterOpp[i] *= _blackman(i, flen2); // filterOpp[i] *= _blackman(i, flen2);
} }
fwin.apply(filterOpp);
fft->ComplexFFT(filterOpp); // filter was expressed in the time domain (impulse response) 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

View File

@ -9,6 +9,7 @@
#include <cmath> #include <cmath>
#include "gfft.h" #include "gfft.h"
#include "fftwindow.h"
#include "export.h" #include "export.h"
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -25,9 +26,9 @@ public:
~fftfilt(); ~fftfilt();
// f1 < f2 ==> bandpass // f1 < f2 ==> bandpass
// f1 > f2 ==> band reject // f1 > f2 ==> band reject
void create_filter(float f1, float f2); void create_filter(float f1, float f2, FFTWindow::Function wf = FFTWindow::Blackman);
void create_dsb_filter(float f2); void create_dsb_filter(float f2, FFTWindow::Function wf = FFTWindow::Blackman);
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, FFTWindow::Function wf = FFTWindow::Blackman); //!< 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 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);

View File

@ -51,7 +51,7 @@ void FFTWindow::create(Function function, int n)
return; return;
} }
switch(function) { switch (function) {
case Flattop: case Flattop:
wFunc = flatTop; wFunc = flatTop;
break; break;
@ -72,6 +72,10 @@ void FFTWindow::create(Function function, int n)
wFunc = hanning; wFunc = hanning;
break; break;
case Blackman:
wFunc = blackman;
break;
case Rectangle: case Rectangle:
default: default:
wFunc = rectangle; wFunc = rectangle;

View File

@ -33,7 +33,8 @@ public:
Hamming, Hamming,
Hanning, Hanning,
Rectangle, Rectangle,
Kaiser Kaiser,
Blackman
}; };
FFTWindow(); FFTWindow();
@ -70,6 +71,11 @@ private:
return (0.35875 - 0.48829 * cos((2.0 * M_PI * i) / n) + 0.14128 * cos((4.0 * M_PI * i) / n) - 0.01168 * cos((6.0 * M_PI * i) / n)) * 2.79; return (0.35875 - 0.48829 * cos((2.0 * M_PI * i) / n) + 0.14128 * cos((4.0 * M_PI * i) / n) - 0.01168 * cos((6.0 * M_PI * i) / n)) * 2.79;
} }
static inline Real blackman(Real n, Real i)
{
return (0.42438 - 0.49734 * cos(2.0 * M_PI * i / n) + 0.078279 * cos(4.0 * M_PI * i / n)) * 2.37;
}
static inline Real hamming(Real n, Real i) static inline Real hamming(Real n, Real i)
{ {
// amplitude correction = 1.855, energy correction = 1.586 // amplitude correction = 1.855, energy correction = 1.586

View File

@ -101,6 +101,11 @@
<string>Kai</string> <string>Kai</string>
</property> </property>
</item> </item>
<item>
<property name="text">
<string>Black</string>
</property>
</item>
</widget> </widget>
</item> </item>
<item> <item>