mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 04:50:29 -04:00 
			
		
		
		
	Tx ph.2: Templatized IntHalfbandFilter and improved coefficients. Changed to order 80 for upsamplers and 48 for downsamplers
This commit is contained in:
		
							parent
							
								
									4ab45f4768
								
							
						
					
					
						commit
						4a001350d3
					
				| @ -397,7 +397,7 @@ if (BUILD_DEBIAN) | ||||
| endif (BUILD_DEBIAN) | ||||
| 
 | ||||
| set_target_properties(sdrbase PROPERTIES DEFINE_SYMBOL "sdrangel_EXPORTS") | ||||
| target_compile_features(sdrbase PUBLIC cxx_generalized_initializers) # cmake >= 3.1.0 | ||||
| target_compile_features(sdrbase PRIVATE cxx_generalized_initializers) # cmake >= 3.1.0 | ||||
| 
 | ||||
| qt5_use_modules(sdrbase Core Widgets OpenGL Multimedia) | ||||
| 
 | ||||
|  | ||||
| @ -54,36 +54,9 @@ private: | ||||
| 	unsigned int m_log2Decim; | ||||
| 	int m_fcPos; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	IntHalfbandFilter m_decimator2;  // 1st stages
 | ||||
| 	IntHalfbandFilter m_decimator4;  // 2nd stages
 | ||||
| 	IntHalfbandFilter m_decimator8;  // 3rd stages
 | ||||
| 	IntHalfbandFilter m_decimator16; // 4th stages
 | ||||
| 	IntHalfbandFilter m_decimator32; // 5th stages
 | ||||
| 	*/ | ||||
| 
 | ||||
| 	Decimators<qint16, SDR_SAMP_SZ, 12> m_decimators; | ||||
| 
 | ||||
| 	void run(); | ||||
| 	/*
 | ||||
| 	void decimate1(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate2_u(SampleVector::iterator* it, const quint16* buf, qint32 len); | ||||
| 	void decimate2(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate2_sup(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate2_cen(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate4(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate4_sup(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate4_cen(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate8(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate8_sup(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate8_cen(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate16(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate16_sup(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate16_cen(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate32(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate32_sup(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	void decimate32_cen(SampleVector::iterator* it, const qint16* buf, qint32 len); | ||||
| 	*/ | ||||
| 	void callback(const qint16* buf, qint32 len); | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -23,7 +23,7 @@ | ||||
| #include <QWaitCondition> | ||||
| #include <rtl-sdr.h> | ||||
| 
 | ||||
| #include "../../../sdrbase/dsp/samplesinkfifo.h" | ||||
| #include "dsp/samplesinkfifo.h" | ||||
| #include "dsp/decimators.h" | ||||
| 
 | ||||
| class RTLSDRThread : public QThread { | ||||
|  | ||||
| @ -20,20 +20,22 @@ | ||||
| #include "dsp/dsptypes.h" | ||||
| #include "dsp/inthalfbandfilter.h" | ||||
| 
 | ||||
| template<uint SdrBits, uint InputBits>  | ||||
| #define DECIMATORS_HB_FILTER_ORDER 48 | ||||
| 
 | ||||
| template<uint SdrBits, uint InputBits> | ||||
| struct decimation_shifts | ||||
| { | ||||
|     static const uint pre1   = 0;  | ||||
|     static const uint pre2   = 0;  | ||||
|     static const uint post2  = 0;  | ||||
|     static const uint pre4   = 0;  | ||||
|     static const uint post4  = 0;  | ||||
|     static const uint pre8   = 0;  | ||||
|     static const uint post8  = 0;  | ||||
|     static const uint pre16  = 0;  | ||||
|     static const uint post16 = 0;  | ||||
|     static const uint pre32  = 0;  | ||||
|     static const uint post32 = 0;  | ||||
|     static const uint pre1   = 0; | ||||
|     static const uint pre2   = 0; | ||||
|     static const uint post2  = 0; | ||||
|     static const uint pre4   = 0; | ||||
|     static const uint post4  = 0; | ||||
|     static const uint pre8   = 0; | ||||
|     static const uint post8  = 0; | ||||
|     static const uint pre16  = 0; | ||||
|     static const uint post16 = 0; | ||||
|     static const uint pre32  = 0; | ||||
|     static const uint post32 = 0; | ||||
|     static const uint pre64  = 0; | ||||
|     static const uint post64 = 0; | ||||
| }; | ||||
| @ -59,17 +61,17 @@ struct decimation_shifts<16, 16> | ||||
| template<> | ||||
| struct decimation_shifts<16, 12> | ||||
| { | ||||
|     static const uint pre1   = 4;  | ||||
|     static const uint pre2   = 3;  | ||||
|     static const uint post2  = 0;  | ||||
|     static const uint pre4   = 2;  | ||||
|     static const uint post4  = 0;  | ||||
|     static const uint pre8   = 1;  | ||||
|     static const uint post8  = 0;  | ||||
|     static const uint pre16  = 0;  | ||||
|     static const uint post16 = 0;  | ||||
|     static const uint pre32  = 0;  | ||||
|     static const uint post32 = 1;  | ||||
|     static const uint pre1   = 4; | ||||
|     static const uint pre2   = 3; | ||||
|     static const uint post2  = 0; | ||||
|     static const uint pre4   = 2; | ||||
|     static const uint post4  = 0; | ||||
|     static const uint pre8   = 1; | ||||
|     static const uint post8  = 0; | ||||
|     static const uint pre16  = 0; | ||||
|     static const uint post16 = 0; | ||||
|     static const uint pre32  = 0; | ||||
|     static const uint post32 = 1; | ||||
|     static const uint pre64  = 0; | ||||
|     static const uint post64 = 2; | ||||
| }; | ||||
| @ -79,15 +81,15 @@ struct decimation_shifts<16, 8> | ||||
| { | ||||
|     static const uint pre1   = 6; | ||||
|     static const uint pre2   = 5; | ||||
|     static const uint post2  = 0;  | ||||
|     static const uint post2  = 0; | ||||
|     static const uint pre4   = 4; | ||||
|     static const uint post4  = 0;  | ||||
|     static const uint post4  = 0; | ||||
|     static const uint pre8   = 3; | ||||
|     static const uint post8  = 0;  | ||||
|     static const uint post8  = 0; | ||||
|     static const uint pre16  = 2; | ||||
|     static const uint post16 = 0;  | ||||
|     static const uint post16 = 0; | ||||
|     static const uint pre32  = 1; | ||||
|     static const uint post32 = 0;  | ||||
|     static const uint post32 = 0; | ||||
|     static const uint pre64  = 0; | ||||
|     static const uint post64 = 0; | ||||
| }; | ||||
| @ -118,12 +120,12 @@ public: | ||||
| 	void decimate64_cen(SampleVector::iterator* it, const T* buf, qint32 len); | ||||
| 
 | ||||
| private: | ||||
| 	IntHalfbandFilter m_decimator2;  // 1st stages
 | ||||
| 	IntHalfbandFilter m_decimator4;  // 2nd stages
 | ||||
| 	IntHalfbandFilter m_decimator8;  // 3rd stages
 | ||||
| 	IntHalfbandFilter m_decimator16; // 4th stages
 | ||||
| 	IntHalfbandFilter m_decimator32; // 5th stages
 | ||||
| 	IntHalfbandFilter m_decimator64; // 6th stages
 | ||||
| 	IntHalfbandFilter<DECIMATORS_HB_FILTER_ORDER> m_decimator2;  // 1st stages
 | ||||
| 	IntHalfbandFilter<DECIMATORS_HB_FILTER_ORDER> m_decimator4;  // 2nd stages
 | ||||
| 	IntHalfbandFilter<DECIMATORS_HB_FILTER_ORDER> m_decimator8;  // 3rd stages
 | ||||
| 	IntHalfbandFilter<DECIMATORS_HB_FILTER_ORDER> m_decimator16; // 4th stages
 | ||||
| 	IntHalfbandFilter<DECIMATORS_HB_FILTER_ORDER> m_decimator32; // 5th stages
 | ||||
| 	IntHalfbandFilter<DECIMATORS_HB_FILTER_ORDER> m_decimator64; // 6th stages
 | ||||
| }; | ||||
| 
 | ||||
