comparison dsp/rateconversion/Resampler.cpp @ 381:88971211795c

Lower filter cutoff to below target Nyquist when downsampling
author Chris Cannam <c.cannam@qmul.ac.uk>
date Fri, 01 Nov 2013 12:07:08 +0000
parents ad21307eaf99
children 0a47ec0a1a56
comparison
equal deleted inserted replaced
380:1494e18439ae 381:88971211795c
48 { 48 {
49 delete[] m_phaseData; 49 delete[] m_phaseData;
50 } 50 }
51 51
52 // peakToPole -> length -> beta -> window 52 // peakToPole -> length -> beta -> window
53 static map<int, map<int, map<double, vector<double> > > > 53 static map<double, map<int, map<double, vector<double> > > >
54 knownFilters; 54 knownFilters;
55 55
56 static Mutex 56 static Mutex
57 knownFilterMutex; 57 knownFilterMutex;
58 58
61 { 61 {
62 int higher = std::max(m_sourceRate, m_targetRate); 62 int higher = std::max(m_sourceRate, m_targetRate);
63 int lower = std::min(m_sourceRate, m_targetRate); 63 int lower = std::min(m_sourceRate, m_targetRate);
64 64
65 m_gcd = MathUtilities::gcd(lower, higher); 65 m_gcd = MathUtilities::gcd(lower, higher);
66 66 m_peakToPole = higher / m_gcd;
67 int peakToPole = higher / m_gcd; 67
68 if (m_targetRate < m_sourceRate) {
69 // antialiasing filter, should be slightly below nyquist
70 m_peakToPole = m_peakToPole / (1.0 - bandwidth/2.0);
71 }
68 72
69 KaiserWindow::Parameters params = 73 KaiserWindow::Parameters params =
70 KaiserWindow::parametersForBandwidth(snr, bandwidth, peakToPole); 74 KaiserWindow::parametersForBandwidth(snr, bandwidth, higher / m_gcd);
71 75
72 params.length = 76 params.length =
73 (params.length % 2 == 0 ? params.length + 1 : params.length); 77 (params.length % 2 == 0 ? params.length + 1 : params.length);
74 78
75 params.length = 79 params.length =
78 m_filterLength = params.length; 82 m_filterLength = params.length;
79 83
80 vector<double> filter; 84 vector<double> filter;
81 knownFilterMutex.lock(); 85 knownFilterMutex.lock();
82 86
83 if (knownFilters[peakToPole][m_filterLength].find(params.beta) == 87 if (knownFilters[m_peakToPole][m_filterLength].find(params.beta) ==
84 knownFilters[peakToPole][m_filterLength].end()) { 88 knownFilters[m_peakToPole][m_filterLength].end()) {
85 89
86 KaiserWindow kw(params); 90 KaiserWindow kw(params);
87 SincWindow sw(m_filterLength, peakToPole * 2); 91 SincWindow sw(m_filterLength, m_peakToPole * 2);
88 92
89 filter = vector<double>(m_filterLength, 0.0); 93 filter = vector<double>(m_filterLength, 0.0);
90 for (int i = 0; i < m_filterLength; ++i) filter[i] = 1.0; 94 for (int i = 0; i < m_filterLength; ++i) filter[i] = 1.0;
91 sw.cut(filter.data()); 95 sw.cut(filter.data());
92 kw.cut(filter.data()); 96 kw.cut(filter.data());
93 97
94 knownFilters[peakToPole][m_filterLength][params.beta] = filter; 98 knownFilters[m_peakToPole][m_filterLength][params.beta] = filter;
95 } 99 }
96 100
97 filter = knownFilters[peakToPole][m_filterLength][params.beta]; 101 filter = knownFilters[m_peakToPole][m_filterLength][params.beta];
98 knownFilterMutex.unlock(); 102 knownFilterMutex.unlock();
99 103
100 int inputSpacing = m_targetRate / m_gcd; 104 int inputSpacing = m_targetRate / m_gcd;
101 int outputSpacing = m_sourceRate / m_gcd; 105 int outputSpacing = m_sourceRate / m_gcd;
102 106
307 311
308 #ifdef DEBUG_RESAMPLER 312 #ifdef DEBUG_RESAMPLER
309 std::cerr << "process: buf siz " << m_buffer.size() << " filt siz for phase " << m_phase << " " << m_phaseData[m_phase].filter.size() << std::endl; 313 std::cerr << "process: buf siz " << m_buffer.size() << " filt siz for phase " << m_phase << " " << m_phaseData[m_phase].filter.size() << std::endl;
310 #endif 314 #endif
311 315
312 double scaleFactor = 1.0; 316 double scaleFactor = (double(m_targetRate) / m_gcd) / m_peakToPole;
313 if (m_targetRate < m_sourceRate) {
314 scaleFactor = double(m_targetRate) / double(m_sourceRate);
315 }
316 317
317 while (outidx < maxout && 318 while (outidx < maxout &&
318 m_buffer.size() >= m_phaseData[m_phase].filter.size() + m_bufferOrigin) { 319 m_buffer.size() >= m_phaseData[m_phase].filter.size() + m_bufferOrigin) {
319 dst[outidx] = scaleFactor * reconstructOne(); 320 dst[outidx] = scaleFactor * reconstructOne();
320 outidx++; 321 outidx++;