| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // Copyright (C) 2018 F4EXB                                                      //
 | 
					
						
							|  |  |  | // written by Edouard Griffiths                                                  //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // Float half-band FIR based interpolator and decimator                        //
 | 
					
						
							|  |  |  | // This is the double buffer variant                                             //
 | 
					
						
							|  |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // 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                  //
 | 
					
						
							| 
									
										
										
										
											2019-04-11 14:32:15 +02:00
										 |  |  | // (at your option) any later version.                                           //
 | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | //                                                                               //
 | 
					
						
							|  |  |  | // 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/>.          //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  | #ifndef INCLUDE_INTHALFBANDFILTER_DBFF_H
 | 
					
						
							|  |  |  | #define INCLUDE_INTHALFBANDFILTER_DBFF_H
 | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <stdint.h>
 | 
					
						
							|  |  |  | #include "dsp/dsptypes.h"
 | 
					
						
							|  |  |  | #include "dsp/hbfiltertraits.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-20 13:49:21 +01:00
										 |  |  | #include "export.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | template<typename AccuType, typename SampleType, uint32_t HBFilterOrder> | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  | class SDRBASE_API IntHalfbandFilterDBFF { | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     IntHalfbandFilterDBFF(); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// downsample by 2, return center part of original spectrum
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  | 	bool workDecimateCenter(FSample* sample) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		// insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  | 	    storeSampleReal((Real) sample->real(), (Real) sample->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		switch(m_state) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			case 0: | 
					
						
							|  |  |  | 				// advance write-pointer
 | 
					
						
							|  |  |  | 			    advancePointer(); | 
					
						
							|  |  |  | 				// next state
 | 
					
						
							|  |  |  | 				m_state = 1; | 
					
						
							|  |  |  | 				// tell caller we don't have a new sample
 | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				// save result
 | 
					
						
							|  |  |  | 				doFIR(sample); | 
					
						
							|  |  |  | 				// advance write-pointer
 | 
					
						
							|  |  |  |                 advancePointer(); | 
					
						
							|  |  |  | 				// next state
 | 
					
						
							|  |  |  | 				m_state = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// tell caller we have a new sample
 | 
					
						
							|  |  |  | 				return true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // upsample by 2, return center part of original spectrum - double buffer variant
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     bool workInterpolateCenterZeroStuffing(FSample* sampleIn, FSample *SampleOut) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         switch(m_state) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             case 0: | 
					
						
							|  |  |  |                 // insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |                 storeSampleReal((Real) 0, (Real) 0); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |                 // save result
 | 
					
						
							|  |  |  |                 doFIR(SampleOut); | 
					
						
							|  |  |  |                 // advance write-pointer
 | 
					
						
							|  |  |  |                 advancePointer(); | 
					
						
							|  |  |  |                 // next state
 | 
					
						
							|  |  |  |                 m_state = 1; | 
					
						
							|  |  |  |                 // tell caller we didn't consume the sample
 | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 // insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |                 storeSampleReal((Real) sampleIn->real(), (Real) sampleIn->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |                 // save result
 | 
					
						
							|  |  |  |                 doFIR(SampleOut); | 
					
						
							|  |  |  |                 // advance write-pointer
 | 
					
						
							|  |  |  |                 advancePointer(); | 
					
						
							|  |  |  |                 // next state
 | 
					
						
							|  |  |  |                 m_state = 0; | 
					
						
							|  |  |  |                 // tell caller we consumed the sample
 | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Optimized upsampler by 2 not calculating FIR with inserted null samples */ | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     bool workInterpolateCenter(FSample* sampleIn, FSample *SampleOut) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         switch(m_state) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         case 0: | 
					
						
							|  |  |  |             // return the middle peak
 | 
					
						
							|  |  |  |             SampleOut->setReal(m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][0]); | 
					
						
							|  |  |  |             SampleOut->setImag(m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][1]); | 
					
						
							|  |  |  |             m_state = 1;  // next state
 | 
					
						
							|  |  |  |             return false; // tell caller we didn't consume the sample
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             // calculate with non null samples
 | 
					
						
							|  |  |  |             doInterpolateFIR(SampleOut); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // insert sample into ring double buffer
 | 
					
						
							|  |  |  |             m_samplesDB[m_ptr][0] = sampleIn->real(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr][1] = sampleIn->imag(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][0] = sampleIn->real(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][1] = sampleIn->imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance pointer
 | 
					
						
							|  |  |  |             if (m_ptr < (HBFIRFilterTraits<HBFilterOrder>::hbOrder/2) - 1) { | 
					
						
							|  |  |  |                 m_ptr++; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 m_ptr = 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             m_state = 0; // next state
 | 
					
						
							|  |  |  |             return true; // tell caller we consumed the sample
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// downsample by 2, return lower half of original spectrum
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  | 	bool workDecimateLowerHalf(FSample* sample) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		switch(m_state) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			case 0: | 
					
						
							|  |  |  | 				// insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  | 			    storeSampleReal((Real) -sample->imag(), (Real) sample->real()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 				// advance write-pointer
 | 
					
						
							|  |  |  |                 advancePointer(); | 
					
						
							|  |  |  | 				// next state
 | 
					
						
							|  |  |  | 				m_state = 1; | 
					
						
							|  |  |  | 				// tell caller we don't have a new sample
 | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case 1: | 
					
						
							|  |  |  | 				// insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |                 storeSampleReal((Real) -sample->real(), (Real) -sample->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 				// save result
 | 
					
						
							|  |  |  | 				doFIR(sample); | 
					
						
							|  |  |  | 				// advance write-pointer
 | 
					
						
							|  |  |  |                 advancePointer(); | 
					
						
							|  |  |  | 				// next state
 | 
					
						
							|  |  |  | 				m_state = 2; | 
					
						
							|  |  |  | 				// tell caller we have a new sample
 | 
					
						
							|  |  |  | 				return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case 2: | 
					
						
							|  |  |  | 				// insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |                 storeSampleReal((Real) sample->imag(), (Real) -sample->real()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 				// advance write-pointer
 | 
					
						
							|  |  |  |                 advancePointer(); | 
					
						
							|  |  |  | 				// next state
 | 
					
						
							|  |  |  | 				m_state = 3; | 
					
						
							|  |  |  | 				// tell caller we don't have a new sample
 | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				// insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |                 storeSampleReal((Real) sample->real(), (Real) sample->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 				// save result
 | 
					
						
							|  |  |  | 				doFIR(sample); | 
					
						
							|  |  |  | 				// advance write-pointer
 | 
					
						
							|  |  |  |                 advancePointer(); | 
					
						
							|  |  |  | 				// next state
 | 
					
						
							|  |  |  | 				m_state = 0; | 
					
						
							|  |  |  | 				// tell caller we have a new sample
 | 
					
						
							|  |  |  | 				return true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Optimized upsampler by 2 not calculating FIR with inserted null samples */ | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     bool workInterpolateLowerHalf(FSample* sampleIn, FSample *sampleOut) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |         FSample s; | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         switch(m_state) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         case 0: | 
					
						
							|  |  |  |             // return the middle peak
 | 
					
						
							|  |  |  |             sampleOut->setReal(m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][1]);  // imag
 | 
					
						
							|  |  |  |             sampleOut->setImag(-m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][0]); // - real
 | 
					
						
							|  |  |  |             m_state = 1;  // next state
 | 
					
						
							|  |  |  |             return false; // tell caller we didn't consume the sample
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case 1: | 
					
						
							|  |  |  |             // calculate with non null samples
 | 
					
						
							|  |  |  |             doInterpolateFIR(&s); | 
					
						
							|  |  |  |             sampleOut->setReal(-s.real()); | 
					
						
							|  |  |  |             sampleOut->setImag(-s.imag()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // insert sample into ring double buffer
 | 
					
						
							|  |  |  |             m_samplesDB[m_ptr][0] = sampleIn->real(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr][1] = sampleIn->imag(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][0] = sampleIn->real(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][1] = sampleIn->imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance pointer
 | 
					
						
							|  |  |  |             if (m_ptr < (HBFIRFilterTraits<HBFilterOrder>::hbOrder/2) - 1) { | 
					
						
							|  |  |  |                 m_ptr++; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 m_ptr = 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             m_state = 2; // next state
 | 
					
						
							|  |  |  |             return true; // tell caller we consumed the sample
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case 2: | 
					
						
							|  |  |  |             // return the middle peak
 | 
					
						
							|  |  |  |             sampleOut->setReal(-m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][1]);  // - imag
 | 
					
						
							|  |  |  |             sampleOut->setImag(m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][0]); // real
 | 
					
						
							|  |  |  |             m_state = 3;  // next state
 | 
					
						
							|  |  |  |             return false; // tell caller we didn't consume the sample
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             // calculate with non null samples
 | 
					
						
							|  |  |  |             doInterpolateFIR(&s); | 
					
						
							|  |  |  |             sampleOut->setReal(s.real()); | 
					
						
							|  |  |  |             sampleOut->setImag(s.imag()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // insert sample into ring double buffer
 | 
					
						
							|  |  |  |             m_samplesDB[m_ptr][0] = sampleIn->real(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr][1] = sampleIn->imag(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][0] = sampleIn->real(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][1] = sampleIn->imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance pointer
 | 
					
						
							|  |  |  |             if (m_ptr < (HBFIRFilterTraits<HBFilterOrder>::hbOrder/2) - 1) { | 
					
						
							|  |  |  |                 m_ptr++; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 m_ptr = 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             m_state = 0; // next state
 | 
					
						
							|  |  |  |             return true; // tell caller we consumed the sample
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // upsample by 2, from lower half of original spectrum - double buffer variant
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     bool workInterpolateLowerHalfZeroStuffing(FSample* sampleIn, FSample *sampleOut) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |         FSample s; | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         switch(m_state) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         case 0: | 
					
						
							|  |  |  |             // insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |             storeSampleReal((Real) 0, (Real) 0); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // save result
 | 
					
						
							|  |  |  |             doFIR(&s); | 
					
						
							|  |  |  |             sampleOut->setReal(s.imag()); | 
					
						
							|  |  |  |             sampleOut->setImag(-s.real()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance write-pointer
 | 
					
						
							|  |  |  |             advancePointer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // next state
 | 
					
						
							|  |  |  |             m_state = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // tell caller we didn't consume the sample
 | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case 1: | 
					
						
							|  |  |  |             // insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |             storeSampleReal((Real) sampleIn->real(), (Real) sampleIn->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // save result
 | 
					
						
							|  |  |  |             doFIR(&s); | 
					
						
							|  |  |  |             sampleOut->setReal(-s.real()); | 
					
						
							|  |  |  |             sampleOut->setImag(-s.imag()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance write-pointer
 | 
					
						
							|  |  |  |             advancePointer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // next state
 | 
					
						
							|  |  |  |             m_state = 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // tell caller we consumed the sample
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case 2: | 
					
						
							|  |  |  |             // insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |             storeSampleReal((Real) 0, (Real) 0); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // save result
 | 
					
						
							|  |  |  |             doFIR(&s); | 
					
						
							|  |  |  |             sampleOut->setReal(-s.imag()); | 
					
						
							|  |  |  |             sampleOut->setImag(s.real()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance write-pointer
 | 
					
						
							|  |  |  |             advancePointer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // next state
 | 
					
						
							|  |  |  |             m_state = 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // tell caller we didn't consume the sample
 | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             // insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |             storeSampleReal((Real) sampleIn->real(), (Real) sampleIn->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // save result
 | 
					
						
							|  |  |  |             doFIR(&s); | 
					
						
							|  |  |  |             sampleOut->setReal(s.real()); | 
					
						
							|  |  |  |             sampleOut->setImag(s.imag()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance write-pointer
 | 
					
						
							|  |  |  |             advancePointer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // next state
 | 
					
						
							|  |  |  |             m_state = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // tell caller we consumed the sample
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// downsample by 2, return upper half of original spectrum
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  | 	bool workDecimateUpperHalf(FSample* sample) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		switch(m_state) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			case 0: | 
					
						
							|  |  |  | 				// insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  | 	            storeSampleReal((Real) sample->imag(), (Real) -sample->real()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 				// advance write-pointer
 | 
					
						
							|  |  |  |                 advancePointer(); | 
					
						
							|  |  |  | 				// next state
 | 
					
						
							|  |  |  | 				m_state = 1; | 
					
						
							|  |  |  | 				// tell caller we don't have a new sample
 | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case 1: | 
					
						
							|  |  |  | 				// insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |                 storeSampleReal((Real) -sample->real(), (Real) -sample->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 				// save result
 | 
					
						
							|  |  |  | 				doFIR(sample); | 
					
						
							|  |  |  | 				// advance write-pointer
 | 
					
						
							|  |  |  |                 advancePointer(); | 
					
						
							|  |  |  | 				// next state
 | 
					
						
							|  |  |  | 				m_state = 2; | 
					
						
							|  |  |  | 				// tell caller we have a new sample
 | 
					
						
							|  |  |  | 				return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			case 2: | 
					
						
							|  |  |  | 				// insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |                 storeSampleReal((Real) -sample->imag(), (Real) sample->real()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 				// advance write-pointer
 | 
					
						
							|  |  |  |                 advancePointer(); | 
					
						
							|  |  |  | 				// next state
 | 
					
						
							|  |  |  | 				m_state = 3; | 
					
						
							|  |  |  | 				// tell caller we don't have a new sample
 | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				// insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |                 storeSampleReal((Real) sample->real(), (Real) sample->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 				// save result
 | 
					
						
							|  |  |  | 				doFIR(sample); | 
					
						
							|  |  |  | 				// advance write-pointer
 | 
					
						
							|  |  |  |                 advancePointer(); | 
					
						
							|  |  |  | 				// next state
 | 
					
						
							|  |  |  | 				m_state = 0; | 
					
						
							|  |  |  | 				// tell caller we have a new sample
 | 
					
						
							|  |  |  | 				return true; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Optimized upsampler by 2 not calculating FIR with inserted null samples */ | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     bool workInterpolateUpperHalf(FSample* sampleIn, FSample *sampleOut) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |         FSample s; | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         switch(m_state) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         case 0: | 
					
						
							|  |  |  |             // return the middle peak
 | 
					
						
							|  |  |  |             sampleOut->setReal(-m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][1]); // - imag
 | 
					
						
							|  |  |  |             sampleOut->setImag(m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][0]); // + real
 | 
					
						
							|  |  |  |             m_state = 1;  // next state
 | 
					
						
							|  |  |  |             return false; // tell caller we didn't consume the sample
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case 1: | 
					
						
							|  |  |  |             // calculate with non null samples
 | 
					
						
							|  |  |  |             doInterpolateFIR(&s); | 
					
						
							|  |  |  |             sampleOut->setReal(-s.real()); | 
					
						
							|  |  |  |             sampleOut->setImag(-s.imag()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // insert sample into ring double buffer
 | 
					
						
							|  |  |  |             m_samplesDB[m_ptr][0] = sampleIn->real(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr][1] = sampleIn->imag(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][0] = sampleIn->real(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][1] = sampleIn->imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance pointer
 | 
					
						
							|  |  |  |             if (m_ptr < (HBFIRFilterTraits<HBFilterOrder>::hbOrder/2) - 1) { | 
					
						
							|  |  |  |                 m_ptr++; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 m_ptr = 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             m_state = 2; // next state
 | 
					
						
							|  |  |  |             return true; // tell caller we consumed the sample
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case 2: | 
					
						
							|  |  |  |             // return the middle peak
 | 
					
						
							|  |  |  |             sampleOut->setReal(m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][1]);  // + imag
 | 
					
						
							|  |  |  |             sampleOut->setImag(-m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][0]);   // - real
 | 
					
						
							|  |  |  |             m_state = 3;  // next state
 | 
					
						
							|  |  |  |             return false; // tell caller we didn't consume the sample
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             // calculate with non null samples
 | 
					
						
							|  |  |  |             doInterpolateFIR(&s); | 
					
						
							|  |  |  |             sampleOut->setReal(s.real()); | 
					
						
							|  |  |  |             sampleOut->setImag(s.imag()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // insert sample into ring double buffer
 | 
					
						
							|  |  |  |             m_samplesDB[m_ptr][0] = sampleIn->real(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr][1] = sampleIn->imag(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][0] = sampleIn->real(); | 
					
						
							|  |  |  |             m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][1] = sampleIn->imag(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance pointer
 | 
					
						
							|  |  |  |             if (m_ptr < (HBFIRFilterTraits<HBFilterOrder>::hbOrder/2) - 1) { | 
					
						
							|  |  |  |                 m_ptr++; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 m_ptr = 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             m_state = 0; // next state
 | 
					
						
							|  |  |  |             return true; // tell caller we consumed the sample
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // upsample by 2, move original spectrum to upper half - double buffer variant
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     bool workInterpolateUpperHalfZeroStuffing(FSample* sampleIn, FSample *sampleOut) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |         FSample s; | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         switch(m_state) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         case 0: | 
					
						
							|  |  |  |             // insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |             storeSampleReal((Real) 0, (Real) 0); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // save result
 | 
					
						
							|  |  |  |             doFIR(&s); | 
					
						
							|  |  |  |             sampleOut->setReal(-s.imag()); | 
					
						
							|  |  |  |             sampleOut->setImag(s.real()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance write-pointer
 | 
					
						
							|  |  |  |             advancePointer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // next state
 | 
					
						
							|  |  |  |             m_state = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // tell caller we didn't consume the sample
 | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case 1: | 
					
						
							|  |  |  |             // insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |             storeSampleReal((Real) sampleIn->real(), (Real) sampleIn->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // save result
 | 
					
						
							|  |  |  |             doFIR(&s); | 
					
						
							|  |  |  |             sampleOut->setReal(-s.real()); | 
					
						
							|  |  |  |             sampleOut->setImag(-s.imag()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance write-pointer
 | 
					
						
							|  |  |  |             advancePointer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // next state
 | 
					
						
							|  |  |  |             m_state = 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // tell caller we consumed the sample
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case 2: | 
					
						
							|  |  |  |             // insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |             storeSampleReal((Real) 0, (Real) 0); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // save result
 | 
					
						
							|  |  |  |             doFIR(&s); | 
					
						
							|  |  |  |             sampleOut->setReal(s.imag()); | 
					
						
							|  |  |  |             sampleOut->setImag(-s.real()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance write-pointer
 | 
					
						
							|  |  |  |             advancePointer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // next state
 | 
					
						
							|  |  |  |             m_state = 3; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // tell caller we didn't consume the sample
 | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             // insert sample into ring-buffer
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |             storeSampleReal((Real) sampleIn->real(), (Real) sampleIn->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // save result
 | 
					
						
							|  |  |  |             doFIR(&s); | 
					
						
							|  |  |  |             sampleOut->setReal(s.real()); | 
					
						
							|  |  |  |             sampleOut->setImag(s.imag()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // advance write-pointer
 | 
					
						
							|  |  |  |             advancePointer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // next state
 | 
					
						
							|  |  |  |             m_state = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // tell caller we consumed the sample
 | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     void myDecimate(const FSample* sample1, FSample* sample2) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |         storeSampleReal((Real) sample1->real(), (Real) sample1->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |         advancePointer(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |         storeSampleReal((Real) sample2->real(), (Real) sample2->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |         doFIR(sample2); | 
					
						
							|  |  |  |         advancePointer(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void myDecimate(AccuType x1, AccuType y1, AccuType *x2, AccuType *y2) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         storeSampleAccu(x1, y1); | 
					
						
							|  |  |  |         advancePointer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         storeSampleAccu(*x2, *y2); | 
					
						
							|  |  |  |         doFIRAccu(x2, y2); | 
					
						
							|  |  |  |         advancePointer(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Simple zero stuffing and filter */ | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     void myInterpolateZeroStuffing(FSample* sample1, FSample* sample2) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |         storeSampleReal((Real) sample1->real(), (Real) sample1->imag()); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |         doFIR(sample1); | 
					
						
							|  |  |  |         advancePointer(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |         storeSampleReal((Real) 0, (Real) 0); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |         doFIR(sample2); | 
					
						
							|  |  |  |         advancePointer(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Optimized upsampler by 2 not calculating FIR with inserted null samples */ | 
					
						
							|  |  |  |     void myInterpolate(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // insert sample into ring double buffer
 | 
					
						
							|  |  |  |         m_samplesDB[m_ptr][0] = *x1; | 
					
						
							|  |  |  |         m_samplesDB[m_ptr][1] = *y1; | 
					
						
							|  |  |  |         m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][0] = *x1; | 
					
						
							|  |  |  |         m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][1] = *y1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // advance pointer
 | 
					
						
							|  |  |  |         if (m_ptr < (HBFIRFilterTraits<HBFilterOrder>::hbOrder/2) - 1) { | 
					
						
							|  |  |  |             m_ptr++; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             m_ptr = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // first output sample calculated with the middle peak
 | 
					
						
							|  |  |  |         *x1 = m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][0]; | 
					
						
							|  |  |  |         *y1 = m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // second sample calculated with the filter
 | 
					
						
							|  |  |  |         doInterpolateFIR(x2, y2); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-31 23:09:50 +02:00
										 |  |  |     void myInterpolateInf(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2, qint32 *x3, qint32 *y3, qint32 *x4, qint32 *y4) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         myInterpolate(x1, y1, x2, y2); | 
					
						
							|  |  |  |         myInterpolate(x3, y3, x4, y4); | 
					
						
							|  |  |  |         // rotation
 | 
					
						
							|  |  |  |         qint32 x; | 
					
						
							|  |  |  |         x = *x1; | 
					
						
							|  |  |  |         *x1 = *y1; | 
					
						
							|  |  |  |         *y1 = -x; | 
					
						
							|  |  |  |         *x2 = -*x2; | 
					
						
							|  |  |  |         *y2 = -*y2; | 
					
						
							|  |  |  |         x = *x3; | 
					
						
							|  |  |  |         *x3 = -*y3; | 
					
						
							|  |  |  |         *y3 = x; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void myInterpolateSup(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2, qint32 *x3, qint32 *y3, qint32 *x4, qint32 *y4) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         myInterpolate(x1, y1, x2, y2); | 
					
						
							|  |  |  |         myInterpolate(x3, y3, x4, y4); | 
					
						
							|  |  |  |         // rotation
 | 
					
						
							|  |  |  |         qint32 x; | 
					
						
							|  |  |  |         x = *x1; | 
					
						
							|  |  |  |         *x1 = -*y1; | 
					
						
							|  |  |  |         *y1 = x; | 
					
						
							|  |  |  |         *x2 = -*x2; | 
					
						
							|  |  |  |         *y2 = -*y2; | 
					
						
							|  |  |  |         x = *x3; | 
					
						
							|  |  |  |         *x3 = *y3; | 
					
						
							|  |  |  |         *y3 = -x; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | protected: | 
					
						
							|  |  |  |     SampleType m_samplesDB[2*(HBFIRFilterTraits<HBFilterOrder>::hbOrder - 1)][2]; // double buffer technique
 | 
					
						
							|  |  |  | 	int m_ptr; | 
					
						
							|  |  |  | 	int m_size; | 
					
						
							|  |  |  | 	int m_state; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     void storeSampleReal(const Real& sampleI, const Real& sampleQ) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |         m_samplesDB[m_ptr][0] = sampleI; | 
					
						
							|  |  |  |         m_samplesDB[m_ptr][1] = sampleQ; | 
					
						
							|  |  |  |         m_samplesDB[m_ptr + m_size][0] = sampleI; | 
					
						
							|  |  |  |         m_samplesDB[m_ptr + m_size][1] = sampleQ; | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void storeSampleAccu(AccuType x, AccuType y) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_samplesDB[m_ptr][0] = x; | 
					
						
							|  |  |  |         m_samplesDB[m_ptr][1] = y; | 
					
						
							|  |  |  |         m_samplesDB[m_ptr + m_size][0] = x; | 
					
						
							|  |  |  |         m_samplesDB[m_ptr + m_size][1] = y; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void advancePointer() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_ptr = m_ptr + 1 < m_size ? m_ptr + 1: 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     void doFIR(FSample* sample) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         int a = m_ptr + m_size; // tip pointer
 | 
					
						
							|  |  |  |         int b = m_ptr + 1; // tail pointer
 | 
					
						
							|  |  |  |         AccuType iAcc = 0; | 
					
						
							|  |  |  |         AccuType qAcc = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             iAcc += (m_samplesDB[a][0] + m_samplesDB[b][0]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffsF[i]; | 
					
						
							|  |  |  |             qAcc += (m_samplesDB[a][1] + m_samplesDB[b][1]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffsF[i]; | 
					
						
							|  |  |  |             a -= 2; | 
					
						
							|  |  |  |             b += 2; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         iAcc += m_samplesDB[b-1][0] << (HBFIRFilterTraits<HBFilterOrder>::hbShift - 1); | 
					
						
							|  |  |  |         qAcc += m_samplesDB[b-1][1] << (HBFIRFilterTraits<HBFilterOrder>::hbShift - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |         sample->setReal(iAcc); | 
					
						
							|  |  |  |         sample->setImag(qAcc); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void doFIRAccu(AccuType *x, AccuType *y) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         int a = m_ptr + m_size; // tip pointer
 | 
					
						
							|  |  |  |         int b = m_ptr + 1; // tail pointer
 | 
					
						
							|  |  |  |         AccuType iAcc = 0; | 
					
						
							|  |  |  |         AccuType qAcc = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             iAcc += (m_samplesDB[a][0] + m_samplesDB[b][0]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffsF[i]; | 
					
						
							|  |  |  |             qAcc += (m_samplesDB[a][1] + m_samplesDB[b][1]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffsF[i]; | 
					
						
							|  |  |  |             a -= 2; | 
					
						
							|  |  |  |             b += 2; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         iAcc += m_samplesDB[b-1][0] / 2.0; | 
					
						
							|  |  |  |         qAcc += m_samplesDB[b-1][1] / 2.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *x = iAcc; // HB_SHIFT incorrect do not loose the gained bit
 | 
					
						
							|  |  |  |         *y = qAcc; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     void doInterpolateFIR(FSample* sample) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         qint16 a = m_ptr; | 
					
						
							|  |  |  |         qint16 b = m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder / 2) - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // go through samples in buffer
 | 
					
						
							|  |  |  |         AccuType iAcc = 0; | 
					
						
							|  |  |  |         AccuType qAcc = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             iAcc += (m_samplesDB[a][0] + m_samplesDB[b][0]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffsF[i]; | 
					
						
							|  |  |  |             qAcc += (m_samplesDB[a][1] + m_samplesDB[b][1]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffsF[i]; | 
					
						
							|  |  |  |             a++; | 
					
						
							|  |  |  |             b--; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |         sample->setReal(iAcc); | 
					
						
							|  |  |  |         sample->setImag(qAcc); | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |     void doInterpolateFIR(Real *x, Real *y) | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         qint16 a = m_ptr; | 
					
						
							|  |  |  |         qint16 b = m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder / 2) - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // go through samples in buffer
 | 
					
						
							|  |  |  |         AccuType iAcc = 0; | 
					
						
							|  |  |  |         AccuType qAcc = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             iAcc += (m_samplesDB[a][0] + m_samplesDB[b][0]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffsF[i]; | 
					
						
							|  |  |  |             qAcc += (m_samplesDB[a][1] + m_samplesDB[b][1]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffsF[i]; | 
					
						
							|  |  |  |             a++; | 
					
						
							|  |  |  |             b--; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  |         *x = iAcc; | 
					
						
							|  |  |  |         *y = qAcc; | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename AccuType, typename SampleType, uint32_t HBFilterOrder> | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  | IntHalfbandFilterDBFF<AccuType, SampleType, HBFilterOrder>::IntHalfbandFilterDBFF() | 
					
						
							| 
									
										
										
										
											2018-02-02 02:12:49 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     m_size = HBFIRFilterTraits<HBFilterOrder>::hbOrder - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int i = 0; i < m_size; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_samplesDB[i][0] = 0; | 
					
						
							|  |  |  |         m_samplesDB[i][1] = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_ptr = 0; | 
					
						
							|  |  |  |     m_state = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 18:01:01 +02:00
										 |  |  | #endif // INCLUDE_INTHALFBANDFILTER_DBFF_H
 |