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.
Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
Interpolator Class Reference

#include <interpolator.h>

Public Member Functions

 Interpolator ()
 
 ~Interpolator ()
 
void create (int phaseSteps, double sampleRate, double cutoff, double nbTapsPerPhase=4.5)
 
void free ()
 
bool decimate (Real *distance, const Complex &next, Complex *result)
 
bool interpolate (Real *distance, const Complex &next, Complex *result)
 
bool resample (Real *distance, const Complex &next, bool *consumed, Complex *result)
 

Private Member Functions

void createTaps (int nTaps, double sampleRate, double cutoff, std::vector< Real > *taps)
 
void advanceFilter (const Complex &next)
 
void advanceFilter ()
 
void doInterpolate (int phase, Complex *result)
 

Static Private Member Functions

static void createPolyphaseLowPass (std::vector< Real > &taps, int phaseSteps, double gain, double sampleRateHz, double cutoffFreqHz, double transitionWidthHz, double oobAttenuationdB)
 
static void createPolyphaseLowPass (std::vector< Real > &taps, int phaseSteps, double gain, double sampleRateHz, double cutoffFreqHz, double nbTapsPerPhase)
 

Private Attributes

float * m_taps
 
float * m_alignedTaps
 
float * m_taps2
 
float * m_alignedTaps2
 
std::vector< Complexm_samples
 
int m_ptr
 
int m_phaseSteps
 
int m_nTaps
 

Detailed Description

Definition at line 28 of file interpolator.h.

Constructor & Destructor Documentation

◆ Interpolator()

Interpolator::Interpolator ( )

Definition at line 70 of file interpolator.cpp.

70  :
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 }
float * m_taps
Definition: interpolator.h:93
float * m_alignedTaps
Definition: interpolator.h:94
float * m_alignedTaps2
Definition: interpolator.h:96
float * m_taps2
Definition: interpolator.h:95

◆ ~Interpolator()

Interpolator::~Interpolator ( )

Definition at line 81 of file interpolator.cpp.

References free().

82 {
83  free();
84 }
+ Here is the call graph for this function:

Member Function Documentation

◆ advanceFilter() [1/2]

void Interpolator::advanceFilter ( const Complex next)
inlineprivate

Definition at line 121 of file interpolator.h.

122  {
123  m_ptr--;
124 
125  if (m_ptr < 0) {
126  m_ptr = m_nTaps - 1;
127  }
128 
129  m_samples[m_ptr] = next;
130  }
std::vector< Complex > m_samples
Definition: interpolator.h:97

◆ advanceFilter() [2/2]

void Interpolator::advanceFilter ( )
inlineprivate

Definition at line 132 of file interpolator.h.

133  {
134  m_ptr--;
135 
136  if (m_ptr < 0) {
137  m_ptr = m_nTaps - 1;
138  }
139 
140  m_samples[m_ptr].real(0.0);
141  m_samples[m_ptr].imag(0.0);
142  }
std::vector< Complex > m_samples
Definition: interpolator.h:97

◆ create()

void Interpolator::create ( int  phaseSteps,
double  sampleRate,
double  cutoff,
double  nbTapsPerPhase = 4.5 
)

Definition at line 86 of file interpolator.cpp.

References createPolyphaseLowPass(), free(), i, m_alignedTaps, m_alignedTaps2, m_nTaps, m_phaseSteps, m_ptr, m_samples, m_taps, and m_taps2.

