diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2acfbbd9b..36d90c533 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -212,6 +212,7 @@ set(sdrbase_HEADERS
sdrbase/dsp/interpolator.h
sdrbase/dsp/hbfiltertraits.h
sdrbase/dsp/inthalfbandfilter.h
+ sdrbase/dsp/inthalfbandfilterdb.h
sdrbase/dsp/kissfft.h
sdrbase/dsp/kissengine.h
sdrbase/dsp/lowpass.h
diff --git a/sdrbase/dsp/inthalfbandfilter.h b/sdrbase/dsp/inthalfbandfilter.h
index 3a45ba65f..b362bd6a9 100644
--- a/sdrbase/dsp/inthalfbandfilter.h
+++ b/sdrbase/dsp/inthalfbandfilter.h
@@ -1,3 +1,20 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2016 F4EXB //
+// written by Edouard Griffiths //
+// //
+// 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_H
#define INCLUDE_INTHALFBANDFILTER_H
@@ -86,51 +103,6 @@ public:
}
}
- // upsample by 2, return center part of original spectrum - double buffer variant
- bool workInterpolateCenterDB(Sample* sampleIn, Sample *SampleOut)
- {
- switch(m_state)
- {
- case 0:
- // insert sample into ring-buffer
- m_samplesDB[m_ptrDB][0] = 0;
- m_samplesDB[m_ptrDB][1] = 0;
- m_samplesDB[m_ptrDB + m_sizeDB][0] = 0;
- m_samplesDB[m_ptrDB + m_sizeDB][1] = 0;
-
- // save result
- doFIRDB(SampleOut);
-
- // advance write-pointer
- m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
-
- // next state
- m_state = 1;
-
- // tell caller we didn't consume the sample
- return false;
-
- default:
- // insert sample into ring-buffer
- m_samplesDB[m_ptrDB][0] = sampleIn->real();
- m_samplesDB[m_ptrDB][1] = sampleIn->imag();
- m_samplesDB[m_ptrDB + m_sizeDB][0] = sampleIn->real();
- m_samplesDB[m_ptrDB + m_sizeDB][1] = sampleIn->imag();
-
- // save result
- doFIRDB(SampleOut);
-
- // advance write-pointer
- m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
-
- // next state
- m_state = 0;
-
- // tell caller we consumed the sample
- return true;
- }
- }
-
bool workDecimateCenter(qint32 *x, qint32 *y)
{
// insert sample into ring-buffer
@@ -356,99 +328,6 @@ public:
}
}
- // upsample by 2, from lower half of original spectrum - double buffer variant
- bool workInterpolateLowerHalfDB(Sample* sampleIn, Sample *sampleOut)
- {
- Sample s;
-
- switch(m_state)
- {
- case 0:
- // insert sample into ring-buffer
- m_samplesDB[m_ptrDB][0] = 0;
- m_samplesDB[m_ptrDB][1] = 0;
- m_samplesDB[m_ptrDB + m_sizeDB][0] = 0;
- m_samplesDB[m_ptrDB + m_sizeDB][1] = 0;
-
- // save result
- doFIRDB(&s);
- sampleOut->setReal(s.imag());
- sampleOut->setImag(-s.real());
-
- // advance write-pointer
- m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
-
- // next state
- m_state = 1;
-
- // tell caller we didn't consume the sample
- return false;
-
- case 1:
- // insert sample into ring-buffer
- m_samplesDB[m_ptrDB][0] = sampleIn->real();
- m_samplesDB[m_ptrDB][1] = sampleIn->imag();
- m_samplesDB[m_ptrDB + m_sizeDB][0] = sampleIn->real();
- m_samplesDB[m_ptrDB + m_sizeDB][1] = sampleIn->imag();
-
- // save result
- doFIRDB(&s);
- sampleOut->setReal(-s.real());
- sampleOut->setImag(-s.imag());
-
- // advance write-pointer
- m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
-
- // next state
- m_state = 2;
-
- // tell caller we consumed the sample
- return true;
-
- case 2:
- // insert sample into ring-buffer
- m_samplesDB[m_ptrDB][0] = 0;
- m_samplesDB[m_ptrDB][1] = 0;
- m_samplesDB[m_ptrDB + m_sizeDB][0] = 0;
- m_samplesDB[m_ptrDB + m_sizeDB][1] = 0;
-
- // save result
- doFIRDB(&s);
- sampleOut->setReal(-s.imag());
- sampleOut->setImag(s.real());
-
- // advance write-pointer
- m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
-
- // next state
- m_state = 3;
-
- // tell caller we didn't consume the sample
- return false;
-
- default:
- // insert sample into ring-buffer
- m_samplesDB[m_ptrDB][0] = sampleIn->real();
- m_samplesDB[m_ptrDB][1] = sampleIn->imag();
- m_samplesDB[m_ptrDB + m_sizeDB][0] = sampleIn->real();
- m_samplesDB[m_ptrDB + m_sizeDB][1] = sampleIn->imag();
-
- // save result
- doFIRDB(&s);
- sampleOut->setReal(s.real());
- sampleOut->setImag(s.imag());
-
- // advance write-pointer
- m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
-
- // next state
- m_state = 0;
-
- // tell caller we consumed the sample
- return true;
- }
- }
-
// downsample by 2, return upper half of original spectrum
bool workDecimateUpperHalf(Sample* sample)
{
@@ -603,99 +482,6 @@ public:
}
}
- // upsample by 2, move original spectrum to upper half - double buffer variant
- bool workInterpolateUpperHalfDB(Sample* sampleIn, Sample *sampleOut)
- {
- Sample s;
-
- switch(m_state)
- {
- case 0:
- // insert sample into ring-buffer
- m_samplesDB[m_ptrDB][0] = 0;
- m_samplesDB[m_ptrDB][1] = 0;
- m_samplesDB[m_ptrDB + m_sizeDB][0] = 0;
- m_samplesDB[m_ptrDB + m_sizeDB][1] = 0;
-
- // save result
- doFIRDB(&s);
- sampleOut->setReal(-s.imag());
- sampleOut->setImag(s.real());
-
- // advance write-pointer
- m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
-
- // next state
- m_state = 1;
-
- // tell caller we didn't consume the sample
- return false;
-
- case 1:
- // insert sample into ring-buffer
- m_samplesDB[m_ptrDB][0] = sampleIn->real();
- m_samplesDB[m_ptrDB][1] = sampleIn->imag();
- m_samplesDB[m_ptrDB + m_sizeDB][0] = sampleIn->real();
- m_samplesDB[m_ptrDB + m_sizeDB][1] = sampleIn->imag();
-
- // save result
- doFIRDB(&s);
- sampleOut->setReal(-s.real());
- sampleOut->setImag(-s.imag());
-
- // advance write-pointer
- m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
-
- // next state
- m_state = 2;
-
- // tell caller we consumed the sample
- return true;
-
- case 2:
- // insert sample into ring-buffer
- m_samplesDB[m_ptrDB][0] = 0;
- m_samplesDB[m_ptrDB][1] = 0;
- m_samplesDB[m_ptrDB + m_sizeDB][0] = 0;
- m_samplesDB[m_ptrDB + m_sizeDB][1] = 0;
-
- // save result
- doFIRDB(&s);
- sampleOut->setReal(s.imag());
- sampleOut->setImag(-s.real());
-
- // advance write-pointer
- m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
-
- // next state
- m_state = 3;
-
- // tell caller we didn't consume the sample
- return false;
-
- default:
- // insert sample into ring-buffer
- m_samplesDB[m_ptrDB][0] = sampleIn->real();
- m_samplesDB[m_ptrDB][1] = sampleIn->imag();
- m_samplesDB[m_ptrDB + m_sizeDB][0] = sampleIn->real();
- m_samplesDB[m_ptrDB + m_sizeDB][1] = sampleIn->imag();
-
- // save result
- doFIRDB(&s);
- sampleOut->setReal(s.real());
- sampleOut->setImag(s.imag());
-
- // advance write-pointer
- m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
-
- // next state
- m_state = 0;
-
- // tell caller we consumed the sample
- return true;
- }
- }
-
void myDecimate(const Sample* sample1, Sample* sample2)
{
m_samples[m_ptr][0] = sample1->real();
@@ -726,42 +512,14 @@ public:
protected:
qint32 m_samples[HBFIRFilterTraits::hbOrder + 1][2]; // Valgrind optim (from qint16)
- qint32 m_samplesDB[2*(HBFIRFilterTraits::hbOrder - 1)][2]; // double buffer technique
qint16 m_ptr;
- int m_ptrDB;
- int m_sizeDB;
int m_state;
- void doFIRDB(Sample* sample)
- {
- int a = m_ptrDB + m_sizeDB; // tip pointer
- int b = m_ptrDB + 1; // tail pointer
- qint32 iAcc = 0;
- qint32 qAcc = 0;
-
- for (int i = 0; i < HBFIRFilterTraits::hbOrder / 4; i++)
- {
- iAcc += (m_samplesDB[a][0] + m_samplesDB[b][0]) * HBFIRFilterTraits::hbCoeffs[i];
- qAcc += (m_samplesDB[a][1] + m_samplesDB[b][1]) * HBFIRFilterTraits::hbCoeffs[i];
- a -= 2;
- b += 2;
- }
-
- iAcc += ((qint32)m_samplesDB[b-1][0]) << (HBFIRFilterTraits::hbShift - 1);
- qAcc += ((qint32)m_samplesDB[b-1][1]) << (HBFIRFilterTraits::hbShift - 1);
-
- sample->setReal(iAcc >> HBFIRFilterTraits::hbShift -1);
- sample->setImag(qAcc >> HBFIRFilterTraits::hbShift -1);
- }
-
void doFIR(Sample* sample)
{
// init read-pointer
-// int a = HBFIRFilterTraits::hbMod[m_ptr + 2 + 1]; // 0 + 1
-// int b = HBFIRFilterTraits::hbMod[m_ptr + 2 - 2]; //-1 - 1
- // ancient way:
- int a = (m_ptr + 1) % (HBFIRFilterTraits::hbOrder + 1);
- int b = (m_ptr + (HBFIRFilterTraits::hbOrder - 1)) % (HBFIRFilterTraits::hbOrder + 1);
+ int a = HBFIRFilterTraits::hbMod[m_ptr + 2 + 1]; // 0 + 1
+ int b = HBFIRFilterTraits::hbMod[m_ptr + 2 - 2]; //-1 - 1
// go through samples in buffer
qint32 iAcc = 0;
@@ -776,16 +534,11 @@ protected:
qAcc += (m_samples[a][1] + m_samples[b][1]) * HBFIRFilterTraits::hbCoeffs[i];
// update read-pointer
-// a = HBFIRFilterTraits::hbMod[a + 2 + 2];
-// b = HBFIRFilterTraits::hbMod[b + 2 - 2];
- // ancient way:
- a = (a + 2) % (HBFIRFilterTraits::hbOrder + 1);
- b = (b + (HBFIRFilterTraits::hbOrder - 1)) % (HBFIRFilterTraits::hbOrder + 1);
+ a = HBFIRFilterTraits::hbMod[a + 2 + 2];
+ b = HBFIRFilterTraits::hbMod[b + 2 - 2];
}
-// a = HBFIRFilterTraits::hbMod[a + 2 - 1];
- // ancient way:
- a = (a + HBFIRFilterTraits::hbOrder) % (HBFIRFilterTraits::hbOrder + 1);
+ a = HBFIRFilterTraits::hbMod[a + 2 - 1];
iAcc += ((qint32)m_samples[a][0] + 1) << (HBFIRFilterTraits::hbShift - 1);
qAcc += ((qint32)m_samples[a][1] + 1) << (HBFIRFilterTraits::hbShift - 1);
@@ -837,22 +590,13 @@ protected:
template
IntHalfbandFilter::IntHalfbandFilter()
{
- m_sizeDB = HBFIRFilterTraits::hbOrder - 1;
-
for (int i = 0; i < HBFIRFilterTraits::hbOrder + 1; i++)
{
m_samples[i][0] = 0;
m_samples[i][1] = 0;
-
- if (i < m_sizeDB)
- {
- m_samplesDB[i][0] = 0;
- m_samplesDB[i][1] = 0;
- }
}
m_ptr = 0;
- m_ptrDB = 0;
m_state = 0;
}
diff --git a/sdrbase/dsp/inthalfbandfilterdb.h b/sdrbase/dsp/inthalfbandfilterdb.h
new file mode 100644
index 000000000..751d7eca5
--- /dev/null
+++ b/sdrbase/dsp/inthalfbandfilterdb.h
@@ -0,0 +1,594 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2016 F4EXB //
+// written by Edouard Griffiths //
+// //
+// Integer 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_DB_H
+#define INCLUDE_INTHALFBANDFILTER_DB_H
+
+#include
+#include "dsp/dsptypes.h"
+#include "dsp/hbfiltertraits.h"
+#include "util/export.h"
+
+template
+class SDRANGEL_API IntHalfbandFilterDB {
+public:
+ IntHalfbandFilterDB();
+
+ // downsample by 2, return center part of original spectrum
+ bool workDecimateCenter(Sample* sample)
+ {
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = sample->real();
+ m_samplesDB[m_ptrDB][1] = sample->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = sample->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = sample->imag();
+
+ switch(m_state)
+ {
+ case 0:
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 1;
+
+ // tell caller we don't have a new sample
+ return false;
+
+ default:
+ // save result
+ doFIR(sample);
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // 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 workInterpolateCenter(Sample* sampleIn, Sample *SampleOut)
+ {
+ switch(m_state)
+ {
+ case 0:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = 0;
+ m_samplesDB[m_ptrDB][1] = 0;
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = 0;
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = 0;
+
+ // save result
+ doFIR(SampleOut);
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 1;
+
+ // tell caller we didn't consume the sample
+ return false;
+
+ default:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = sampleIn->real();
+ m_samplesDB[m_ptrDB][1] = sampleIn->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = sampleIn->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = sampleIn->imag();
+
+ // save result
+ doFIR(SampleOut);
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 0;
+
+ // tell caller we consumed the sample
+ return true;
+ }
+ }
+
+ bool workDecimateCenter(qint32 *x, qint32 *y)
+ {
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = *x;
+ m_samplesDB[m_ptrDB][1] = *y;
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = *x;
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = *y;
+
+ switch(m_state)
+ {
+ case 0:
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 1;
+
+ // tell caller we don't have a new sample
+ return false;
+
+ default:
+ // save result
+ doFIR(x, y);
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 0;
+
+ // tell caller we have a new sample
+ return true;
+ }
+ }
+
+ // downsample by 2, return lower half of original spectrum
+ bool workDecimateLowerHalf(Sample* sample)
+ {
+ switch(m_state)
+ {
+ case 0:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = -sample->imag();
+ m_samplesDB[m_ptrDB][1] = sample->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = -sample->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = sample->real();
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 1;
+
+ // tell caller we don't have a new sample
+ return false;
+
+ case 1:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = -sample->real();
+ m_samplesDB[m_ptrDB][1] = -sample->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = -sample->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = -sample->imag();
+
+ // save result
+ doFIR(sample);
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 2;
+
+ // tell caller we have a new sample
+ return true;
+
+ case 2:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = sample->imag();
+ m_samplesDB[m_ptrDB][1] = -sample->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = sample->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = -sample->real();
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 3;
+
+ // tell caller we don't have a new sample
+ return false;
+
+ default:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = sample->real();
+ m_samplesDB[m_ptrDB][1] = sample->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = sample->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = sample->imag();
+
+ // save result
+ doFIR(sample);
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 0;
+
+ // tell caller we have a new sample
+ return true;
+ }
+ }
+
+ // upsample by 2, from lower half of original spectrum - double buffer variant
+ bool workInterpolateLowerHalf(Sample* sampleIn, Sample *sampleOut)
+ {
+ Sample s;
+
+ switch(m_state)
+ {
+ case 0:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = 0;
+ m_samplesDB[m_ptrDB][1] = 0;
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = 0;
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = 0;
+
+ // save result
+ doFIR(&s);
+ sampleOut->setReal(s.imag());
+ sampleOut->setImag(-s.real());
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 1;
+
+ // tell caller we didn't consume the sample
+ return false;
+
+ case 1:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = sampleIn->real();
+ m_samplesDB[m_ptrDB][1] = sampleIn->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = sampleIn->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = sampleIn->imag();
+
+ // save result
+ doFIR(&s);
+ sampleOut->setReal(-s.real());
+ sampleOut->setImag(-s.imag());
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 2;
+
+ // tell caller we consumed the sample
+ return true;
+
+ case 2:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = 0;
+ m_samplesDB[m_ptrDB][1] = 0;
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = 0;
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = 0;
+
+ // save result
+ doFIR(&s);
+ sampleOut->setReal(-s.imag());
+ sampleOut->setImag(s.real());
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 3;
+
+ // tell caller we didn't consume the sample
+ return false;
+
+ default:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = sampleIn->real();
+ m_samplesDB[m_ptrDB][1] = sampleIn->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = sampleIn->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = sampleIn->imag();
+
+ // save result
+ doFIR(&s);
+ sampleOut->setReal(s.real());
+ sampleOut->setImag(s.imag());
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 0;
+
+ // tell caller we consumed the sample
+ return true;
+ }
+ }
+
+ // downsample by 2, return upper half of original spectrum
+ bool workDecimateUpperHalf(Sample* sample)
+ {
+ switch(m_state)
+ {
+ case 0:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = sample->imag();
+ m_samplesDB[m_ptrDB][1] = -sample->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = sample->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = -sample->real();
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 1;
+
+ // tell caller we don't have a new sample
+ return false;
+
+ case 1:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = -sample->real();
+ m_samplesDB[m_ptrDB][1] = -sample->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = -sample->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = -sample->imag();
+
+ // save result
+ doFIR(sample);
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 2;
+
+ // tell caller we have a new sample
+ return true;
+
+ case 2:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = -sample->imag();
+ m_samplesDB[m_ptrDB][1] = sample->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = -sample->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = sample->real();
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 3;
+
+ // tell caller we don't have a new sample
+ return false;
+
+ default:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = sample->real();
+ m_samplesDB[m_ptrDB][1] = sample->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = sample->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = sample->imag();
+
+ // save result
+ doFIR(sample);
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 0;
+
+ // tell caller we have a new sample
+ return true;
+ }
+ }
+
+ // upsample by 2, move original spectrum to upper half - double buffer variant
+ bool workInterpolateUpperHalf(Sample* sampleIn, Sample *sampleOut)
+ {
+ Sample s;
+
+ switch(m_state)
+ {
+ case 0:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = 0;
+ m_samplesDB[m_ptrDB][1] = 0;
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = 0;
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = 0;
+
+ // save result
+ doFIR(&s);
+ sampleOut->setReal(-s.imag());
+ sampleOut->setImag(s.real());
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 1;
+
+ // tell caller we didn't consume the sample
+ return false;
+
+ case 1:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = sampleIn->real();
+ m_samplesDB[m_ptrDB][1] = sampleIn->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = sampleIn->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = sampleIn->imag();
+
+ // save result
+ doFIR(&s);
+ sampleOut->setReal(-s.real());
+ sampleOut->setImag(-s.imag());
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 2;
+
+ // tell caller we consumed the sample
+ return true;
+
+ case 2:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = 0;
+ m_samplesDB[m_ptrDB][1] = 0;
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = 0;
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = 0;
+
+ // save result
+ doFIR(&s);
+ sampleOut->setReal(s.imag());
+ sampleOut->setImag(-s.real());
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 3;
+
+ // tell caller we didn't consume the sample
+ return false;
+
+ default:
+ // insert sample into ring-buffer
+ m_samplesDB[m_ptrDB][0] = sampleIn->real();
+ m_samplesDB[m_ptrDB][1] = sampleIn->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = sampleIn->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = sampleIn->imag();
+
+ // save result
+ doFIR(&s);
+ sampleOut->setReal(s.real());
+ sampleOut->setImag(s.imag());
+
+ // advance write-pointer
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ // next state
+ m_state = 0;
+
+ // tell caller we consumed the sample
+ return true;
+ }
+ }
+
+ void myDecimate(const Sample* sample1, Sample* sample2)
+ {
+ m_samplesDB[m_ptrDB][0] = sample1->real();
+ m_samplesDB[m_ptrDB][1] = sample1->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = sample1->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = sample1->imag();
+
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ m_samplesDB[m_ptrDB][0] = sample2->real();
+ m_samplesDB[m_ptrDB][1] = sample2->imag();
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = sample2->real();
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = sample2->imag();
+
+ doFIR(sample2);
+
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+ }
+
+ void myDecimate(qint32 x1, qint32 y1, qint32 *x2, qint32 *y2)
+ {
+ m_samplesDB[m_ptrDB][0] = x1;
+ m_samplesDB[m_ptrDB][1] = y1;
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = x1;
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = y1;
+
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+
+ m_samplesDB[m_ptrDB][0] = *x2;
+ m_samplesDB[m_ptrDB][1] = *y2;
+ m_samplesDB[m_ptrDB + m_sizeDB][0] = *x2;
+ m_samplesDB[m_ptrDB + m_sizeDB][1] = *y2;
+
+ doFIR(x2, y2);
+
+ m_ptrDB = (m_ptrDB + 1) % m_sizeDB;
+ }
+
+protected:
+ qint32 m_samplesDB[2*(HBFIRFilterTraits::hbOrder - 1)][2]; // double buffer technique
+ int m_ptrDB;
+ int m_sizeDB;
+ int m_state;
+
+ void doFIR(Sample* sample)
+ {
+ int a = m_ptrDB + m_sizeDB; // tip pointer
+ int b = m_ptrDB + 1; // tail pointer
+ qint32 iAcc = 0;
+ qint32 qAcc = 0;
+
+ for (int i = 0; i < HBFIRFilterTraits::hbOrder / 4; i++)
+ {
+ iAcc += (m_samplesDB[a][0] + m_samplesDB[b][0]) * HBFIRFilterTraits::hbCoeffs[i];
+ qAcc += (m_samplesDB[a][1] + m_samplesDB[b][1]) * HBFIRFilterTraits::hbCoeffs[i];
+ a -= 2;
+ b += 2;
+ }
+
+ iAcc += ((qint32)m_samplesDB[b-1][0]) << (HBFIRFilterTraits::hbShift - 1);
+ qAcc += ((qint32)m_samplesDB[b-1][1]) << (HBFIRFilterTraits::hbShift - 1);
+
+ sample->setReal(iAcc >> HBFIRFilterTraits::hbShift -1);
+ sample->setImag(qAcc >> HBFIRFilterTraits::hbShift -1);
+ }
+
+ void doFIR(qint32 *x, qint32 *y)
+ {
+ int a = m_ptrDB + m_sizeDB; // tip pointer
+ int b = m_ptrDB + 1; // tail pointer
+ qint32 iAcc = 0;
+ qint32 qAcc = 0;
+
+ for (int i = 0; i < HBFIRFilterTraits::hbOrder / 4; i++)
+ {
+ iAcc += (m_samplesDB[a][0] + m_samplesDB[b][0]) * HBFIRFilterTraits::hbCoeffs[i];
+ qAcc += (m_samplesDB[a][1] + m_samplesDB[b][1]) * HBFIRFilterTraits::hbCoeffs[i];
+ a -= 2;
+ b += 2;
+ }
+
+ iAcc += ((qint32)m_samplesDB[b-1][0]) << (HBFIRFilterTraits::hbShift - 1);
+ qAcc += ((qint32)m_samplesDB[b-1][1]) << (HBFIRFilterTraits::hbShift - 1);
+
+ *x = iAcc >> (HBFIRFilterTraits::hbShift -1); // HB_SHIFT incorrect do not loose the gained bit
+ *y = qAcc >> (HBFIRFilterTraits::hbShift -1);
+ }
+};
+
+template
+IntHalfbandFilterDB::IntHalfbandFilterDB()
+{
+ m_sizeDB = HBFIRFilterTraits::hbOrder - 1;
+
+ for (int i = 0; i < m_sizeDB; i++)
+ {
+ m_samplesDB[i][0] = 0;
+ m_samplesDB[i][1] = 0;
+ }
+
+ m_ptrDB = 0;
+ m_state = 0;
+}
+
+#endif // INCLUDE_INTHALFBANDFILTER_DB_H
diff --git a/sdrbase/dsp/upchannelizer.cpp b/sdrbase/dsp/upchannelizer.cpp
index 1d463185c..709ba7d37 100644
--- a/sdrbase/dsp/upchannelizer.cpp
+++ b/sdrbase/dsp/upchannelizer.cpp
@@ -202,20 +202,20 @@ void UpChannelizer::applyConfiguration()
}
UpChannelizer::FilterStage::FilterStage(Mode mode) :
- m_filter(new IntHalfbandFilter),
+ m_filter(new IntHalfbandFilterDB),
m_workFunction(0)
{
switch(mode) {
case ModeCenter:
- m_workFunction = &IntHalfbandFilter::workInterpolateCenterDB;
+ m_workFunction = &IntHalfbandFilterDB::workInterpolateCenter;
break;
case ModeLowerHalf:
- m_workFunction = &IntHalfbandFilter::workInterpolateLowerHalfDB;
+ m_workFunction = &IntHalfbandFilterDB::workInterpolateLowerHalf;
break;
case ModeUpperHalf:
- m_workFunction = &IntHalfbandFilter::workInterpolateUpperHalfDB;
+ m_workFunction = &IntHalfbandFilterDB::workInterpolateUpperHalf;
break;
}
}
diff --git a/sdrbase/dsp/upchannelizer.h b/sdrbase/dsp/upchannelizer.h
index d773ecab3..a4a6410cb 100644
--- a/sdrbase/dsp/upchannelizer.h
+++ b/sdrbase/dsp/upchannelizer.h
@@ -23,7 +23,7 @@
#include
#include "util/export.h"
#include "util/message.h"
-#include "dsp/inthalfbandfilter.h"
+#include "dsp/inthalfbandfilterdb.h"
#define UPCHANNELIZER_HB_FILTER_ORDER 96
@@ -69,8 +69,8 @@ protected:
ModeUpperHalf
};
- typedef bool (IntHalfbandFilter::*WorkFunction)(Sample* sIn, Sample *sOut);
- IntHalfbandFilter* m_filter;
+ typedef bool (IntHalfbandFilterDB::*WorkFunction)(Sample* sIn, Sample *sOut);
+ IntHalfbandFilterDB* m_filter;
WorkFunction m_workFunction;
FilterStage(Mode mode);