| 
									
										
										
										
											2023-11-19 06:43:20 +01:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany     //
 | 
					
						
							|  |  |  | // written by Christian Daniel                                                       //
 | 
					
						
							|  |  |  | // Copyright (C) 2014-2015 John Greb <hexameron@spam.no>                             //
 | 
					
						
							|  |  |  | // Copyright (C) 2015-2018, 2022-2023 Edouard Griffiths, F4EXB <f4exb06@gmail.com>   //
 | 
					
						
							|  |  |  | // Copyright (C) 2020 Kacper Michajłow <kasper93@gmail.com>                          //
 | 
					
						
							|  |  |  | //                                                                                   //
 | 
					
						
							|  |  |  | // This program is free software; you can redistribute it and/or modify              //
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by              //
 | 
					
						
							|  |  |  | // the Free Software Foundation as version 3 of the License, or                      //
 | 
					
						
							|  |  |  | // (at your option) any later version.                                               //
 | 
					
						
							|  |  |  | //                                                                                   //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,                   //
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of                    //
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the                      //
 | 
					
						
							|  |  |  | // GNU General Public License V3 for more details.                                   //
 | 
					
						
							|  |  |  | //                                                                                   //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License                 //
 | 
					
						
							|  |  |  | // along with this program. If not, see <http://www.gnu.org/licenses/>.              //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2017-03-16 02:45:51 +01:00
										 |  |  |  * Filters from Fldigi. | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef	_FFTFILT_H
 | 
					
						
							|  |  |  | #define	_FFTFILT_H
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 11:29:41 +02:00
										 |  |  | #include <complex>
 | 
					
						
							| 
									
										
										
										
											2020-11-03 13:52:12 +01:00
										 |  |  | #include <cmath>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | #include "gfft.h"
 | 
					
						
							| 
									
										
										
										
											2022-05-18 01:30:32 +02:00
										 |  |  | #include "fftwindow.h"
 | 
					
						
							| 
									
										
										
										
											2023-11-05 10:33:27 +01:00
										 |  |  | #include "fftnr.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-20 13:49:21 +01:00
										 |  |  | #include "export.h"
 | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | //----------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-03 20:23:38 +01:00
										 |  |  | class SDRBASE_API fftfilt { | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | enum {NONE, BLACKMAN, HAMMING, HANNING}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-15 11:29:41 +02:00
										 |  |  | public: | 
					
						
							|  |  |  | 	typedef std::complex<float> cmplx; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 18:55:39 +01:00
										 |  |  | 	fftfilt(int len); | 
					
						
							| 
									
										
										
										
											2015-05-15 11:29:41 +02:00
										 |  |  | 	fftfilt(float f1, float f2, int len); | 
					
						
							| 
									
										
										
										
											2015-06-21 12:46:47 +02:00
										 |  |  | 	fftfilt(float f2, int len); | 
					
						
							| 
									
										
										
										
											2015-05-15 11:29:41 +02:00
										 |  |  | 	~fftfilt(); | 
					
						
							|  |  |  | // f1 < f2 ==> bandpass
 | 
					
						
							|  |  |  | // f1 > f2 ==> band reject
 | 
					
						
							| 
									
										
										
										
											2022-05-18 01:30:32 +02:00
										 |  |  | 	void create_filter(float f1, float f2, FFTWindow::Function wf = FFTWindow::Blackman); | 
					
						
							| 
									
										
										
										
											2022-12-10 19:02:38 +01:00
										 |  |  |     void create_filter(const std::vector<std::pair<float, float>>& limits, bool pass = true, FFTWindow::Function wf = FFTWindow::Blackman); | 
					
						
							| 
									
										
										
										
											2022-12-12 07:50:35 +01:00
										 |  |  |     void create_filter(const std::vector<std::pair<float, float>>& limits, bool pass = true); //!< Windowless version
 | 
					
						
							| 
									
										
										
										
											2022-05-18 01:30:32 +02:00
										 |  |  | 	void create_dsb_filter(float f2, FFTWindow::Function wf = FFTWindow::Blackman); | 
					
						
							|  |  |  |     void create_asym_filter(float fopp, float fin, FFTWindow::Function wf = FFTWindow::Blackman); //!< two different filters for in band and opposite band
 | 
					
						
							| 
									
										
										
										
											2018-05-22 00:10:56 +02:00
										 |  |  |     void create_rrc_filter(float fb, float a); //!< root raised cosine. fb is half the band pass
 | 
					
						
							| 
									
										
										
										
											2015-05-15 11:29:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-21 12:46:47 +02:00
										 |  |  | 	int noFilt(const cmplx& in, cmplx **out); | 
					
						
							| 
									
										
										
										
											2015-05-15 11:29:41 +02:00
										 |  |  | 	int runFilt(const cmplx& in, cmplx **out); | 
					
						
							| 
									
										
										
										
											2017-03-15 15:37:51 +01:00
										 |  |  | 	int runSSB(const cmplx& in, cmplx **out, bool usb, bool getDC = true); | 
					
						
							| 
									
										
										
										
											2018-05-13 17:27:24 +02:00
										 |  |  | 	int runDSB(const cmplx& in, cmplx **out, bool getDC = true); | 
					
						
							| 
									
										
										
										
											2024-07-10 22:37:52 +02:00
										 |  |  | 	int runAsym(const cmplx & in, cmplx **out, bool usb); //!< Asymmetrical filtering can be used for vestigial sideband
 | 
					
						
							| 
									
										
										
										
											2015-05-15 11:29:41 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-05 10:33:27 +01:00
										 |  |  |     void setDNR(bool dnr) { m_dnr = dnr; } | 
					
						
							|  |  |  |     void setDNRScheme(FFTNoiseReduction::Scheme scheme) { m_dnrScheme = scheme; } | 
					
						
							|  |  |  |     void setDNRAboveAvgFactor(float aboveAvgFactor) { m_dnrAboveAvgFactor = aboveAvgFactor; } | 
					
						
							|  |  |  |     void setDNRSigmaFactor(float sigmaFactor) { m_dnrSigmaFactor = sigmaFactor; } | 
					
						
							|  |  |  |     void setDNRNbPeaks(int nbPeaks) { m_dnrNbPeaks = nbPeaks; } | 
					
						
							|  |  |  |     void setDNRAlpha(float alpha) { m_noiseReduction.setAlpha(alpha); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | protected: | 
					
						
							| 
									
										
										
										
											2023-11-05 10:33:27 +01:00
										 |  |  |     // helper class for FFT based noise reduction
 | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | 	int flen; | 
					
						
							|  |  |  | 	int flen2; | 
					
						
							|  |  |  | 	g_fft<float> *fft; | 
					
						
							|  |  |  | 	cmplx *filter; | 
					
						
							| 
									
										
										
										
											2017-03-16 10:11:03 +01:00
										 |  |  |     cmplx *filterOpp; | 
					
						
							| 
									
										
										
										
											2014-12-25 21:24:03 +00:00
										 |  |  | 	cmplx *data; | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | 	cmplx *ovlbuf; | 
					
						
							|  |  |  | 	cmplx *output; | 
					
						
							|  |  |  | 	int inptr; | 
					
						
							|  |  |  | 	int pass; | 
					
						
							|  |  |  | 	int window; | 
					
						
							| 
									
										
										
										
											2023-11-05 10:33:27 +01:00
										 |  |  |     bool m_dnr; | 
					
						
							|  |  |  |     FFTNoiseReduction::Scheme m_dnrScheme; | 
					
						
							|  |  |  |     float m_dnrAboveAvgFactor; //!< above average factor
 | 
					
						
							|  |  |  |     float m_dnrSigmaFactor; //!< sigma multiplicator for average + std deviation
 | 
					
						
							|  |  |  |     int m_dnrNbPeaks; //!< number of peaks (peaks scheme)
 | 
					
						
							|  |  |  |     FFTNoiseReduction m_noiseReduction; | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-22 00:10:56 +02:00
										 |  |  | 	inline float fsinc(float fc, int i, int len) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-02-24 10:29:27 +01:00
										 |  |  | 	    int len2 = len/2; | 
					
						
							|  |  |  | 		return (i == len2) ? 2.0 * fc: | 
					
						
							|  |  |  | 				sin(2 * M_PI * fc * (i - len2)) / (M_PI * (i - len2)); | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-21 12:46:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-22 00:10:56 +02:00
										 |  |  | 	inline float _blackman(int i, int len) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2017-03-16 02:45:51 +01:00
										 |  |  | 		return (0.42 - | 
					
						
							|  |  |  | 				 0.50 * cos(2.0 * M_PI * i / len) + | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | 				 0.08 * cos(4.0 * M_PI * i / len)); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-06-21 12:46:47 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-22 00:10:56 +02:00
										 |  |  | 	/** 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
 | 
					
						
							| 
									
										
										
										
											2018-05-22 02:20:36 +02:00
										 |  |  |         float tr = fb*a; // half the transition zone
 | 
					
						
							| 
									
										
										
										
											2018-05-22 00:10:56 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | 	void init_filter(); | 
					
						
							| 
									
										
										
										
											2015-06-21 12:46:47 +02:00
										 |  |  | 	void init_dsb_filter(); | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-11 19:30:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Sliding FFT filter from Fldigi */ | 
					
						
							| 
									
										
										
										
											2018-03-03 20:23:38 +01:00
										 |  |  | class SDRBASE_API sfft { | 
					
						
							| 
									
										
										
										
											2015-01-11 19:30:48 +00:00
										 |  |  | #define K1 0.99999
 | 
					
						
							| 
									
										
										
										
											2015-05-15 11:29:41 +02:00
										 |  |  | public: | 
					
						
							|  |  |  | 	typedef std::complex<float> cmplx; | 
					
						
							|  |  |  | 	sfft(int len); | 
					
						
							|  |  |  | 	~sfft(); | 
					
						
							|  |  |  | 	void run(const cmplx& input); | 
					
						
							|  |  |  | 	void fetch(float *result); | 
					
						
							| 
									
										
										
										
											2015-01-11 19:30:48 +00:00
										 |  |  | private: | 
					
						
							|  |  |  | 	int fftlen; | 
					
						
							|  |  |  | 	int first; | 
					
						
							|  |  |  | 	int last; | 
					
						
							|  |  |  | 	int ptr; | 
					
						
							|  |  |  | 	struct vrot_bins_pair; | 
					
						
							|  |  |  | 	vrot_bins_pair *vrot_bins; | 
					
						
							|  |  |  | 	cmplx *delay; | 
					
						
							|  |  |  | 	float k2; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-27 17:36:13 +01:00
										 |  |  | #endif
 |