Referenced by WFMDemod::applyAudioSampleRate(), AMDemod::applyAudioSampleRate(), NFMDemod::applyAudioSampleRate(), BFMDemod::applyAudioSampleRate(), WFMMod::applyAudioSampleRate(), AMMod::applyAudioSampleRate(), NFMMod::applyAudioSampleRate(), SSBDemod::applyAudioSampleRate(), SSBMod::applyAudioSampleRate(), ChannelAnalyzer::applyChannelSettings(), WFMDemod::applyChannelSettings(), AMDemod::applyChannelSettings(), UDPSink::applyChannelSettings(), UDPSource::applyChannelSettings(), NFMDemod::applyChannelSettings(), DSDDemod::applyChannelSettings(), BFMDemod::applyChannelSettings(), WFMMod::applyChannelSettings(), AMMod::applyChannelSettings(), NFMMod::applyChannelSettings(), SSBDemod::applyChannelSettings(), FreeDVMod::applyChannelSettings(), SSBMod::applyChannelSettings(), FreeDVDemod::applyChannelSettings(), ATVMod::applyChannelSettings(), AMMod::applyFeedbackAudioSampleRate(), NFMMod::applyFeedbackAudioSampleRate(), SSBMod::applyFeedbackAudioSampleRate(), FreeDVMod::applyFreeDVMode(), FreeDVDemod::applyFreeDVMode(), ChannelAnalyzer::applySettings(), WFMDemod::applySettings(), AMDemod::applySettings(), UDPSink::applySettings(), UDPSource::applySettings(), NFMDemod::applySettings(), DSDDemod::applySettings(), BFMDemod::applySettings(), WFMMod::applySettings(), AMMod::applySettings(), NFMMod::applySettings(), SSBDemod::applySettings(), SSBMod::applySettings(), ATVDemod::applySettings(), ATVMod::applySettings(), LoRaDemod::handleMessage(), LoRaDemod::LoRaDemod(), FreqTracker::setInterpolator(), and UDPSink::UDPSink().

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 }
float * m_taps
Definition: interpolator.h:93
float * m_alignedTaps
Definition: interpolator.h:94
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
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
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ createPolyphaseLowPass() [1/2]

void Interpolator::createPolyphaseLowPass ( std::vector< Real > &  taps,
int  phaseSteps,
double  gain,
double  sampleRateHz,
double  cutoffFreqHz,
double  transitionWidthHz,
double  oobAttenuationdB 
)
staticprivate

Definition at line 7 of file interpolator.cpp.

Referenced by create().

15 {
16  double nbTapsPerPhase = (oobAttenuationdB * sampleRateHz) / (22.0 * transitionWidthHz * phaseSteps);
17  return createPolyphaseLowPass(taps, phaseSteps, gain, sampleRateHz, cutoffFreqHz, nbTapsPerPhase);
18 }
static void createPolyphaseLowPass(std::vector< Real > &taps, int phaseSteps, double gain, double sampleRateHz, double cutoffFreqHz, double transitionWidthHz, double oobAttenuationdB)
Definition: interpolator.cpp:7
+ Here is the caller graph for this function:

◆ createPolyphaseLowPass() [2/2]

void Interpolator::createPolyphaseLowPass ( std::vector< Real > &  taps,
int  phaseSteps,
double  gain,
double  sampleRateHz,
double  cutoffFreqHz,
double  nbTapsPerPhase 
)
staticprivate

Definition at line 21 of file interpolator.cpp.

