Mercurial > hg > qm-dsp
comparison dsp/rateconversion/Resampler.cpp @ 156:edb86e0d850c
Lower filter cutoff to below target Nyquist when downsampling
author | Chris Cannam |
---|---|
date | Fri, 01 Nov 2013 12:07:08 +0000 |
parents | 23558405a7d1 |
children | 0a47ec0a1a56 |
comparison
equal
deleted
inserted
replaced
155:529f42b50d81 | 156:edb86e0d850c |
---|---|
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++; |