| template<typename T, uint SdrBits, uint InputBits> | ||||
| @ -308,7 +310,7 @@ void Decimators<T, SdrBits, InputBits>::decimate16_inf(SampleVector::iterator* i | ||||
| 
 | ||||
| 		m_decimator2.myDecimate(xreal[0], yimag[0], &xreal[1], &yimag[1]); | ||||
| 		m_decimator2.myDecimate(xreal[2], yimag[2], &xreal[3], &yimag[3]); | ||||
|          | ||||
| 
 | ||||
| 		m_decimator4.myDecimate(xreal[1], yimag[1], &xreal[3], &yimag[3]); | ||||
| 
 | ||||
| 		(**it).setReal(xreal[3] >> decimation_shifts<SdrBits, InputBits>::post16); | ||||
|  | ||||
| @ -187,20 +187,20 @@ void DownChannelizer::applyConfiguration() | ||||
| } | ||||
| 
 | ||||
| DownChannelizer::FilterStage::FilterStage(Mode mode) : | ||||
| 	m_filter(new IntHalfbandFilter), | ||||
| 	m_filter(new IntHalfbandFilter<DOWNCHANNELIZER_HB_FILTER_ORDER>), | ||||
| 	m_workFunction(0) | ||||
| { | ||||
| 	switch(mode) { | ||||
| 		case ModeCenter: | ||||
| 			m_workFunction = &IntHalfbandFilter::workDecimateCenter; | ||||
| 			m_workFunction = &IntHalfbandFilter<DOWNCHANNELIZER_HB_FILTER_ORDER>::workDecimateCenter; | ||||
| 			break; | ||||
| 
 | ||||
| 		case ModeLowerHalf: | ||||
| 			m_workFunction = &IntHalfbandFilter::workDecimateLowerHalf; | ||||
| 			m_workFunction = &IntHalfbandFilter<DOWNCHANNELIZER_HB_FILTER_ORDER>::workDecimateLowerHalf; | ||||
| 			break; | ||||
| 
 | ||||
| 		case ModeUpperHalf: | ||||
| 			m_workFunction = &IntHalfbandFilter::workDecimateUpperHalf; | ||||
| 			m_workFunction = &IntHalfbandFilter<DOWNCHANNELIZER_HB_FILTER_ORDER>::workDecimateUpperHalf; | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -23,9 +23,11 @@ | ||||
| #include <QMutex> | ||||
| #include "util/export.h" | ||||
| #include "util/message.h" | ||||
| #include "dsp/inthalfbandfilter.h" | ||||
| 
 | ||||
| #define DOWNCHANNELIZER_HB_FILTER_ORDER 48 | ||||
| 
 | ||||
| class MessageQueue; | ||||
| class IntHalfbandFilter; | ||||
| 
 | ||||
| class SDRANGEL_API DownChannelizer : public BasebandSampleSink { | ||||
| 	Q_OBJECT | ||||
| @ -67,8 +69,8 @@ protected: | ||||
| 			ModeUpperHalf | ||||
| 		}; | ||||
| 
 | ||||
| 		typedef bool (IntHalfbandFilter::*WorkFunction)(Sample* s); | ||||
| 		IntHalfbandFilter* m_filter; | ||||
| 		typedef bool (IntHalfbandFilter<DOWNCHANNELIZER_HB_FILTER_ORDER>::*WorkFunction)(Sample* s); | ||||
| 		IntHalfbandFilter<DOWNCHANNELIZER_HB_FILTER_ORDER>* m_filter; | ||||
| 		WorkFunction m_workFunction; | ||||
| 
 | ||||
| 		FilterStage(Mode mode); | ||||
|  | ||||
| @ -1,11 +1,102 @@ | ||||
| #include "dsp/inthalfbandfilter.h" | ||||
| 
 | ||||
| IntHalfbandFilter::IntHalfbandFilter() | ||||
| { | ||||
| 	for(int i = 0; i < HB_FILTERORDER + 1; i++) { | ||||
| 		m_samples[i][0] = 0; | ||||
| 		m_samples[i][1] = 0; | ||||
| 	} | ||||
| 	m_ptr = 0; | ||||
| 	m_state = 0; | ||||
| } | ||||
| const qint16 HBFIRFilterTraits<32>::hbMod[32+6] = { | ||||
|         31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, 20,21,22, | ||||
|         23,24,25,26,27,28,29,30,31,32,0,1,2 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| const qint32 HBFIRFilterTraits<32>::hbCoeffs[8] = { | ||||
|         //* Firwin as in https://www.dsprelated.com/showcode/270.php */
 | ||||
|         (qint32)(-0.0018878783958199373254477348993418672762 * (1 << hbShift)), | ||||
|         (qint32)( 0.0038624783041994003966734805288751886110 * (1 << hbShift)), | ||||
|         (qint32)(-0.0082424665965482504098593707908548822161 * (1 << hbShift)), | ||||
|         (qint32)( 0.0159471139705940345709933581019868142903 * (1 << hbShift)), | ||||
|         (qint32)(-0.0286765592339759019246958615667608682998 * (1 << hbShift)), | ||||
|         (qint32)( 0.0507185615622293764492845014046906726435 * (1 << hbShift)), | ||||
|         (qint32)(-0.0980159074728618323613105189906491432339 * (1 << hbShift)), | ||||
|         (qint32)( 0.3159417644358786247948955860920250415802 * (1 << hbShift)), | ||||
| }; | ||||
| 
 | ||||
| const qint16 HBFIRFilterTraits<48>::hbMod[48+6] = { | ||||
|         47,48,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, | ||||
|         24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46, | ||||
|         47,48,0,1,2 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| const qint32 HBFIRFilterTraits<48>::hbCoeffs[12] = { | ||||
|         //* Firwin as in https://www.dsprelated.com/showcode/270.php */
 | ||||
|         (qint32)(-0.0011627994808655962074434020436797254661 * (1 << hbShift)), | ||||
|         (qint32)( 0.0017451165792459334517860991553561689216 * (1 << hbShift)), | ||||
|         (qint32)(-0.0029357205890606303047563052643909031758 * (1 << hbShift)), | ||||
|         (qint32)( 0.0048726090910227891003780875678330630763 * (1 << hbShift)), | ||||
|         (qint32)(-0.0077313759655872928144848543752232217230 * (1 << hbShift)), | ||||
|         (qint32)( 0.0117637971494846688830238079503942572046 * (1 << hbShift)), | ||||
|         (qint32)(-0.0173810771817523163074170611253066454083 * (1 << hbShift)), | ||||
|         (qint32)( 0.0253500636065296450216699497559602605179 * (1 << hbShift)), | ||||
|         (qint32)(-0.0373266939135983855102551842719549313188 * (1 << hbShift)), | ||||
|         (qint32)( 0.0576685041500848358242414803953579394147 * (1 << hbShift)), | ||||
|         (qint32)(-0.1024912545928038654086122960507054813206 * (1 << hbShift)), | ||||
|         (qint32)( 0.3173768238826674692454332671331940218806 * (1 << hbShift)), | ||||
| }; | ||||
| 
 | ||||
| const qint16 HBFIRFilterTraits<64>::hbMod[64+6] = { | ||||
|         63,64,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, | ||||
|         24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46, | ||||
|         47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,0,1,2 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| const qint32 HBFIRFilterTraits<64>::hbCoeffs[16] = { | ||||
|         //* Remez as in https://www.dsprelated.com/showcode/270.php */
 | ||||
|         (qint32)(-0.0004653050334792540416659067936677729449 * (1 << hbShift)), | ||||
|         (qint32)( 0.0007120490624526883919470643391491648799 * (1 << hbShift)), | ||||
|         (qint32)(-0.0012303473710125558716887983479182366864 * (1 << hbShift)), | ||||
|         (qint32)( 0.0019716520179919017584369012041634050547 * (1 << hbShift)), | ||||
|         (qint32)(-0.0029947484165425580261710170049127555103 * (1 << hbShift)), | ||||
|         (qint32)( 0.0043703902150498061263128590780979720876 * (1 << hbShift)), | ||||
|         (qint32)(-0.0061858352927315653213558022116558277048 * (1 << hbShift)), | ||||
|         (qint32)( 0.0085554408639278121950777489246320328675 * (1 << hbShift)), | ||||
|         (qint32)(-0.0116397924445187355563247066925214312505 * (1 << hbShift)), | ||||
|         (qint32)( 0.0156852221106748394852115069397768820636 * (1 << hbShift)), | ||||
|         (qint32)(-0.0211070832238078286147153761476147337817 * (1 << hbShift)), | ||||
|         (qint32)( 0.0286850846890029896607554604770484729670 * (1 << hbShift)), | ||||
|         (qint32)(-0.0400956173930921908055147184768429724500 * (1 << hbShift)), | ||||
|         (qint32)( 0.0597215923200692666572564348825835622847 * (1 << hbShift)), | ||||
|         (qint32)(-0.1036982054813635201195864965484361164272 * (1 << hbShift)), | ||||
|         (qint32)( 0.3175014394028848885298543791577685624361 * (1 << hbShift)), | ||||
| }; | ||||
| 
 | ||||
| const qint16 HBFIRFilterTraits<80>::hbMod[80+6] = { | ||||
|         79,80,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, | ||||
|         24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46, | ||||
|         47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69, | ||||
|         70,71,72,73,74,75,76,77,78,79,80,0,1,2 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| const qint32 HBFIRFilterTraits<80>::hbCoeffs[20] = { | ||||
|         //* Remez as in https://www.dsprelated.com/showcode/270.php */
 | ||||
|         (qint32)(-0.0001054430663706784843331246137587697831 * (1 << hbShift)), | ||||
|         (qint32)( 0.0001895717826405601933066613629108587702 * (1 << hbShift)), | ||||
|         (qint32)(-0.0003519516996893227891822497621632237497 * (1 << hbShift)), | ||||
|         (qint32)( 0.0005975111594421821190753485453228677216 * (1 << hbShift)), | ||||
|         (qint32)(-0.0009524124279789792160699768430731637636 * (1 << hbShift)), | ||||
|         (qint32)( 0.0014474605824692796454677967687985074008 * (1 << hbShift)), | ||||
|         (qint32)(-0.0021186428821101787461911314380813564640 * (1 << hbShift)), | ||||
|         (qint32)( 0.0030082068742630901220236339099756150972 * (1 << hbShift)), | ||||
|         (qint32)(-0.0041664004891296358909502650647027621744 * (1 << hbShift)), | ||||
|         (qint32)( 0.0056547140936428538088298623165428580251 * (1 << hbShift)), | ||||
|         (qint32)(-0.0075518323360079901707120342280177283101 * (1 << hbShift)), | ||||
|         (qint32)( 0.0099644038858163180155669280679830990266 * (1 << hbShift)), | ||||
|         (qint32)(-0.0130470841719700410971105597468522319105 * (1 << hbShift)), | ||||
|         (qint32)( 0.0170422818715445859028001507340377429500 * (1 << hbShift)), | ||||
|         (qint32)(-0.0223637819225956900603957677731159492396 * (1 << hbShift)), | ||||
|         (qint32)( 0.0297925991327811050257690084208661573939 * (1 << hbShift)), | ||||
|         (qint32)(-0.0410092859102263174175817539435229264200 * (1 << hbShift)), | ||||
|         (qint32)( 0.0604034694948822267757115866970707429573 * (1 << hbShift)), | ||||
|         (qint32)(-0.1041194584045879306666293473426776472479 * (1 << hbShift)), | ||||
|         (qint32)( 0.3176437752925042046214798574510496109724 * (1 << hbShift)), | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| #ifndef INCLUDE_INTHALFBANDFILTER_H | ||||
| #define INCLUDE_INTHALFBANDFILTER_H | ||||
| 
 | ||||
| #include <QtGlobal> | ||||
| #include <stdint.h> | ||||
| #include "dsp/dsptypes.h" | ||||
| #include "util/export.h" | ||||
| 
 | ||||
| @ -9,33 +9,11 @@ | ||||
| 
 | ||||
| /*
 | ||||
|  * supported filter orders: 64, 48, 32 | ||||
|  * any usage of another value will be prevented by compilation errors | ||||
|  */ | ||||
| #define HB_FILTERORDER 64 | ||||
| #define HB_SHIFT 14 | ||||
| 
 | ||||
| template<uint32_t HBFilterOrder> | ||||
| struct HBFIRFilterTraits | ||||
| { | ||||
|     static const qint32 hbOrder = 32; | ||||
|     static const qint32 hbShift = 14; | ||||
|     static constexpr qint16 hbMod[38] = { 31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                         20,21,22,23,24,25,26,27,28,29,30,31,32,0,1,2}; | ||||
|     /* Coefficents. This is a sinc function:
 | ||||
|      * Half of the half of coefficients are stored because: | ||||
|      * - half of the coefficients are 0 | ||||
|      * - there is a symmertry around the central 1.0 coefficient (not stored either) | ||||
|      * There are actually order+1 coefficients | ||||
|      */ | ||||
|     static constexpr qint32 hbCoeffs[8] = { | ||||
|         (qint32)(-0.015956912844043127236437484839370881673 * (1 << hbShift)), | ||||
|         (qint32)( 0.013023031678944928940522274274371739011 * (1 << hbShift)), | ||||
|         (qint32)(-0.01866942273717486777684371190844103694  * (1 << hbShift)), | ||||
|         (qint32)( 0.026550887571157304190005987720724078827 * (1 << hbShift)), | ||||
|         (qint32)(-0.038350314277854319344740474662103224546 * (1 << hbShift)), | ||||
|         (qint32)( 0.058429248652825838128421764849917963147 * (1 << hbShift)), | ||||
|         (qint32)(-0.102889802028955756885153505209018476307 * (1 << hbShift)), | ||||
|         (qint32)( 0.317237706405931241260276465254719369113 * (1 << hbShift)) | ||||
|     }; | ||||
| }; | ||||
| 
 | ||||
| template<> | ||||
| @ -43,18 +21,8 @@ struct HBFIRFilterTraits<32> | ||||
| { | ||||
|     static const qint32 hbOrder = 32; | ||||
|     static const qint32 hbShift = 14; | ||||
|     static constexpr qint16 hbMod[32+6] = { 31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                         20,21,22,23,24,25,26,27,28,29,30,31,32,0,1,2}; | ||||
|     static constexpr qint32 hbCoeffs[8] = { | ||||
|         (qint32)(-0.015956912844043127236437484839370881673 * (1 << hbShift)), | ||||
|         (qint32)( 0.013023031678944928940522274274371739011 * (1 << hbShift)), | ||||
|         (qint32)(-0.01866942273717486777684371190844103694  * (1 << hbShift)), | ||||
|         (qint32)( 0.026550887571157304190005987720724078827 * (1 << hbShift)), | ||||
|         (qint32)(-0.038350314277854319344740474662103224546 * (1 << hbShift)), | ||||
|         (qint32)( 0.058429248652825838128421764849917963147 * (1 << hbShift)), | ||||
|         (qint32)(-0.102889802028955756885153505209018476307 * (1 << hbShift)), | ||||
|         (qint32)( 0.317237706405931241260276465254719369113 * (1 << hbShift)) | ||||
|     }; | ||||
|     static const qint16 hbMod[32+6]; | ||||
|     static const qint32 hbCoeffs[8]; | ||||
| }; | ||||
| 
 | ||||
| template<> | ||||
| @ -62,23 +30,8 @@ struct HBFIRFilterTraits<48> | ||||
| { | ||||
|     static const qint32 hbOrder = 48; | ||||
|     static const qint32 hbShift = 14; | ||||
|     static constexpr qint16 hbMod[48+6] = { 47,48,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                         20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41, | ||||
|                         42,43,44,45,46,47,48,0,1,2} ; | ||||
|     static constexpr qint32 hbCoeffs[12] = { | ||||
|         (qint32)(-0.004102576237611492253332112767338912818 * (1 << hbShift)), | ||||
|         (qint32)( 0.003950551047979387886410762575906119309 * (1 << hbShift)), | ||||
|         (qint32)(-0.005807875789391703583164350277456833282 * (1 << hbShift)), | ||||
|         (qint32)( 0.00823497890520805998770814682075069868  * (1 << hbShift)), | ||||
|         (qint32)(-0.011372226513199541059195851744334504474 * (1 << hbShift)), | ||||
|         (qint32)( 0.015471557140973646315984524335362948477 * (1 << hbShift)), | ||||
|         (qint32)(-0.020944996398689276484450516591095947661 * (1 << hbShift)), | ||||
|         (qint32)( 0.028568078132034283034279553703527199104 * (1 << hbShift)), | ||||
|         (qint32)(-0.040015143905614086738964374490024056286 * (1 << hbShift)), | ||||
|         (qint32)( 0.059669519431831075095828964549582451582 * (1 << hbShift)), | ||||
|         (qint32)(-0.103669138691865420076609893840213771909 * (1 << hbShift)), | ||||
|         (qint32)( 0.317491986549921390015072120149852707982 * (1 << hbShift)) | ||||
|     }; | ||||
|     static const qint16 hbMod[48+6]; | ||||
|     static const qint32 hbCoeffs[12]; | ||||
| }; | ||||
| 
 | ||||
| template<> | ||||
| @ -86,29 +39,20 @@ struct HBFIRFilterTraits<64> | ||||
| { | ||||
|     static const qint32 hbOrder = 64; | ||||
|     static const qint32 hbShift = 14; | ||||
|     static constexpr qint16 hbMod[64+6] = { 63,64,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                         20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44, | ||||
|                         45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,0,1,2} ; | ||||
|     static constexpr qint32 hbCoeffs[16] = { | ||||
|         (qint32)(-0.001114417441601693505720538368564120901 * (1 << hbShift)), | ||||
|         (qint32)( 0.001268007827185253051302527005361753254 * (1 << hbShift)), | ||||
|         (qint32)(-0.001959831378850490895410230152151598304 * (1 << hbShift)), | ||||
|         (qint32)( 0.002878308307661380308073439948657323839 * (1 << hbShift)), | ||||
|         (qint32)(-0.004071361818258721100571850826099762344 * (1 << hbShift)), | ||||
|         (qint32)( 0.005597288494657440618973431867289036745 * (1 << hbShift)), | ||||
|         (qint32)(-0.007532345003308904551886371336877346039 * (1 << hbShift)), | ||||
|         (qint32)( 0.009980346844667375288961963519795972388 * (1 << hbShift)), | ||||
|         (qint32)(-0.013092614174300500062830820979797863401 * (1 << hbShift)), | ||||
|         (qint32)( 0.01710934914871829748417297878404497169  * (1 << hbShift)), | ||||
|         (qint32)(-0.022443558692997273018576720460259821266 * (1 << hbShift)), | ||||
|         (qint32)( 0.029875811511593811098386197500076377764 * (1 << hbShift)), | ||||
|         (qint32)(-0.041086352085710403647667021687084343284 * (1 << hbShift)), | ||||
|         (qint32)( 0.060465467462665789533104998554335907102 * (1 << hbShift)), | ||||
|         (qint32)(-0.104159517495977321788203084906854201108 * (1 << hbShift)), | ||||
|         (qint32)( 0.317657589850154464805598308885237202048 * (1 << hbShift)), | ||||
|     }; | ||||
|     static const qint16 hbMod[64+6]; | ||||
|     static const qint32 hbCoeffs[16]; | ||||
| }; | ||||
| 
 | ||||
| template<> | ||||
| struct HBFIRFilterTraits<80> | ||||
| { | ||||
|     static const qint32 hbOrder = 80; | ||||
|     static const qint32 hbShift = 14; | ||||
|     static const qint16 hbMod[80+6]; | ||||
|     static const qint32 hbCoeffs[20]; | ||||
| }; | ||||
| 
 | ||||
| template<uint32_t HBFilterOrder> | ||||
| class SDRANGEL_API IntHalfbandFilter { | ||||
| public: | ||||
| 	IntHalfbandFilter(); | ||||
| @ -124,7 +68,7 @@ public: | ||||
| 		{ | ||||
| 			case 0: | ||||
| 				// advance write-pointer
 | ||||
| 				m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
| 				m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
| 				// next state
 | ||||
| 				m_state = 1; | ||||
| @ -137,7 +81,7 @@ public: | ||||
| 				doFIR(sample); | ||||
| 
 | ||||
| 				// advance write-pointer
 | ||||
| 				m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
| 				m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
| 				// next state
 | ||||
| 				m_state = 0; | ||||
| @ -161,7 +105,7 @@ public: | ||||
|                 doFIR(SampleOut); | ||||
| 
 | ||||
|                 // advance write-pointer
 | ||||
|                 m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
|                 m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
|                 // next state
 | ||||
|                 m_state = 1; | ||||
| @ -178,7 +122,7 @@ public: | ||||
|                 doFIR(SampleOut); | ||||
| 
 | ||||
|                 // advance write-pointer
 | ||||
|                 m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
|                 m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
|                 // next state
 | ||||
|                 m_state = 0; | ||||
| @ -198,7 +142,7 @@ public: | ||||
| 		{ | ||||
| 			case 0: | ||||
| 				// advance write-pointer
 | ||||
| 				m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
| 				m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
| 				// next state
 | ||||
| 				m_state = 1; | ||||
| @ -211,7 +155,7 @@ public: | ||||
| 				doFIR(x, y); | ||||
| 
 | ||||
| 				// advance write-pointer
 | ||||
| 				m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
| 				m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
| 				// next state
 | ||||
| 				m_state = 0; | ||||
| @ -270,7 +214,7 @@ public: | ||||
| 				m_samples[m_ptr][1] = sample->real(); | ||||
| 
 | ||||
| 				// advance write-pointer
 | ||||
| 				m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
| 				m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
| 				// next state
 | ||||
| 				m_state = 1; | ||||
| @ -287,7 +231,7 @@ public: | ||||
| 				doFIR(sample); | ||||
| 
 | ||||
| 				// advance write-pointer
 | ||||
| 				m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
| 				m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
| 				// next state
 | ||||
| 				m_state = 2; | ||||
| @ -301,7 +245,7 @@ public: | ||||
| 				m_samples[m_ptr][1] = -sample->real(); | ||||
| 
 | ||||
| 				// advance write-pointer
 | ||||
| 				m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
| 				m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
| 				// next state
 | ||||
| 				m_state = 3; | ||||
| @ -318,7 +262,7 @@ public: | ||||
| 				doFIR(sample); | ||||
| 
 | ||||
| 				// advance write-pointer
 | ||||
| 				m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
| 				m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
| 				// next state
 | ||||
| 				m_state = 0; | ||||
| @ -346,7 +290,7 @@ public: | ||||
|             sampleOut->setImag(-s.real()); | ||||
| 
 | ||||
|             // advance write-pointer
 | ||||
|             m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
|             m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
|             // next state
 | ||||
|             m_state = 1; | ||||
| @ -365,7 +309,7 @@ public: | ||||
|             sampleOut->setImag(-s.imag()); | ||||
| 
 | ||||
|             // advance write-pointer
 | ||||
|             m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
|             m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
|             // next state
 | ||||
|             m_state = 2; | ||||
| @ -384,7 +328,7 @@ public: | ||||
|             sampleOut->setImag(s.real()); | ||||
| 
 | ||||
|             // advance write-pointer
 | ||||
|             m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
|             m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
|             // next state
 | ||||
|             m_state = 3; | ||||
| @ -403,7 +347,7 @@ public: | ||||
|             sampleOut->setImag(s.imag()); | ||||
| 
 | ||||
|             // advance write-pointer
 | ||||
|             m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
|             m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
|             // next state
 | ||||
|             m_state = 0; | ||||
| @ -424,7 +368,7 @@ public: | ||||
| 				m_samples[m_ptr][1] = -sample->real(); | ||||
| 
 | ||||
| 				// advance write-pointer
 | ||||
| 				m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
| 				m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
| 				// next state
 | ||||
| 				m_state = 1; | ||||
| @ -441,7 +385,7 @@ public: | ||||
| 				doFIR(sample); | ||||
| 
 | ||||
| 				// advance write-pointer
 | ||||
| 				m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
| 				m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
| 				// next state
 | ||||
| 				m_state = 2; | ||||
| @ -455,7 +399,7 @@ public: | ||||
| 				m_samples[m_ptr][1] = sample->real(); | ||||
| 
 | ||||
| 				// advance write-pointer
 | ||||
| 				m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
| 				m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
| 				// next state
 | ||||
| 				m_state = 3; | ||||
| @ -472,7 +416,7 @@ public: | ||||
| 				doFIR(sample); | ||||
| 
 | ||||
| 				// advance write-pointer
 | ||||
| 				m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
| 				m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
| 				// next state
 | ||||
| 				m_state = 0; | ||||
| @ -500,7 +444,7 @@ public: | ||||
|             sampleOut->setImag(s.real()); | ||||
| 
 | ||||
|             // advance write-pointer
 | ||||
|             m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
|             m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
|             // next state
 | ||||
|             m_state = 1; | ||||
| @ -519,7 +463,7 @@ public: | ||||
|             sampleOut->setImag(-s.imag()); | ||||
| 
 | ||||
|             // advance write-pointer
 | ||||
|             m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
|             m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
|             // next state
 | ||||
|             m_state = 2; | ||||
| @ -538,7 +482,7 @@ public: | ||||
|             sampleOut->setImag(-s.real()); | ||||
| 
 | ||||
|             // advance write-pointer
 | ||||
|             m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
|             m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
|             // next state
 | ||||
|             m_state = 3; | ||||
| @ -557,7 +501,7 @@ public: | ||||
|             sampleOut->setImag(s.imag()); | ||||
| 
 | ||||
|             // advance write-pointer
 | ||||
|             m_ptr = (m_ptr + HB_FILTERORDER) % (HB_FILTERORDER + 1); | ||||
|             m_ptr = (m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder) % (HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1); | ||||
| 
 | ||||
|             // next state
 | ||||
|             m_state = 0; | ||||
| @ -569,161 +513,67 @@ public: | ||||
| 
 | ||||
|     void myDecimate(const Sample* sample1, Sample* sample2) | ||||
|     { | ||||
|     #if HB_FILTERORDER == 64 | ||||
|         static const qint16 HB_MOD[64+6] = { 63,64,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                             20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44, | ||||
|                             45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,0,1,2} ; | ||||
|     #elif HB_FILTERORDER == 48 | ||||
|         static const qint16 HB_MOD[48+6] = { 47,48,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                             20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41, | ||||
|                             42,43,44,45,46,47,48,0,1,2} ; | ||||
|     #elif HB_FILTERORDER == 32 | ||||
|         static const qint16 HB_MOD[38] = { 31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                             20,21,22,23,24,25,26,27,28,29,30,31,32,0,1,2}; | ||||
|     #else | ||||
|         #error unsupported filter order | ||||
|     #endif | ||||
| 
 | ||||
|         m_samples[m_ptr][0] = sample1->real(); | ||||
|         m_samples[m_ptr][1] = sample1->imag(); | ||||
|         m_ptr = HB_MOD[m_ptr + 2 - 1]; | ||||
|         m_ptr = HBFIRFilterTraits<HBFilterOrder>::hbMod[m_ptr + 2 - 1]; | ||||
| 
 | ||||
|         m_samples[m_ptr][0] = sample2->real(); | ||||
|         m_samples[m_ptr][1] = sample2->imag(); | ||||
| 
 | ||||
|         doFIR(sample2); | ||||
| 
 | ||||
|         m_ptr = HB_MOD[m_ptr + 2 - 1]; | ||||
|         m_ptr = HBFIRFilterTraits<HBFilterOrder>::hbMod[m_ptr + 2 - 1]; | ||||
|     } | ||||
| 
 | ||||
|     void myDecimate(qint32 x1, qint32 y1, qint32 *x2, qint32 *y2) | ||||
|     { | ||||
|     #if HB_FILTERORDER == 64 | ||||
|         static const qint16 HB_MOD[64+6] = { 63,64,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                             20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44, | ||||
|                             45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,0,1,2} ; | ||||
|     #elif HB_FILTERORDER == 48 | ||||
|         static const qint16 HB_MOD[48+6] = { 47,48,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                             20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41, | ||||
|                             42,43,44,45,46,47,48,0,1,2} ; | ||||
|     #elif HB_FILTERORDER == 32 | ||||
|         static const qint16 HB_MOD[38] = { 31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                             20,21,22,23,24,25,26,27,28,29,30,31,32,0,1,2}; | ||||
|     #else | ||||
|         #error unsupported filter order | ||||
|     #endif | ||||
| 
 | ||||
|         m_samples[m_ptr][0] = x1; | ||||
|         m_samples[m_ptr][1] = y1; | ||||
|         m_ptr = HB_MOD[m_ptr + 2 - 1]; | ||||
|         m_ptr = HBFIRFilterTraits<HBFilterOrder>::hbMod[m_ptr + 2 - 1]; | ||||
| 
 | ||||
|         m_samples[m_ptr][0] = *x2; | ||||
|         m_samples[m_ptr][1] = *y2; | ||||
| 
 | ||||
|         doFIR(x2, y2); | ||||
| 
 | ||||
|         m_ptr = HB_MOD[m_ptr + 2 - 1]; | ||||
|         m_ptr = HBFIRFilterTraits<HBFilterOrder>::hbMod[m_ptr + 2 - 1]; | ||||
|     } | ||||
| 
 | ||||
| protected: | ||||
| 	qint32 m_samples[HB_FILTERORDER + 1][2]; // Valgrind optim (from qint16)
 | ||||
| 	qint32 m_samples[HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1][2]; // Valgrind optim (from qint16)
 | ||||
| 	qint16 m_ptr; | ||||
| 	int m_state; | ||||
| 
 | ||||
| 	void doFIR(Sample* sample) | ||||
| 	{ | ||||
|         // Coefficents. This is a sinc function:
 | ||||
|         // Half of the half of coefficients are stored because:
 | ||||
|         // - half of the coefficients are 0
 | ||||
|         // - there is a symmertry around the central 1.0 coefficient (not stored either)
 | ||||
|         // There are actually order+1 coefficients
 | ||||
| 
 | ||||
| #if HB_FILTERORDER == 64 | ||||
|         static const qint16 HB_MOD[64+6] = { 63,64,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                             20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44, | ||||
|                             45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,0,1,2} ; | ||||
| 		static const qint32 COEFF[16] = { | ||||
|             (qint32)(-0.001114417441601693505720538368564120901 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.001268007827185253051302527005361753254 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.001959831378850490895410230152151598304 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.002878308307661380308073439948657323839 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.004071361818258721100571850826099762344 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.005597288494657440618973431867289036745 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.007532345003308904551886371336877346039 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.009980346844667375288961963519795972388 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.013092614174300500062830820979797863401 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.01710934914871829748417297878404497169  * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.022443558692997273018576720460259821266 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.029875811511593811098386197500076377764 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.041086352085710403647667021687084343284 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.060465467462665789533104998554335907102 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.104159517495977321788203084906854201108 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.317657589850154464805598308885237202048 * (1 << HB_SHIFT)), | ||||
| 		}; | ||||
| #elif HB_FILTERORDER == 48 | ||||
|         static const qint16 HB_MOD[48+6] = { 47,48,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                             20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41, | ||||
|                             42,43,44,45,46,47,48,0,1,2} ; | ||||
| 		static const qint32 COEFF[12] = { | ||||
|             (qint32)(-0.004102576237611492253332112767338912818 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.003950551047979387886410762575906119309 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.005807875789391703583164350277456833282 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.00823497890520805998770814682075069868  * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.011372226513199541059195851744334504474 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.015471557140973646315984524335362948477 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.020944996398689276484450516591095947661 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.028568078132034283034279553703527199104 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.040015143905614086738964374490024056286 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.059669519431831075095828964549582451582 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.103669138691865420076609893840213771909 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.317491986549921390015072120149852707982 * (1 << HB_SHIFT)) | ||||
| 		}; | ||||
| #elif HB_FILTERORDER == 32 | ||||
| 		static const qint16 HB_MOD[32+6] = { 31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
| 							20,21,22,23,24,25,26,27,28,29,30,31,32,0,1,2} ; | ||||
| 		static const qint32 COEFF[8] = { | ||||
| 			(qint32)(-0.015956912844043127236437484839370881673 * (1 << HB_SHIFT)), | ||||
| 			(qint32)( 0.013023031678944928940522274274371739011 * (1 << HB_SHIFT)), | ||||
| 			(qint32)(-0.01866942273717486777684371190844103694  * (1 << HB_SHIFT)), | ||||
| 			(qint32)( 0.026550887571157304190005987720724078827 * (1 << HB_SHIFT)), | ||||
| 			(qint32)(-0.038350314277854319344740474662103224546 * (1 << HB_SHIFT)), | ||||
| 			(qint32)( 0.058429248652825838128421764849917963147 * (1 << HB_SHIFT)), | ||||
| 			(qint32)(-0.102889802028955756885153505209018476307 * (1 << HB_SHIFT)), | ||||
| 			(qint32)( 0.317237706405931241260276465254719369113 * (1 << HB_SHIFT)) | ||||
| 		}; | ||||
| #else | ||||
| #error unsupported filter order | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| 		// init read-pointer
 | ||||
| 		int a = HB_MOD[m_ptr + 2 + 1]; // 0 + 1
 | ||||
| 		int b = HB_MOD[m_ptr + 2 - 2]; //-1 - 1
 | ||||
| 		int a = HBFIRFilterTraits<HBFilterOrder>::hbMod[m_ptr + 2 + 1]; // 0 + 1
 | ||||
| 		int b = HBFIRFilterTraits<HBFilterOrder>::hbMod[m_ptr + 2 - 2]; //-1 - 1
 | ||||
| 
 | ||||
| 		// go through samples in buffer
 | ||||
| 		qint32 iAcc = 0; | ||||
| 		qint32 qAcc = 0; | ||||
| 
 | ||||
| 		for (int i = 0; i < HB_FILTERORDER / 4; i++) | ||||
| 		for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++) | ||||
| 		{ | ||||
| 			// do multiply-accumulate
 | ||||
| 			//qint32 iTmp = m_samples[a][0] + m_samples[b][0]; // Valgrind optim
 | ||||
| 			//qint32 qTmp = m_samples[a][1] + m_samples[b][1]; // Valgrind optim
 | ||||
| 			iAcc += (m_samples[a][0] + m_samples[b][0]) * COEFF[i]; | ||||
| 			qAcc += (m_samples[a][1] + m_samples[b][1]) * COEFF[i]; | ||||
| 			iAcc += (m_samples[a][0] + m_samples[b][0]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffs[i]; | ||||
| 			qAcc += (m_samples[a][1] + m_samples[b][1]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffs[i]; | ||||
| 
 | ||||
| 			// update read-pointer
 | ||||
| 			a = HB_MOD[a + 2 + 2]; | ||||
| 			b = HB_MOD[b + 2 - 2]; | ||||
| 			a = HBFIRFilterTraits<HBFilterOrder>::hbMod[a + 2 + 2]; | ||||
| 			b = HBFIRFilterTraits<HBFilterOrder>::hbMod[b + 2 - 2]; | ||||
| 		} | ||||
| 
 | ||||
| 		a = HB_MOD[a + 2 - 1]; | ||||
| 		a = HBFIRFilterTraits<HBFilterOrder>::hbMod[a + 2 - 1]; | ||||
| 
 | ||||
| 		iAcc += ((qint32)m_samples[a][0] + 1) << (HB_SHIFT - 1); | ||||
| 		qAcc += ((qint32)m_samples[a][1] + 1) << (HB_SHIFT - 1); | ||||
| 		iAcc += ((qint32)m_samples[a][0] + 1) << (HBFIRFilterTraits<HBFilterOrder>::hbShift - 1); | ||||
| 		qAcc += ((qint32)m_samples[a][1] + 1) << (HBFIRFilterTraits<HBFilterOrder>::hbShift - 1); | ||||
| 
 | ||||
| 		sample->setReal(iAcc >> HB_SHIFT); | ||||
| 		sample->setImag(qAcc >> HB_SHIFT); | ||||
| 		sample->setReal(iAcc >> HBFIRFilterTraits<HBFilterOrder>::hbShift); | ||||
| 		sample->setImag(qAcc >> HBFIRFilterTraits<HBFilterOrder>::hbShift); | ||||
| 	} | ||||
| 
 | ||||
| 	void doFIR(qint32 *x, qint32 *y) | ||||
| @ -731,97 +581,50 @@ protected: | ||||
| 		// Coefficents. This is a sinc function:
 | ||||
| 	    // Half of the half of coefficients are stored because:
 | ||||
| 	    // - half of the coefficients are 0
 | ||||
| 	    // - there is a symmertry around the central 1.0 coefficient (not stored either)
 | ||||
| 	    // - there is a symmertry around the central 0.5 coefficient (not stored either)
 | ||||
| 	    // There are actually order+1 coefficients
 | ||||
| 
 | ||||
| 	#if HB_FILTERORDER == 64 | ||||
|         static const qint16 HB_MOD[64+6] = { 63,64,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                             20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44, | ||||
|                             45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,0,1,2} ; | ||||
| 		static const qint32 COEFF[16] = { | ||||
|             (qint32)(-0.001114417441601693505720538368564120901 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.001268007827185253051302527005361753254 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.001959831378850490895410230152151598304 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.002878308307661380308073439948657323839 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.004071361818258721100571850826099762344 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.005597288494657440618973431867289036745 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.007532345003308904551886371336877346039 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.009980346844667375288961963519795972388 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.013092614174300500062830820979797863401 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.01710934914871829748417297878404497169  * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.022443558692997273018576720460259821266 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.029875811511593811098386197500076377764 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.041086352085710403647667021687084343284 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.060465467462665789533104998554335907102 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.104159517495977321788203084906854201108 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.317657589850154464805598308885237202048 * (1 << HB_SHIFT)), | ||||
| 		}; | ||||
| 	#elif HB_FILTERORDER == 48 | ||||
|         static const qint16 HB_MOD[48+6] = { 47,48,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
|                             20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41, | ||||
|                             42,43,44,45,46,47,48,0,1,2} ; | ||||
|         static const qint32 COEFF[12] = { | ||||
|             (qint32)(-0.004102576237611492253332112767338912818 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.003950551047979387886410762575906119309 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.005807875789391703583164350277456833282 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.00823497890520805998770814682075069868  * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.011372226513199541059195851744334504474 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.015471557140973646315984524335362948477 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.020944996398689276484450516591095947661 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.028568078132034283034279553703527199104 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.040015143905614086738964374490024056286 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.059669519431831075095828964549582451582 * (1 << HB_SHIFT)), | ||||
|             (qint32)(-0.103669138691865420076609893840213771909 * (1 << HB_SHIFT)), | ||||
|             (qint32)( 0.317491986549921390015072120149852707982 * (1 << HB_SHIFT)) | ||||
|         }; | ||||
| 	#elif HB_FILTERORDER == 32 | ||||
| 		static const int HB_MOD[38] = { 31,32,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19, | ||||
| 							20,21,22,23,24,25,26,27,28,29,30,31,32,0,1,2} ; | ||||
| 		static const qint32 COEFF[8] = { | ||||
| 			(qint32)(-0.015956912844043127236437484839370881673 * (1 << HB_SHIFT)), | ||||
| 			(qint32)( 0.013023031678944928940522274274371739011 * (1 << HB_SHIFT)), | ||||
| 			(qint32)(-0.01866942273717486777684371190844103694  * (1 << HB_SHIFT)), | ||||
| 			(qint32)( 0.026550887571157304190005987720724078827 * (1 << HB_SHIFT)), | ||||
| 			(qint32)(-0.038350314277854319344740474662103224546 * (1 << HB_SHIFT)), | ||||
| 			(qint32)( 0.058429248652825838128421764849917963147 * (1 << HB_SHIFT)), | ||||
| 			(qint32)(-0.102889802028955756885153505209018476307 * (1 << HB_SHIFT)), | ||||
| 			(qint32)( 0.317237706405931241260276465254719369113 * (1 << HB_SHIFT)) | ||||
| 		}; | ||||
| 	#else | ||||
| 	#error unsupported filter order | ||||
| 	#endif | ||||
| 
 | ||||
| 
 | ||||
| 		// init read-pointer
 | ||||
| 		int a = HB_MOD[m_ptr + 2 + 1]; // 0 + 1
 | ||||
| 		int b = HB_MOD[m_ptr + 2 - 2]; //-1 - 1
 | ||||
| 		int a = HBFIRFilterTraits<HBFilterOrder>::hbMod[m_ptr + 2 + 1]; // 0 + 1
 | ||||
| 		int b = HBFIRFilterTraits<HBFilterOrder>::hbMod[m_ptr + 2 - 2]; //-1 - 1
 | ||||
| 
 | ||||
| 		// go through samples in buffer
 | ||||
| 		qint32 iAcc = 0; | ||||
| 		qint32 qAcc = 0; | ||||
| 
 | ||||
| 		for (int i = 0; i < HB_FILTERORDER / 4; i++) | ||||
| 		for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++) | ||||
| 		{ | ||||
| 			// do multiply-accumulate
 | ||||
| 			//qint32 iTmp = m_samples[a][0] + m_samples[b][0]; // Valgrind optim
 | ||||
| 			//qint32 qTmp = m_samples[a][1] + m_samples[b][1]; // Valgrind optim
 | ||||
| 			iAcc += (m_samples[a][0] + m_samples[b][0]) * COEFF[i]; | ||||
| 			qAcc += (m_samples[a][1] + m_samples[b][1]) * COEFF[i]; | ||||
| 			iAcc += (m_samples[a][0] + m_samples[b][0]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffs[i]; | ||||
| 			qAcc += (m_samples[a][1] + m_samples[b][1]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffs[i]; | ||||
| 
 | ||||
| 			// update read-pointer
 | ||||
| 			a = HB_MOD[a + 2 + 2]; | ||||
| 			b = HB_MOD[b + 2 - 2]; | ||||
| 			a = HBFIRFilterTraits<HBFilterOrder>::hbMod[a + 2 + 2]; | ||||
| 			b = HBFIRFilterTraits<HBFilterOrder>::hbMod[b + 2 - 2]; | ||||
| 		} | ||||
| 
 | ||||
| 		a = HB_MOD[a + 2 - 1]; | ||||
| 		a = HBFIRFilterTraits<HBFilterOrder>::hbMod[a + 2 - 1]; | ||||
| 
 | ||||
| 		iAcc += ((qint32)m_samples[a][0] + 1) << (HB_SHIFT - 1); | ||||
| 		qAcc += ((qint32)m_samples[a][1] + 1) << (HB_SHIFT - 1); | ||||
| 		iAcc += ((qint32)m_samples[a][0] + 1) << (HBFIRFilterTraits<HBFilterOrder>::hbShift - 1); | ||||
| 		qAcc += ((qint32)m_samples[a][1] + 1) << (HBFIRFilterTraits<HBFilterOrder>::hbShift - 1); | ||||
| 
 | ||||
| 		*x = iAcc >> (HB_SHIFT -1); // HB_SHIFT incorrect do not loose the gained bit
 | ||||
| 		*y = qAcc >> (HB_SHIFT -1); | ||||
| 		*x = iAcc >> (HBFIRFilterTraits<HBFilterOrder>::hbShift -1); // HB_SHIFT incorrect do not loose the gained bit
 | ||||
| 		*y = qAcc >> (HBFIRFilterTraits<HBFilterOrder>::hbShift -1); | ||||
| 	} | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| template<uint32_t HBFilterOrder> | ||||
| IntHalfbandFilter<HBFilterOrder>::IntHalfbandFilter() | ||||
| { | ||||
|     for(int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder + 1; i++) { | ||||
|         m_samples[i][0] = 0; | ||||
|         m_samples[i][1] = 0; | ||||
|     } | ||||
|     m_ptr = 0; | ||||
|     m_state = 0; | ||||
| } | ||||
| 
 | ||||
| #endif // INCLUDE_INTHALFBANDFILTER_H
 | ||||
|  | ||||
| @ -120,12 +120,12 @@ public: | ||||
| 	void decimate64_cen(SampleSinkFifoDoubleBuffered& fifo, const T* buf, qint32 len); | ||||
| 
 | ||||
| private: | ||||
| 	IntHalfbandFilter m_decimator2;  // 1st stages
 | ||||
| 	IntHalfbandFilter m_decimator4;  // 2nd stages
 | ||||
| 	IntHalfbandFilter m_decimator8;  // 3rd stages
 | ||||
| 	IntHalfbandFilter m_decimator16; // 4th stages
 | ||||
| 	IntHalfbandFilter m_decimator32; // 5th stages
 | ||||
| 	IntHalfbandFilter m_decimator64; // 6th stages
 | ||||
| 	IntHalfbandFilter<32> m_decimator2;  // 1st stages
 | ||||
| 	IntHalfbandFilter<32> m_decimator4;  // 2nd stages
 | ||||
| 	IntHalfbandFilter<32> m_decimator8;  // 3rd stages
 | ||||
| 	IntHalfbandFilter<32> m_decimator16; // 4th stages
 | ||||
| 	IntHalfbandFilter<32> m_decimator32; // 5th stages
 | ||||
| 	IntHalfbandFilter<32> m_decimator64; // 6th stages
 | ||||
| }; | ||||
| 
 | ||||
| template<typename T, uint32_t SdrBits, uint32_t InputBits> | ||||
| @ -337,7 +337,7 @@ void SampleSinkFifoDecimator<T, SdrBits, InputBits>::decimate16_inf(SampleSinkFi | ||||
| 
 | ||||
| 		m_decimator2.myDecimate(xreal[0], yimag[0], &xreal[1], &yimag[1]); | ||||
| 		m_decimator2.myDecimate(xreal[2], yimag[2], &xreal[3], &yimag[3]); | ||||
|          | ||||
| 
 | ||||
| 		m_decimator4.myDecimate(xreal[1], yimag[1], &xreal[3], &yimag[3]); | ||||
| 
 | ||||
| 		(*it).setReal(xreal[3] >> decimation_shifts<SdrBits, InputBits>::post16); | ||||
|  | ||||
| @ -185,20 +185,20 @@ void UpChannelizer::applyConfiguration() | ||||
| } | ||||
| 
 | ||||
| UpChannelizer::FilterStage::FilterStage(Mode mode) : | ||||
|     m_filter(new IntHalfbandFilter), | ||||
|     m_filter(new IntHalfbandFilter<UPCHANNELIZER_HB_FILTER_ORDER>), | ||||
|     m_workFunction(0) | ||||
| { | ||||
|     switch(mode) { | ||||
|         case ModeCenter: | ||||
|             m_workFunction = &IntHalfbandFilter::workInterpolateCenter; | ||||
|             m_workFunction = &IntHalfbandFilter<UPCHANNELIZER_HB_FILTER_ORDER>::workInterpolateCenter; | ||||
|             break; | ||||
| 
 | ||||
|         case ModeLowerHalf: | ||||
|             m_workFunction = &IntHalfbandFilter::workInterpolateLowerHalf; | ||||
|             m_workFunction = &IntHalfbandFilter<UPCHANNELIZER_HB_FILTER_ORDER>::workInterpolateLowerHalf; | ||||
|             break; | ||||
| 
 | ||||
|         case ModeUpperHalf: | ||||
|             m_workFunction = &IntHalfbandFilter::workInterpolateUpperHalf; | ||||
|             m_workFunction = &IntHalfbandFilter<UPCHANNELIZER_HB_FILTER_ORDER>::workInterpolateUpperHalf; | ||||
|             break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -23,9 +23,11 @@ | ||||
| #include <QMutex> | ||||
| #include "util/export.h" | ||||
| #include "util/message.h" | ||||
| #include "dsp/inthalfbandfilter.h" | ||||
| 
 | ||||
| #define UPCHANNELIZER_HB_FILTER_ORDER 80 | ||||
| 
 | ||||
| class MessageQueue; | ||||
| class IntHalfbandFilter; | ||||
| 
 | ||||
| class SDRANGEL_API UpChannelizer : public BasebandSampleSource { | ||||
|     Q_OBJECT | ||||
| @ -67,8 +69,8 @@ protected: | ||||
|             ModeUpperHalf | ||||
|         }; | ||||
| 
 | ||||
|         typedef bool (IntHalfbandFilter::*WorkFunction)(Sample* sIn, Sample *sOut); | ||||
|         IntHalfbandFilter* m_filter; | ||||
|         typedef bool (IntHalfbandFilter<UPCHANNELIZER_HB_FILTER_ORDER>::*WorkFunction)(Sample* sIn, Sample *sOut); | ||||
|         IntHalfbandFilter<UPCHANNELIZER_HB_FILTER_ORDER>* m_filter; | ||||
|         WorkFunction m_workFunction; | ||||
| 
 | ||||
|         FilterStage(Mode mode); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user