fix for mis-merge of region dialog gain patch (#2879), from colinf
[ardour.git] / libs / rubberband / src / Resampler.cpp
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4     Rubber Band
5     An audio time-stretching and pitch-shifting library.
6     Copyright 2007-2008 Chris Cannam.
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
15 #include "Resampler.h"
16
17 #include "Profiler.h"
18
19 #include <cstdlib>
20 #include <cmath>
21
22 #include <iostream>
23
24
25 #include <samplerate.h>
26
27
28
29 namespace RubberBand {
30
31 class ResamplerImpl
32 {
33 public:
34     virtual ~ResamplerImpl() { }
35     
36     virtual int resample(const float *const R__ *const R__ in, 
37                          float *const R__ *const R__ out,
38                          int incount,
39                          float ratio,
40                          bool final) = 0;
41
42     virtual void reset() = 0;
43 };
44
45 namespace Resamplers {
46
47
48
49 class D_SRC : public ResamplerImpl
50 {
51 public:
52     D_SRC(Resampler::Quality quality, int channels, int maxBufferSize,
53           int m_debugLevel);
54     ~D_SRC();
55
56     int resample(const float *const R__ *const R__ in,
57                  float *const R__ *const R__ out,
58                  int incount,
59                  float ratio,
60                  bool final);
61
62     void reset();
63
64 protected:
65     SRC_STATE *m_src;
66     float *m_iin;
67     float *m_iout;
68     float m_lastRatio;
69     int m_channels;
70     int m_iinsize;
71     int m_ioutsize;
72     int m_debugLevel;
73 };
74
75 D_SRC::D_SRC(Resampler::Quality quality, int channels, int maxBufferSize,
76              int debugLevel) :
77     m_src(0),
78     m_iin(0),
79     m_iout(0),
80     m_lastRatio(1.f),
81     m_channels(channels),
82     m_iinsize(0),
83     m_ioutsize(0),
84     m_debugLevel(debugLevel)
85 {
86     if (m_debugLevel > 0) {
87         std::cerr << "Resampler::Resampler: using libsamplerate implementation"
88                   << std::endl;
89     }
90
91     int err = 0;
92     m_src = src_new(quality == Resampler::Best ? SRC_SINC_BEST_QUALITY :
93                     quality == Resampler::Fastest ? SRC_LINEAR :
94                     SRC_SINC_FASTEST,
95                     channels, &err);
96
97     if (err) {
98         std::cerr << "Resampler::Resampler: failed to create libsamplerate resampler: " 
99                   << src_strerror(err) << std::endl;
100         throw Resampler::ImplementationError; //!!! of course, need to catch this!
101     }
102
103     if (maxBufferSize > 0 && m_channels > 1) {
104         m_iinsize = maxBufferSize * m_channels;
105         m_ioutsize = maxBufferSize * m_channels * 2;
106         m_iin = allocFloat(m_iinsize);
107         m_iout = allocFloat(m_ioutsize);
108     }
109
110     reset();
111 }
112
113 D_SRC::~D_SRC()
114 {
115     src_delete(m_src);
116     if (m_iinsize > 0) {
117         free(m_iin);
118     }
119     if (m_ioutsize > 0) {
120         free(m_iout);
121     }
122 }
123
124 int
125 D_SRC::resample(const float *const R__ *const R__ in,
126                 float *const R__ *const R__ out,
127                 int incount,
128                 float ratio,
129                 bool final)
130 {
131     SRC_DATA data;
132
133     int outcount = lrintf(ceilf(incount * ratio));
134
135     if (m_channels == 1) {
136         data.data_in = const_cast<float *>(*in); //!!!???
137         data.data_out = *out;
138     } else {
139         if (incount * m_channels > m_iinsize) {
140             m_iinsize = incount * m_channels;
141             m_iin = allocFloat(m_iin, m_iinsize);
142         }
143         if (outcount * m_channels > m_ioutsize) {
144             m_ioutsize = outcount * m_channels;
145             m_iout = allocFloat(m_iout, m_ioutsize);
146         }
147         for (int i = 0; i < incount; ++i) {
148             for (int c = 0; c < m_channels; ++c) {
149                 m_iin[i * m_channels + c] = in[c][i];
150             }
151         }
152         data.data_in = m_iin;
153         data.data_out = m_iout;
154     }
155
156     data.input_frames = incount;
157     data.output_frames = outcount;
158     data.src_ratio = ratio;
159     data.end_of_input = (final ? 1 : 0);
160
161     int err = 0;
162     err = src_process(m_src, &data);
163
164     if (err) {
165         std::cerr << "Resampler::process: libsamplerate error: "
166                   << src_strerror(err) << std::endl;
167         throw Resampler::ImplementationError; //!!! of course, need to catch this!
168     }
169
170     if (m_channels > 1) {
171         for (int i = 0; i < data.output_frames_gen; ++i) {
172             for (int c = 0; c < m_channels; ++c) {
173                 out[c][i] = m_iout[i * m_channels + c];
174             }
175         }
176     }
177
178     m_lastRatio = ratio;
179
180     return data.output_frames_gen;
181 }
182
183 void
184 D_SRC::reset()
185 {
186     src_reset(m_src);
187 }
188
189
190
191 } /* end namespace Resamplers */
192
193 Resampler::Resampler(Resampler::Quality quality, int channels,
194                      int maxBufferSize, int debugLevel)
195 {
196     m_method = -1;
197     
198     switch (quality) {
199
200     case Resampler::Best:
201         m_method = 1;
202         break;
203
204     case Resampler::FastestTolerable:
205         m_method = 1;
206         break;
207
208     case Resampler::Fastest:
209         m_method = 1;
210         break;
211     }
212
213     if (m_method == -1) {
214         std::cerr << "Resampler::Resampler(" << quality << ", " << channels
215                   << ", " << maxBufferSize << "): No implementation available!"
216                   << std::endl;
217         abort();
218     }
219
220     switch (m_method) {
221     case 0:
222         std::cerr << "Resampler::Resampler(" << quality << ", " << channels
223                   << ", " << maxBufferSize << "): No implementation available!"
224                   << std::endl;
225         abort();
226         break;
227
228     case 1:
229         d = new Resamplers::D_SRC(quality, channels, maxBufferSize, debugLevel);
230         break;
231
232     case 2:
233         std::cerr << "Resampler::Resampler(" << quality << ", " << channels
234                   << ", " << maxBufferSize << "): No implementation available!"
235                   << std::endl;
236         abort();
237         break;
238     }
239 }
240
241 Resampler::~Resampler()
242 {
243     delete d;
244 }
245
246 int 
247 Resampler::resample(const float *const R__ *const R__ in,
248                     float *const R__ *const R__ out,
249                     int incount, float ratio, bool final)
250 {
251     Profiler profiler("Resampler::resample");
252     return d->resample(in, out, incount, ratio, final);
253 }
254
255 void
256 Resampler::reset()
257 {
258     d->reset();
259 }
260
261 }