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