1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Rubber Band Library
5 An audio time-stretching and pitch-shifting library.
6 Copyright 2007-2021 Particular Programs Ltd.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version. See the file
12 COPYING included with this distribution for more information.
13
14 Alternatively, if you have a valid commercial licence for the
15 Rubber Band Library obtained by agreement with the copyright
16 holders, you may redistribute and/or modify it under the terms
17 described in that licence.
18
19 If you wish to distribute code using the Rubber Band Library
20 under terms other than those of the GNU General Public License,
21 you must obtain a valid commercial licence before doing so.
22 */
23
24 #include "Resampler.h"
25
26 #include "../system/Allocators.h"
27 #include "../system/VectorOps.h"
28
29 #include <cstdlib>
30 #include <cmath>
31
32 #include <iostream>
33 #include <algorithm>
34
35 #ifdef HAVE_IPP
36 #include <ippversion.h>
37 #if (IPP_VERSION_MAJOR < 7)
38 #error Unsupported IPP version, must be >= 7
39 #else
40 #include <ipps.h>
41 #endif
42 #endif
43
44 #ifdef HAVE_SAMPLERATE
45 #define HAVE_LIBSAMPLERATE 1
46 #endif
47
48 #ifdef HAVE_LIBSAMPLERATE
49 #include <samplerate.h>
50 #endif
51
52 #ifdef HAVE_LIBRESAMPLE
53 #include <libresample.h>
54 #endif
55
56 #ifdef USE_SPEEX
57 #include "../speex/speex_resampler.h"
58 #endif
59
60 #ifdef USE_BQRESAMPLER
61 #include "BQResampler.h"
62 #endif
63
64 #ifndef HAVE_IPP
65 #ifndef HAVE_LIBSAMPLERATE
66 #ifndef HAVE_LIBRESAMPLE
67 #ifndef USE_SPEEX
68 #ifndef USE_BQRESAMPLER
69 #error No resampler implementation selected!
70 #endif
71 #endif
72 #endif
73 #endif
74 #endif
75
76 #define BQ_R__ R__
77
78 using namespace std;
79
80 namespace RubberBand {
81
82 class Resampler::Impl
83 {
84 public:
~Impl()85 virtual ~Impl() { }
86
87 virtual int resample(float *const BQ_R__ *const BQ_R__ out,
88 int outcount,
89 const float *const BQ_R__ *const BQ_R__ in,
90 int incount,
91 double ratio,
92 bool final) = 0;
93
94 virtual int resampleInterleaved(float *const BQ_R__ out,
95 int outcount,
96 const float *const BQ_R__ in,
97 int incount,
98 double ratio,
99 bool final) = 0;
100
101 virtual int getChannelCount() const = 0;
102 virtual double getEffectiveRatio(double ratio) const = 0;
103
104 virtual void reset() = 0;
105 };
106
107 namespace Resamplers {
108
109 #ifdef HAVE_IPP
110
111 class D_IPP : public Resampler::Impl
112 {
113 public:
114 D_IPP(Resampler::Quality quality, Resampler::RatioChange,
115 int channels, double initialSampleRate,
116 int maxBufferSize, int debugLevel);
117 ~D_IPP();
118
119 int resample(float *const BQ_R__ *const BQ_R__ out,
120 int outcount,
121 const float *const BQ_R__ *const BQ_R__ in,
122 int incount,
123 double ratio,
124 bool final);
125
126 int resampleInterleaved(float *const BQ_R__ out,
127 int outcount,
128 const float *const BQ_R__ in,
129 int incount,
130 double ratio,
131 bool final = false);
132
getChannelCount() const133 int getChannelCount() const { return m_channels; }
getEffectiveRatio(double ratio) const134 double getEffectiveRatio(double ratio) const { return ratio; }
135
136 void reset();
137
138 protected:
139 // to m_outbuf
140 int doResample(int outcount, double ratio, bool final);
141
142 IppsResamplingPolyphase_32f **m_state;
143 double m_initialSampleRate;
144 float **m_inbuf;
145 size_t m_inbufsz;
146 float **m_outbuf;
147 size_t m_outbufsz;
148 int m_bufsize;
149 int m_channels;
150 int m_window;
151 float m_factor;
152 int m_history;
153 int *m_lastread;
154 double *m_time;
155 int m_debugLevel;
156
157 void setBufSize(int);
158 };
159
D_IPP(Resampler::Quality,Resampler::RatioChange,int channels,double initialSampleRate,int maxBufferSize,int debugLevel)160 D_IPP::D_IPP(Resampler::Quality /* quality */,
161 Resampler::RatioChange /* ratioChange */,
162 int channels, double initialSampleRate,
163 int maxBufferSize, int debugLevel) :
164 m_state(0),
165 m_initialSampleRate(initialSampleRate),
166 m_channels(channels),
167 m_debugLevel(debugLevel)
168 {
169 if (m_debugLevel > 0) {
170 cerr << "Resampler::Resampler: using implementation: IPP" << endl;
171 }
172
173 m_window = 32;
174 int nStep = 64;
175 IppHintAlgorithm hint = ippAlgHintFast;
176 m_factor = 8; // initial upper bound on m_ratio, may be amended later
177
178 // This is largely based on the IPP docs and examples. Adapted
179 // from the docs:
180 //
181 // m_time defines the time value for which the first output
182 // sample is calculated. The input vector with indices less
183 // than m_time [whose initial value is m_history below]
184 // contains the history data of filters.
185 //
186 // The history length is [(1/2) window * max(1, 1/factor) ]+1
187 // where window is the size of the ideal lowpass filter
188 // window. The input vector must contain the same number of
189 // elements with indices greater than m_time + length for the
190 // right filter wing for the last element.
191
192 m_history = int(m_window * 0.5 * max(1.0, 1.0 / m_factor)) + 1;
193
194 m_state = new IppsResamplingPolyphase_32f *[m_channels];
195
196 m_lastread = new int[m_channels];
197 m_time = new double[m_channels];
198
199 m_inbufsz = 0;
200 m_outbufsz = 0;
201 m_inbuf = 0;
202 m_outbuf = 0;
203 m_bufsize = 0;
204
205 setBufSize(maxBufferSize + m_history);
206
207 if (m_debugLevel > 1) {
208 cerr << "bufsize = " << m_bufsize << ", window = " << m_window << ", nStep = " << nStep << ", history = " << m_history << endl;
209 }
210
211 int specSize = 0;
212 ippsResamplePolyphaseGetSize_32f(float(m_window),
213 nStep,
214 &specSize,
215 hint);
216 if (specSize == 0) {
217 #ifndef NO_EXCEPTIONS
218 throw Resampler::ImplementationError;
219 #else
220 abort();
221 #endif
222 }
223
224 for (int c = 0; c < m_channels; ++c) {
225 m_state[c] = (IppsResamplingPolyphase_32f *)ippsMalloc_8u(specSize);
226 ippsResamplePolyphaseInit_32f(float(m_window),
227 nStep,
228 0.95f,
229 9.0f,
230 m_state[c],
231 hint);
232
233 m_lastread[c] = m_history;
234 m_time[c] = m_history;
235 }
236
237 if (m_debugLevel > 1) {
238 cerr << "Resampler init done" << endl;
239 }
240 }
241
~D_IPP()242 D_IPP::~D_IPP()
243 {
244 for (int c = 0; c < m_channels; ++c) {
245 ippsFree(m_state[c]);
246 }
247
248 deallocate_channels(m_inbuf, m_channels);
249 deallocate_channels(m_outbuf, m_channels);
250
251 delete[] m_lastread;
252 delete[] m_time;
253 delete[] m_state;
254 }
255
256 void
setBufSize(int sz)257 D_IPP::setBufSize(int sz)
258 {
259 if (m_debugLevel > 1) {
260 if (m_bufsize > 0) {
261 cerr << "resize bufsize " << m_bufsize << " -> ";
262 } else {
263 cerr << "initialise bufsize to ";
264 }
265 }
266
267 m_bufsize = sz;
268
269 if (m_debugLevel > 1) {
270 cerr << m_bufsize << endl;
271 }
272
273 int n1 = m_bufsize + m_history + 2;
274
275 if (m_debugLevel > 1) {
276 cerr << "inbuf allocating " << m_bufsize << " + " << m_history << " + 2 = " << n1 << endl;
277 }
278
279 int n2 = (int)lrintf(ceil((m_bufsize - m_history) * m_factor + 2));
280
281 if (m_debugLevel > 1) {
282 cerr << "outbuf allocating (" << m_bufsize << " - " << m_history << ") * " << m_factor << " + 2 = " << n2 << endl;
283 }
284
285 m_inbuf = reallocate_and_zero_extend_channels
286 (m_inbuf, m_channels, m_inbufsz, m_channels, n1);
287
288 m_outbuf = reallocate_and_zero_extend_channels
289 (m_outbuf, m_channels, m_outbufsz, m_channels, n2);
290
291 m_inbufsz = n1;
292 m_outbufsz = n2;
293 }
294
295 int
resample(float * const BQ_R__ * const BQ_R__ out,int outspace,const float * const BQ_R__ * const BQ_R__ in,int incount,double ratio,bool final)296 D_IPP::resample(float *const BQ_R__ *const BQ_R__ out,
297 int outspace,
298 const float *const BQ_R__ *const BQ_R__ in,
299 int incount,
300 double ratio,
301 bool final)
302 {
303 if (ratio > m_factor) {
304 m_factor = ratio;
305 m_history = int(m_window * 0.5 * max(1.0, 1.0 / m_factor)) + 1;
306 }
307
308 if (m_debugLevel > 2) {
309 cerr << "incount = " << incount << ", ratio = " << ratio << ", est space = " << lrintf(ceil(incount * ratio)) << ", outspace = " << outspace << ", final = " << final << endl;
310 }
311
312 for (int c = 0; c < m_channels; ++c) {
313 if (m_lastread[c] + incount + m_history > m_bufsize) {
314 setBufSize(m_lastread[c] + incount + m_history);
315 }
316 }
317
318 for (int c = 0; c < m_channels; ++c) {
319 for (int i = 0; i < incount; ++i) {
320 m_inbuf[c][m_lastread[c] + i] = in[c][i];
321 }
322 m_lastread[c] += incount;
323 }
324
325 if (m_debugLevel > 2) {
326 cerr << "lastread advanced to " << m_lastread[0] << endl;
327 }
328
329 int got = doResample(outspace, ratio, final);
330
331 for (int c = 0; c < m_channels; ++c) {
332 v_copy(out[c], m_outbuf[c], got);
333 }
334
335 return got;
336 }
337
338 int
resampleInterleaved(float * const BQ_R__ out,int outspace,const float * const BQ_R__ in,int incount,double ratio,bool final)339 D_IPP::resampleInterleaved(float *const BQ_R__ out,
340 int outspace,
341 const float *const BQ_R__ in,
342 int incount,
343 double ratio,
344 bool final)
345 {
346 if (ratio > m_factor) {
347 m_factor = ratio;
348 m_history = int(m_window * 0.5 * max(1.0, 1.0 / m_factor)) + 1;
349 }
350
351 if (m_debugLevel > 2) {
352 cerr << "incount = " << incount << ", ratio = " << ratio << ", est space = " << lrintf(ceil(incount * ratio)) << ", outspace = " << outspace << ", final = " << final << endl;
353 }
354
355 for (int c = 0; c < m_channels; ++c) {
356 if (m_lastread[c] + incount + m_history > m_bufsize) {
357 setBufSize(m_lastread[c] + incount + m_history);
358 }
359 }
360
361 for (int c = 0; c < m_channels; ++c) {
362 for (int i = 0; i < incount; ++i) {
363 m_inbuf[c][m_lastread[c] + i] = in[i * m_channels + c];
364 }
365 m_lastread[c] += incount;
366 }
367
368 if (m_debugLevel > 2) {
369 cerr << "lastread advanced to " << m_lastread[0] << " after injection of "
370 << incount << " samples" << endl;
371 }
372
373 int got = doResample(outspace, ratio, final);
374
375 v_interleave(out, m_outbuf, m_channels, got);
376
377 return got;
378 }
379
380 int
doResample(int outspace,double ratio,bool final)381 D_IPP::doResample(int outspace, double ratio, bool final)
382 {
383 int outcount = 0;
384
385 for (int c = 0; c < m_channels; ++c) {
386
387 int n = m_lastread[c] - m_history - int(m_time[c]);
388
389 if (c == 0 && m_debugLevel > 2) {
390 cerr << "at start, lastread = " << m_lastread[c] << ", history = "
391 << m_history << ", time = " << m_time[c] << ", therefore n = "
392 << n << endl;
393 }
394
395 if (n <= 0) {
396 if (c == 0 && m_debugLevel > 1) {
397 cerr << "not enough input samples to do anything" << endl;
398 }
399 continue;
400 }
401
402 if (c == 0 && m_debugLevel > 2) {
403 cerr << "before resample call, time = " << m_time[c] << endl;
404 }
405
406 // We're committed to not overrunning outspace, so we need to
407 // offer the resampler only enough samples to ensure it won't
408
409 int limit = int(floor(outspace / ratio));
410 if (n > limit) {
411 if (c == 0 && m_debugLevel > 1) {
412 cerr << "trimming input samples from " << n << " to " << limit
413 << " to avoid overrunning " << outspace << " at output"
414 << endl;
415 }
416 n = limit;
417 }
418
419 ippsResamplePolyphase_32f(m_inbuf[c],
420 n,
421 m_outbuf[c],
422 ratio,
423 1.0f,
424 &m_time[c],
425 &outcount,
426 m_state[c]);
427
428 int t = int(floor(m_time[c]));
429
430 int moveFrom = t - m_history;
431
432 if (c == 0 && m_debugLevel > 2) {
433 cerr << "converted " << n << " samples to " << outcount
434 << " (nb outbufsz = " << m_outbufsz
435 << "), time advanced to " << m_time[c] << endl;
436 cerr << "rounding time to " << t << ", lastread = "
437 << m_lastread[c] << ", history = " << m_history << endl;
438 cerr << "will move " << m_lastread[c] - moveFrom
439 << " unconverted samples back from index " << moveFrom
440 << " to 0" << endl;
441 }
442
443 if (moveFrom >= m_lastread[c]) {
444
445 moveFrom = m_lastread[c];
446
447 if (c == 0 && m_debugLevel > 2) {
448 cerr << "number of samples to move is <= 0, "
449 << "not actually moving any" << endl;
450 }
451 } else {
452
453 v_move(m_inbuf[c],
454 m_inbuf[c] + moveFrom,
455 m_lastread[c] - moveFrom);
456 }
457
458 m_lastread[c] -= moveFrom;
459 m_time[c] -= moveFrom;
460
461 if (c == 0 && m_debugLevel > 2) {
462 cerr << "lastread reduced to " << m_lastread[c]
463 << ", time reduced to " << m_time[c]
464 << endl;
465 }
466
467 if (final && n < limit) {
468
469 // Looks like this actually produces too many samples
470 // (additionalcount is a few samples too large).
471
472 // Also, we aren't likely to have enough space in the
473 // output buffer as the caller won't have allowed for
474 // all the samples we're retrieving here.
475
476 // What to do?
477
478 int additionalcount = 0;
479
480 if (c == 0 && m_debugLevel > 2) {
481 cerr << "final call, padding input with " << m_history
482 << " zeros (symmetrical with m_history)" << endl;
483 }
484
485 for (int i = 0; i < m_history; ++i) {
486 m_inbuf[c][m_lastread[c] + i] = 0.f;
487 }
488
489 if (c == 0 && m_debugLevel > 2) {
490 cerr << "before resample call, time = " << m_time[c] << endl;
491 }
492
493 int nAdditional = m_lastread[c] - int(m_time[c]);
494
495 if (n + nAdditional > limit) {
496 if (c == 0 && m_debugLevel > 1) {
497 cerr << "trimming final input samples from " << nAdditional
498 << " to " << (limit - n)
499 << " to avoid overrunning " << outspace << " at output"
500 << endl;
501 }
502 nAdditional = limit - n;
503 }
504
505 ippsResamplePolyphase_32f(m_inbuf[c],
506 nAdditional,
507 m_outbuf[c],
508 ratio,
509 1.0f,
510 &m_time[c],
511 &additionalcount,
512 m_state[c]);
513
514 if (c == 0 && m_debugLevel > 2) {
515 cerr << "converted " << n << " samples to " << additionalcount
516 << ", time advanced to " << m_time[c] << endl;
517 cerr << "outcount = " << outcount << ", additionalcount = " << additionalcount << ", sum " << outcount + additionalcount << endl;
518 }
519
520 if (c == 0) {
521 outcount += additionalcount;
522 }
523 }
524 }
525
526 if (m_debugLevel > 2) {
527 cerr << "returning " << outcount << " samples" << endl;
528 }
529
530 return outcount;
531 }
532
533 void
reset()534 D_IPP::reset()
535 {
536 //!!!
537 }
538
539 #endif /* HAVE_IPP */
540
541 #ifdef HAVE_LIBSAMPLERATE
542
543 class D_SRC : public Resampler::Impl
544 {
545 public:
546 D_SRC(Resampler::Quality quality, Resampler::RatioChange ratioChange,
547 int channels, double initialSampleRate,
548 int maxBufferSize, int m_debugLevel);
549 ~D_SRC();
550
551 int resample(float *const BQ_R__ *const BQ_R__ out,
552 int outcount,
553 const float *const BQ_R__ *const BQ_R__ in,
554 int incount,
555 double ratio,
556 bool final);
557
558 int resampleInterleaved(float *const BQ_R__ out,
559 int outcount,
560 const float *const BQ_R__ in,
561 int incount,
562 double ratio,
563 bool final = false);
564
getChannelCount() const565 int getChannelCount() const { return m_channels; }
getEffectiveRatio(double ratio) const566 double getEffectiveRatio(double ratio) const { return ratio; }
567
568 void reset();
569
570 protected:
571 SRC_STATE *m_src;
572 float *m_iin;
573 float *m_iout;
574 int m_channels;
575 int m_iinsize;
576 int m_ioutsize;
577 double m_prevRatio;
578 bool m_ratioUnset;
579 bool m_smoothRatios;
580 int m_debugLevel;
581 };
582
D_SRC(Resampler::Quality quality,Resampler::RatioChange ratioChange,int channels,double,int maxBufferSize,int debugLevel)583 D_SRC::D_SRC(Resampler::Quality quality, Resampler::RatioChange ratioChange,
584 int channels, double, int maxBufferSize, int debugLevel) :
585 m_src(0),
586 m_iin(0),
587 m_iout(0),
588 m_channels(channels),
589 m_iinsize(0),
590 m_ioutsize(0),
591 m_prevRatio(1.0),
592 m_ratioUnset(true),
593 m_smoothRatios(ratioChange == Resampler::SmoothRatioChange),
594 m_debugLevel(debugLevel)
595 {
596 if (m_debugLevel > 0) {
597 cerr << "Resampler::Resampler: using implementation: libsamplerate"
598 << endl;
599 }
600
601 if (channels < 1) {
602 cerr << "Resampler::Resampler: unable to create resampler: invalid channel count " << channels << " supplied" << endl;
603 #ifdef NO_EXCEPTIONS
604 throw Resampler::ImplementationError;
605 #endif
606 return;
607 }
608
609 int err = 0;
610 m_src = src_new(quality == Resampler::Best ? SRC_SINC_BEST_QUALITY :
611 quality == Resampler::Fastest ? SRC_SINC_FASTEST :
612 SRC_SINC_MEDIUM_QUALITY,
613 channels, &err);
614
615 if (err) {
616 cerr << "Resampler::Resampler: failed to create libsamplerate resampler: "
617 << src_strerror(err) << endl;
618 #ifndef NO_EXCEPTIONS
619 throw Resampler::ImplementationError;
620 #endif
621 return;
622 } else if (!m_src) {
623 cerr << "Resampler::Resampler: failed to create libsamplerate resampler, but no error reported?" << endl;
624 #ifndef NO_EXCEPTIONS
625 throw Resampler::ImplementationError;
626 #endif
627 return;
628 }
629
630 if (maxBufferSize > 0 && m_channels > 1) {
631 m_iinsize = maxBufferSize * m_channels;
632 m_ioutsize = maxBufferSize * m_channels * 2;
633 m_iin = allocate<float>(m_iinsize);
634 m_iout = allocate<float>(m_ioutsize);
635 }
636
637 reset();
638 }
639
~D_SRC()640 D_SRC::~D_SRC()
641 {
642 src_delete(m_src);
643 deallocate(m_iin);
644 deallocate(m_iout);
645 }
646
647 int
resample(float * const BQ_R__ * const BQ_R__ out,int outcount,const float * const BQ_R__ * const BQ_R__ in,int incount,double ratio,bool final)648 D_SRC::resample(float *const BQ_R__ *const BQ_R__ out,
649 int outcount,
650 const float *const BQ_R__ *const BQ_R__ in,
651 int incount,
652 double ratio,
653 bool final)
654 {
655 if (m_channels == 1) {
656 return resampleInterleaved(*out, outcount, *in, incount, ratio, final);
657 }
658
659 if (incount * m_channels > m_iinsize) {
660 m_iin = reallocate<float>(m_iin, m_iinsize, incount * m_channels);
661 m_iinsize = incount * m_channels;
662 }
663 if (outcount * m_channels > m_ioutsize) {
664 m_iout = reallocate<float>(m_iout, m_ioutsize, outcount * m_channels);
665 m_ioutsize = outcount * m_channels;
666 }
667
668 v_interleave(m_iin, in, m_channels, incount);
669
670 int n = resampleInterleaved(m_iout, outcount, m_iin, incount, ratio, final);
671
672 v_deinterleave(out, m_iout, m_channels, n);
673
674 return n;
675 }
676
677 int
resampleInterleaved(float * const BQ_R__ out,int outcount,const float * const BQ_R__ in,int incount,double ratio,bool final)678 D_SRC::resampleInterleaved(float *const BQ_R__ out,
679 int outcount,
680 const float *const BQ_R__ in,
681 int incount,
682 double ratio,
683 bool final)
684 {
685 SRC_DATA data;
686
687 // libsamplerate smooths the filter change over the duration of
688 // the processing block to avoid artifacts due to sudden changes,
689 // and it uses outcount to determine how long to smooth the change
690 // over. This is a good thing, but it does mean (a) we should
691 // never pass outcount significantly longer than the actual
692 // expected output, and (b) when the ratio has just changed, we
693 // should aim to supply a shortish block next
694
695 if (outcount > int(ceil(incount * ratio) + 5)) {
696 outcount = int(ceil(incount * ratio) + 5);
697 }
698
699 if (m_ratioUnset || !m_smoothRatios) {
700
701 // The first time we set a ratio, we want to do it directly
702 src_set_ratio(m_src, ratio);
703 m_ratioUnset = false;
704 m_prevRatio = ratio;
705
706 } else if (ratio != m_prevRatio) {
707
708 // If we are processing a block of appreciable length, turn it
709 // into two recursive calls, one for the short smoothing block
710 // and the other for the rest. Update m_prevRatio before doing
711 // this so that the calls don't themselves recurse!
712 m_prevRatio = ratio;
713
714 int shortBlock = 200;
715 if (outcount > shortBlock * 2) {
716 int shortIn = int(floor(shortBlock / ratio));
717 if (shortIn >= 10) {
718 int shortOut =
719 resampleInterleaved(out, shortBlock,
720 in, shortIn,
721 ratio, false);
722 int remainingOut = 0;
723 if (shortOut < outcount) {
724 remainingOut =
725 resampleInterleaved(out + shortOut * m_channels,
726 outcount - shortOut,
727 in + shortIn * m_channels,
728 incount - shortIn,
729 ratio, final);
730 }
731 return shortOut + remainingOut;
732 }
733 }
734 }
735
736 data.data_in = const_cast<float *>(in);
737 data.data_out = out;
738
739 data.input_frames = incount;
740 data.output_frames = outcount;
741 data.src_ratio = ratio;
742 data.end_of_input = (final ? 1 : 0);
743
744 int err = src_process(m_src, &data);
745
746 if (err) {
747 cerr << "Resampler::process: libsamplerate error: "
748 << src_strerror(err) << endl;
749 #ifndef NO_EXCEPTIONS
750 throw Resampler::ImplementationError;
751 #endif
752 }
753
754 return (int)data.output_frames_gen;
755 }
756
757 void
reset()758 D_SRC::reset()
759 {
760 src_reset(m_src);
761 m_ratioUnset = true;
762 }
763
764 #endif /* HAVE_LIBSAMPLERATE */
765
766 #ifdef HAVE_LIBRESAMPLE
767
768 class D_Resample : public Resampler::Impl
769 {
770 public:
771 D_Resample(Resampler::Quality quality, Resampler::RatioChange,
772 int channels, double initialSampleRate,
773 int maxBufferSize, int m_debugLevel);
774 ~D_Resample();
775
776 int resample(float *const BQ_R__ *const BQ_R__ out,
777 int outcount,
778 const float *const BQ_R__ *const BQ_R__ in,
779 int incount,
780 double ratio,
781 bool final);
782
783 int resampleInterleaved(float *const BQ_R__ out,
784 int outcount,
785 const float *const BQ_R__ in,
786 int incount,
787 double ratio,
788 bool final);
789
getChannelCount() const790 int getChannelCount() const { return m_channels; }
getEffectiveRatio(double ratio) const791 double getEffectiveRatio(double ratio) const { return ratio; }
792
793 void reset();
794
795 protected:
796 void *m_src;
797 float *m_iin;
798 float *m_iout;
799 double m_lastRatio;
800 int m_channels;
801 int m_iinsize;
802 int m_ioutsize;
803 int m_debugLevel;
804 };
805
D_Resample(Resampler::Quality quality,int channels,double,int maxBufferSize,int debugLevel)806 D_Resample::D_Resample(Resampler::Quality quality,
807 int channels, double, int maxBufferSize, int debugLevel) :
808 m_src(0),
809 m_iin(0),
810 m_iout(0),
811 m_channels(channels),
812 m_iinsize(0),
813 m_ioutsize(0),
814 m_debugLevel(debugLevel)
815 {
816 if (m_debugLevel > 0) {
817 cerr << "Resampler::Resampler: using implementation: libresample"
818 << endl;
819 }
820
821 float min_factor = 0.125f;
822 float max_factor = 8.0f;
823
824 m_src = resample_open(quality == Resampler::Best ? 1 : 0, min_factor, max_factor);
825
826 if (!m_src) {
827 cerr << "Resampler::Resampler: failed to create libresample resampler: "
828 << endl;
829 throw Resampler::ImplementationError; //!!! of course, need to catch this!
830 }
831
832 if (maxBufferSize > 0 && m_channels > 1) {
833 m_iinsize = maxBufferSize * m_channels;
834 m_ioutsize = maxBufferSize * m_channels * 2;
835 m_iin = allocate<float>(m_iinsize);
836 m_iout = allocate<float>(m_ioutsize);
837 }
838
839 reset();
840 }
841
~D_Resample()842 D_Resample::~D_Resample()
843 {
844 resample_close(m_src);
845 if (m_iinsize > 0) {
846 deallocate(m_iin);
847 }
848 if (m_ioutsize > 0) {
849 deallocate(m_iout);
850 }
851 }
852
853 int
resample(float * const BQ_R__ * const BQ_R__ out,int outcount,const float * const BQ_R__ * const BQ_R__ in,int incount,double ratio,bool final)854 D_Resample::resample(float *const BQ_R__ *const BQ_R__ out,
855 int outcount,
856 const float *const BQ_R__ *const BQ_R__ in,
857 int incount,
858 double ratio,
859 bool final)
860 {
861 float *data_in;
862 float *data_out;
863 int input_frames, output_frames, end_of_input, source_used;
864 float src_ratio;
865
866 int outcount = (int)lrint(ceil(incount * ratio));
867
868 if (m_channels == 1) {
869 data_in = const_cast<float *>(*in); //!!!???
870 data_out = *out;
871 } else {
872 if (incount * m_channels > m_iinsize) {
873 m_iin = reallocate<float>(m_iin, m_iinsize, incount * m_channels);
874 m_iinsize = incount * m_channels;
875 }
876 if (outcount * m_channels > m_ioutsize) {
877 m_iout = reallocate<float>(m_iout, m_ioutsize, outcount * m_channels);
878 m_ioutsize = outcount * m_channels;
879 }
880 v_interleave(m_iin, in, m_channels, incount);
881 data_in = m_iin;
882 data_out = m_iout;
883 }
884
885 input_frames = incount;
886 output_frames = outcount;
887 src_ratio = ratio;
888 end_of_input = (final ? 1 : 0);
889
890 int output_frames_gen = resample_process(m_src,
891 src_ratio,
892 data_in,
893 input_frames,
894 end_of_input,
895 &source_used,
896 data_out,
897 output_frames);
898
899 if (output_frames_gen < 0) {
900 cerr << "Resampler::process: libresample error: "
901 << endl;
902 throw Resampler::ImplementationError; //!!! of course, need to catch this!
903 }
904
905 if (m_channels > 1) {
906 v_deinterleave(out, m_iout, m_channels, output_frames_gen);
907 }
908
909 return output_frames_gen;
910 }
911
912 int
resampleInterleaved(float * const BQ_R__ out,int outcount,const float * const BQ_R__ in,int incount,double ratio,bool final)913 D_Resample::resampleInterleaved(float *const BQ_R__ out,
914 int outcount,
915 const float *const BQ_R__ in,
916 int incount,
917 double ratio,
918 bool final)
919 {
920 int input_frames, output_frames, end_of_input, source_used;
921 float src_ratio;
922
923 int outcount = (int)lrint(ceil(incount * ratio));
924
925 input_frames = incount;
926 output_frames = outcount;
927 src_ratio = ratio;
928 end_of_input = (final ? 1 : 0);
929
930 int output_frames_gen = resample_process(m_src,
931 src_ratio,
932 const_cast<float *>(in),
933 input_frames,
934 end_of_input,
935 &source_used,
936 out,
937 output_frames);
938
939 if (output_frames_gen < 0) {
940 cerr << "Resampler::process: libresample error: "
941 << endl;
942 throw Resampler::ImplementationError; //!!! of course, need to catch this!
943 }
944
945 return output_frames_gen;
946 }
947
948 void
reset()949 D_Resample::reset()
950 {
951 }
952
953 #endif /* HAVE_LIBRESAMPLE */
954
955 #ifdef USE_BQRESAMPLER
956
957 class D_BQResampler : public Resampler::Impl
958 {
959 public:
960 D_BQResampler(Resampler::Parameters params, int channels);
961 ~D_BQResampler();
962
963 int resample(float *const BQ_R__ *const BQ_R__ out,
964 int outcount,
965 const float *const BQ_R__ *const BQ_R__ in,
966 int incount,
967 double ratio,
968 bool final);
969
970 int resampleInterleaved(float *const BQ_R__ out,
971 int outcount,
972 const float *const BQ_R__ in,
973 int incount,
974 double ratio,
975 bool final = false);
976
getChannelCount() const977 int getChannelCount() const {
978 return m_channels;
979 }
980
getEffectiveRatio(double ratio) const981 double getEffectiveRatio(double ratio) const {
982 return m_resampler->getEffectiveRatio(ratio);
983 }
984
985 void reset();
986
987 protected:
988 BQResampler *m_resampler;
989 float *m_iin;
990 float *m_iout;
991 int m_channels;
992 int m_iinsize;
993 int m_ioutsize;
994 int m_debugLevel;
995 };
996
D_BQResampler(Resampler::Parameters params,int channels)997 D_BQResampler::D_BQResampler(Resampler::Parameters params, int channels) :
998 m_resampler(0),
999 m_iin(0),
1000 m_iout(0),
1001 m_channels(channels),
1002 m_iinsize(0),
1003 m_ioutsize(0),
1004 m_debugLevel(params.debugLevel)
1005 {
1006 if (m_debugLevel > 0) {
1007 cerr << "Resampler::Resampler: using implementation: BQResampler" << endl;
1008 }
1009
1010 BQResampler::Parameters rparams;
1011 switch (params.quality) {
1012 case Resampler::Best:
1013 rparams.quality = BQResampler::Best;
1014 break;
1015 case Resampler::FastestTolerable:
1016 rparams.quality = BQResampler::FastestTolerable;
1017 break;
1018 case Resampler::Fastest:
1019 rparams.quality = BQResampler::Fastest;
1020 break;
1021 }
1022 switch (params.dynamism) {
1023 case Resampler::RatioOftenChanging:
1024 rparams.dynamism = BQResampler::RatioOftenChanging;
1025 break;
1026 case Resampler::RatioMostlyFixed:
1027 rparams.dynamism = BQResampler::RatioMostlyFixed;
1028 break;
1029 }
1030 switch (params.ratioChange) {
1031 case Resampler::SmoothRatioChange:
1032 rparams.ratioChange = BQResampler::SmoothRatioChange;
1033 break;
1034 case Resampler::SuddenRatioChange:
1035 rparams.ratioChange = BQResampler::SuddenRatioChange;
1036 break;
1037 }
1038 rparams.referenceSampleRate = params.initialSampleRate;
1039 rparams.debugLevel = params.debugLevel;
1040
1041 m_resampler = new BQResampler(rparams, m_channels);
1042
1043 if (params.maxBufferSize > 0 && m_channels > 1) {
1044 m_iinsize = params.maxBufferSize * m_channels;
1045 m_ioutsize = params.maxBufferSize * m_channels * 2;
1046 m_iin = allocate<float>(m_iinsize);
1047 m_iout = allocate<float>(m_ioutsize);
1048 }
1049 }
1050
~D_BQResampler()1051 D_BQResampler::~D_BQResampler()
1052 {
1053 delete m_resampler;
1054 deallocate(m_iin);
1055 deallocate(m_iout);
1056 }
1057
1058 int
resample(float * const BQ_R__ * const BQ_R__ out,int outcount,const float * const BQ_R__ * const BQ_R__ in,int incount,double ratio,bool final)1059 D_BQResampler::resample(float *const BQ_R__ *const BQ_R__ out,
1060 int outcount,
1061 const float *const BQ_R__ *const BQ_R__ in,
1062 int incount,
1063 double ratio,
1064 bool final)
1065 {
1066 if (m_channels == 1) {
1067 return resampleInterleaved(*out, outcount, *in, incount, ratio, final);
1068 }
1069
1070 if (incount * m_channels > m_iinsize) {
1071 m_iin = reallocate<float>(m_iin, m_iinsize, incount * m_channels);
1072 m_iinsize = incount * m_channels;
1073 }
1074 if (outcount * m_channels > m_ioutsize) {
1075 m_iout = reallocate<float>(m_iout, m_ioutsize, outcount * m_channels);
1076 m_ioutsize = outcount * m_channels;
1077 }
1078
1079 v_interleave(m_iin, in, m_channels, incount);
1080
1081 int n = resampleInterleaved(m_iout, outcount, m_iin, incount, ratio, final);
1082
1083 v_deinterleave(out, m_iout, m_channels, n);
1084
1085 return n;
1086 }
1087
1088 int
resampleInterleaved(float * const BQ_R__ out,int outcount,const float * const BQ_R__ in,int incount,double ratio,bool final)1089 D_BQResampler::resampleInterleaved(float *const BQ_R__ out,
1090 int outcount,
1091 const float *const BQ_R__ in,
1092 int incount,
1093 double ratio,
1094 bool final)
1095 {
1096 return m_resampler->resampleInterleaved(out, outcount,
1097 in, incount,
1098 ratio, final);
1099 }
1100
1101 void
reset()1102 D_BQResampler::reset()
1103 {
1104 m_resampler->reset();
1105 }
1106
1107 #endif /* USE_BQRESAMPLER */
1108
1109 #ifdef USE_SPEEX
1110
1111 class D_Speex : public Resampler::Impl
1112 {
1113 public:
1114 D_Speex(Resampler::Quality quality, Resampler::RatioChange,
1115 int channels, double initialSampleRate,
1116 int maxBufferSize, int debugLevel);
1117 ~D_Speex();
1118
1119 int resample(float *const BQ_R__ *const BQ_R__ out,
1120 int outcount,
1121 const float *const BQ_R__ *const BQ_R__ in,
1122 int incount,
1123 double ratio,
1124 bool final);
1125
1126 int resampleInterleaved(float *const BQ_R__ out,
1127 int outcount,
1128 const float *const BQ_R__ in,
1129 int incount,
1130 double ratio,
1131 bool final = false);
1132
getChannelCount() const1133 int getChannelCount() const { return m_channels; }
getEffectiveRatio(double ratio) const1134 double getEffectiveRatio(double ratio) const { return ratio; }
1135
1136 void reset();
1137
1138 protected:
1139 SpeexResamplerState *m_resampler;
1140 double m_initialSampleRate;
1141 float *m_iin;
1142 float *m_iout;
1143 int m_channels;
1144 int m_iinsize;
1145 int m_ioutsize;
1146 double m_lastratio;
1147 bool m_initial;
1148 int m_debugLevel;
1149
1150 void setRatio(double);
1151 void doResample(const float *in, unsigned int &incount,
1152 float *out, unsigned int &outcount,
1153 double ratio, bool final);
1154 };
1155
D_Speex(Resampler::Quality quality,Resampler::RatioChange,int channels,double initialSampleRate,int maxBufferSize,int debugLevel)1156 D_Speex::D_Speex(Resampler::Quality quality, Resampler::RatioChange,
1157 int channels, double initialSampleRate,
1158 int maxBufferSize, int debugLevel) :
1159 m_resampler(0),
1160 m_initialSampleRate(initialSampleRate),
1161 m_iin(0),
1162 m_iout(0),
1163 m_channels(channels),
1164 m_iinsize(0),
1165 m_ioutsize(0),
1166 m_lastratio(-1.0),
1167 m_initial(true),
1168 m_debugLevel(debugLevel)
1169 {
1170 int q = (quality == Resampler::Best ? 10 :
1171 quality == Resampler::Fastest ? 0 : 4);
1172
1173 if (m_debugLevel > 0) {
1174 cerr << "Resampler::Resampler: using implementation: Speex with q = "
1175 << q << endl;
1176 }
1177
1178 int rrate = int(round(m_initialSampleRate));
1179
1180 int err = 0;
1181 m_resampler = speex_resampler_init_frac(m_channels,
1182 1, 1,
1183 rrate, rrate,
1184 q,
1185 &err);
1186
1187
1188 if (err) {
1189 cerr << "Resampler::Resampler: failed to create Speex resampler"
1190 << endl;
1191 #ifndef NO_EXCEPTIONS
1192 throw Resampler::ImplementationError;
1193 #endif
1194 }
1195
1196 if (maxBufferSize > 0 && m_channels > 1) {
1197 m_iinsize = maxBufferSize * m_channels;
1198 m_ioutsize = maxBufferSize * m_channels * 2;
1199 m_iin = allocate<float>(m_iinsize);
1200 m_iout = allocate<float>(m_ioutsize);
1201 }
1202 }
1203
~D_Speex()1204 D_Speex::~D_Speex()
1205 {
1206 speex_resampler_destroy(m_resampler);
1207 deallocate<float>(m_iin);
1208 deallocate<float>(m_iout);
1209 }
1210
1211 void
setRatio(double ratio)1212 D_Speex::setRatio(double ratio)
1213 {
1214 // Speex wants a ratio of two unsigned integers, not a single
1215 // float. Let's do that.
1216
1217 unsigned int big = 272408136U;
1218 unsigned int denom = 1, num = 1;
1219
1220 if (ratio < 1.f) {
1221 denom = big;
1222 double dnum = double(big) * double(ratio);
1223 num = (unsigned int)dnum;
1224 } else if (ratio > 1.f) {
1225 num = big;
1226 double ddenom = double(big) / double(ratio);
1227 denom = (unsigned int)ddenom;
1228 }
1229
1230 if (m_debugLevel > 1) {
1231 cerr << "D_Speex: Desired ratio " << ratio << ", requesting ratio "
1232 << num << "/" << denom << " = " << float(double(num)/double(denom))
1233 << endl;
1234 }
1235
1236 int fromRate = int(round(m_initialSampleRate));
1237 int toRate = int(round(m_initialSampleRate * ratio));
1238
1239 int err = speex_resampler_set_rate_frac
1240 (m_resampler, denom, num, fromRate, toRate);
1241
1242 if (err) {
1243 cerr << "Resampler::Resampler: failed to set rate on Speex resampler"
1244 << endl;
1245 #ifndef NO_EXCEPTIONS
1246 throw Resampler::ImplementationError;
1247 #endif
1248 }
1249
1250 speex_resampler_get_ratio(m_resampler, &denom, &num);
1251
1252 if (m_debugLevel > 1) {
1253 cerr << "D_Speex: Desired ratio " << ratio << ", got ratio "
1254 << num << "/" << denom << " = " << float(double(num)/double(denom))
1255 << endl;
1256 }
1257
1258 m_lastratio = ratio;
1259
1260 if (m_initial) {
1261 speex_resampler_skip_zeros(m_resampler);
1262 m_initial = false;
1263 }
1264 }
1265
1266 int
resample(float * const BQ_R__ * const BQ_R__ out,int outcount,const float * const BQ_R__ * const BQ_R__ in,int incount,double ratio,bool final)1267 D_Speex::resample(float *const BQ_R__ *const BQ_R__ out,
1268 int outcount,
1269 const float *const BQ_R__ *const BQ_R__ in,
1270 int incount,
1271 double ratio,
1272 bool final)
1273 {
1274 if (ratio != m_lastratio) {
1275 setRatio(ratio);
1276 }
1277
1278 unsigned int uincount = incount;
1279 unsigned int uoutcount = outcount;
1280
1281 float *data_in, *data_out;
1282
1283 if (m_channels == 1) {
1284 data_in = const_cast<float *>(*in);
1285 data_out = *out;
1286 } else {
1287 if (int(incount * m_channels) > m_iinsize) {
1288 m_iin = reallocate<float>(m_iin, m_iinsize, incount * m_channels);
1289 m_iinsize = incount * m_channels;
1290 }
1291 if (int(outcount * m_channels) > m_ioutsize) {
1292 m_iout = reallocate<float>(m_iout, m_ioutsize, outcount * m_channels);
1293 m_ioutsize = outcount * m_channels;
1294 }
1295 v_interleave(m_iin, in, m_channels, incount);
1296 data_in = m_iin;
1297 data_out = m_iout;
1298 }
1299
1300 doResample(data_in, uincount, data_out, uoutcount, ratio, final);
1301
1302 if (m_channels > 1) {
1303 v_deinterleave(out, m_iout, m_channels, uoutcount);
1304 }
1305
1306 return uoutcount;
1307 }
1308
1309 int
resampleInterleaved(float * const BQ_R__ out,int outcount,const float * const BQ_R__ in,int incount,double ratio,bool final)1310 D_Speex::resampleInterleaved(float *const BQ_R__ out,
1311 int outcount,
1312 const float *const BQ_R__ in,
1313 int incount,
1314 double ratio,
1315 bool final)
1316 {
1317 if (ratio != m_lastratio) {
1318 setRatio(ratio);
1319 }
1320
1321 unsigned int uincount = incount;
1322 unsigned int uoutcount = outcount;
1323
1324 float *data_in = const_cast<float *>(in);
1325 float *data_out = out;
1326
1327 doResample(data_in, uincount, data_out, uoutcount, ratio, final);
1328
1329 return uoutcount;
1330 }
1331
1332 void
doResample(const float * data_in,unsigned int & uincount,float * data_out,unsigned int & uoutcount,double ratio,bool final)1333 D_Speex::doResample(const float *data_in, unsigned int &uincount,
1334 float *data_out, unsigned int &uoutcount,
1335 double ratio, bool final)
1336 {
1337 int initial_outcount = int(uoutcount);
1338
1339 int err = speex_resampler_process_interleaved_float
1340 (m_resampler,
1341 data_in, &uincount,
1342 data_out, &uoutcount);
1343
1344 if (err) {
1345 cerr << "Resampler::Resampler: Speex resampler returned error "
1346 << err << endl;
1347 #ifndef NO_EXCEPTIONS
1348 throw Resampler::ImplementationError;
1349 #endif
1350 }
1351
1352 if (final) {
1353 int actual = int(uoutcount);
1354 int expected = std::min(initial_outcount, int(round(uincount * ratio)));
1355 if (actual < expected) {
1356 unsigned int final_out = expected - actual;
1357 unsigned int final_in = (unsigned int)(round(final_out / ratio));
1358 if (final_in > 0) {
1359 float *pad = allocate_and_zero<float>(final_in * m_channels);
1360 err = speex_resampler_process_interleaved_float
1361 (m_resampler,
1362 pad, &final_in,
1363 data_out + actual * m_channels, &final_out);
1364 deallocate(pad);
1365 uoutcount += final_out;
1366 if (err) {
1367 cerr << "Resampler::Resampler: Speex resampler returned error "
1368 << err << endl;
1369 #ifndef NO_EXCEPTIONS
1370 throw Resampler::ImplementationError;
1371 #endif
1372 }
1373 }
1374 }
1375 }
1376 }
1377
1378 void
reset()1379 D_Speex::reset()
1380 {
1381 m_lastratio = -1.0; // force reset of ratio
1382 m_initial = true;
1383 speex_resampler_reset_mem(m_resampler);
1384 }
1385
1386 #endif
1387
1388 } /* end namespace Resamplers */
1389
Resampler(Resampler::Parameters params,int channels)1390 Resampler::Resampler(Resampler::Parameters params, int channels)
1391 {
1392 m_method = -1;
1393
1394 if (params.initialSampleRate == 0) {
1395 params.initialSampleRate = 44100;
1396 }
1397
1398 switch (params.quality) {
1399
1400 case Resampler::Best:
1401 #ifdef HAVE_IPP
1402 m_method = 0;
1403 #endif
1404 #ifdef USE_SPEEX
1405 m_method = 2;
1406 #endif
1407 #ifdef HAVE_LIBRESAMPLE
1408 m_method = 3;
1409 #endif
1410 #ifdef USE_BQRESAMPLER
1411 m_method = 4;
1412 #endif
1413 #ifdef HAVE_LIBSAMPLERATE
1414 m_method = 1;
1415 #endif
1416 break;
1417
1418 case Resampler::FastestTolerable:
1419 #ifdef HAVE_IPP
1420 m_method = 0;
1421 #endif
1422 #ifdef HAVE_LIBRESAMPLE
1423 m_method = 3;
1424 #endif
1425 #ifdef USE_SPEEX
1426 m_method = 2;
1427 #endif
1428 #ifdef USE_BQRESAMPLER
1429 m_method = 4;
1430 #endif
1431 #ifdef HAVE_LIBSAMPLERATE
1432 m_method = 1;
1433 #endif
1434 break;
1435
1436 case Resampler::Fastest:
1437 #ifdef HAVE_IPP
1438 m_method = 0;
1439 #endif
1440 #ifdef HAVE_LIBRESAMPLE
1441 m_method = 3;
1442 #endif
1443 #ifdef USE_SPEEX
1444 m_method = 2;
1445 #endif
1446 #ifdef USE_BQRESAMPLER
1447 m_method = 4;
1448 #endif
1449 #ifdef HAVE_LIBSAMPLERATE
1450 m_method = 1;
1451 #endif
1452 break;
1453 }
1454
1455 if (m_method == -1) {
1456 cerr << "Resampler::Resampler: No implementation available!" << endl;
1457 abort();
1458 }
1459
1460 switch (m_method) {
1461 case 0:
1462 #ifdef HAVE_IPP
1463 d = new Resamplers::D_IPP
1464 (params.quality, params.ratioChange,
1465 channels,
1466 params.initialSampleRate, params.maxBufferSize, params.debugLevel);
1467 #else
1468 cerr << "Resampler::Resampler: No implementation available!" << endl;
1469 abort();
1470 #endif
1471 break;
1472
1473 case 1:
1474 #ifdef HAVE_LIBSAMPLERATE
1475 d = new Resamplers::D_SRC
1476 (params.quality, params.ratioChange,
1477 channels,
1478 params.initialSampleRate, params.maxBufferSize, params.debugLevel);
1479 #else
1480 cerr << "Resampler::Resampler: No implementation available!" << endl;
1481 abort();
1482 #endif
1483 break;
1484
1485 case 2:
1486 #ifdef USE_SPEEX
1487 d = new Resamplers::D_Speex
1488 (params.quality, params.ratioChange,
1489 channels,
1490 params.initialSampleRate, params.maxBufferSize, params.debugLevel);
1491 #else
1492 cerr << "Resampler::Resampler: No implementation available!" << endl;
1493 abort();
1494 #endif
1495 break;
1496
1497 case 3:
1498 #ifdef HAVE_LIBRESAMPLE
1499 d = new Resamplers::D_Resample
1500 (params.quality, params.ratioChange,
1501 channels,
1502 params.initialSampleRate, params.maxBufferSize, params.debugLevel);
1503 #else
1504 cerr << "Resampler::Resampler: No implementation available!" << endl;
1505 abort();
1506 #endif
1507 break;
1508
1509 case 4:
1510 #ifdef USE_BQRESAMPLER
1511 d = new Resamplers::D_BQResampler(params, channels);
1512 #else
1513 cerr << "Resampler::Resampler: No implementation available!" << endl;
1514 abort();
1515 #endif
1516 break;
1517 }
1518
1519 if (!d) {
1520 cerr << "Resampler::Resampler: Internal error: No implementation selected"
1521 << endl;
1522 abort();
1523 }
1524 }
1525
~Resampler()1526 Resampler::~Resampler()
1527 {
1528 delete d;
1529 }
1530
1531 int
resample(float * const BQ_R__ * const BQ_R__ out,int outcount,const float * const BQ_R__ * const BQ_R__ in,int incount,double ratio,bool final)1532 Resampler::resample(float *const BQ_R__ *const BQ_R__ out,
1533 int outcount,
1534 const float *const BQ_R__ *const BQ_R__ in,
1535 int incount,
1536 double ratio,
1537 bool final)
1538 {
1539 return d->resample(out, outcount, in, incount, ratio, final);
1540 }
1541
1542 int
resampleInterleaved(float * const BQ_R__ out,int outcount,const float * const BQ_R__ in,int incount,double ratio,bool final)1543 Resampler::resampleInterleaved(float *const BQ_R__ out,
1544 int outcount,
1545 const float *const BQ_R__ in,
1546 int incount,
1547 double ratio,
1548 bool final)
1549 {
1550 return d->resampleInterleaved(out, outcount, in, incount, ratio, final);
1551 }
1552
1553 int
getChannelCount() const1554 Resampler::getChannelCount() const
1555 {
1556 return d->getChannelCount();
1557 }
1558
1559 double
getEffectiveRatio(double ratio) const1560 Resampler::getEffectiveRatio(double ratio) const
1561 {
1562 return d->getEffectiveRatio(ratio);
1563 }
1564
1565 void
reset()1566 Resampler::reset()
1567 {
1568 d->reset();
1569 }
1570
1571 }
1572