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.
interpolator.cpp
Go to the documentation of this file.
1 #define _USE_MATH_DEFINES
2 #include <math.h>
3 #include <vector>
4 #include "dsp/interpolator.h"
5 
6 
8  std::vector<Real>& taps,
9  int phaseSteps,
10  double gain,
11  double sampleRateHz,
12  double cutoffFreqHz,
13  double transitionWidthHz,
14  double oobAttenuationdB)
15 {
16  double nbTapsPerPhase = (oobAttenuationdB * sampleRateHz) / (22.0 * transitionWidthHz * phaseSteps);
17  return createPolyphaseLowPass(taps, phaseSteps, gain, sampleRateHz, cutoffFreqHz, nbTapsPerPhase);
18 }
19 
20 
22  std::vector<Real>& taps,
23  int phaseSteps,
24  double gain,
25  double sampleRateHz,
26  double cutoffFreqHz,
27  double nbTapsPerPhase)
28 {
29  int ntaps = (int)(nbTapsPerPhase * phaseSteps);
30  qDebug("Interpolator::createPolyphaseLowPass: ntaps: %d", ntaps);
31 
32  if ((ntaps % 2) != 0) {
33  ntaps++;
34  }
35 
36  ntaps *= phaseSteps;
37 
38  taps.resize(ntaps);
39  std::vector<float> window(ntaps);
40 
41  for (int n = 0; n < ntaps; n++) {
42  window[n] = 0.54 - 0.46 * cos ((2 * M_PI * n) / (ntaps - 1));
43  }
44 
45  int M = (ntaps - 1) / 2;
46  double fwT0 = 2 * M_PI * cutoffFreqHz / sampleRateHz;
47 
48  for (int n = -M; n <= M; n++)
49  {
50  if (n == 0) {
51  taps[n + M] = fwT0 / M_PI * window[n + M];
52  } else {
53  taps[n + M] = sin (n * fwT0) / (n * M_PI) * window[n + M];
54  }
55  }
56 
57  double max = taps[0 + M];
58 
59  for (int n = 1; n <= M; n++) {
60  max += 2.0 * taps[n + M];
61  }
62 
63  gain /= max;
64 
65  for (int i = 0; i < ntaps; i++) {
66  taps[i] *= gain;
67  }
68 }
69 
71  m_taps(0),
72  m_alignedTaps(0),
73  m_taps2(0),
74  m_alignedTaps2(0),
75  m_ptr(0),
76  m_phaseSteps(1),
77  m_nTaps(1)
78 {
79 }
80 
82 {
83  free();
84 }
85 
86 void Interpolator::create(int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase)
87 {
88  free();
89 
90  std::vector<Real> taps;
91 
93  taps,
94  phaseSteps, // number of polyphases
95  1.0, // gain
96  phaseSteps * sampleRate, // sampling frequency
97  cutoff, // hz beginning of transition band
98  nbTapsPerPhase);
99 
100  // init state
101  m_ptr = 0;
102  m_nTaps = taps.size() / phaseSteps;
103  m_phaseSteps = phaseSteps;
104  m_samples.resize(m_nTaps + 2);
105 
106  for (int i = 0; i < m_nTaps + 2; i++) {
107  m_samples[i] = 0;
108  }
109 
110  // reorder into polyphase
111  std::vector<Real> polyphase(taps.size());
112 
113  for (int phase = 0; phase < phaseSteps; phase++)
114  {
115  for (int i = 0; i < m_nTaps; i++) {
116  polyphase[phase * m_nTaps + i] = taps[i * phaseSteps + phase];
117  }
118  }
119 
120  // normalize phase filters
121  for (int phase = 0; phase < phaseSteps; phase++)
122  {
123  Real sum = 0;
124 
125  for (int i = phase * m_nTaps; i < phase * m_nTaps + m_nTaps; i++) {
126  sum += polyphase[i];
127  }
128 
129  for (int i = phase * m_nTaps; i < phase * m_nTaps + m_nTaps; i++) {
130  polyphase[i] /= sum;
131  }
132  }
133 
134  // move taps around to match sse storage requirements
135  m_taps = new float[2 * taps.size() + 8];
136 
137  for (uint i = 0; i < 2 * taps.size() + 8; ++i) {
138  m_taps[i] = 0;
139  }
140 
141  m_alignedTaps = (float*)((((quint64)m_taps) + 15) & ~15);
142 
143  for (uint i = 0; i < taps.size(); ++i)
144  {
145  m_alignedTaps[2 * i + 0] = polyphase[i];
146  m_alignedTaps[2 * i + 1] = polyphase[i];
147  }
148 
149  m_taps2 = new float[2 * taps.size() + 8];
150 
151  for (uint i = 0; i < 2 * taps.size() + 8; ++i) {
152  m_taps2[i] = 0;
153  }
154 
155  m_alignedTaps2 = (float*)((((quint64)m_taps2) + 15) & ~15);
156 
157  for (uint i = 1; i < taps.size(); ++i)
158  {
159  m_alignedTaps2[2 * (i - 1) + 0] = polyphase[i];
160  m_alignedTaps2[2 * (i - 1) + 1] = polyphase[i];
161  }
162 }
163 
165 {
166  if (m_taps != NULL)
167  {
168  delete[] m_taps;
169  m_taps = NULL;
170  m_alignedTaps = NULL;
171  delete[] m_taps2;
172  m_taps2 = NULL;
173  m_alignedTaps2 = NULL;
174  }
175 }
Fixed< IntType, IntBits > cos(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2271
void create(int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase=4.5)
float * m_taps
Definition: interpolator.h:93
float * m_alignedTaps
Definition: interpolator.h:94
#define M_PI
Definition: rdsdemod.cpp:27
static void createPolyphaseLowPass(std::vector< Real > &taps, int phaseSteps, double gain, double sampleRateHz, double cutoffFreqHz, double transitionWidthHz, double oobAttenuationdB)
Definition: interpolator.cpp:7
float * m_alignedTaps2
Definition: interpolator.h:96
Fixed< IntType, IntBits > sin(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2265
std::vector< Complex > m_samples
Definition: interpolator.h:97
int32_t i
Definition: decimators.h:244
float * m_taps2
Definition: interpolator.h:95
float Real
Definition: dsptypes.h:42
T max(const T &x, const T &y)
Definition: framework.h:446