diff --git a/CMakeLists.txt b/CMakeLists.txt
index b39c72ef7..047c3caa1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -315,6 +315,7 @@ target_link_libraries(sdrangelbench
${QT_LIBRARIES}
)
+target_compile_features(sdrangelbench PRIVATE cxx_generalized_initializers) # cmake >= 3.1.0
qt5_use_modules(sdrangelbench Multimedia)
##############################################################################
diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt
index c69bced99..1ae66fa84 100644
--- a/sdrbase/CMakeLists.txt
+++ b/sdrbase/CMakeLists.txt
@@ -21,6 +21,7 @@ set(sdrbase_SOURCES
dsp/ctcssdetector.cpp
dsp/cwkeyer.cpp
dsp/cwkeyersettings.cpp
+ dsp/decimatorsff.cpp
dsp/decimatorsfi.cpp
dsp/dspcommands.cpp
dsp/dspengine.cpp
@@ -104,6 +105,7 @@ set(sdrbase_HEADERS
dsp/cwkeyer.h
dsp/cwkeyersettings.h
dsp/decimators.h
+ dsp/decimatorsff.h
dsp/decimatorsfi.h
dsp/decimatorsu.h
dsp/interpolators.h
@@ -125,7 +127,8 @@ set(sdrbase_HEADERS
dsp/hbfiltertraits.h
dsp/inthalfbandfilter.h
dsp/inthalfbandfilterdb.h
- dsp/inthalfbandfilterdbf.h
+ dsp/inthalfbandfilterdbff.h
+ dsp/inthalfbandfilterdbfi.h
dsp/inthalfbandfiltereo1.h
dsp/inthalfbandfiltereo1i.h
dsp/inthalfbandfilterst.h
diff --git a/sdrbase/dsp/decimatorsff.cpp b/sdrbase/dsp/decimatorsff.cpp
new file mode 100644
index 000000000..0134865e8
--- /dev/null
+++ b/sdrbase/dsp/decimatorsff.cpp
@@ -0,0 +1,1173 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2018 Edouard Griffiths, F4EXB //
+// //
+// 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 . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#include "decimatorsff.h"
+
+void DecimatorsFF::decimate1(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ float xreal, yimag;
+
+ for (int pos = 0; pos < nbIAndQ - 1; pos += 2)
+ {
+ xreal = buf[pos+0];
+ yimag = buf[pos+1];
+ (**it).setReal(xreal);
+ (**it).setImag(yimag);
+ ++(*it); // Valgrind optim (comment not repeated)
+ }
+}
+
+void DecimatorsFF::decimate2_cen(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double intbuf[2];
+
+ for (int pos = 0; pos < nbIAndQ - 3; pos += 4)
+ {
+ intbuf[0] = buf[pos+2];
+ intbuf[1] = buf[pos+3];
+
+ m_decimator2.myDecimate(
+ buf[pos+0],
+ buf[pos+1],
+ &intbuf[0],
+ &intbuf[1]);
+
+ (**it).setReal(intbuf[0]);
+ (**it).setImag(intbuf[1]);
+
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate2_inf(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double xreal, yimag;
+
+ for (int pos = 0; pos < nbIAndQ - 7; pos += 8)
+ {
+ xreal = (buf[pos+0] - buf[pos+3]);
+ yimag = (buf[pos+1] + buf[pos+2]);
+ (**it).setReal(xreal);
+ (**it).setImag(yimag);
+ ++(*it);
+
+ xreal = (buf[pos+7] - buf[pos+4]);
+ yimag = (- buf[pos+5] - buf[pos+6]);
+ (**it).setReal(xreal);
+ (**it).setImag(yimag);
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate2_sup(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double xreal, yimag;
+
+ for (int pos = 0; pos < nbIAndQ - 7; pos += 8)
+ {
+ xreal = (buf[pos+1] - buf[pos+2]);
+ yimag = (- buf[pos+0] - buf[pos+3]);
+ (**it).setReal(xreal);
+ (**it).setImag(yimag);
+ ++(*it);
+
+ xreal = (buf[pos+6] - buf[pos+5]);
+ yimag = (buf[pos+4] + buf[pos+7]);
+ (**it).setReal(xreal);
+ (**it).setImag(yimag);
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate4_inf(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double xreal, yimag;
+
+ for (int pos = 0; pos < nbIAndQ - 7; pos += 8)
+ {
+ xreal = (buf[pos+0] - buf[pos+3] + buf[pos+7] - buf[pos+4]);
+ yimag = (buf[pos+1] - buf[pos+5] + buf[pos+2] - buf[pos+6]);
+
+ (**it).setReal(xreal);
+ (**it).setImag(yimag);
+
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate4_sup(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ // Sup (USB):
+ // x y x y x y x y / x -> 1,-2,-5,6 / y -> -0,-3,4,7
+ // [ rotate: 1, 0, -2, 3, -5, -4, 6, -7]
+ // Inf (LSB):
+ // x y x y x y x y / x -> 0,-3,-4,7 / y -> 1,2,-5,-6
+ // [ rotate: 0, 1, -3, 2, -4, -5, 7, -6]
+ double xreal, yimag;
+
+ for (int pos = 0; pos < nbIAndQ - 7; pos += 8)
+ {
+ xreal = (buf[pos+1] - buf[pos+2] - buf[pos+5] + buf[pos+6]);
+ yimag = (- buf[pos+0] - buf[pos+3] + buf[pos+4] + buf[pos+7]);
+
+ (**it).setReal(xreal);
+ (**it).setImag(yimag);
+
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate8_inf(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double xreal[2], yimag[2];
+
+ for (int pos = 0; pos < nbIAndQ - 15; pos += 8)
+ {
+ xreal[0] = (buf[pos+0] - buf[pos+3] + buf[pos+7] - buf[pos+4]);
+ yimag[0] = (buf[pos+1] - buf[pos+5] + buf[pos+2] - buf[pos+6]);
+ pos += 8;
+
+ xreal[1] = (buf[pos+0] - buf[pos+3] + buf[pos+7] - buf[pos+4]);
+ yimag[1] = (buf[pos+1] - buf[pos+5] + buf[pos+2] - buf[pos+6]);
+
+ m_decimator2.myDecimate(xreal[0], yimag[0], &xreal[1], &yimag[1]);
+
+ (**it).setReal(xreal[1]);
+ (**it).setImag(yimag[1]);
+
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate8_sup(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double xreal[2], yimag[2];
+
+ for (int pos = 0; pos < nbIAndQ - 15; pos += 8)
+ {
+ xreal[0] = (buf[pos+1] - buf[pos+2] - buf[pos+5] + buf[pos+6]);
+ yimag[0] = (- buf[pos+0] - buf[pos+3] + buf[pos+4] + buf[pos+7]);
+ pos += 8;
+
+ xreal[1] = (buf[pos+1] - buf[pos+2] - buf[pos+5] + buf[pos+6]);
+ yimag[1] = (- buf[pos+0] - buf[pos+3] + buf[pos+4] + buf[pos+7]);
+
+ m_decimator2.myDecimate(xreal[0], yimag[0], &xreal[1], &yimag[1]);
+
+ (**it).setReal(xreal[1]);
+ (**it).setImag(yimag[1]);
+
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate16_inf(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ // Offset tuning: 4x downsample and rotate, then
+ // downsample 4x more. [ rotate: 0, 1, -3, 2, -4, -5, 7, -6]
+ double xreal[4], yimag[4];
+
+ for (int pos = 0; pos < nbIAndQ - 31; )
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ xreal[i] = (buf[pos+0] - buf[pos+3] + buf[pos+7] - buf[pos+4]);
+ yimag[i] = (buf[pos+1] - buf[pos+5] + buf[pos+2] - buf[pos+6]);
+ pos += 8;
+ }
+
+ 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]);
+ (**it).setImag(yimag[3]);
+
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate16_sup(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ // Offset tuning: 4x downsample and rotate, then
+ // downsample 4x more. [ rotate: 1, 0, -2, 3, -5, -4, 6, -7]
+ double xreal[4], yimag[4];
+
+ for (int pos = 0; pos < nbIAndQ - 31; )
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ xreal[i] = (buf[pos+1] - buf[pos+2] - buf[pos+5] + buf[pos+6]);
+ yimag[i] = (buf[pos+4] + buf[pos+7] - buf[pos+0] - buf[pos+3]);
+ pos += 8;
+ }
+
+ 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]);
+ (**it).setImag(yimag[3]);
+
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate32_inf(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double xreal[8], yimag[8];
+
+ for (int pos = 0; pos < nbIAndQ - 63; )
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ xreal[i] = (buf[pos+0] - buf[pos+3] + buf[pos+7] - buf[pos+4]);
+ yimag[i] = (buf[pos+1] - buf[pos+5] + buf[pos+2] - buf[pos+6]);
+ pos += 8;
+ }
+
+ m_decimator2.myDecimate(xreal[0], yimag[0], &xreal[1], &yimag[1]);
+ m_decimator2.myDecimate(xreal[2], yimag[2], &xreal[3], &yimag[3]);
+ m_decimator2.myDecimate(xreal[4], yimag[4], &xreal[5], &yimag[5]);
+ m_decimator2.myDecimate(xreal[6], yimag[6], &xreal[7], &yimag[7]);
+
+ m_decimator4.myDecimate(xreal[1], yimag[1], &xreal[3], &yimag[3]);
+ m_decimator4.myDecimate(xreal[5], yimag[5], &xreal[7], &yimag[7]);
+
+ m_decimator8.myDecimate(xreal[3], yimag[3], &xreal[7], &yimag[7]);
+
+ (**it).setReal(xreal[7]);
+ (**it).setImag(yimag[7]);
+
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate32_sup(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double xreal[8], yimag[8];
+
+ for (int pos = 0; pos < nbIAndQ - 63; )
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ xreal[i] = (buf[pos+1] - buf[pos+2] - buf[pos+5] + buf[pos+6]);
+ yimag[i] = (buf[pos+4] + buf[pos+7] - buf[pos+0] - buf[pos+3]);
+ pos += 8;
+ }
+
+ m_decimator2.myDecimate(xreal[0], yimag[0], &xreal[1], &yimag[1]);
+ m_decimator2.myDecimate(xreal[2], yimag[2], &xreal[3], &yimag[3]);
+ m_decimator2.myDecimate(xreal[4], yimag[4], &xreal[5], &yimag[5]);
+ m_decimator2.myDecimate(xreal[6], yimag[6], &xreal[7], &yimag[7]);
+
+ m_decimator4.myDecimate(xreal[1], yimag[1], &xreal[3], &yimag[3]);
+ m_decimator4.myDecimate(xreal[5], yimag[5], &xreal[7], &yimag[7]);
+
+ m_decimator8.myDecimate(xreal[3], yimag[3], &xreal[7], &yimag[7]);
+
+ (**it).setReal(xreal[7]);
+ (**it).setImag(yimag[7]);
+
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate64_inf(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double xreal[16], yimag[16];
+
+ for (int pos = 0; pos < nbIAndQ - 127; )
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ xreal[i] = (buf[pos+0] - buf[pos+3] + buf[pos+7] - buf[pos+4]);
+ yimag[i] = (buf[pos+1] - buf[pos+5] + buf[pos+2] - buf[pos+6]);
+ pos += 8;
+ }
+
+ m_decimator2.myDecimate(xreal[0], yimag[0], &xreal[1], &yimag[1]);
+ m_decimator2.myDecimate(xreal[2], yimag[2], &xreal[3], &yimag[3]);
+ m_decimator2.myDecimate(xreal[4], yimag[4], &xreal[5], &yimag[5]);
+ m_decimator2.myDecimate(xreal[6], yimag[6], &xreal[7], &yimag[7]);
+ m_decimator2.myDecimate(xreal[8], yimag[8], &xreal[9], &yimag[9]);
+ m_decimator2.myDecimate(xreal[10], yimag[10], &xreal[11], &yimag[11]);
+ m_decimator2.myDecimate(xreal[12], yimag[12], &xreal[13], &yimag[13]);
+ m_decimator2.myDecimate(xreal[14], yimag[14], &xreal[15], &yimag[15]);
+
+ m_decimator4.myDecimate(xreal[1], yimag[1], &xreal[3], &yimag[3]);
+ m_decimator4.myDecimate(xreal[5], yimag[5], &xreal[7], &yimag[7]);
+ m_decimator4.myDecimate(xreal[9], yimag[9], &xreal[11], &yimag[11]);
+ m_decimator4.myDecimate(xreal[13], yimag[13], &xreal[15], &yimag[15]);
+
+ m_decimator8.myDecimate(xreal[3], yimag[3], &xreal[7], &yimag[7]);
+ m_decimator8.myDecimate(xreal[11], yimag[11], &xreal[15], &yimag[15]);
+
+ m_decimator16.myDecimate(xreal[7], yimag[7], &xreal[15], &yimag[15]);
+
+ (**it).setReal(xreal[15]);
+ (**it).setImag(yimag[15]);
+
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate64_sup(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double xreal[16], yimag[16];
+
+ for (int pos = 0; pos < nbIAndQ - 127; )
+ {
+ for (int i = 0; i < 16; i++)
+ {
+ xreal[i] = (buf[pos+1] - buf[pos+2] - buf[pos+5] + buf[pos+6]);
+ yimag[i] = (buf[pos+4] + buf[pos+7] - buf[pos+0] - buf[pos+3]);
+ pos += 8;
+ }
+
+ m_decimator2.myDecimate(xreal[0], yimag[0], &xreal[1], &yimag[1]);
+ m_decimator2.myDecimate(xreal[2], yimag[2], &xreal[3], &yimag[3]);
+ m_decimator2.myDecimate(xreal[4], yimag[4], &xreal[5], &yimag[5]);
+ m_decimator2.myDecimate(xreal[6], yimag[6], &xreal[7], &yimag[7]);
+ m_decimator2.myDecimate(xreal[8], yimag[8], &xreal[9], &yimag[9]);
+ m_decimator2.myDecimate(xreal[10], yimag[10], &xreal[11], &yimag[11]);
+ m_decimator2.myDecimate(xreal[12], yimag[12], &xreal[13], &yimag[13]);
+ m_decimator2.myDecimate(xreal[14], yimag[14], &xreal[15], &yimag[15]);
+
+ m_decimator4.myDecimate(xreal[1], yimag[1], &xreal[3], &yimag[3]);
+ m_decimator4.myDecimate(xreal[5], yimag[5], &xreal[7], &yimag[7]);
+ m_decimator4.myDecimate(xreal[9], yimag[9], &xreal[11], &yimag[11]);
+ m_decimator4.myDecimate(xreal[13], yimag[13], &xreal[15], &yimag[15]);
+
+ m_decimator8.myDecimate(xreal[3], yimag[3], &xreal[7], &yimag[7]);
+ m_decimator8.myDecimate(xreal[11], yimag[11], &xreal[15], &yimag[15]);
+
+ m_decimator16.myDecimate(xreal[7], yimag[7], &xreal[15], &yimag[15]);
+
+ (**it).setReal(xreal[15]);
+ (**it).setImag(yimag[15]);
+
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate4_cen(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double intbuf[4];
+
+ for (int pos = 0; pos < nbIAndQ - 7; pos += 8)
+ {
+ intbuf[0] = buf[pos+2];
+ intbuf[1] = buf[pos+3];
+ intbuf[2] = buf[pos+6];
+ intbuf[3] = buf[pos+7];
+
+ m_decimator2.myDecimate(
+ buf[pos+0],
+ buf[pos+1],
+ &intbuf[0],
+ &intbuf[1]);
+ m_decimator2.myDecimate(
+ buf[pos+4],
+ buf[pos+5],
+ &intbuf[2],
+ &intbuf[3]);
+
+ m_decimator4.myDecimate(
+ intbuf[0],
+ intbuf[1],
+ &intbuf[2],
+ &intbuf[3]);
+
+ (**it).setReal(intbuf[2]);
+ (**it).setImag(intbuf[3]);
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate8_cen(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double intbuf[8];
+
+ for (int pos = 0; pos < nbIAndQ - 15; pos += 16)
+ {
+ intbuf[0] = buf[pos+2];
+ intbuf[1] = buf[pos+3];
+ intbuf[2] = buf[pos+6];
+ intbuf[3] = buf[pos+7];
+ intbuf[4] = buf[pos+10];
+ intbuf[5] = buf[pos+11];
+ intbuf[6] = buf[pos+14];
+ intbuf[7] = buf[pos+15];
+
+ m_decimator2.myDecimate(
+ buf[pos+0],
+ buf[pos+1],
+ &intbuf[0],
+ &intbuf[1]);
+ m_decimator2.myDecimate(
+ buf[pos+4],
+ buf[pos+5],
+ &intbuf[2],
+ &intbuf[3]);
+ m_decimator2.myDecimate(
+ buf[pos+8],
+ buf[pos+9],
+ &intbuf[4],
+ &intbuf[5]);
+ m_decimator2.myDecimate(
+ buf[pos+12],
+ buf[pos+13],
+ &intbuf[6],
+ &intbuf[7]);
+
+ m_decimator4.myDecimate(
+ intbuf[0],
+ intbuf[1],
+ &intbuf[2],
+ &intbuf[3]);
+ m_decimator4.myDecimate(
+ intbuf[4],
+ intbuf[5],
+ &intbuf[6],
+ &intbuf[7]);
+
+ m_decimator8.myDecimate(
+ intbuf[2],
+ intbuf[3],
+ &intbuf[6],
+ &intbuf[7]);
+
+ (**it).setReal(intbuf[6]);
+ (**it).setImag(intbuf[7]);
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate16_cen(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double intbuf[16];
+
+ for (int pos = 0; pos < nbIAndQ - 31; pos += 32)
+ {
+ intbuf[0] = buf[pos+2];
+ intbuf[1] = buf[pos+3];
+ intbuf[2] = buf[pos+6];
+ intbuf[3] = buf[pos+7];
+ intbuf[4] = buf[pos+10];
+ intbuf[5] = buf[pos+11];
+ intbuf[6] = buf[pos+14];
+ intbuf[7] = buf[pos+15];
+ intbuf[8] = buf[pos+18];
+ intbuf[9] = buf[pos+19];
+ intbuf[10] = buf[pos+22];
+ intbuf[11] = buf[pos+23];
+ intbuf[12] = buf[pos+26];
+ intbuf[13] = buf[pos+27];
+ intbuf[14] = buf[pos+30];
+ intbuf[15] = buf[pos+31];
+
+ m_decimator2.myDecimate(
+ buf[pos+0],
+ buf[pos+1],
+ &intbuf[0],
+ &intbuf[1]);
+ m_decimator2.myDecimate(
+ buf[pos+4],
+ buf[pos+5],
+ &intbuf[2],
+ &intbuf[3]);
+ m_decimator2.myDecimate(
+ buf[pos+8],
+ buf[pos+9],
+ &intbuf[4],
+ &intbuf[5]);
+ m_decimator2.myDecimate(
+ buf[pos+12],
+ buf[pos+13],
+ &intbuf[6],
+ &intbuf[7]);
+ m_decimator2.myDecimate(
+ buf[pos+16],
+ buf[pos+17],
+ &intbuf[8],
+ &intbuf[9]);
+ m_decimator2.myDecimate(
+ buf[pos+20],
+ buf[pos+21],
+ &intbuf[10],
+ &intbuf[11]);
+ m_decimator2.myDecimate(
+ buf[pos+24],
+ buf[pos+25],
+ &intbuf[12],
+ &intbuf[13]);
+ m_decimator2.myDecimate(
+ buf[pos+28],
+ buf[pos+29],
+ &intbuf[14],
+ &intbuf[15]);
+
+ m_decimator4.myDecimate(
+ intbuf[0],
+ intbuf[1],
+ &intbuf[2],
+ &intbuf[3]);
+ m_decimator4.myDecimate(
+ intbuf[4],
+ intbuf[5],
+ &intbuf[6],
+ &intbuf[7]);
+ m_decimator4.myDecimate(
+ intbuf[8],
+ intbuf[9],
+ &intbuf[10],
+ &intbuf[11]);
+ m_decimator4.myDecimate(
+ intbuf[12],
+ intbuf[13],
+ &intbuf[14],
+ &intbuf[15]);
+
+ m_decimator8.myDecimate(
+ intbuf[2],
+ intbuf[3],
+ &intbuf[6],
+ &intbuf[7]);
+ m_decimator8.myDecimate(
+ intbuf[10],
+ intbuf[11],
+ &intbuf[14],
+ &intbuf[15]);
+
+ m_decimator16.myDecimate(
+ intbuf[6],
+ intbuf[7],
+ &intbuf[14],
+ &intbuf[15]);
+
+ (**it).setReal(intbuf[14]);
+ (**it).setImag(intbuf[15]);
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate32_cen(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double intbuf[32];
+
+ for (int pos = 0; pos < nbIAndQ - 63; pos += 64)
+ {
+ intbuf[0] = buf[pos+2];
+ intbuf[1] = buf[pos+3];
+ intbuf[2] = buf[pos+6];
+ intbuf[3] = buf[pos+7];
+ intbuf[4] = buf[pos+10];
+ intbuf[5] = buf[pos+11];
+ intbuf[6] = buf[pos+14];
+ intbuf[7] = buf[pos+15];
+ intbuf[8] = buf[pos+18];
+ intbuf[9] = buf[pos+19];
+ intbuf[10] = buf[pos+22];
+ intbuf[11] = buf[pos+23];
+ intbuf[12] = buf[pos+26];
+ intbuf[13] = buf[pos+27];
+ intbuf[14] = buf[pos+30];
+ intbuf[15] = buf[pos+31];
+ intbuf[16] = buf[pos+34];
+ intbuf[17] = buf[pos+35];
+ intbuf[18] = buf[pos+38];
+ intbuf[19] = buf[pos+39];
+ intbuf[20] = buf[pos+42];
+ intbuf[21] = buf[pos+43];
+ intbuf[22] = buf[pos+46];
+ intbuf[23] = buf[pos+47];
+ intbuf[24] = buf[pos+50];
+ intbuf[25] = buf[pos+51];
+ intbuf[26] = buf[pos+54];
+ intbuf[27] = buf[pos+55];
+ intbuf[28] = buf[pos+58];
+ intbuf[29] = buf[pos+59];
+ intbuf[30] = buf[pos+62];
+ intbuf[31] = buf[pos+63];
+
+ m_decimator2.myDecimate(
+ buf[pos+0],
+ buf[pos+1],
+ &intbuf[0],
+ &intbuf[1]);
+ m_decimator2.myDecimate(
+ buf[pos+4],
+ buf[pos+5],
+ &intbuf[2],
+ &intbuf[3]);
+ m_decimator2.myDecimate(
+ buf[pos+8],
+ buf[pos+9],
+ &intbuf[4],
+ &intbuf[5]);
+ m_decimator2.myDecimate(
+ buf[pos+12],
+ buf[pos+13],
+ &intbuf[6],
+ &intbuf[7]);
+ m_decimator2.myDecimate(
+ buf[pos+16],
+ buf[pos+17],
+ &intbuf[8],
+ &intbuf[9]);
+ m_decimator2.myDecimate(
+ buf[pos+20],
+ buf[pos+21],
+ &intbuf[10],
+ &intbuf[11]);
+ m_decimator2.myDecimate(
+ buf[pos+24],
+ buf[pos+25],
+ &intbuf[12],
+ &intbuf[13]);
+ m_decimator2.myDecimate(
+ buf[pos+28],
+ buf[pos+29],
+ &intbuf[14],
+ &intbuf[15]);
+ m_decimator2.myDecimate(
+ buf[pos+32],
+ buf[pos+33],
+ &intbuf[16],
+ &intbuf[17]);
+ m_decimator2.myDecimate(
+ buf[pos+36],
+ buf[pos+37],
+ &intbuf[18],
+ &intbuf[19]);
+ m_decimator2.myDecimate(
+ buf[pos+40],
+ buf[pos+41],
+ &intbuf[20],
+ &intbuf[21]);
+ m_decimator2.myDecimate(
+ buf[pos+44],
+ buf[pos+45],
+ &intbuf[22],
+ &intbuf[23]);
+ m_decimator2.myDecimate(
+ buf[pos+48],
+ buf[pos+49],
+ &intbuf[24],
+ &intbuf[25]);
+ m_decimator2.myDecimate(
+ buf[pos+52],
+ buf[pos+53],
+ &intbuf[26],
+ &intbuf[27]);
+ m_decimator2.myDecimate(
+ buf[pos+56],
+ buf[pos+57],
+ &intbuf[28],
+ &intbuf[29]);
+ m_decimator2.myDecimate(
+ buf[pos+60],
+ buf[pos+61],
+ &intbuf[30],
+ &intbuf[31]);
+
+ m_decimator4.myDecimate(
+ intbuf[0],
+ intbuf[1],
+ &intbuf[2],
+ &intbuf[3]);
+ m_decimator4.myDecimate(
+ intbuf[4],
+ intbuf[5],
+ &intbuf[6],
+ &intbuf[7]);
+ m_decimator4.myDecimate(
+ intbuf[8],
+ intbuf[9],
+ &intbuf[10],
+ &intbuf[11]);
+ m_decimator4.myDecimate(
+ intbuf[12],
+ intbuf[13],
+ &intbuf[14],
+ &intbuf[15]);
+ m_decimator4.myDecimate(
+ intbuf[16],
+ intbuf[17],
+ &intbuf[18],
+ &intbuf[19]);
+ m_decimator4.myDecimate(
+ intbuf[20],
+ intbuf[21],
+ &intbuf[22],
+ &intbuf[23]);
+ m_decimator4.myDecimate(
+ intbuf[24],
+ intbuf[25],
+ &intbuf[26],
+ &intbuf[27]);
+ m_decimator4.myDecimate(
+ intbuf[28],
+ intbuf[29],
+ &intbuf[30],
+ &intbuf[31]);
+
+ m_decimator8.myDecimate(
+ intbuf[2],
+ intbuf[3],
+ &intbuf[6],
+ &intbuf[7]);
+ m_decimator8.myDecimate(
+ intbuf[10],
+ intbuf[11],
+ &intbuf[14],
+ &intbuf[15]);
+ m_decimator8.myDecimate(
+ intbuf[18],
+ intbuf[19],
+ &intbuf[22],
+ &intbuf[23]);
+ m_decimator8.myDecimate(
+ intbuf[26],
+ intbuf[27],
+ &intbuf[30],
+ &intbuf[31]);
+
+ m_decimator16.myDecimate(
+ intbuf[6],
+ intbuf[7],
+ &intbuf[14],
+ &intbuf[15]);
+ m_decimator16.myDecimate(
+ intbuf[22],
+ intbuf[23],
+ &intbuf[30],
+ &intbuf[31]);
+
+ m_decimator32.myDecimate(
+ intbuf[14],
+ intbuf[15],
+ &intbuf[30],
+ &intbuf[31]);
+
+ (**it).setReal(intbuf[30]);
+ (**it).setImag(intbuf[31]);
+ ++(*it);
+ }
+}
+
+void DecimatorsFF::decimate64_cen(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ)
+{
+ double intbuf[64];
+
+ for (int pos = 0; pos < nbIAndQ - 127; pos += 128)
+ {
+ intbuf[0] = buf[pos+2];
+ intbuf[1] = buf[pos+3];
+ intbuf[2] = buf[pos+6];
+ intbuf[3] = buf[pos+7];
+ intbuf[4] = buf[pos+10];
+ intbuf[5] = buf[pos+11];
+ intbuf[6] = buf[pos+14];
+ intbuf[7] = buf[pos+15];
+ intbuf[8] = buf[pos+18];
+ intbuf[9] = buf[pos+19];
+ intbuf[10] = buf[pos+22];
+ intbuf[11] = buf[pos+23];
+ intbuf[12] = buf[pos+26];
+ intbuf[13] = buf[pos+27];
+ intbuf[14] = buf[pos+30];
+ intbuf[15] = buf[pos+31];
+ intbuf[16] = buf[pos+34];
+ intbuf[17] = buf[pos+35];
+ intbuf[18] = buf[pos+38];
+ intbuf[19] = buf[pos+39];
+ intbuf[20] = buf[pos+42];
+ intbuf[21] = buf[pos+43];
+ intbuf[22] = buf[pos+46];
+ intbuf[23] = buf[pos+47];
+ intbuf[24] = buf[pos+50];
+ intbuf[25] = buf[pos+51];
+ intbuf[26] = buf[pos+54];
+ intbuf[27] = buf[pos+55];
+ intbuf[28] = buf[pos+58];
+ intbuf[29] = buf[pos+59];
+ intbuf[30] = buf[pos+62];
+ intbuf[31] = buf[pos+63];
+
+ intbuf[32] = buf[pos+66];
+ intbuf[33] = buf[pos+67];
+ intbuf[34] = buf[pos+70];
+ intbuf[35] = buf[pos+71];
+ intbuf[36] = buf[pos+74];
+ intbuf[37] = buf[pos+75];
+ intbuf[38] = buf[pos+78];
+ intbuf[39] = buf[pos+79];
+ intbuf[40] = buf[pos+82];
+ intbuf[41] = buf[pos+83];
+ intbuf[42] = buf[pos+86];
+ intbuf[43] = buf[pos+87];
+ intbuf[44] = buf[pos+90];
+ intbuf[45] = buf[pos+91];
+ intbuf[46] = buf[pos+94];
+ intbuf[47] = buf[pos+95];
+ intbuf[48] = buf[pos+98];
+ intbuf[49] = buf[pos+99];
+ intbuf[50] = buf[pos+102];
+ intbuf[51] = buf[pos+103];
+ intbuf[52] = buf[pos+106];
+ intbuf[53] = buf[pos+107];
+ intbuf[54] = buf[pos+110];
+ intbuf[55] = buf[pos+111];
+ intbuf[56] = buf[pos+114];
+ intbuf[57] = buf[pos+115];
+ intbuf[58] = buf[pos+118];
+ intbuf[59] = buf[pos+119];
+ intbuf[60] = buf[pos+122];
+ intbuf[61] = buf[pos+123];
+ intbuf[62] = buf[pos+126];
+ intbuf[63] = buf[pos+127];
+
+ m_decimator2.myDecimate(
+ buf[pos+0],
+ buf[pos+1],
+ &intbuf[0],
+ &intbuf[1]);
+ m_decimator2.myDecimate(
+ buf[pos+4],
+ buf[pos+5],
+ &intbuf[2],
+ &intbuf[3]);
+ m_decimator2.myDecimate(
+ buf[pos+8],
+ buf[pos+9],
+ &intbuf[4],
+ &intbuf[5]);
+ m_decimator2.myDecimate(
+ buf[pos+12],
+ buf[pos+13],
+ &intbuf[6],
+ &intbuf[7]);
+ m_decimator2.myDecimate(
+ buf[pos+16],
+ buf[pos+17],
+ &intbuf[8],
+ &intbuf[9]);
+ m_decimator2.myDecimate(
+ buf[pos+20],
+ buf[pos+21],
+ &intbuf[10],
+ &intbuf[11]);
+ m_decimator2.myDecimate(
+ buf[pos+24],
+ buf[pos+25],
+ &intbuf[12],
+ &intbuf[13]);
+ m_decimator2.myDecimate(
+ buf[pos+28],
+ buf[pos+29],
+ &intbuf[14],
+ &intbuf[15]);
+ m_decimator2.myDecimate(
+ buf[pos+32],
+ buf[pos+33],
+ &intbuf[16],
+ &intbuf[17]);
+ m_decimator2.myDecimate(
+ buf[pos+36],
+ buf[pos+37],
+ &intbuf[18],
+ &intbuf[19]);
+ m_decimator2.myDecimate(
+ buf[pos+40],
+ buf[pos+41],
+ &intbuf[20],
+ &intbuf[21]);
+ m_decimator2.myDecimate(
+ buf[pos+44],
+ buf[pos+45],
+ &intbuf[22],
+ &intbuf[23]);
+ m_decimator2.myDecimate(
+ buf[pos+48],
+ buf[pos+49],
+ &intbuf[24],
+ &intbuf[25]);
+ m_decimator2.myDecimate(
+ buf[pos+52],
+ buf[pos+53],
+ &intbuf[26],
+ &intbuf[27]);
+ m_decimator2.myDecimate(
+ buf[pos+56],
+ buf[pos+57],
+ &intbuf[28],
+ &intbuf[29]);
+ m_decimator2.myDecimate(
+ buf[pos+60],
+ buf[pos+61],
+ &intbuf[30],
+ &intbuf[31]);
+ m_decimator2.myDecimate(
+ buf[pos+64],
+ buf[pos+65],
+ &intbuf[32],
+ &intbuf[33]);
+ m_decimator2.myDecimate(
+ buf[pos+68],
+ buf[pos+69],
+ &intbuf[34],
+ &intbuf[35]);
+ m_decimator2.myDecimate(
+ buf[pos+72],
+ buf[pos+73],
+ &intbuf[36],
+ &intbuf[37]);
+ m_decimator2.myDecimate(
+ buf[pos+76],
+ buf[pos+77],
+ &intbuf[38],
+ &intbuf[39]);
+ m_decimator2.myDecimate(
+ buf[pos+80],
+ buf[pos+81],
+ &intbuf[40],
+ &intbuf[41]);
+ m_decimator2.myDecimate(
+ buf[pos+84],
+ buf[pos+85],
+ &intbuf[42],
+ &intbuf[43]);
+ m_decimator2.myDecimate(
+ buf[pos+88],
+ buf[pos+89],
+ &intbuf[44],
+ &intbuf[45]);
+ m_decimator2.myDecimate(
+ buf[pos+92],
+ buf[pos+93],
+ &intbuf[46],
+ &intbuf[47]);
+ m_decimator2.myDecimate(
+ buf[pos+96],
+ buf[pos+97],
+ &intbuf[48],
+ &intbuf[49]);
+ m_decimator2.myDecimate(
+ buf[pos+100],
+ buf[pos+101],
+ &intbuf[50],
+ &intbuf[51]);
+ m_decimator2.myDecimate(
+ buf[pos+104],
+ buf[pos+105],
+ &intbuf[52],
+ &intbuf[53]);
+ m_decimator2.myDecimate(
+ buf[pos+108],
+ buf[pos+109],
+ &intbuf[54],
+ &intbuf[55]);
+ m_decimator2.myDecimate(
+ buf[pos+112],
+ buf[pos+113],
+ &intbuf[56],
+ &intbuf[57]);
+ m_decimator2.myDecimate(
+ buf[pos+116],
+ buf[pos+117],
+ &intbuf[58],
+ &intbuf[59]);
+ m_decimator2.myDecimate(
+ buf[pos+120],
+ buf[pos+121],
+ &intbuf[60],
+ &intbuf[61]);
+ m_decimator2.myDecimate(
+ buf[pos+124],
+ buf[pos+125],
+ &intbuf[62],
+ &intbuf[63]);
+
+ m_decimator4.myDecimate(
+ intbuf[0],
+ intbuf[1],
+ &intbuf[2],
+ &intbuf[3]);
+ m_decimator4.myDecimate(
+ intbuf[4],
+ intbuf[5],
+ &intbuf[6],
+ &intbuf[7]);
+ m_decimator4.myDecimate(
+ intbuf[8],
+ intbuf[9],
+ &intbuf[10],
+ &intbuf[11]);
+ m_decimator4.myDecimate(
+ intbuf[12],
+ intbuf[13],
+ &intbuf[14],
+ &intbuf[15]);
+ m_decimator4.myDecimate(
+ intbuf[16],
+ intbuf[17],
+ &intbuf[18],
+ &intbuf[19]);
+ m_decimator4.myDecimate(
+ intbuf[20],
+ intbuf[21],
+ &intbuf[22],
+ &intbuf[23]);
+ m_decimator4.myDecimate(
+ intbuf[24],
+ intbuf[25],
+ &intbuf[26],
+ &intbuf[27]);
+ m_decimator4.myDecimate(
+ intbuf[28],
+ intbuf[29],
+ &intbuf[30],
+ &intbuf[31]);
+ m_decimator4.myDecimate(
+ intbuf[32],
+ intbuf[33],
+ &intbuf[34],
+ &intbuf[35]);
+ m_decimator4.myDecimate(
+ intbuf[36],
+ intbuf[37],
+ &intbuf[38],
+ &intbuf[39]);
+ m_decimator4.myDecimate(
+ intbuf[40],
+ intbuf[41],
+ &intbuf[42],
+ &intbuf[43]);
+ m_decimator4.myDecimate(
+ intbuf[44],
+ intbuf[45],
+ &intbuf[46],
+ &intbuf[47]);
+ m_decimator4.myDecimate(
+ intbuf[48],
+ intbuf[49],
+ &intbuf[50],
+ &intbuf[51]);
+ m_decimator4.myDecimate(
+ intbuf[52],
+ intbuf[53],
+ &intbuf[54],
+ &intbuf[55]);
+ m_decimator4.myDecimate(
+ intbuf[56],
+ intbuf[57],
+ &intbuf[58],
+ &intbuf[59]);
+ m_decimator4.myDecimate(
+ intbuf[60],
+ intbuf[61],
+ &intbuf[62],
+ &intbuf[63]);
+
+ m_decimator8.myDecimate(
+ intbuf[2],
+ intbuf[3],
+ &intbuf[6],
+ &intbuf[7]);
+ m_decimator8.myDecimate(
+ intbuf[10],
+ intbuf[11],
+ &intbuf[14],
+ &intbuf[15]);
+ m_decimator8.myDecimate(
+ intbuf[18],
+ intbuf[19],
+ &intbuf[22],
+ &intbuf[23]);
+ m_decimator8.myDecimate(
+ intbuf[26],
+ intbuf[27],
+ &intbuf[30],
+ &intbuf[31]);
+ m_decimator8.myDecimate(
+ intbuf[34],
+ intbuf[35],
+ &intbuf[38],
+ &intbuf[39]);
+ m_decimator8.myDecimate(
+ intbuf[42],
+ intbuf[43],
+ &intbuf[46],
+ &intbuf[47]);
+ m_decimator8.myDecimate(
+ intbuf[50],
+ intbuf[51],
+ &intbuf[54],
+ &intbuf[55]);
+ m_decimator8.myDecimate(
+ intbuf[58],
+ intbuf[59],
+ &intbuf[62],
+ &intbuf[63]);
+
+ m_decimator16.myDecimate(
+ intbuf[6],
+ intbuf[7],
+ &intbuf[14],
+ &intbuf[15]);
+ m_decimator16.myDecimate(
+ intbuf[22],
+ intbuf[23],
+ &intbuf[30],
+ &intbuf[31]);
+ m_decimator16.myDecimate(
+ intbuf[38],
+ intbuf[39],
+ &intbuf[46],
+ &intbuf[47]);
+ m_decimator16.myDecimate(
+ intbuf[54],
+ intbuf[55],
+ &intbuf[62],
+ &intbuf[63]);
+
+ m_decimator32.myDecimate(
+ intbuf[14],
+ intbuf[15],
+ &intbuf[30],
+ &intbuf[31]);
+ m_decimator32.myDecimate(
+ intbuf[46],
+ intbuf[47],
+ &intbuf[62],
+ &intbuf[63]);
+
+ m_decimator64.myDecimate(
+ intbuf[30],
+ intbuf[31],
+ &intbuf[62],
+ &intbuf[63]);
+
+ (**it).setReal(intbuf[62]);
+ (**it).setImag(intbuf[63]);
+ ++(*it);
+ }
+}
+
diff --git a/sdrbase/dsp/decimatorsff.h b/sdrbase/dsp/decimatorsff.h
new file mode 100644
index 000000000..649a0fc6c
--- /dev/null
+++ b/sdrbase/dsp/decimatorsff.h
@@ -0,0 +1,59 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2018 Edouard Griffiths, F4EXB //
+// //
+// 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 SDRBASE_DSP_DECIMATORSFF_H_
+#define SDRBASE_DSP_DECIMATORSFF_H_
+
+#include "dsp/inthalfbandfilterdbff.h"
+#include "export.h"
+
+#define DECIMATORSFF_HB_FILTER_ORDER 64
+
+/** Decimators with float input and float output */
+class SDRBASE_API DecimatorsFF
+{
+public:
+ void decimate1(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate2_inf(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate2_sup(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate2_cen(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate4_inf(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate4_sup(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate4_cen(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate8_inf(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate8_sup(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate8_cen(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate16_inf(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate16_sup(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate16_cen(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate32_inf(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate32_sup(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate32_cen(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ void decimate64_inf(FSampleVector::iterator* it, const float* buf, qint32 nbIAndQ);
+ 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
+};
+
+
+
+#endif /* SDRBASE_DSP_DECIMATORSFF_H_ */
diff --git a/sdrbase/dsp/decimatorsfi.h b/sdrbase/dsp/decimatorsfi.h
index 31f8fe50e..283cb6e0a 100644
--- a/sdrbase/dsp/decimatorsfi.h
+++ b/sdrbase/dsp/decimatorsfi.h
@@ -17,10 +17,10 @@
#ifndef SDRBASE_DSP_DECIMATORSFI_H_
#define SDRBASE_DSP_DECIMATORSFI_H_
-#include "dsp/inthalfbandfilterdbf.h"
+#include "dsp/inthalfbandfilterdbfi.h"
#include "export.h"
-#define DECIMATORSF_HB_FILTER_ORDER 64
+#define DECIMATORSFI_HB_FILTER_ORDER 64
/** Decimators with float input and integer output */
class SDRBASE_API DecimatorsFI
@@ -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);
- 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
+ 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
};
diff --git a/sdrbase/dsp/dsptypes.h b/sdrbase/dsp/dsptypes.h
index e3913a785..f39f9deb7 100644
--- a/sdrbase/dsp/dsptypes.h
+++ b/sdrbase/dsp/dsptypes.h
@@ -64,6 +64,28 @@ struct Sample
FixReal m_imag;
};
+struct FSample
+{
+ FSample() : m_real(0), m_imag(0) {}
+ FSample(Real real) : m_real(real), m_imag(0) {}
+ FSample(Real real, Real imag) : m_real(real), m_imag(imag) {}
+ FSample(const FSample& other) : m_real(other.m_real), m_imag(other.m_imag) {}
+ inline FSample& operator=(const FSample& other) { m_real = other.m_real; m_imag = other.m_imag; return *this; }
+
+ inline FSample& operator+=(const FSample& other) { m_real += other.m_real; m_imag += other.m_imag; return *this; }
+ inline FSample& operator-=(const FSample& other) { m_real -= other.m_real; m_imag -= other.m_imag; return *this; }
+ inline FSample& operator/=(const Real& divisor) { m_real /= divisor; m_imag /= divisor; return *this; }
+
+ inline void setReal(Real v) { m_real = v; }
+ inline void setImag(Real v) { m_imag = v; }
+
+ inline Real real() const { return m_real; }
+ inline Real imag() const { return m_imag; }
+
+ Real m_real;
+ Real m_imag;
+};
+
struct AudioSample {
qint16 l;
qint16 r;
@@ -71,6 +93,7 @@ struct AudioSample {
#pragma pack(pop)
typedef std::vector SampleVector;
+typedef std::vector FSampleVector;
typedef std::vector AudioVector;
#endif // INCLUDE_DSPTYPES_H
diff --git a/sdrbase/dsp/inthalfbandfilterdbff.h b/sdrbase/dsp/inthalfbandfilterdbff.h
new file mode 100644
index 000000000..2816f2696
--- /dev/null
+++ b/sdrbase/dsp/inthalfbandfilterdbff.h
@@ -0,0 +1,711 @@
+///////////////////////////////////////////////////////////////////////////////////
+// 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_DBFF_H
+#define INCLUDE_INTHALFBANDFILTER_DBFF_H
+
+#include
+#include "dsp/dsptypes.h"
+#include "dsp/hbfiltertraits.h"
+#include "export.h"
+
+template
+class SDRBASE_API IntHalfbandFilterDBFF {
+public:
+ IntHalfbandFilterDBFF();
+
+ // downsample by 2, return center part of original spectrum
+ bool workDecimateCenter(FSample* sample)
+ {
+ // insert sample into ring-buffer
+ storeSampleReal((Real) sample->real(), (Real) sample->imag());
+
+ 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
+ bool workInterpolateCenterZeroStuffing(FSample* sampleIn, FSample *SampleOut)
+ {
+ switch(m_state)
+ {
+ case 0:
+ // insert sample into ring-buffer
+ storeSampleReal((Real) 0, (Real) 0);
+ // 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
+ storeSampleReal((Real) sampleIn->real(), (Real) sampleIn->imag());
+ // 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 */
+ bool workInterpolateCenter(FSample* sampleIn, FSample *SampleOut)
+ {
+ switch(m_state)
+ {
+ case 0:
+ // return the middle peak
+ SampleOut->setReal(m_samplesDB[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][0]);
+ SampleOut->setImag(m_samplesDB[m_ptr + (HBFIRFilterTraits::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::hbOrder/2][0] = sampleIn->real();
+ m_samplesDB[m_ptr + HBFIRFilterTraits::hbOrder/2][1] = sampleIn->imag();
+
+ // advance pointer
+ if (m_ptr < (HBFIRFilterTraits::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
+ bool workDecimateLowerHalf(FSample* sample)
+ {
+ switch(m_state)
+ {
+ case 0:
+ // insert sample into ring-buffer
+ storeSampleReal((Real) -sample->imag(), (Real) sample->real());
+ // 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
+ storeSampleReal((Real) -sample->real(), (Real) -sample->imag());
+ // 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
+ storeSampleReal((Real) sample->imag(), (Real) -sample->real());
+ // 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
+ storeSampleReal((Real) sample->real(), (Real) sample->imag());
+ // 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 */
+ bool workInterpolateLowerHalf(FSample* sampleIn, FSample *sampleOut)
+ {
+ FSample s;
+
+ switch(m_state)
+ {
+ case 0:
+ // return the middle peak
+ sampleOut->setReal(m_samplesDB[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][1]); // imag
+ sampleOut->setImag(-m_samplesDB[m_ptr + (HBFIRFilterTraits::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::hbOrder/2][0] = sampleIn->real();
+ m_samplesDB[m_ptr + HBFIRFilterTraits::hbOrder/2][1] = sampleIn->imag();
+
+ // advance pointer
+ if (m_ptr < (HBFIRFilterTraits::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::hbOrder/4) - 1][1]); // - imag
+ sampleOut->setImag(m_samplesDB[m_ptr + (HBFIRFilterTraits::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::hbOrder/2][0] = sampleIn->real();
+ m_samplesDB[m_ptr + HBFIRFilterTraits::hbOrder/2][1] = sampleIn->imag();
+
+ // advance pointer
+ if (m_ptr < (HBFIRFilterTraits::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
+ bool workInterpolateLowerHalfZeroStuffing(FSample* sampleIn, FSample *sampleOut)
+ {
+ FSample s;
+
+ switch(m_state)
+ {
+ case 0:
+ // insert sample into ring-buffer
+ storeSampleReal((Real) 0, (Real) 0);
+
+ // 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
+ storeSampleReal((Real) sampleIn->real(), (Real) sampleIn->imag());
+
+ // 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
+ storeSampleReal((Real) 0, (Real) 0);
+
+ // 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
+ storeSampleReal((Real) sampleIn->real(), (Real) sampleIn->imag());
+
+ // 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
+ bool workDecimateUpperHalf(FSample* sample)
+ {
+ switch(m_state)
+ {
+ case 0:
+ // insert sample into ring-buffer
+ storeSampleReal((Real) sample->imag(), (Real) -sample->real());
+ // 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
+ storeSampleReal((Real) -sample->real(), (Real) -sample->imag());
+ // 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
+ storeSampleReal((Real) -sample->imag(), (Real) sample->real());
+ // 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
+ storeSampleReal((Real) sample->real(), (Real) sample->imag());
+ // 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 */
+ bool workInterpolateUpperHalf(FSample* sampleIn, FSample *sampleOut)
+ {
+ FSample s;
+
+ switch(m_state)
+ {
+ case 0:
+ // return the middle peak
+ sampleOut->setReal(-m_samplesDB[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][1]); // - imag
+ sampleOut->setImag(m_samplesDB[m_ptr + (HBFIRFilterTraits::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::hbOrder/2][0] = sampleIn->real();
+ m_samplesDB[m_ptr + HBFIRFilterTraits::hbOrder/2][1] = sampleIn->imag();
+
+ // advance pointer
+ if (m_ptr < (HBFIRFilterTraits::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::hbOrder/4) - 1][1]); // + imag
+ sampleOut->setImag(-m_samplesDB[m_ptr + (HBFIRFilterTraits::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::hbOrder/2][0] = sampleIn->real();
+ m_samplesDB[m_ptr + HBFIRFilterTraits::hbOrder/2][1] = sampleIn->imag();
+
+ // advance pointer
+ if (m_ptr < (HBFIRFilterTraits::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
+ bool workInterpolateUpperHalfZeroStuffing(FSample* sampleIn, FSample *sampleOut)
+ {
+ FSample s;
+
+ switch(m_state)
+ {
+ case 0:
+ // insert sample into ring-buffer
+ storeSampleReal((Real) 0, (Real) 0);
+
+ // 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
+ storeSampleReal((Real) sampleIn->real(), (Real) sampleIn->imag());
+
+ // 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
+ storeSampleReal((Real) 0, (Real) 0);
+
+ // 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
+ storeSampleReal((Real) sampleIn->real(), (Real) sampleIn->imag());
+
+ // 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;
+ }
+ }
+
+ void myDecimate(const FSample* sample1, FSample* sample2)
+ {
+ storeSampleReal((Real) sample1->real(), (Real) sample1->imag());
+ advancePointer();
+
+ storeSampleReal((Real) sample2->real(), (Real) sample2->imag());
+ 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 */
+ void myInterpolateZeroStuffing(FSample* sample1, FSample* sample2)
+ {
+ storeSampleReal((Real) sample1->real(), (Real) sample1->imag());
+ doFIR(sample1);
+ advancePointer();
+
+ storeSampleReal((Real) 0, (Real) 0);
+ 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::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 storeSampleReal(const Real& sampleI, const Real& sampleQ)
+ {
+ 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;
+ }
+
+ 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;
+ }
+
+ void doFIR(FSample* sample)
+ {
+ 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] << (HBFIRFilterTraits::hbShift - 1);
+ qAcc += m_samplesDB[b-1][1] << (HBFIRFilterTraits::hbShift - 1);
+
+ sample->setReal(iAcc);
+ sample->setImag(qAcc);
+ }
+
+ 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::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(FSample* sample)
+ {
+ 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--;
+ }
+
+ sample->setReal(iAcc);
+ sample->setImag(qAcc);
+ }
+
+ void doInterpolateFIR(Real *x, Real *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;
+ *y = qAcc;
+ }
+};
+
+template
+IntHalfbandFilterDBFF::IntHalfbandFilterDBFF()
+{
+ 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_DBFF_H
diff --git a/sdrbase/dsp/inthalfbandfilterdbf.h b/sdrbase/dsp/inthalfbandfilterdbfi.h
similarity index 98%
rename from sdrbase/dsp/inthalfbandfilterdbf.h
rename to sdrbase/dsp/inthalfbandfilterdbfi.h
index 5dc7bad7a..f83c4fd33 100644
--- a/sdrbase/dsp/inthalfbandfilterdbf.h
+++ b/sdrbase/dsp/inthalfbandfilterdbfi.h
@@ -18,8 +18,8 @@
// along with this program. If not, see . //
///////////////////////////////////////////////////////////////////////////////////
-#ifndef INCLUDE_INTHALFBANDFILTER_DBF_H
-#define INCLUDE_INTHALFBANDFILTER_DBF_H
+#ifndef INCLUDE_INTHALFBANDFILTER_DBFI_H
+#define INCLUDE_INTHALFBANDFILTER_DBFI_H
#include
#include "dsp/dsptypes.h"
@@ -27,9 +27,9 @@
#include "export.h"
template
-class SDRBASE_API IntHalfbandFilterDBF {
+class SDRBASE_API IntHalfbandFilterDBFI {
public:
- IntHalfbandFilterDBF();
+ IntHalfbandFilterDBFI();
// downsample by 2, return center part of original spectrum
bool workDecimateCenter(Sample* sample)
@@ -694,7 +694,7 @@ protected:
};
template
-IntHalfbandFilterDBF::IntHalfbandFilterDBF()
+IntHalfbandFilterDBFI::IntHalfbandFilterDBFI()
{
m_size = HBFIRFilterTraits::hbOrder - 1;
diff --git a/sdrbench/mainbench.cpp b/sdrbench/mainbench.cpp
index ea3ef4b7e..5477d1246 100644
--- a/sdrbench/mainbench.cpp
+++ b/sdrbench/mainbench.cpp
@@ -26,7 +26,8 @@ MainBench *MainBench::m_instance = 0;
MainBench::MainBench(qtwebapp::LoggerWithFile *logger, const ParserBench& parser, QObject *parent) :
QObject(parent),
m_logger(logger),
- m_parser(parser)
+ m_parser(parser),
+ m_uniform_distribution(-1.0, 1.0)
{
qDebug() << "MainBench::MainBench: start";
m_instance = this;
@@ -49,6 +50,10 @@ void MainBench::run()
testDecimateII();
} else if (m_parser.getTestType() == ParserBench::TestDecimatorsFI) {
testDecimateFI();
+ } else if (m_parser.getTestType() == ParserBench::TestDecimatorsFF) {
+ testDecimateFF();
+ } else {
+ qDebug() << "MainBench::run: unknown test type: " << m_parser.getTestType();
}
emit finished();
@@ -73,13 +78,9 @@ void MainBench::testDecimateII()
}
nsecs = timer.nsecsElapsed();
- QDebug debug = qDebug();
- debug.noquote();
- debug << tr("MainBench::testDecimateII: ran test in %L1 ns").arg(nsecs);
-
+ printResults("MainBench::testDecimateII", nsecs);
qDebug() << "MainBench::testDecimateII: cleanup test data";
-
delete[] buf;
}
@@ -92,6 +93,8 @@ void MainBench::testDecimateFI()
float *buf = new float[m_parser.getNbSamples()*2];
m_convertBuffer.resize(m_parser.getNbSamples()/(1<
+#include
+#include
#include "dsp/decimators.h"
#include "dsp/decimatorsfi.h"
+#include "dsp/decimatorsff.h"
#include "parserbench.h"
namespace qtwebapp {
@@ -45,12 +48,17 @@ signals:
private:
void testDecimateII();
void testDecimateFI();
+ void testDecimateFF();
void decimateII(const qint16 *buf, int len);
void decimateFI(const float *buf, int len);
+ void decimateFF(const float *buf, int len);
+ void printResults(const QString& prefix, qint64 nsecs);
static MainBench *m_instance;
qtwebapp::LoggerWithFile *m_logger;
const ParserBench& m_parser;
+ std::mt19937 m_generator;
+ std::uniform_real_distribution m_uniform_distribution;
#ifdef SDR_RX_SAMPLE_24BIT
Decimators m_decimatorsII;
@@ -58,8 +66,10 @@ private:
Decimators m_decimatorsII;
#endif
DecimatorsFI m_decimatorsFI;
+ DecimatorsFF m_decimatorsFF;
SampleVector m_convertBuffer;
+ FSampleVector m_convertBufferF;
};
#endif // SDRBENCH_MAINBENCH_H_
diff --git a/sdrbench/parserbench.cpp b/sdrbench/parserbench.cpp
index b1d7f741f..cd0a2fe0d 100644
--- a/sdrbench/parserbench.cpp
+++ b/sdrbench/parserbench.cpp
@@ -116,6 +116,8 @@ ParserBench::TestType ParserBench::getTestType() const
{
if (m_testStr == "decimatefi") {
return TestDecimatorsFI;
+ } else if (m_testStr == "decimateff") {
+ return TestDecimatorsFF;
} else {
return TestDecimatorsII;
}
diff --git a/sdrbench/parserbench.h b/sdrbench/parserbench.h
index 2b67f23e1..10a930a3a 100644
--- a/sdrbench/parserbench.h
+++ b/sdrbench/parserbench.h
@@ -27,7 +27,8 @@ public:
typedef enum
{
TestDecimatorsII,
- TestDecimatorsFI
+ TestDecimatorsFI,
+ TestDecimatorsFF
} TestType;
ParserBench();