comparison dsp/rateconversion/Resampler.cpp @ 190:786d446fe22b

Slightly simplify resampler
author Chris Cannam
date Wed, 07 Oct 2015 09:33:28 +0100
parents 3f30343e1de8
children fdaa63607c15
comparison
equal deleted inserted replaced
189:e4a57215ddee 190:786d446fe22b
15 #include "Resampler.h" 15 #include "Resampler.h"
16 16
17 #include "maths/MathUtilities.h" 17 #include "maths/MathUtilities.h"
18 #include "base/KaiserWindow.h" 18 #include "base/KaiserWindow.h"
19 #include "base/SincWindow.h" 19 #include "base/SincWindow.h"
20 #include "thread/Thread.h"
21 20
22 #include <iostream> 21 #include <iostream>
23 #include <vector> 22 #include <vector>
24 #include <map> 23 #include <map>
25 #include <cassert> 24 #include <cassert>
25 #include <algorithm>
26 26
27 using std::vector; 27 using std::vector;
28 using std::map; 28 using std::map;
29 using std::cerr; 29 using std::cerr;
30 using std::endl; 30 using std::endl;
34 34
35 Resampler::Resampler(int sourceRate, int targetRate) : 35 Resampler::Resampler(int sourceRate, int targetRate) :
36 m_sourceRate(sourceRate), 36 m_sourceRate(sourceRate),
37 m_targetRate(targetRate) 37 m_targetRate(targetRate)
38 { 38 {
39 #ifdef DEBUG_RESAMPLER
40 cerr << "Resampler::Resampler(" << sourceRate << "," << targetRate << ")" << endl;
41 #endif
39 initialise(100, 0.02); 42 initialise(100, 0.02);
40 } 43 }
41 44
42 Resampler::Resampler(int sourceRate, int targetRate, 45 Resampler::Resampler(int sourceRate, int targetRate,
43 double snr, double bandwidth) : 46 double snr, double bandwidth) :
50 Resampler::~Resampler() 53 Resampler::~Resampler()
51 { 54 {
52 delete[] m_phaseData; 55 delete[] m_phaseData;
53 } 56 }
54 57
55 // peakToPole -> length -> beta -> window
56 static map<double, map<int, map<double, vector<double> > > >
57 knownFilters;
58
59 static Mutex
60 knownFilterMutex;
61
62 void 58 void
63 Resampler::initialise(double snr, double bandwidth) 59 Resampler::initialise(double snr, double bandwidth)
64 { 60 {
65 int higher = std::max(m_sourceRate, m_targetRate); 61 int higher = std::max(m_sourceRate, m_targetRate);
66 int lower = std::min(m_sourceRate, m_targetRate); 62 int lower = std::min(m_sourceRate, m_targetRate);
83 (params.length > 200001 ? 200001 : params.length); 79 (params.length > 200001 ? 200001 : params.length);
84 80
85 m_filterLength = params.length; 81 m_filterLength = params.length;
86 82
87 vector<double> filter; 83 vector<double> filter;
88 knownFilterMutex.lock(); 84
89 85 KaiserWindow kw(params);
90 if (knownFilters[m_peakToPole][m_filterLength].find(params.beta) == 86 SincWindow sw(m_filterLength, m_peakToPole * 2);
91 knownFilters[m_peakToPole][m_filterLength].end()) { 87
92 88 filter = vector<double>(m_filterLength, 0.0);
93 KaiserWindow kw(params); 89 for (int i = 0; i < m_filterLength; ++i) filter[i] = 1.0;
94 SincWindow sw(m_filterLength, m_peakToPole * 2); 90 sw.cut(filter.data());
95 91 kw.cut(filter.data());
96 filter = vector<double>(m_filterLength, 0.0); 92
97 for (int i = 0; i < m_filterLength; ++i) filter[i] = 1.0;
98 sw.cut(filter.data());
99 kw.cut(filter.data());
100
101 knownFilters[m_peakToPole][m_filterLength][params.beta] = filter;
102 }
103
104 filter = knownFilters[m_peakToPole][m_filterLength][params.beta];
105 knownFilterMutex.unlock();
106
107 int inputSpacing = m_targetRate / m_gcd; 93 int inputSpacing = m_targetRate / m_gcd;
108 int outputSpacing = m_sourceRate / m_gcd; 94 int outputSpacing = m_sourceRate / m_gcd;
109 95
110 #ifdef DEBUG_RESAMPLER 96 #ifdef DEBUG_RESAMPLER
111 cerr << "resample " << m_sourceRate << " -> " << m_targetRate 97 cerr << "resample " << m_sourceRate << " -> " << m_targetRate
291 { 277 {
292 Phase &pd = m_phaseData[m_phase]; 278 Phase &pd = m_phaseData[m_phase];
293 double v = 0.0; 279 double v = 0.0;
294 int n = pd.filter.size(); 280 int n = pd.filter.size();
295 281
296 assert(n + m_bufferOrigin <= (int)m_buffer.size()); 282 if (n + m_bufferOrigin > (int)m_buffer.size()) {
297 283 cerr << "ERROR: n + m_bufferOrigin > m_buffer.size() [" << n << " + "
298 const double *const __restrict__ buf = m_buffer.data() + m_bufferOrigin; 284 << m_bufferOrigin << " > " << m_buffer.size() << "]" << endl;
299 const double *const __restrict__ filt = pd.filter.data(); 285 throw std::logic_error("n + m_bufferOrigin > m_buffer.size()");
286 }
287
288 #if defined(__MSVC__)
289 #define R__ __restrict
290 #elif defined(__GNUC__)
291 #define R__ __restrict__
292 #else
293 #define R__
294 #endif
295
296 const double *const R__ buf(m_buffer.data() + m_bufferOrigin);
297 const double *const R__ filt(pd.filter.data());
300 298
301 for (int i = 0; i < n; ++i) { 299 for (int i = 0; i < n; ++i) {
302 // NB gcc can only vectorize this with -ffast-math 300 // NB gcc can only vectorize this with -ffast-math
303 v += buf[i] * filt[i]; 301 v += buf[i] * filt[i];
304 } 302 }
309 } 307 }
310 308
311 int 309 int
312 Resampler::process(const double *src, double *dst, int n) 310 Resampler::process(const double *src, double *dst, int n)
313 { 311 {
314 for (int i = 0; i < n; ++i) { 312 m_buffer.insert(m_buffer.end(), src, src + n);
315 m_buffer.push_back(src[i]);
316 }
317 313
318 int maxout = int(ceil(double(n) * m_targetRate / m_sourceRate)); 314 int maxout = int(ceil(double(n) * m_targetRate / m_sourceRate));
319 int outidx = 0; 315 int outidx = 0;
320 316
321 #ifdef DEBUG_RESAMPLER 317 #ifdef DEBUG_RESAMPLER
326 322
327 while (outidx < maxout && 323 while (outidx < maxout &&
328 m_buffer.size() >= m_phaseData[m_phase].filter.size() + m_bufferOrigin) { 324 m_buffer.size() >= m_phaseData[m_phase].filter.size() + m_bufferOrigin) {
329 dst[outidx] = scaleFactor * reconstructOne(); 325 dst[outidx] = scaleFactor * reconstructOne();
330 outidx++; 326 outidx++;
327 }
328
329 if (m_bufferOrigin > (int)m_buffer.size()) {
330 cerr << "ERROR: m_bufferOrigin > m_buffer.size() ["
331 << m_bufferOrigin << " > " << m_buffer.size() << "]" << endl;
332 throw std::logic_error("m_bufferOrigin > m_buffer.size()");
331 } 333 }
332 334
333 m_buffer = vector<double>(m_buffer.begin() + m_bufferOrigin, m_buffer.end()); 335 m_buffer = vector<double>(m_buffer.begin() + m_bufferOrigin, m_buffer.end());
334 m_bufferOrigin = 0; 336 m_bufferOrigin = 0;
335 337