Mercurial > hg > qm-dsp
comparison dsp/rateconversion/Resampler.cpp @ 398:333e27d1efa1
Fixes to resampler frequency tests
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Mon, 12 May 2014 17:56:08 +0100 |
parents | b63c22ce235b |
children | 6a634a9081a8 |
comparison
equal
deleted
inserted
replaced
397:fd207df9432e | 398:333e27d1efa1 |
---|---|
24 #include <map> | 24 #include <map> |
25 #include <cassert> | 25 #include <cassert> |
26 | 26 |
27 using std::vector; | 27 using std::vector; |
28 using std::map; | 28 using std::map; |
29 using std::cerr; | |
30 using std::endl; | |
29 | 31 |
30 //#define DEBUG_RESAMPLER 1 | 32 //#define DEBUG_RESAMPLER 1 |
31 //#define DEBUG_RESAMPLER_VERBOSE | 33 //#define DEBUG_RESAMPLER_VERBOSE 1 |
32 | 34 |
33 Resampler::Resampler(int sourceRate, int targetRate) : | 35 Resampler::Resampler(int sourceRate, int targetRate) : |
34 m_sourceRate(sourceRate), | 36 m_sourceRate(sourceRate), |
35 m_targetRate(targetRate) | 37 m_targetRate(targetRate) |
36 { | 38 { |
104 | 106 |
105 int inputSpacing = m_targetRate / m_gcd; | 107 int inputSpacing = m_targetRate / m_gcd; |
106 int outputSpacing = m_sourceRate / m_gcd; | 108 int outputSpacing = m_sourceRate / m_gcd; |
107 | 109 |
108 #ifdef DEBUG_RESAMPLER | 110 #ifdef DEBUG_RESAMPLER |
109 std::cerr << "resample " << m_sourceRate << " -> " << m_targetRate | 111 cerr << "resample " << m_sourceRate << " -> " << m_targetRate |
110 << ": inputSpacing " << inputSpacing << ", outputSpacing " | 112 << ": inputSpacing " << inputSpacing << ", outputSpacing " |
111 << outputSpacing << ": filter length " << m_filterLength | 113 << outputSpacing << ": filter length " << m_filterLength |
112 << std::endl; | 114 << endl; |
113 #endif | 115 #endif |
114 | 116 |
115 // Now we have a filter of (odd) length flen in which the lower | 117 // Now we have a filter of (odd) length flen in which the lower |
116 // sample rate corresponds to every n'th point and the higher rate | 118 // sample rate corresponds to every n'th point and the higher rate |
117 // to every m'th where n and m are higher and lower rates divided | 119 // to every m'th where n and m are higher and lower rates divided |
202 p.filter.push_back(filter[i * inputSpacing + phase]); | 204 p.filter.push_back(filter[i * inputSpacing + phase]); |
203 } | 205 } |
204 | 206 |
205 m_phaseData[phase] = p; | 207 m_phaseData[phase] = p; |
206 } | 208 } |
209 | |
210 #ifdef DEBUG_RESAMPLER | |
211 int cp = 0; | |
212 int totDrop = 0; | |
213 for (int i = 0; i < inputSpacing; ++i) { | |
214 cerr << "phase = " << cp << ", drop = " << m_phaseData[cp].drop | |
215 << ", filter length = " << m_phaseData[cp].filter.size() | |
216 << ", next phase = " << m_phaseData[cp].nextPhase << endl; | |
217 totDrop += m_phaseData[cp].drop; | |
218 cp = m_phaseData[cp].nextPhase; | |
219 } | |
220 cerr << "total drop = " << totDrop << endl; | |
221 #endif | |
207 | 222 |
208 // The May implementation of this uses a pull model -- we ask the | 223 // The May implementation of this uses a pull model -- we ask the |
209 // resampler for a certain number of output samples, and it asks | 224 // resampler for a certain number of output samples, and it asks |
210 // its source stream for as many as it needs to calculate | 225 // its source stream for as many as it needs to calculate |
211 // those. This means (among other things) that the source stream | 226 // those. This means (among other things) that the source stream |
264 | 279 |
265 m_buffer = vector<double>(fill, 0); | 280 m_buffer = vector<double>(fill, 0); |
266 m_bufferOrigin = 0; | 281 m_bufferOrigin = 0; |
267 | 282 |
268 #ifdef DEBUG_RESAMPLER | 283 #ifdef DEBUG_RESAMPLER |
269 std::cerr << "initial phase " << m_phase << " (as " << (m_filterLength/2) << " % " << inputSpacing << ")" | 284 cerr << "initial phase " << m_phase << " (as " << (m_filterLength/2) << " % " << inputSpacing << ")" |
270 << ", latency " << m_latency << std::endl; | 285 << ", latency " << m_latency << endl; |
271 #endif | 286 #endif |
272 } | 287 } |
273 | 288 |
274 double | 289 double |
275 Resampler::reconstructOne() | 290 Resampler::reconstructOne() |
281 assert(n + m_bufferOrigin <= (int)m_buffer.size()); | 296 assert(n + m_bufferOrigin <= (int)m_buffer.size()); |
282 | 297 |
283 const double *const __restrict__ buf = m_buffer.data() + m_bufferOrigin; | 298 const double *const __restrict__ buf = m_buffer.data() + m_bufferOrigin; |
284 const double *const __restrict__ filt = pd.filter.data(); | 299 const double *const __restrict__ filt = pd.filter.data(); |
285 | 300 |
286 // std::cerr << "phase = " << m_phase << ", drop = " << pd.drop << ", buffer for reconstruction starts..."; | 301 // cerr << "phase = " << m_phase << ", drop = " << pd.drop << ", buffer for reconstruction starts..."; |
287 // for (int i = 0; i < 20; ++i) { | 302 // for (int i = 0; i < 20; ++i) { |
288 // if (i % 5 == 0) std::cerr << "\n" << i << " "; | 303 // if (i % 5 == 0) cerr << "\n" << i << " "; |
289 // std::cerr << buf[i] << " "; | 304 // cerr << buf[i] << " "; |
290 // } | 305 // } |
291 // std::cerr << std::endl; | 306 // cerr << endl; |
292 | 307 |
293 for (int i = 0; i < n; ++i) { | 308 for (int i = 0; i < n; ++i) { |
294 // NB gcc can only vectorize this with -ffast-math | 309 // NB gcc can only vectorize this with -ffast-math |
295 v += buf[i] * filt[i]; | 310 v += buf[i] * filt[i]; |
296 } | 311 } |
309 | 324 |
310 int maxout = int(ceil(double(n) * m_targetRate / m_sourceRate)); | 325 int maxout = int(ceil(double(n) * m_targetRate / m_sourceRate)); |
311 int outidx = 0; | 326 int outidx = 0; |
312 | 327 |
313 #ifdef DEBUG_RESAMPLER | 328 #ifdef DEBUG_RESAMPLER |
314 std::cerr << "process: buf siz " << m_buffer.size() << " filt siz for phase " << m_phase << " " << m_phaseData[m_phase].filter.size() << std::endl; | 329 cerr << "process: buf siz " << m_buffer.size() << " filt siz for phase " << m_phase << " " << m_phaseData[m_phase].filter.size() << endl; |
315 #endif | 330 #endif |
316 | 331 |
317 double scaleFactor = (double(m_targetRate) / m_gcd) / m_peakToPole; | 332 double scaleFactor = (double(m_targetRate) / m_gcd) / m_peakToPole; |
318 | 333 |
319 while (outidx < maxout && | 334 while (outidx < maxout && |
326 m_bufferOrigin = 0; | 341 m_bufferOrigin = 0; |
327 | 342 |
328 return outidx; | 343 return outidx; |
329 } | 344 } |
330 | 345 |
331 std::vector<double> | 346 vector<double> |
332 Resampler::process(const double *src, int n) | 347 Resampler::process(const double *src, int n) |
333 { | 348 { |
334 int maxout = int(ceil(double(n) * m_targetRate / m_sourceRate)); | 349 int maxout = int(ceil(double(n) * m_targetRate / m_sourceRate)); |
335 std::vector<double> out(maxout, 0.0); | 350 vector<double> out(maxout, 0.0); |
336 int got = process(src, out.data(), n); | 351 int got = process(src, out.data(), n); |
337 assert(got <= maxout); | 352 assert(got <= maxout); |
338 if (got < maxout) out.resize(got); | 353 if (got < maxout) out.resize(got); |
339 return out; | 354 return out; |
340 } | 355 } |
341 | 356 |
342 std::vector<double> | 357 vector<double> |
343 Resampler::resample(int sourceRate, int targetRate, const double *data, int n) | 358 Resampler::resample(int sourceRate, int targetRate, const double *data, int n) |
344 { | 359 { |
345 Resampler r(sourceRate, targetRate); | 360 Resampler r(sourceRate, targetRate); |
346 | 361 |
347 int latency = r.getLatency(); | 362 int latency = r.getLatency(); |
362 | 377 |
363 // in order to return this much output to the user: | 378 // in order to return this much output to the user: |
364 | 379 |
365 int m = int(ceil((double(n) * targetRate) / sourceRate)); | 380 int m = int(ceil((double(n) * targetRate) / sourceRate)); |
366 | 381 |
367 // std::cerr << "n = " << n << ", sourceRate = " << sourceRate << ", targetRate = " << targetRate << ", m = " << m << ", latency = " << latency << ", inputPad = " << inputPad << ", m1 = " << m1 << ", n1 = " << n1 << ", n1 - n = " << n1 - n << std::endl; | 382 #ifdef DEBUG_RESAMPLER |
383 cerr << "n = " << n << ", sourceRate = " << sourceRate << ", targetRate = " << targetRate << ", m = " << m << ", latency = " << latency << ", inputPad = " << inputPad << ", m1 = " << m1 << ", n1 = " << n1 << ", n1 - n = " << n1 - n << endl; | |
384 #endif | |
368 | 385 |
369 vector<double> pad(n1 - n, 0.0); | 386 vector<double> pad(n1 - n, 0.0); |
370 vector<double> out(m1 + 1, 0.0); | 387 vector<double> out(m1 + 1, 0.0); |
371 | 388 |
372 int got = r.process(data, out.data(), n); | 389 int gotData = r.process(data, out.data(), n); |
373 got += r.process(pad.data(), out.data() + got, pad.size()); | 390 int gotPad = r.process(pad.data(), out.data() + gotData, pad.size()); |
374 | 391 int got = gotData + gotPad; |
375 #ifdef DEBUG_RESAMPLER | 392 |
376 std::cerr << "resample: " << n << " in, " << got << " out" << std::endl; | 393 #ifdef DEBUG_RESAMPLER |
394 cerr << "resample: " << n << " in, " << pad.size() << " padding, " << got << " out (" << gotData << " data, " << gotPad << " padding, latency = " << latency << ")" << endl; | |
377 #endif | 395 #endif |
378 #ifdef DEBUG_RESAMPLER_VERBOSE | 396 #ifdef DEBUG_RESAMPLER_VERBOSE |
379 std::cerr << "first 10 in:" << std::endl; | 397 int printN = 50; |
380 for (int i = 0; i < 10; ++i) { | 398 cerr << "first " << printN << " in:" << endl; |
381 std::cerr << data[i] << " "; | 399 for (int i = 0; i < printN && i < n; ++i) { |
382 if (i == 5) std::cerr << std::endl; | 400 if (i % 5 == 0) cerr << endl << i << "... "; |
383 } | 401 cerr << data[i] << " "; |
384 std::cerr << std::endl; | 402 } |
403 cerr << endl; | |
385 #endif | 404 #endif |
386 | 405 |
387 int toReturn = got - latency; | 406 int toReturn = got - latency; |
388 if (toReturn > m) toReturn = m; | 407 if (toReturn > m) toReturn = m; |
389 | 408 |
390 vector<double> sliced(out.begin() + latency, | 409 vector<double> sliced(out.begin() + latency, |
391 out.begin() + latency + toReturn); | 410 out.begin() + latency + toReturn); |
392 | 411 |
393 #ifdef DEBUG_RESAMPLER_VERBOSE | 412 #ifdef DEBUG_RESAMPLER_VERBOSE |
394 std::cerr << "all out (after latency compensation), length " << sliced.size() << ":"; | 413 cerr << "first " << printN << " out (after latency compensation), length " << sliced.size() << ":"; |
395 for (int i = 0; i < sliced.size(); ++i) { | 414 for (int i = 0; i < printN && i < sliced.size(); ++i) { |
396 if (i % 5 == 0) std::cerr << std::endl << i << "... "; | 415 if (i % 5 == 0) cerr << endl << i << "... "; |
397 std::cerr << sliced[i] << " "; | 416 cerr << sliced[i] << " "; |
398 } | 417 } |
399 std::cerr << std::endl; | 418 cerr << endl; |
400 #endif | 419 #endif |
401 | 420 |
402 return sliced; | 421 return sliced; |
403 } | 422 } |
404 | 423 |