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.
inthalfbandfilterdbf.h
Go to the documentation of this file.
1 // Copyright (C) 2018 F4EXB //
3 // written by Edouard Griffiths //
4 // //
5 // Float 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_DBF_H
23 #define INCLUDE_INTHALFBANDFILTER_DBF_H
24 
25 #include <stdint.h>
26 #include "dsp/dsptypes.h"
27 #include "dsp/hbfiltertraits.h"
28 #include "export.h"
29 
30 template<typename AccuType, typename SampleType, uint32_t HBFilterOrder>
32 public:
34 
35  void myDecimate(AccuType x1, AccuType y1, AccuType *x2, AccuType *y2)
36  {
37  storeSample(x1, y1);
38  advancePointer();
39 
40  storeSample(*x2, *y2);
41  doFIR(x2, y2);
42  advancePointer();
43  }
44 
46  void myInterpolate(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2)
47  {
48  // insert sample into ring double buffer
49  m_samplesDB[m_ptr][0] = *x1;
50  m_samplesDB[m_ptr][1] = *y1;
51  m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][0] = *x1;
52  m_samplesDB[m_ptr + HBFIRFilterTraits<HBFilterOrder>::hbOrder/2][1] = *y1;
53 
54  // advance pointer
55  if (m_ptr < (HBFIRFilterTraits<HBFilterOrder>::hbOrder/2) - 1) {
56  m_ptr++;
57  } else {
58  m_ptr = 0;
59  }
60 
61  // first output sample calculated with the middle peak
62  *x1 = m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][0];
63  *y1 = m_samplesDB[m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder/4) - 1][1];
64 
65  // second sample calculated with the filter
66  doInterpolateFIR(x2, y2);
67  }
68 
69  void myInterpolateInf(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2, qint32 *x3, qint32 *y3, qint32 *x4, qint32 *y4)
70  {
71  myInterpolate(x1, y1, x2, y2);
72  myInterpolate(x3, y3, x4, y4);
73  // rotation
74  qint32 x;
75  x = *x1;
76  *x1 = *y1;
77  *y1 = -x;
78  *x2 = -*x2;
79  *y2 = -*y2;
80  x = *x3;
81  *x3 = -*y3;
82  *y3 = x;
83  }
84 
85  void myInterpolateSup(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2, qint32 *x3, qint32 *y3, qint32 *x4, qint32 *y4)
86  {
87  myInterpolate(x1, y1, x2, y2);
88  myInterpolate(x3, y3, x4, y4);
89  // rotation
90  qint32 x;
91  x = *x1;
92  *x1 = -*y1;
93  *y1 = x;
94  *x2 = -*x2;
95  *y2 = -*y2;
96  x = *x3;
97  *x3 = *y3;
98  *y3 = -x;
99  }
100 
101 protected:
102  SampleType m_samplesDB[2*(HBFIRFilterTraits<HBFilterOrder>::hbOrder - 1)][2]; // double buffer technique
103  int m_ptr;
104  int m_size;
105  int m_state;
106 
107  void storeSample(AccuType x, AccuType y)
108  {
109  m_samplesDB[m_ptr][0] = x;
110  m_samplesDB[m_ptr][1] = y;
111  m_samplesDB[m_ptr + m_size][0] = x;
112  m_samplesDB[m_ptr + m_size][1] = y;
113  }
114 
116  {
117  m_ptr = m_ptr + 1 < m_size ? m_ptr + 1: 0;
118  }
119 
120  void doFIR(AccuType *x, AccuType *y)
121  {
122  int a = m_ptr + m_size; // tip pointer
123  int b = m_ptr + 1; // tail pointer
124  AccuType iAcc = 0;
125  AccuType qAcc = 0;
126 
127  for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++)
128  {
129  iAcc += (m_samplesDB[a][0] + m_samplesDB[b][0]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffsF[i];
130  qAcc += (m_samplesDB[a][1] + m_samplesDB[b][1]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffsF[i];
131  a -= 2;
132  b += 2;
133  }
134 
135  iAcc += m_samplesDB[b-1][0] / 2.0;
136  qAcc += m_samplesDB[b-1][1] / 2.0;
137 
138  *x = iAcc; // HB_SHIFT incorrect do not loose the gained bit
139  *y = qAcc;
140  }
141 
142  void doInterpolateFIR(qint32 *x, qint32 *y)
143  {
144  qint16 a = m_ptr;
145  qint16 b = m_ptr + (HBFIRFilterTraits<HBFilterOrder>::hbOrder / 2) - 1;
146 
147  // go through samples in buffer
148  AccuType iAcc = 0;
149  AccuType qAcc = 0;
150 
151  for (int i = 0; i < HBFIRFilterTraits<HBFilterOrder>::hbOrder / 4; i++)
152  {
153  iAcc += (m_samplesDB[a][0] + m_samplesDB[b][0]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffsF[i];
154  qAcc += (m_samplesDB[a][1] + m_samplesDB[b][1]) * HBFIRFilterTraits<HBFilterOrder>::hbCoeffsF[i];
155  a++;
156  b--;
157  }
158 
159  *x = iAcc * SDR_RX_SCALED;
160  *y = qAcc * SDR_RX_SCALED;
161  }
162 };
163 
164 template<typename AccuType, typename SampleType, uint32_t HBFilterOrder>
166 {
168 
169  for (int i = 0; i < m_size; i++)
170  {
171  m_samplesDB[i][0] = 0;
172  m_samplesDB[i][1] = 0;
173  }
174 
175  m_ptr = 0;
176  m_state = 0;
177 }
178 
179 #endif // INCLUDE_INTHALFBANDFILTER_DBF_H
void myInterpolate(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2)
void storeSample(AccuType x, AccuType y)
void myInterpolateInf(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2, qint32 *x3, qint32 *y3, qint32 *x4, qint32 *y4)
int32_t i
Definition: decimators.h:244
void myInterpolateSup(qint32 *x1, qint32 *y1, qint32 *x2, qint32 *y2, qint32 *x3, qint32 *y3, qint32 *x4, qint32 *y4)
void myDecimate(AccuType x1, AccuType y1, AccuType *x2, AccuType *y2)
void doFIR(AccuType *x, AccuType *y)
void doInterpolateFIR(qint32 *x, qint32 *y)
#define SDRBASE_API
Definition: export.h:40
#define SDR_RX_SCALED
Definition: dsptypes.h:34