References cos(), i, M_PI, leansdr::max(), and sin().

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 }
Fixed< IntType, IntBits > cos(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2271
#define M_PI
Definition: rdsdemod.cpp:27
Fixed< IntType, IntBits > sin(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2265
int32_t i
Definition: decimators.h:244
T max(const T &x, const T &y)
Definition: framework.h:446
+ Here is the call graph for this function:

◆ createTaps()

void Interpolator::createTaps ( int  nTaps,
double  sampleRate,
double  cutoff,
std::vector< Real > *  taps 
)
private

◆ decimate()

bool Interpolator::decimate ( Real distance,
const Complex next,
Complex result 
)
inline

Definition at line 38 of file interpolator.h.

References floor().

Referenced by LoRaDemod::feed(), WFMDemod::feed(), AMDemod::feed(), DSDDemod::feed(), UDPSink::feed(), SSBDemod::feed(), NFMDemod::feed(), FreqTracker::feed(), BFMDemod::feed(), FreeDVDemod::feed(), ChannelAnalyzer::feed(), ATVDemod::feed(), UDPSource::pull(), AMMod::pull(), NFMMod::pull(), SSBMod::pull(), FreeDVMod::pull(), ATVMod::pull(), AMMod::pushFeedback(), NFMMod::pushFeedback(), and SSBMod::pushFeedback().

39  {
40  advanceFilter(next);
41  *distance -= 1.0;
42 
43  if (*distance >= 1.0) {
44  return false;
45  }
46 
47  doInterpolate((int) floor(*distance * (Real)m_phaseSteps), result);
48 
49  return true;
50  }
void advanceFilter()
Definition: interpolator.h:132
Fixed< IntType, IntBits > floor(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2301
void doInterpolate(int phase, Complex *result)
Definition: interpolator.h:144
float Real
Definition: dsptypes.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ doInterpolate()

void Interpolator::doInterpolate ( int  phase,
Complex result 
)
inlineprivate

Definition at line 144 of file interpolator.h.

References i.

145  {
146  if (phase < 0) {
147  phase = 0;
148  }
149 #if USE_SSE2
150  // beware of the ringbuffer
151  if(m_ptr == 0) {
152  // only one straight block
153  const float* src = (const float*)&m_samples[0];
154  const __m128* filter = (const __m128*)&m_alignedTaps[phase * m_nTaps * 2];
155  __m128 sum = _mm_setzero_ps();
156  int todo = m_nTaps / 2;
157 
158  for(int i = 0; i < todo; i++) {
159  sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(src), *filter));
160  src += 4;
161  filter += 1;
162  }
163 
164  // add upper half to lower half and store
165  _mm_storel_pi((__m64*)result, _mm_add_ps(sum, _mm_shuffle_ps(sum, _mm_setzero_ps(), _MM_SHUFFLE(1, 0, 3, 2))));
166  } else {
167  // two blocks
168  const float* src = (const float*)&m_samples[m_ptr];
169  const __m128* filter = (const __m128*)&m_alignedTaps[phase * m_nTaps * 2];
170  __m128 sum = _mm_setzero_ps();
171 
172  // first block
173  int block = m_nTaps - m_ptr;
174  int todo = block / 2;
175  if(block & 1)
176  todo++;
177  for(int i = 0; i < todo; i++) {
178  sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(src), *filter));
179  src += 4;
180  filter += 1;
181  }
182  if(block & 1) {
183  // one sample beyond the end -> switch coefficient table
184  filter = (const __m128*)&m_alignedTaps2[phase * m_nTaps * 2 + todo * 4 - 4];
185  }
186  // second block
187  src = (const float*)&m_samples[0];
188  block = m_ptr;
189  todo = block / 2;
190  for(int i = 0; i < todo; i++) {
191  sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(src), *filter));
192  src += 4;
193  filter += 1;
194  }
195  if(block & 1) {
196  // one sample remaining
197  sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadl_pi(_mm_setzero_ps(), (const __m64*)src), filter[0]));
198  }
199 
200  // add upper half to lower half and store
201  _mm_storel_pi((__m64*)result, _mm_add_ps(sum, _mm_shuffle_ps(sum, _mm_setzero_ps(), _MM_SHUFFLE(1, 0, 3, 2))));
202  }
203 #else
204  int sample = m_ptr;
205  const Real* coeff = &m_alignedTaps[phase * m_nTaps * 2];
206  Real rAcc = 0;
207  Real iAcc = 0;
208 
209  for (int i = 0; i < m_nTaps; i++) {
210  rAcc += *coeff * m_samples[sample].real();
211  iAcc += *coeff * m_samples[sample].imag();
212  sample = (sample + 1) % m_nTaps;
213  coeff += 2;
214  }
215 
216  *result = Complex(rAcc, iAcc);
217 #endif
218 
219  }
float * m_alignedTaps
Definition: interpolator.h:94
float * m_alignedTaps2
Definition: interpolator.h:96
std::vector< Complex > m_samples
Definition: interpolator.h:97
int32_t i
Definition: decimators.h:244
std::complex< Real > Complex
Definition: dsptypes.h:43
float Real
Definition: dsptypes.h:42

