SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
inthalfbandfilterdb.h
Go to the documentation of this file.
1 // Copyright (C) 2016 F4EXB //
3 // written by Edouard Griffiths //
4 // //
5 // Integer half-band FIR based interpolator and decimator //
6 // This is the double buffer variant //
7 // //
8 // This program is free software; you can redistribute it and/or modify //
9 // it under the terms of the GNU General Public License as published by //
10 // the Free Software Foundation as version 3 of the License, or //
11 // (at your option) any later version. //
12 // //
13 // This program is distributed in the hope that it will be useful, //
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
16 // GNU General Public License V3 for more details. //
17 // //
18 // You should have received a copy of the GNU General Public License //
19 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
21 
22 #ifndef INCLUDE_INTHALFBANDFILTER_DB_H
23 #define INCLUDE_INTHALFBANDFILTER_DB_H
24 
25 #include <stdint.h>
26 #include "dsp/dsptypes.h"
27 #include "dsp/hbfiltertraits.h"
28 
29 template<typename AccuType, uint32_t HBFilterOrder>
31 public:
33  {
35 
36  for (int i = 0; i < m_size; i++)
37  {
38  m_samplesDB[i][0] = 0;
39  m_samplesDB[i][1] = 0;
40  }
41 
42  m_ptr = 0;
43  m_state = 0;
44  }
45 
46  // downsample by 2, return center part of original spectrum
47  bool workDecimateCenter(Sample* sample)
48  {
49  // insert sample into ring-buffer
50  storeSampleFixReal((FixReal) sample->real(), (FixReal) sample->imag());
51 
52  switch(m_state)
53  {
54  case 0:
55  // advance write-pointer
57  // next state
58  m_state = 1;
59  // tell caller we don't have a new sample
60  return false;
61 
62  default:
63  // save result
64  doFIR(sample);
65  // advance write-pointer
67  // next state
68  m_state = 0;
69 
70  // tell caller we have a new sample
71  return true;
72  }
73  }
74 
75  // upsample by 2, return center part of original spectrum - double buffer variant
76  bool workInterpolateCenterZeroStuffing(Sample* sampleIn, Sample *SampleOut)
77  {
78  switch(m_state)
79  {
80  case 0:
81  // insert sample into ring-buffer
83  // save result
84  doFIR(SampleOut);
85  // advance write-pointer
87  // next state
88  m_state = 1;
89  // tell caller we didn't consume the sample
90  return false;
91 
92  default:
93  // insert sample into ring-buffer
94  storeSampleFixReal((FixReal) sampleIn->real(), (FixReal) sampleIn->imag());
95  // save result
96  doFIR(SampleOut);
97  // advance write-pointer
99  // next state
100  m_state = 0;
101  // tell caller we consumed the sample
102  return true;
103  }
104  }
105 
107  bool workInterpolateCenter(Sample* sampleIn, Sample *SampleOut)
108  {
109  switch(m_state)
110  {
111  case 0:
112  // return the middle peak
115  m_state = 1; // next state
116  return false; // tell caller we didn't consume the sample
117 
118  default:
119  // calculate with non null samples
120  doInterpolateFIR(SampleOut);
121 
122  // insert sample into ring double buffer
123  m_samplesDB[m_ptr][0] = sampleIn->real();
124  m_samplesDB[m_ptr][1] = sampleIn->imag();
127 
128  // advance pointer
130  m_ptr++;
131  } else {
132  m_ptr = 0;
133  }
134 
135  m_state = 0; // next state
136  return true; // tell caller we consumed the sample
137  }
138  }
139 
140 // bool workDecimateCenter(qint32 *x, qint32 *y)
141 // {
142 // // insert sample into ring-buffer
143 // storeSample32(*x, *y);
144 //
145 // switch (m_state)
146 // {
147 // case 0:
148 // // advance write-pointer
149 // advancePointer();
150 // // next state
151 // m_state = 1;
152 // // tell caller we don't have a new sample
153 // return false;
154 //
155 // default:
156 // // save result
157 // doFIR(x, y);
158 // // advance write-pointer
159 // advancePointer();
160 // // next state
161 // m_state = 0;
162 // // tell caller we have a new sample
163 // return true;
164 // }
165 // }
166 
167  // downsample by 2, return lower half of original spectrum
169  {
170  switch(m_state)
171  {
172  case 0:
173  // insert sample into ring-buffer
174  storeSampleFixReal((FixReal) -sample->imag(), (FixReal) sample->real());
175  // advance write-pointer
176  advancePointer();
177  // next state
178  m_state = 1;
179  // tell caller we don't have a new sample
180  return false;
181 
182  case 1:
183  // insert sample into ring-buffer
184  storeSampleFixReal((FixReal) -sample->real(), (FixReal) -sample->imag());
185  // save result
186  doFIR(sample);
187  // advance write-pointer
188  advancePointer();
189  // next state
190  m_state = 2;
191  // tell caller we have a new sample
192  return true;
193 
194  case 2:
195  // insert sample into ring-buffer
196  storeSampleFixReal((FixReal) sample->imag(), (FixReal) -sample->real());
197  // advance write-pointer
198  advancePointer();
199  // next state
200  m_state = 3;
201  // tell caller we don't have a new sample
202  return false;
203 
204  default:
205  // insert sample into ring-buffer
206  storeSampleFixReal((FixReal) sample->real(), (FixReal) sample->imag());
207  // save result
208  doFIR(sample);
209  // advance write-pointer
210  advancePointer();
211  // next state
212  m_state = 0;
213  // tell caller we have a new sample
214  return true;
215  }
216  }
217 
219  bool workInterpolateLowerHalf(Sample* sampleIn, Sample *sampleOut)
220  {
221  Sample s;
222 
223  switch(m_state)
224  {
225  case 0:
226  // return the middle peak
227  sampleOut->setReal(m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][1]); // imag
228  sampleOut->setImag(-m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][0]); // - real
229  m_state = 1; // next state
230  return false; // tell caller we didn't consume the sample
231 
232  case 1:
233  // calculate with non null samples
234  doInterpolateFIR(&s);
235  sampleOut->setReal(-s.real());
236  sampleOut->setImag(-s.imag());
237 
238  // insert sample into ring double buffer
239  m_samplesDB[m_ptr][0] = sampleIn->real();
240  m_samplesDB[m_ptr][1] = sampleIn->imag();
243 
244  // advance pointer
246  m_ptr++;
247  } else {
248  m_ptr = 0;
249  }
250 
251  m_state = 2; // next state
252  return true; // tell caller we consumed the sample
253 
254  case 2:
255  // return the middle peak
256  sampleOut->setReal(-m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][1]); // - imag
257  sampleOut->setImag(m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][0]); // real
258  m_state = 3; // next state
259  return false; // tell caller we didn't consume the sample
260 
261  default:
262  // calculate with non null samples
263  doInterpolateFIR(&s);
264  sampleOut->setReal(s.real());
265  sampleOut->setImag(s.imag());
266 
267  // insert sample into ring double buffer
268  m_samplesDB[m_ptr][0] = sampleIn->real();
269  m_samplesDB[m_ptr][1] = sampleIn->imag();
272 
273  // advance pointer
275  m_ptr++;
276  } else {
277  m_ptr = 0;
278  }
279 
280  m_state = 0; // next state
281  return true; // tell caller we consumed the sample
282  }
283  }
284 
285  // upsample by 2, from lower half of original spectrum - double buffer variant
287  {
288  Sample s;
289 
290  switch(m_state)
291  {
292  case 0:
293  // insert sample into ring-buffer
295 
296  // save result
297  doFIR(&s);
298  sampleOut->setReal(s.imag());
299  sampleOut->setImag(-s.real());
300 
301  // advance write-pointer
302  advancePointer();
303 
304  // next state
305  m_state = 1;
306 
307  // tell caller we didn't consume the sample
308  return false;
309 
310  case 1:
311  // insert sample into ring-buffer
312  storeSampleFixReal((FixReal) sampleIn->real(), (FixReal) sampleIn->imag());
313 
314  // save result
315  doFIR(&s);
316  sampleOut->setReal(-s.real());
317  sampleOut->setImag(-s.imag());
318 
319  // advance write-pointer
320  advancePointer();
321 
322  // next state
323  m_state = 2;
324 
325  // tell caller we consumed the sample
326  return true;
327 
328  case 2:
329  // insert sample into ring-buffer
331 
332  // save result
333  doFIR(&s);
334  sampleOut->setReal(-s.imag());
335  sampleOut->setImag(s.real());
336 
337  // advance write-pointer
338  advancePointer();
339 
340  // next state
341  m_state = 3;
342 
343  // tell caller we didn't consume the sample
344  return false;
345 
346  default:
347  // insert sample into ring-buffer
348  storeSampleFixReal((FixReal) sampleIn->real(), (FixReal) sampleIn->imag());
349 
350  // save result
351  doFIR(&s);
352  sampleOut->setReal(s.real());
353  sampleOut->setImag(s.imag());
354 
355  // advance write-pointer
356  advancePointer();
357 
358  // next state
359  m_state = 0;
360 
361  // tell caller we consumed the sample
362  return true;
363  }
364  }
365 
366  // downsample by 2, return upper half of original spectrum
368  {
369  switch(m_state)
370  {
371  case 0:
372  // insert sample into ring-buffer
373  storeSampleFixReal((FixReal) sample->imag(), (FixReal) -sample->real());
374  // advance write-pointer
375  advancePointer();
376  // next state
377  m_state = 1;
378  // tell caller we don't have a new sample
379  return false;
380 
381  case 1:
382  // insert sample into ring-buffer
383  storeSampleFixReal((FixReal) -sample->real(), (FixReal) -sample->imag());
384  // save result
385  doFIR(sample);
386  // advance write-pointer
387  advancePointer();
388  // next state
389  m_state = 2;
390  // tell caller we have a new sample
391  return true;
392 
393  case 2:
394  // insert sample into ring-buffer
395  storeSampleFixReal((FixReal) -sample->imag(), (FixReal) sample->real());
396  // advance write-pointer
397  advancePointer();
398  // next state
399  m_state = 3;
400  // tell caller we don't have a new sample
401  return false;
402 
403  default:
404  // insert sample into ring-buffer
405  storeSampleFixReal((FixReal) sample->real(), (FixReal) sample->imag());
406  // save result
407  doFIR(sample);
408  // advance write-pointer
409  advancePointer();
410  // next state
411  m_state = 0;
412  // tell caller we have a new sample
413  return true;
414  }
415  }
416 
418  bool workInterpolateUpperHalf(Sample* sampleIn, Sample *sampleOut)
419  {
420  Sample s;
421 
422  switch(m_state)
423  {
424  case 0:
425  // return the middle peak
426  sampleOut->setReal(-m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][1]); // - imag
427  sampleOut->setImag(m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][0]); // + real
428  m_state = 1; // next state
429  return false; // tell caller we didn't consume the sample
430 
431  case 1:
432  // calculate with non null samples
433  doInterpolateFIR(&s);
434  sampleOut->setReal(-s.real());
435  sampleOut->setImag(-s.imag());
436 
437  // insert sample into ring double buffer
438  m_samplesDB[m_ptr][0] = sampleIn->real();
439  m_samplesDB[m_ptr][1] = sampleIn->imag();
442 
443  // advance pointer
445  m_ptr++;
446  } else {
447  m_ptr = 0;
448  }
449 
450  m_state = 2; // next state
451  return true; // tell caller we consumed the sample
452 
453  case 2:
454  // return the middle peak
455  sampleOut->setReal(m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][1]); // + imag
456  sampleOut->setImag(-m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][0]); // - real
457  m_state = 3; // next state
458  return false; // tell caller we didn't consume the sample
459 
460  default:
461  // calculate with non null samples
462  doInterpolateFIR(&s);
463  sampleOut->setReal(s.real());
464  sampleOut->setImag(s.imag());
465 
466  // insert sample into ring double buffer
467  m_samplesDB[m_ptr][0] = sampleIn->real();
468  m_samplesDB[m_ptr][1] = sampleIn->imag();
471 
472  // advance pointer
474  m_ptr++;
475  } else {
476  m_ptr = 0;
477  }
478 
479  m_state = 0; // next state
480  return true; // tell caller we consumed the sample
481  }
482  }
483 
484  // upsample by 2, move original spectrum to upper half - double buffer variant
486  {
487  Sample s;
488 
489  switch(m_state)
490  {
491  case 0:
492  // insert sample into ring-buffer
494 
495  // save result
496  doFIR(&s);
497  sampleOut->setReal(-s.imag());
498  sampleOut->setImag(s.real());
499 
500  // advance write-pointer
501  advancePointer();
502 
503  // next state
504  m_state = 1;
505 
506  // tell caller we didn't consume the sample
507  return false;
508 
509  case 1:
510  // insert sample into ring-buffer
511  storeSampleFixReal((FixReal) sampleIn->real(), (FixReal) sampleIn->imag());
512 
513  // save result
514  doFIR(&s);
515  sampleOut->setReal(-s.real());
516  sampleOut->setImag(-s.imag());
517 
518  // advance write-pointer
519  advancePointer();
520 
521  // next state
522  m_state = 2;
523 
524  // tell caller we consumed the sample
525  return true;
526 
527  case 2:
528  // insert sample into ring-buffer
530 
531  // save result
532  doFIR(&s);
533  sampleOut->setReal(s.imag());
534  sampleOut->setImag(-s.real());
535 
536  // advance write-pointer
537  advancePointer();
538 
539  // next state
540  m_state = 3;
541 
542  // tell caller we didn't consume the sample
543  return false;
544 
545  default:
546  // insert sample into ring-buffer
547  storeSampleFixReal((FixReal) sampleIn->real(), (FixReal) sampleIn->imag());
548 
549  // save result
550  doFIR(&s);
551  sampleOut->setReal(s.real());
552  sampleOut->setImag(s.imag());
553 
554  // advance write-pointer
555  advancePointer();
556 
557  // next state
558  m_state = 0;
559 
560  // tell caller we consumed the sample
561  return true;
562  }
563  }
564 
565  void myDecimate(const Sample* sample1, Sample* sample2)
566  {
567  storeSampleFixReal((FixReal) sample1->real(), (FixReal) sample1->imag());
568  advancePointer();
569 
570  storeSampleFixReal((FixReal) sample2->real(), (FixReal) sample2->imag());
571  doFIR(sample2);
572  advancePointer();
573  }
574 
575  void myDecimate(AccuType x1, AccuType y1, AccuType *x2, AccuType *y2)
576  {
577  storeSampleAccu(x1, y1);
578  advancePointer();
579 
580  storeSampleAccu(*x2, *y2);
581  doFIRAccu(x2, y2);
582  advancePointer();
583  }
584 
586  void myInterpolateZeroStuffing(Sample* sample1, Sample* sample2)
587  {
588  storeSampleFixReal((FixReal) sample1->real(), (FixReal) sample1->imag());
589  doFIR(sample1);
590  advancePointer();
591 
593  doFIR(sample2);
594  advancePointer();
595  }
596 
598 // void myInterpolateZeroStuffing(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2)
599 // {
600 // storeSampleAccu(*x1, *y1);
601 // doFIR(x1, y1);
602 // advancePointer();
603 //
604 // storeSampleAccu(0, 0);
605 // doFIR(x2, y2);
606 // advancePointer();
607 // }
608 
610  void myInterpolate(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2)
611  {
612  // insert sample into ring double buffer
613  m_samplesDB[m_ptr][0] = *x1;
614  m_samplesDB[m_ptr][1] = *y1;
617 
618  // advance pointer
620  m_ptr++;
621  } else {
622  m_ptr = 0;
623  }
624 
625  // first output sample calculated with the middle peak
628 
629  // second sample calculated with the filter
630  doInterpolateFIR(x2, y2);
631  }
632 
633  void myInterpolateInf(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2, qint32 *x3, qint32 *y3, qint32 *x4, qint32 *y4)
634  {
635  myInterpolate(x1, y1, x2, y2);
636  myInterpolate(x3, y3, x4, y4);
637  // rotation
638  qint32 x;
639  x = *x1;
640  *x1 = *y1;
641  *y1 = -x;
642  *x2 = -*x2;
643  *y2 = -*y2;
644  x = *x3;
645  *x3 = -*y3;
646  *y3 = x;
647  }
648 
649  void myInterpolateSup(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2, qint32 *x3, qint32 *y3, qint32 *x4, qint32 *y4)
650  {
651  myInterpolate(x1, y1, x2, y2);
652  myInterpolate(x3, y3, x4, y4);
653  // rotation
654  qint32 x;
655  x = *x1;
656  *x1 = -*y1;
657  *y1 = x;
658  *x2 = -*x2;
659  *y2 = -*y2;
660  x = *x3;
661  *x3 = *y3;
662  *y3 = -x;
663  }
664 
665 protected:
666  AccuType m_samplesDB[2*(HBFIRFilterTraits<HBFilterOrder>::hbOrder - 1)][2]; // double buffer technique
667  int m_ptr;
668  int m_size;
669  int m_state;
670 
671  void storeSampleFixReal(const FixReal& sampleI, const FixReal& sampleQ)
672  {
673  m_samplesDB[m_ptr][0] = sampleI;
674  m_samplesDB[m_ptr][1] = sampleQ;
675  m_samplesDB[m_ptr + m_size][0] = sampleI;
676  m_samplesDB[m_ptr + m_size][1] = sampleQ;
677  }
678 
679  void storeSampleAccu(AccuType x, AccuType y)
680  {
681  m_samplesDB[m_ptr][0] = x;
682  m_samplesDB[m_ptr][1] = y;
683  m_samplesDB[m_ptr + m_size][0] = x;
684  m_samplesDB[m_ptr + m_size][1] = y;
685  }
686 
688  {
689  m_ptr = m_ptr + 1 < m_size ? m_ptr + 1: 0;
690  }
691 
692  void doFIR(Sample* sample)
693  {
694  int a = m_ptr + m_size; // tip pointer
695  int b = m_ptr + 1; // tail pointer
696  AccuType iAcc = 0;
697  AccuType qAcc = 0;
698 
699  for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++)
700  {
703  a -= 2;
704  b += 2;
705  }
706 
709 
712  }
713 
714  void doFIR(qint32 *x, qint32 *y)
715  {
716  int a = m_ptr + m_size; // tip pointer
717  int b = m_ptr + 1; // tail pointer
718  AccuType iAcc = 0;
719  AccuType qAcc = 0;
720 
721  for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++)
722  {
725  a -= 2;
726  b += 2;
727  }
728 
731 
732  *x = iAcc >> (HBFIRFilterTraits<HBFilterOrder>::hbShift -1); // HB_SHIFT incorrect do not loose the gained bit
734  }
735 
736  void doFIRAccu(AccuType *x, AccuType *y)
737  {
738  int a = m_ptr + m_size; // tip pointer
739  int b = m_ptr + 1; // tail pointer
740  AccuType iAcc = 0;
741  AccuType qAcc = 0;
742 
743  for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++)
744  {
747  a -= 2;
748  b += 2;
749  }
750 
753 
754  *x = iAcc >> (HBFIRFilterTraits<HBFilterOrder>::hbShift -1); // HB_SHIFT incorrect do not loose the gained bit
756  }
757 
758  void doInterpolateFIR(Sample* sample)
759  {
760  qint16 a = m_ptr;
761  qint16 b = m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder / 2) - 1;
762 
763  // go through samples in buffer
764  AccuType iAcc = 0;
765  AccuType qAcc = 0;
766 
767  for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++)
768  {
771  a++;
772  b--;
773  }
774 
777  }
778 
779  void doInterpolateFIR(qint32 *x, qint32 *y)
780  {
781  qint16 a = m_ptr;
782  qint16 b = m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder / 2) - 1;
783 
784  // go through samples in buffer
785  AccuType iAcc = 0;
786  AccuType qAcc = 0;
787 
788  for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++)
789  {
792  a++;
793  b--;
794  }
795 
798  }
799 };
800 
801 #endif // INCLUDE_INTHALFBANDFILTER_DB_H
bool workInterpolateUpperHalfZeroStuffing(Sample *sampleIn, Sample *sampleOut)
bool workInterpolateCenter(Sample *sampleIn, Sample *SampleOut)
void myInterpolate(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2)
bool workInterpolateCenterZeroStuffing(Sample *sampleIn, Sample *SampleOut)
bool workDecimateCenter(Sample *sample)
void doInterpolateFIR(qint32 *x, qint32 *y)
bool workDecimateUpperHalf(Sample *sample)
void myInterpolateSup(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2, qint32 *x3, qint32 *y3, qint32 *x4, qint32 *y4)
void doFIR(Sample *sample)
void doFIRAccu(AccuType *x, AccuType *y)
AccuType m_samplesDB[2 *(HBFIRFilterTraits< HBFilterOrder >::hbOrder - 1)][2]
int32_t i
Definition: decimators.h:244
void setImag(FixReal v)
Definition: dsptypes.h:59
void myInterpolateInf(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2, qint32 *x3, qint32 *y3, qint32 *x4, qint32 *y4)
void doFIR(qint32 *x, qint32 *y)
bool workInterpolateLowerHalfZeroStuffing(Sample *sampleIn, Sample *sampleOut)
void setReal(FixReal v)
Definition: dsptypes.h:58
void storeSampleFixReal(const FixReal &sampleI, const FixReal &sampleQ)
FixReal real() const
Definition: dsptypes.h:61
FixReal imag() const
Definition: dsptypes.h:62
bool workDecimateLowerHalf(Sample *sample)
void myDecimate(AccuType x1, AccuType y1, AccuType *x2, AccuType *y2)
void doInterpolateFIR(Sample *sample)
bool workInterpolateUpperHalf(Sample *sampleIn, Sample *sampleOut)
void myDecimate(const Sample *sample1, Sample *sample2)
qint16 FixReal
Definition: dsptypes.h:35
void myInterpolateZeroStuffing(Sample *sample1, Sample *sample2)
bool workInterpolateLowerHalf(Sample *sampleIn, Sample *sampleOut)
void storeSampleAccu(AccuType x, AccuType y)