Fix some compilation warnings
[ardour.git] / libs / rubberband / src / StretcherChannelData.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 "StretcherChannelData.h"
16
17 #include "Resampler.h"
18
19
20 namespace RubberBand 
21 {
22       
23 RubberBandStretcher::Impl::ChannelData::ChannelData(size_t windowSize,
24                                                     int overSample,
25                                                     size_t outbufSize) :
26     oversample(overSample)
27 {
28     std::set<size_t> s;
29     construct(s, windowSize, outbufSize);
30 }
31
32 RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set<size_t> &windowSizes,
33                                                     int overSample,
34                                                     size_t initialWindowSize,
35                                                     size_t outbufSize) :
36     oversample(overSample)
37 {
38     construct(windowSizes, initialWindowSize, outbufSize);
39 }
40
41 void
42 RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &windowSizes,
43                                                   size_t initialWindowSize,
44                                                   size_t outbufSize)
45 {
46     size_t maxSize = initialWindowSize;
47
48     if (!windowSizes.empty()) {
49         // std::set is ordered by value
50         std::set<size_t>::const_iterator i = windowSizes.end();
51         maxSize = *--i;
52     }
53     if (windowSizes.find(initialWindowSize) == windowSizes.end()) {
54         if (initialWindowSize > maxSize) maxSize = initialWindowSize;
55     }
56
57     // max size of the real "half" of freq data
58     size_t realSize = (maxSize * oversample)/2 + 1;
59
60 //    std::cerr << "ChannelData::construct([" << windowSizes.size() << "], " << maxSize << ", " << outbufSize << ")" << std::endl;
61     
62     if (outbufSize < maxSize) outbufSize = maxSize;
63
64     inbuf = new RingBuffer<float>(maxSize);
65     outbuf = new RingBuffer<float>(outbufSize);
66
67     mag = allocDouble(realSize);
68     phase = allocDouble(realSize);
69     prevPhase = allocDouble(realSize);
70     prevError = allocDouble(realSize);
71     unwrappedPhase = allocDouble(realSize);
72     envelope = allocDouble(realSize);
73
74     freqPeak = new size_t[realSize];
75
76     fltbuf = allocFloat(maxSize);
77
78     accumulator = allocFloat(maxSize);
79     windowAccumulator = allocFloat(maxSize);
80
81     for (std::set<size_t>::const_iterator i = windowSizes.begin();
82          i != windowSizes.end(); ++i) {
83         ffts[*i] = new FFT(*i * oversample);
84         ffts[*i]->initDouble();
85     }
86     if (windowSizes.find(initialWindowSize) == windowSizes.end()) {
87         ffts[initialWindowSize] = new FFT(initialWindowSize * oversample);
88         ffts[initialWindowSize]->initDouble();
89     }
90     fft = ffts[initialWindowSize];
91
92     dblbuf = fft->getDoubleTimeBuffer();
93
94     resampler = 0;
95     resamplebuf = 0;
96     resamplebufSize = 0;
97
98     reset();
99
100     for (size_t i = 0; i < realSize; ++i) {
101         freqPeak[i] = 0;
102     }
103
104     for (size_t i = 0; i < initialWindowSize * oversample; ++i) {
105         dblbuf[i] = 0.0;
106     }
107
108     for (size_t i = 0; i < maxSize; ++i) {
109         accumulator[i] = 0.f;
110         windowAccumulator[i] = 0.f;
111     }
112
113     // Avoid dividing opening sample (which will be discarded anyway) by zero
114     windowAccumulator[0] = 1.f;
115 }
116
117 void
118 RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize)
119 {
120     size_t oldSize = inbuf->getSize();
121     size_t realSize = (windowSize * oversample) / 2 + 1;
122
123 //    std::cerr << "ChannelData::setWindowSize(" << windowSize << ") [from " << oldSize << "]" << std::endl;
124
125     if (oldSize >= windowSize) {
126
127         // no need to reallocate buffers, just reselect fft
128
129         //!!! we can't actually do this without locking against the
130         //process thread, can we?  we need to zero the mag/phase
131         //buffers without interference
132
133         if (ffts.find(windowSize) == ffts.end()) {
134             //!!! this also requires a lock, but it shouldn't occur in
135             //RT mode with proper initialisation
136             ffts[windowSize] = new FFT(windowSize * oversample);
137             ffts[windowSize]->initDouble();
138         }
139         
140         fft = ffts[windowSize];
141
142         dblbuf = fft->getDoubleTimeBuffer();
143
144         for (size_t i = 0; i < windowSize * oversample; ++i) {
145             dblbuf[i] = 0.0;
146         }
147
148         for (size_t i = 0; i < realSize; ++i) {
149             mag[i] = 0.0;
150             phase[i] = 0.0;
151             prevPhase[i] = 0.0;
152             prevError[i] = 0.0;
153             unwrappedPhase[i] = 0.0;
154             freqPeak[i] = 0;
155         }
156
157         return;
158     }
159
160     //!!! at this point we need a lock in case a different client
161     //thread is calling process() -- we need this lock even if we
162     //aren't running in threaded mode ourselves -- if we're in RT
163     //mode, then the process call should trylock and fail if the lock
164     //is unavailable (since this should never normally be the case in
165     //general use in RT mode)
166
167     RingBuffer<float> *newbuf = inbuf->resized(windowSize);
168     delete inbuf;
169     inbuf = newbuf;
170
171     // We don't want to preserve data in these arrays
172
173     mag = allocDouble(mag, realSize);
174     phase = allocDouble(phase, realSize);
175     prevPhase = allocDouble(prevPhase, realSize);
176     prevError = allocDouble(prevError, realSize);
177     unwrappedPhase = allocDouble(unwrappedPhase, realSize);
178     envelope = allocDouble(envelope, realSize);
179
180     delete[] freqPeak;
181     freqPeak = new size_t[realSize];
182
183     fltbuf = allocFloat(fltbuf, windowSize);
184
185     // But we do want to preserve data in these
186
187     float *newAcc = allocFloat(windowSize);
188
189     for (size_t i = 0; i < oldSize; ++i) newAcc[i] = accumulator[i];
190
191     freeFloat(accumulator);
192     accumulator = newAcc;
193
194     newAcc = allocFloat(windowSize);
195
196     for (size_t i = 0; i < oldSize; ++i) newAcc[i] = windowAccumulator[i];
197
198     freeFloat(windowAccumulator);
199     windowAccumulator = newAcc;
200     
201     //!!! and resampler?
202
203     for (size_t i = 0; i < realSize; ++i) {
204         freqPeak[i] = 0;
205     }
206
207     for (size_t i = 0; i < windowSize; ++i) {
208         fltbuf[i] = 0.f;
209     }
210
211     if (ffts.find(windowSize) == ffts.end()) {
212         ffts[windowSize] = new FFT(windowSize * oversample);
213         ffts[windowSize]->initDouble();
214     }
215     
216     fft = ffts[windowSize];
217
218     dblbuf = fft->getDoubleTimeBuffer();
219
220     for (size_t i = 0; i < windowSize * oversample; ++i) {
221         dblbuf[i] = 0.0;
222     }
223 }
224
225 void
226 RubberBandStretcher::Impl::ChannelData::setOutbufSize(size_t outbufSize)
227 {
228     size_t oldSize = outbuf->getSize();
229
230 //    std::cerr << "ChannelData::setOutbufSize(" << outbufSize << ") [from " << oldSize << "]" << std::endl;
231
232     if (oldSize < outbufSize) {
233
234         //!!! at this point we need a lock in case a different client
235         //thread is calling process()
236
237         RingBuffer<float> *newbuf = outbuf->resized(outbufSize);
238         delete outbuf;
239         outbuf = newbuf;
240     }
241 }
242
243 void
244 RubberBandStretcher::Impl::ChannelData::setResampleBufSize(size_t sz)
245 {
246     resamplebuf = allocFloat(resamplebuf, sz);
247     resamplebufSize = sz;
248 }
249
250 RubberBandStretcher::Impl::ChannelData::~ChannelData()
251 {
252     delete resampler;
253
254     freeFloat(resamplebuf);
255
256     delete inbuf;
257     delete outbuf;
258
259     freeDouble(mag);
260     freeDouble(phase);
261     freeDouble(prevPhase);
262     freeDouble(prevError);
263     freeDouble(unwrappedPhase);
264     freeDouble(envelope);
265     delete[] freqPeak;
266     freeFloat(accumulator);
267     freeFloat(windowAccumulator);
268     freeFloat(fltbuf);
269
270     for (std::map<size_t, FFT *>::iterator i = ffts.begin();
271          i != ffts.end(); ++i) {
272         delete i->second;
273     }
274 }
275
276 void
277 RubberBandStretcher::Impl::ChannelData::reset()
278 {
279     inbuf->reset();
280     outbuf->reset();
281
282     if (resampler) resampler->reset();
283
284     size_t size = inbuf->getSize();
285
286     for (size_t i = 0; i < size; ++i) {
287         accumulator[i] = 0.f;
288         windowAccumulator[i] = 0.f;
289     }
290
291     // Avoid dividing opening sample (which will be discarded anyway) by zero
292     windowAccumulator[0] = 1.f;
293     
294     accumulatorFill = 0;
295     prevIncrement = 0;
296     chunkCount = 0;
297     inCount = 0;
298     inputSize = -1;
299     outCount = 0;
300     unchanged = true;
301     draining = false;
302     outputComplete = false;
303 }
304
305 }