diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt index 1ae66fa84..e42a8097b 100644 --- a/sdrbase/CMakeLists.txt +++ b/sdrbase/CMakeLists.txt @@ -127,8 +127,7 @@ set(sdrbase_HEADERS dsp/hbfiltertraits.h dsp/inthalfbandfilter.h dsp/inthalfbandfilterdb.h - dsp/inthalfbandfilterdbff.h - dsp/inthalfbandfilterdbfi.h + dsp/inthalfbandfilterdbf.h dsp/inthalfbandfiltereo1.h dsp/inthalfbandfiltereo1i.h dsp/inthalfbandfilterst.h diff --git a/sdrbase/dsp/decimatorsff.h b/sdrbase/dsp/decimatorsff.h index 649a0fc6c..92e9a9e96 100644 --- a/sdrbase/dsp/decimatorsff.h +++ b/sdrbase/dsp/decimatorsff.h @@ -17,7 +17,7 @@ #ifndef SDRBASE_DSP_DECIMATORSFF_H_ #define SDRBASE_DSP_DECIMATORSFF_H_ -#include "dsp/inthalfbandfilterdbff.h" +#include "dsp/inthalfbandfilterdbf.h" #include "export.h" #define DECIMATORSFF_HB_FILTER_ORDER 64 @@ -46,12 +46,12 @@ public: void decimate64_sup(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ); void decimate64_cen(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ); - IntHalfbandFilterDBFF m_decimator2; // 1st stages - IntHalfbandFilterDBFF m_decimator4; // 2nd stages - IntHalfbandFilterDBFF m_decimator8; // 3rd stages - IntHalfbandFilterDBFF m_decimator16; // 4th stages - IntHalfbandFilterDBFF m_decimator32; // 5th stages - IntHalfbandFilterDBFF m_decimator64; // 6th stages + IntHalfbandFilterDBF m_decimator2; // 1st stages + IntHalfbandFilterDBF m_decimator4; // 2nd stages + IntHalfbandFilterDBF m_decimator8; // 3rd stages + IntHalfbandFilterDBF m_decimator16; // 4th stages + IntHalfbandFilterDBF m_decimator32; // 5th stages + IntHalfbandFilterDBF m_decimator64; // 6th stages }; diff --git a/sdrbase/dsp/decimatorsfi.cpp b/sdrbase/dsp/decimatorsfi.cpp index aeda9ad03..95f2e47c3 100644 --- a/sdrbase/dsp/decimatorsfi.cpp +++ b/sdrbase/dsp/decimatorsfi.cpp @@ -14,7 +14,7 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -#include +#include "decimatorsfi.h" void DecimatorsFI::decimate1(SampleVector::iterator* it, const float* buf, qint32 nbIAndQ) { diff --git a/sdrbase/dsp/decimatorsfi.h b/sdrbase/dsp/decimatorsfi.h index 283cb6e0a..45f6ae2fe 100644 --- a/sdrbase/dsp/decimatorsfi.h +++ b/sdrbase/dsp/decimatorsfi.h @@ -17,7 +17,7 @@ #ifndef SDRBASE_DSP_DECIMATORSFI_H_ #define SDRBASE_DSP_DECIMATORSFI_H_ -#include "dsp/inthalfbandfilterdbfi.h" +#include "dsp/inthalfbandfilterdbf.h" #include "export.h" #define DECIMATORSFI_HB_FILTER_ORDER 64 @@ -46,12 +46,12 @@ public: void decimate64_sup(SampleVector::iterator* it, const float* buf, qint32 nbIAndQ); void decimate64_cen(SampleVector::iterator* it, const float* buf, qint32 nbIAndQ); - IntHalfbandFilterDBFI m_decimator2; // 1st stages - IntHalfbandFilterDBFI m_decimator4; // 2nd stages - IntHalfbandFilterDBFI m_decimator8; // 3rd stages - IntHalfbandFilterDBFI m_decimator16; // 4th stages - IntHalfbandFilterDBFI m_decimator32; // 5th stages - IntHalfbandFilterDBFI m_decimator64; // 6th stages + IntHalfbandFilterDBF m_decimator2; // 1st stages + IntHalfbandFilterDBF m_decimator4; // 2nd stages + IntHalfbandFilterDBF m_decimator8; // 3rd stages + IntHalfbandFilterDBF m_decimator16; // 4th stages + IntHalfbandFilterDBF m_decimator32; // 5th stages + IntHalfbandFilterDBF m_decimator64; // 6th stages }; diff --git a/sdrbase/dsp/inthalfbandfilterdbf.h b/sdrbase/dsp/inthalfbandfilterdbf.h new file mode 100644 index 000000000..938bf57d3 --- /dev/null +++ b/sdrbase/dsp/inthalfbandfilterdbf.h @@ -0,0 +1,146 @@ +/////////////////////////////////////////////////////////////////////////////////// +// 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 // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef INCLUDE_INTHALFBANDFILTER_DBF_H +#define INCLUDE_INTHALFBANDFILTER_DBF_H + +#include +#include "dsp/dsptypes.h" +#include "dsp/hbfiltertraits.h" +#include "export.h" + +template +class SDRBASE_API IntHalfbandFilterDBF { +public: + IntHalfbandFilterDBF(); + + void myDecimate(AccuType x1, AccuType y1, AccuType *x2, AccuType *y2) + { + storeSample(x1, y1); + advancePointer(); + + storeSample(*x2, *y2); + doFIR(x2, y2); + 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::hbOrder/2][0] = *x1; + m_samplesDB[m_ptr + HBFIRFilterTraits::hbOrder/2][1] = *y1; + + // advance pointer + if (m_ptr < (HBFIRFilterTraits::hbOrder/2) - 1) { + m_ptr++; + } else { + m_ptr = 0; + } + + // first output sample calculated with the middle peak + *x1 = m_samplesDB[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][0]; + *y1 = m_samplesDB[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][1]; + + // second sample calculated with the filter + doInterpolateFIR(x2, y2); + } + +protected: + SampleType m_samplesDB[2*(HBFIRFilterTraits::hbOrder - 1)][2]; // double buffer technique + int m_ptr; + int m_size; + int m_state; + + void storeSample(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; + } + + void doFIR(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::hbOrder / 4; i++) + { + iAcc += (m_samplesDB[a][0] + m_samplesDB[b][0]) * HBFIRFilterTraits::hbCoeffsF[i]; + qAcc += (m_samplesDB[a][1] + m_samplesDB[b][1]) * HBFIRFilterTraits::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; + } + + void doInterpolateFIR(qint32 *x, qint32 *y) + { + qint16 a = m_ptr; + qint16 b = m_ptr + (HBFIRFilterTraits::hbOrder / 2) - 1; + + // go through samples in buffer + AccuType iAcc = 0; + AccuType qAcc = 0; + + for (int i = 0; i < HBFIRFilterTraits::hbOrder / 4; i++) + { + iAcc += (m_samplesDB[a][0] + m_samplesDB[b][0]) * HBFIRFilterTraits::hbCoeffsF[i]; + qAcc += (m_samplesDB[a][1] + m_samplesDB[b][1]) * HBFIRFilterTraits::hbCoeffsF[i]; + a++; + b--; + } + + *x = iAcc * SDR_RX_SCALED; + *y = qAcc * SDR_RX_SCALED; + } +}; + +template +IntHalfbandFilterDBF::IntHalfbandFilterDBF() +{ + m_size = HBFIRFilterTraits::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; +} + +#endif // INCLUDE_INTHALFBANDFILTER_DBF_H