From 8a5daee1b8b17a4dbf04ab70d9c89532956d771c Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 3 Feb 2020 14:37:29 +0100 Subject: [PATCH] Added Kaiser window --- sdrbase/dsp/fftwindow.cpp | 30 +++++++++++++++++++++++++++- sdrbase/dsp/fftwindow.h | 39 ++++++++++++++++++++++++++++++++++++- sdrgui/gui/glspectrumgui.ui | 5 +++++ sdrgui/readme.md | 1 + 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/sdrbase/dsp/fftwindow.cpp b/sdrbase/dsp/fftwindow.cpp index bcde02ea9..3ff5b5e66 100644 --- a/sdrbase/dsp/fftwindow.cpp +++ b/sdrbase/dsp/fftwindow.cpp @@ -18,12 +18,39 @@ #include "dsp/fftwindow.h" +FFTWindow::FFTWindow() : + m_kaiserAlpha(2.15) // beta = 6.76 first sidelobe at -70dB +{ + m_kaiserI0Alpha = zeroethOrderBessel(m_kaiserAlpha); +} + +void FFTWindow::setKaiserAlpha(Real alpha) +{ + m_kaiserAlpha = alpha; + m_kaiserI0Alpha = zeroethOrderBessel(m_kaiserAlpha); +} + +void FFTWindow::setKaiserBeta(Real beta) +{ + m_kaiserAlpha = beta / M_PI; + m_kaiserI0Alpha = zeroethOrderBessel(m_kaiserAlpha); +} + void FFTWindow::create(Function function, int n) { Real (*wFunc)(Real n, Real i); m_window.clear(); + if (function == Kaiser) // Kaiser special case + { + for(int i = 0; i < n; i++) { + m_window.push_back(kaiser(n, i)); + } + + return; + } + switch(function) { case Flattop: wFunc = flatTop; @@ -51,8 +78,9 @@ void FFTWindow::create(Function function, int n) break; } - for(int i = 0; i < n; i++) + for(int i = 0; i < n; i++) { m_window.push_back(wFunc(n, i)); + } } void FFTWindow::apply(const std::vector& in, std::vector* out) diff --git a/sdrbase/dsp/fftwindow.h b/sdrbase/dsp/fftwindow.h index 0b6674dde..1bcbb6bc1 100644 --- a/sdrbase/dsp/fftwindow.h +++ b/sdrbase/dsp/fftwindow.h @@ -36,18 +36,25 @@ public: Flattop, Hamming, Hanning, - Rectangle + Rectangle, + Kaiser }; + FFTWindow(); + void create(Function function, int n); void apply(const std::vector& in, std::vector* out); void apply(const std::vector& in, std::vector* out); void apply(std::vector& in); void apply(const Complex* in, Complex* out); void apply(Complex* in); + void setKaiserAlpha(Real alpha); //!< set the Kaiser window alpha factor (default 2.15) + void setKaiserBeta(Real beta); //!< set the Kaiser window beta factor = pi * alpha private: std::vector m_window; + Real m_kaiserAlpha; //!< alpha factor for Kaiser window + Real m_kaiserI0Alpha; //!< zeroethOrderBessel of alpha above static inline Real flatTop(Real n, Real i) { @@ -83,6 +90,36 @@ private: { return 1.0; } + + // https://raw.githubusercontent.com/johnglover/simpl/master/src/loris/KaiserWindow.C + inline Real kaiser(Real n, Real i) + { + Real K = ((2.0*i) / n) - 1.0; + Real arg = sqrt(1.0 - (K*K)); + return zeroethOrderBessel(m_kaiserAlpha*arg) / m_kaiserI0Alpha; + } + + static inline Real zeroethOrderBessel( Real x ) + { + const Real eps = 0.000001; + + // initialize the series term for m=0 and the result + Real besselValue = 0; + Real term = 1; + Real m = 0; + + // accumulate terms as long as they are significant + while(term > eps * besselValue) + { + besselValue += term; + + // update the term + ++m; + term *= (x*x) / (4*m*m); + } + + return besselValue; + } }; #endif // INCLUDE_FFTWINDOWS_H diff --git a/sdrgui/gui/glspectrumgui.ui b/sdrgui/gui/glspectrumgui.ui index 6af63db77..7fd12f85c 100644 --- a/sdrgui/gui/glspectrumgui.ui +++ b/sdrgui/gui/glspectrumgui.ui @@ -387,6 +387,11 @@ Rec + + + Kai + + diff --git a/sdrgui/readme.md b/sdrgui/readme.md index 629b7bc44..885f29991 100644 --- a/sdrgui/readme.md +++ b/sdrgui/readme.md @@ -364,6 +364,7 @@ Use this combo box to select which window is applied to the FFT: - **Ham**: Hamming - **Han**: Hanning (default) - **Rec**: Rectangular (no window) + - **Kai**: Kaiser with alpha = 2.15 (beta = 6.76) gives sidelobes < -70dB

4.2. FFT size