◆ free()

void Interpolator::free ( )

Definition at line 164 of file interpolator.cpp.

References m_alignedTaps, m_alignedTaps2, m_taps, and m_taps2.

Referenced by create(), and ~Interpolator().

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 }
float * m_taps
Definition: interpolator.h:93
float * m_alignedTaps
Definition: interpolator.h:94
float * m_alignedTaps2
Definition: interpolator.h:96
float * m_taps2
Definition: interpolator.h:95
+ Here is the caller graph for this function:

◆ interpolate()

bool Interpolator::interpolate ( Real distance,
const Complex next,
Complex result 
)
inline

Definition at line 53 of file interpolator.h.

References floor().

Referenced by AMDemod::feed(), SSBDemod::feed(), NFMDemod::feed(), FreqTracker::feed(), FreeDVDemod::feed(), UDPSource::pull(), AMMod::pull(), WFMMod::pull(), NFMMod::pull(), SSBMod::pull(), FreeDVMod::pull(), ATVMod::pull(), AMMod::pushFeedback(), NFMMod::pushFeedback(), and SSBMod::pushFeedback().

54  {
55  bool consumed = false;
56 
57  if (*distance >= 1.0)
58  {
59  advanceFilter(next);
60  *distance -= 1.0;
61  consumed = true;
62  }
63 
64  doInterpolate((int)floor(*distance * (Real)m_phaseSteps), result);
65 
66  return consumed;
67  }
void advanceFilter()
Definition: interpolator.h:132
Fixed< IntType, IntBits > floor(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2301
void doInterpolate(int phase, Complex *result)
Definition: interpolator.h:144
float Real
Definition: dsptypes.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ resample()

bool Interpolator::resample ( Real distance,
const Complex next,
bool *  consumed,
Complex result 
)
inline

Definition at line 71 of file interpolator.h.

References floor().

72  {
73  while (*distance >= 1.0)
74  {
75  if (!(*consumed))
76  {
77  advanceFilter(next);
78  *distance -= 1.0;
79  *consumed = true;
80  }
81  else
82  {
83  return false;
84  }
85  }
86 
87  doInterpolate((int)floor(*distance * (Real)m_phaseSteps), result);
88 
89  return true;
90  }
void advanceFilter()
Definition: interpolator.h:132
Fixed< IntType, IntBits > floor(Fixed< IntType, IntBits > const &x)
Definition: fixed.h:2301
void doInterpolate(int phase, Complex *result)
Definition: interpolator.h:144
float Real
Definition: dsptypes.h:42
+ Here is the call graph for this function:

Member Data Documentation

◆ m_alignedTaps

float* Interpolator::m_alignedTaps
private

Definition at line 94 of file interpolator.h.

Referenced by create(), and free().

◆ m_alignedTaps2

float* Interpolator::m_alignedTaps2
private

Definition at line 96 of file interpolator.h.

Referenced by create(), and free().

◆ m_nTaps

int Interpolator::m_nTaps
private

Definition at line 100 of file interpolator.h.

Referenced by create().

◆ m_phaseSteps

int Interpolator::m_phaseSteps
private

Definition at line 99 of file interpolator.h.

Referenced by create().

◆ m_ptr

int Interpolator::m_ptr
private

Definition at line 98 of file interpolator.h.

Referenced by create().

◆ m_samples

std::vector<Complex> Interpolator::m_samples
private

Definition at line 97 of file interpolator.h.

Referenced by create().

◆ m_taps

float* Interpolator::m_taps
private

Definition at line 93 of file interpolator.h.

Referenced by create(), and free().

◆ m_taps2

float* Interpolator::m_taps2
private

Definition at line 95 of file interpolator.h.

Referenced by create(), and free().


The documentation for this class was generated from the following files: