merge from 2.0-ongoing @ 3581
[ardour.git] / libs / ardour / rb_effect.cc
1 /*
2     Copyright (C) 2004-2007 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <algorithm>
21 #include <cmath>
22
23 #include <pbd/error.h>
24 #include <rubberband/RubberBandStretcher.h>
25
26 #include <ardour/types.h>
27 #include <ardour/stretch.h>
28 #include <ardour/pitch.h>
29 #include <ardour/audiofilesource.h>
30 #include <ardour/session.h>
31 #include <ardour/audioregion.h>
32
33 #include "i18n.h"
34
35 using namespace std;
36 using namespace ARDOUR;
37 using namespace PBD;
38 using namespace RubberBand;
39
40 Pitch::Pitch (Session& s, TimeFXRequest& req)
41         : RBEffect (s, req)
42 {
43 }
44
45 Stretch::Stretch (Session& s, TimeFXRequest& req)
46         : RBEffect (s, req)
47 {
48 }
49
50 RBEffect::RBEffect (Session& s, TimeFXRequest& req)
51         : Filter (s)
52         , tsr (req)
53
54 {
55         tsr.progress = 0.0f;
56 }
57
58 RBEffect::~RBEffect ()
59 {
60 }
61
62 int
63 RBEffect::run (boost::shared_ptr<AudioRegion> region)
64 {
65         SourceList nsrcs;
66         nframes_t done;
67         int ret = -1;
68         const nframes_t bufsize = 256;
69         gain_t* gain_buffer = 0;
70         Sample** buffers = 0;
71         char suffix[32];
72         string new_name;
73         string::size_type at;
74         nframes_t pos = 0;
75         int avail = 0;
76
77         cerr << "RBEffect: source region: position = " << region->position()
78              << ", start = " << region->start()
79              << ", length = " << region->length() 
80              << ", ancestral_start = " << region->ancestral_start()
81              << ", ancestral_length = " << region->ancestral_length()
82              << ", stretch " << region->stretch()
83              << ", shift " << region->shift() << endl;
84
85         /*
86            We have two cases to consider:
87           
88            1. The region has not been stretched before.
89           
90            In this case, we just want to read region->length() frames
91            from region->start().
92           
93            We will create a new region of region->length() *
94            tsr.time_fraction frames.  The new region will have its
95            start set to 0 (because it has a new audio file that begins
96            at the start of the stretched area) and its ancestral_start
97            set to region->start() (so that we know where to begin
98            reading if we want to stretch it again).
99           
100            2. The region has been stretched before.
101           
102            The region starts at region->start() frames into its
103            (possibly previously stretched) source file.  But we don't
104            want to read from its source file; we want to read from the
105            file it was originally stretched from.
106            
107            The region's source begins at region->ancestral_start()
108            frames into its master source file.  Thus, we need to start
109            reading at region->ancestral_start() + (region->start() /
110            region->stretch()) frames into the master source.  This
111            value will also become the ancestral_start for the new
112            region.
113            
114            We cannot use region->ancestral_length() to establish how
115            many frames to read, because it won't be up to date if the
116            region has been trimmed since it was last stretched.  We
117            must read region->length() / region->stretch() frames and
118            stretch them by tsr.time_fraction * region->stretch(), for
119            a new region of region->length() * tsr.time_fraction
120            frames.
121           
122            Case 1 is of course a special case of 2, where
123            region->ancestral_start() == 0 and region->stretch() == 1.
124           
125            When we ask to read from a region, we supply a position on
126            the global timeline.  The read function calculates the
127            offset into the source as (position - region->position()) +
128            region->start().  This calculation is used regardless of
129            whether we are reading from a master or
130            previously-stretched region.  In order to read from a point
131            n frames into the master source, we need to provide n -
132            region->start() + region->position() as our position
133            argument to master_read_at().
134           
135            Note that region->ancestral_length() is not used.
136           
137            I hope this is clear.
138         */
139
140         double stretch = region->stretch() * tsr.time_fraction;
141         double shift = region->shift() * tsr.pitch_fraction;
142
143         nframes_t read_start = region->ancestral_start() +
144                 nframes_t(region->start() / (double)region->stretch());
145
146         nframes_t read_duration =
147                 nframes_t(region->length() / (double)region->stretch());
148
149         uint32_t channels = region->n_channels();
150
151         RubberBandStretcher stretcher
152                 (session.frame_rate(), channels,
153                  (RubberBandStretcher::Options) tsr.opts, stretch, shift);
154         
155         tsr.progress = 0.0f;
156         tsr.done = false;
157
158         stretcher.setExpectedInputDuration(read_duration);
159         stretcher.setDebugLevel(1);
160
161         stretcher.setExpectedInputDuration(duration);
162         stretcher.setDebugLevel(1);
163
164         /* the name doesn't need to be super-precise, but allow for 2 fractional
165            digits just to disambiguate close but not identical FX
166         */
167
168         if (stretch == 1.0) {
169                 snprintf (suffix, sizeof (suffix), "@%d", (int) floor (shift * 100.0f));
170         } else if (shift == 1.0) {
171                 snprintf (suffix, sizeof (suffix), "@%d", (int) floor (stretch * 100.0f));
172         } else {
173                 snprintf (suffix, sizeof (suffix), "@%d-%d", 
174                           (int) floor (stretch * 100.0f),
175                           (int) floor (shift * 100.0f));
176         }
177
178         /* create new sources */
179
180         if (make_new_sources (region, nsrcs, suffix)) {
181                 goto out;
182         }
183
184         gain_buffer = new gain_t[bufsize];
185         buffers = new float *[channels];
186
187         for (uint32_t i = 0; i < channels; ++i) {
188                 buffers[i] = new float[bufsize];
189         }
190
191         /* we read from the master (original) sources for the region,
192            not the ones currently in use, in case it's already been
193            subject to timefx.  */
194
195         /* study first, process afterwards. */
196
197         pos = 0;
198         avail = 0;
199         done = 0;
200
201         try { 
202                 while (pos < read_duration && !tsr.cancel) {
203                         
204                         nframes_t this_read = 0;
205                         
206                         for (uint32_t i = 0; i < channels; ++i) {
207                                 
208                                 this_read = 0;
209
210                                 nframes_t this_time;
211                                 this_time = min(bufsize, read_duration - pos);
212                                 
213                                 nframes_t this_position;
214                                 this_position = read_start + pos -
215                                         region->start() + region->position();
216
217                                 this_read = region->master_read_at
218                                         (buffers[i],
219                                          buffers[i],
220                                          gain_buffer,
221                                          this_position,
222                                          this_time,
223                                          i);
224                                 
225                                 if (this_read != this_time) {
226                                         error << string_compose
227                                                 (_("tempoize: error reading data from %1 at %2 (wanted %3, got %4)"),
228                                                  region->name(), pos + region->position(), this_time, this_read) << endmsg;
229                                         goto out;
230                                 }
231                         }
232                         
233                         pos += this_read;
234                         done += this_read;
235
236                         tsr.progress = ((float) done / read_duration) * 0.25;
237
238                         stretcher.study(buffers, this_read, pos == read_duration);
239                 }
240                 
241                 done = 0;
242                 pos = 0;
243
244                 while (pos < read_duration && !tsr.cancel) {
245                         
246                         nframes_t this_read = 0;
247                         
248                         for (uint32_t i = 0; i < channels; ++i) {
249                                 
250                                 this_read = 0;
251                                 nframes_t this_time;
252                                 this_time = min(bufsize, read_duration - pos);
253
254                                 nframes_t this_position;
255                                 this_position = read_start + pos -
256                                         region->start() + region->position();
257                                 
258                                 this_read = region->master_read_at
259                                         (buffers[i],
260                                          buffers[i],
261                                          gain_buffer,
262                                          this_position,
263                                          this_time,
264                                          i);
265                                 
266                                 if (this_read != this_time) {
267                                         error << string_compose
268                                                 (_("tempoize: error reading data from %1 at %2 (wanted %3, got %4)"),
269                                                  region->name(), pos + region->position(), this_time, this_read) << endmsg;
270                                         goto out;
271                                 }
272                         }
273
274                         pos += this_read;
275                         done += this_read;
276
277                         tsr.progress = 0.25 + ((float) done / read_duration) * 0.75;
278
279                         stretcher.process(buffers, this_read, pos == read_duration);
280
281                         int avail = 0;
282
283                         while ((avail = stretcher.available()) > 0) {
284
285                                 this_read = min(bufsize, uint32_t(avail));
286
287                                 stretcher.retrieve(buffers, this_read);
288                         
289                                 for (uint32_t i = 0; i < nsrcs.size(); ++i) {
290
291                                         if (nsrcs[i]->write(buffers[i], this_read) !=
292                                             this_read) {
293                                                 error << string_compose (_("error writing tempo-adjusted data to %1"), nsrcs[i]->name()) << endmsg;
294                                                 goto out;
295                                         }
296                                 }
297                         }
298                 }
299
300                 while ((avail = stretcher.available()) >= 0) {
301
302                         uint32_t this_read = min(bufsize, uint32_t(avail));
303
304                         stretcher.retrieve(buffers, this_read);
305
306                         for (uint32_t i = 0; i < nsrcs.size(); ++i) {
307
308                                 if (nsrcs[i]->write(buffers[i], this_read) !=
309                                     this_read) {
310                                         error << string_compose (_("error writing tempo-adjusted data to %1"), nsrcs[i]->name()) << endmsg;
311                                         goto out;
312                                 }
313                         }
314                 }
315
316         } catch (runtime_error& err) {
317                 error << _("timefx code failure. please notify ardour-developers.") << endmsg;
318                 error << err.what() << endmsg;
319                 goto out;
320         }
321
322         new_name = region->name();
323         at = new_name.find ('@');
324
325         // remove any existing stretch indicator
326
327         if (at != string::npos && at > 2) {
328                 new_name = new_name.substr (0, at - 1);
329         }
330
331         new_name += suffix;
332
333         ret = finish (region, nsrcs, new_name);
334
335         /* now reset ancestral data for each new region */
336
337         for (vector<boost::shared_ptr<AudioRegion> >::iterator x = results.begin(); x != results.end(); ++x) {
338
339
340                 (*x)->set_ancestral_data (read_start,
341                                           read_duration,
342                                           stretch,
343                                           shift);
344                 (*x)->set_master_sources (region->get_master_sources());
345         }
346
347   out:
348
349         if (gain_buffer) {
350                 delete [] gain_buffer;
351         }
352
353         if (buffers) {
354                 for (uint32_t i = 0; i < channels; ++i) {
355                         delete buffers[i];
356                 }
357                 delete [] buffers;
358         }
359
360         if (ret || tsr.cancel) {
361                 for (SourceList::iterator si = nsrcs.begin(); si != nsrcs.end(); ++si) {
362                         (*si)->mark_for_remove ();
363                 }
364         }
365         
366         tsr.done = true;
367
368         return ret;
369 }
370
371
372
373
374