diff --git a/sdrbase/dsp/inthalfbandfilter.h b/sdrbase/dsp/inthalfbandfilter.h index a60b70017..c1fd7aea7 100644 --- a/sdrbase/dsp/inthalfbandfilter.h +++ b/sdrbase/dsp/inthalfbandfilter.h @@ -287,7 +287,7 @@ public: } // upsample by 2, from lower half of original spectrum - bool workInterpolateLowerHalf(Sample* sampleIn, Sample *sampleOut) + bool workInterpolateLowerHalfZeroStuffing(Sample* sampleIn, Sample *sampleOut) { Sample s; @@ -371,6 +371,73 @@ public: } } + /** Optimized upsampler by 2 not calculating FIR with inserted null samples */ + bool workInterpolateLowerHalf(Sample* sampleIn, Sample *sampleOut) + { + Sample s; + + switch(m_state) + { + case 0: + // return the middle peak + sampleOut->setReal(m_samples[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][1]); // imag + sampleOut->setImag(-m_samples[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_samples[m_ptr][0] = sampleIn->real(); + m_samples[m_ptr][1] = sampleIn->imag(); + m_samples[m_ptr + HBFIRFilterTraits::hbOrder/2][0] = sampleIn->real(); + m_samples[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_samples[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][1]); // - imag + sampleOut->setImag(m_samples[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_samples[m_ptr][0] = sampleIn->real(); + m_samples[m_ptr][1] = sampleIn->imag(); + m_samples[m_ptr + HBFIRFilterTraits::hbOrder/2][0] = sampleIn->real(); + m_samples[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 upper half of original spectrum bool workDecimateUpperHalf(Sample* sample) { @@ -441,7 +508,7 @@ public: } // upsample by 2, move original spectrum to upper half - bool workInterpolateUpperHalf(Sample* sampleIn, Sample *sampleOut) + bool workInterpolateUpperHalfZeroStuffing(Sample* sampleIn, Sample *sampleOut) { Sample s; @@ -525,6 +592,73 @@ public: } } + /** Optimized upsampler by 2 not calculating FIR with inserted null samples */ + bool workInterpolateUpperHalf(Sample* sampleIn, Sample *sampleOut) + { + Sample s; + + switch(m_state) + { + case 0: + // return the middle peak + sampleOut->setReal(-m_samples[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][1]); // - imag + sampleOut->setImag(m_samples[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_samples[m_ptr][0] = sampleIn->real(); + m_samples[m_ptr][1] = sampleIn->imag(); + m_samples[m_ptr + HBFIRFilterTraits::hbOrder/2][0] = sampleIn->real(); + m_samples[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_samples[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][1]); // + imag + sampleOut->setImag(-m_samples[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_samples[m_ptr][0] = sampleIn->real(); + m_samples[m_ptr][1] = sampleIn->imag(); + m_samples[m_ptr + HBFIRFilterTraits::hbOrder/2][0] = sampleIn->real(); + m_samples[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 + } + } + void myDecimate(const Sample* sample1, Sample* sample2) { m_samples[m_ptr][0] = sample1->real(); diff --git a/sdrbase/dsp/inthalfbandfilterdb.h b/sdrbase/dsp/inthalfbandfilterdb.h index cc587acce..e6aade996 100644 --- a/sdrbase/dsp/inthalfbandfilterdb.h +++ b/sdrbase/dsp/inthalfbandfilterdb.h @@ -203,11 +203,78 @@ public: } } - // upsample by 2, from lower half of original spectrum - double buffer variant + /** Optimized upsampler by 2 not calculating FIR with inserted null samples */ bool workInterpolateLowerHalf(Sample* sampleIn, Sample *sampleOut) { Sample 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(Sample* sampleIn, Sample *sampleOut) + { + Sample s; + switch(m_state) { case 0: @@ -335,11 +402,78 @@ public: } } - // upsample by 2, move original spectrum to upper half - double buffer variant + /** Optimized upsampler by 2 not calculating FIR with inserted null samples */ bool workInterpolateUpperHalf(Sample* sampleIn, Sample *sampleOut) { Sample 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(Sample* sampleIn, Sample *sampleOut) + { + Sample s; + switch(m_state) { case 0: diff --git a/sdrbase/dsp/inthalfbandfiltereo1.h b/sdrbase/dsp/inthalfbandfiltereo1.h index 125cd5e88..a2b5067ef 100644 --- a/sdrbase/dsp/inthalfbandfiltereo1.h +++ b/sdrbase/dsp/inthalfbandfiltereo1.h @@ -207,7 +207,7 @@ public: } // upsample by 2, from lower half of original spectrum - double buffer variant - bool workInterpolateLowerHalf(Sample* sampleIn, Sample *sampleOut) + bool workInterpolateLowerHalfZeroStuffing(Sample* sampleIn, Sample *sampleOut) { Sample s; @@ -287,6 +287,73 @@ public: } } + /** Optimized upsampler by 2 not calculating FIR with inserted null samples */ + bool workInterpolateLowerHalf(Sample* sampleIn, Sample *sampleOut) + { + Sample s; + + switch(m_state) + { + case 0: + // return the middle peak + sampleOut->setReal(m_samples[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][1]); // imag + sampleOut->setImag(-m_samples[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_samples[m_ptr][0] = sampleIn->real(); + m_samples[m_ptr][1] = sampleIn->imag(); + m_samples[m_ptr + HBFIRFilterTraits::hbOrder/2][0] = sampleIn->real(); + m_samples[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_samples[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][1]); // - imag + sampleOut->setImag(m_samples[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_samples[m_ptr][0] = sampleIn->real(); + m_samples[m_ptr][1] = sampleIn->imag(); + m_samples[m_ptr + HBFIRFilterTraits::hbOrder/2][0] = sampleIn->real(); + m_samples[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 upper half of original spectrum bool workDecimateUpperHalf(Sample* sample) { @@ -339,7 +406,7 @@ public: } // upsample by 2, move original spectrum to upper half - double buffer variant - bool workInterpolateUpperHalf(Sample* sampleIn, Sample *sampleOut) + bool workInterpolateUpperHalfZeroStuffing(Sample* sampleIn, Sample *sampleOut) { Sample s; @@ -419,6 +486,73 @@ public: } } + /** Optimized upsampler by 2 not calculating FIR with inserted null samples */ + bool workInterpolateUpperHalf(Sample* sampleIn, Sample *sampleOut) + { + Sample s; + + switch(m_state) + { + case 0: + // return the middle peak + sampleOut->setReal(-m_samples[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][1]); // - imag + sampleOut->setImag(m_samples[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_samples[m_ptr][0] = sampleIn->real(); + m_samples[m_ptr][1] = sampleIn->imag(); + m_samples[m_ptr + HBFIRFilterTraits::hbOrder/2][0] = sampleIn->real(); + m_samples[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_samples[m_ptr + (HBFIRFilterTraits::hbOrder/4) - 1][1]); // + imag + sampleOut->setImag(-m_samples[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_samples[m_ptr][0] = sampleIn->real(); + m_samples[m_ptr][1] = sampleIn->imag(); + m_samples[m_ptr + HBFIRFilterTraits::hbOrder/2][0] = sampleIn->real(); + m_samples[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 + } + } + void myDecimate(const Sample* sample1, Sample* sample2) { storeSample((FixReal) sample1->real(), (FixReal) sample1->imag());