ensure that the name used the control out IO for a route always uses the desired...
[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         : AudioFilter (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         /* the name doesn't need to be super-precise, but allow for 2 fractional
162            digits just to disambiguate close but not identical FX
163         */
164
165         if (stretch == 1.0) {
166                 snprintf (suffix, sizeof (suffix), "@%d", (int) floor (shift * 100.0f));
167         } else if (shift == 1.0) {
168                 snprintf (suffix, sizeof (suffix), "@%d", (int) floor (stretch * 100.0f));
169         } else {
170                 snprintf (suffix, sizeof (suffix), "@%d-%d", 
171                           (int) floor (stretch * 100.0f),
172                           (int) floor (shift * 100.0f));
173         }
174
175         /* create new sources */
176
177         if (make_new_sources (region, nsrcs, suffix)) {
178                 goto out;
179         }
180
181         gain_buffer = new gain_t[bufsize];
182         buffers = new float *[channels];
183
184         for (uint32_t i = 0; i < channels; ++i) {
185                 buffers[i] = new float[bufsize];
186         }
187
188         /* we read from the master (original) sources for the region,
189            not the ones currently in use, in case it's already been
190            subject to timefx.  */
191
192         /* study first, process afterwards. */
193
194         pos = 0;
195         avail = 0;
196         done = 0;
197
198         try { 
199                 while (pos < read_duration && !tsr.cancel) {
200                         
201                         nframes_t this_read = 0;
202
203                         for (uint32_t i = 0; i < channels; ++i) {
204                                 
205                                 this_read = 0;
206
207                                 nframes_t this_time;
208                                 this_time = min(bufsize, read_duration - pos);
209                                 
210                                 nframes_t this_position;
211                                 this_position = read_start + pos -
212                                         region->start() + region->position();
213
214                                 this_read = region->master_read_at
215                                         (buffers[i],
216                                          buffers[i],
217                                          gain_buffer,
218                                          this_position,
219                                          this_time,
220                                          i);
221                                 
222                                 if (this_read != this_time) {
223                                         error << string_compose
224                                                 (_("tempoize: error reading data from %1 at %2 (wanted %3, got %4)"),
225                                                  region->name(), this_position, this_time, this_read) << endmsg;
226                                         goto out;
227                                 }
228                         }
229                         
230                         pos += this_read;
231                         done += this_read;
232
233                         tsr.progress = ((float) done / read_duration) * 0.25;
234
235                         stretcher.study(buffers, this_read, pos == read_duration);
236                 }
237                 
238                 done = 0;
239                 pos = 0;
240
241                 while (pos < read_duration && !tsr.cancel) {
242                         
243                         nframes_t this_read = 0;
244                         
245                         for (uint32_t i = 0; i < channels; ++i) {
246                                 
247                                 this_read = 0;
248                                 nframes_t this_time;
249                                 this_time = min(bufsize, read_duration - pos);
250
251                                 nframes_t this_position;
252                                 this_position = read_start + pos -
253                                         region->start() + region->position();
254                                 
255                                 this_read = region->master_read_at
256                                         (buffers[i],
257                                          buffers[i],
258                                          gain_buffer,
259                                          this_position,
260                                          this_time,
261                                          i);
262                                 
263                                 if (this_read != this_time) {
264                                         error << string_compose
265                                                 (_("tempoize: error reading data from %1 at %2 (wanted %3, got %4)"),
266                                                  region->name(), pos + region->position(), this_time, this_read) << endmsg;
267                                         goto out;
268                                 }
269                         }
270
271                         pos += this_read;
272                         done += this_read;
273
274                         tsr.progress = 0.25 + ((float) done / read_duration) * 0.75;
275
276                         stretcher.process(buffers, this_read, pos == read_duration);
277
278                         int avail = 0;
279
280                         while ((avail = stretcher.available()) > 0) {
281
282                                 this_read = min(bufsize, uint32_t(avail));
283
284                                 stretcher.retrieve(buffers, this_read);
285                         
286                                 for (uint32_t i = 0; i < nsrcs.size(); ++i) {
287
288                                         if (nsrcs[i]->write(buffers[i], this_read) !=
289                                             this_read) {
290                                                 error << string_compose (_("error writing tempo-adjusted data to %1"), nsrcs[i]->name()) << endmsg;
291                                                 goto out;
292                                         }
293                                 }
294                         }
295                 }
296
297                 while ((avail = stretcher.available()) >= 0) {
298
299                         uint32_t this_read = min(bufsize, uint32_t(avail));
300
301                         stretcher.retrieve(buffers, this_read);
302
303                         for (uint32_t i = 0; i < nsrcs.size(); ++i) {
304
305                                 if (nsrcs[i]->write(buffers[i], this_read) !=
306                                     this_read) {
307                                         error << string_compose (_("error writing tempo-adjusted data to %1"), nsrcs[i]->name()) << endmsg;
308                                         goto out;
309                                 }
310                         }
311                 }
312
313         } catch (runtime_error& err) {
314                 error << _("timefx code failure. please notify ardour-developers.") << endmsg;
315                 error << err.what() << endmsg;
316                 goto out;
317         }
318
319         new_name = region->name();
320         at = new_name.find ('@');
321
322         // remove any existing stretch indicator
323
324         if (at != string::npos && at > 2) {
325                 new_name = new_name.substr (0, at - 1);
326         }
327
328         new_name += suffix;
329
330         ret = finish (region, nsrcs, new_name);
331
332         /* now reset ancestral data for each new region */
333
334         for (vector<boost::shared_ptr<AudioRegion> >::iterator x = results.begin(); x != results.end(); ++x) {
335
336                 (*x)->set_ancestral_data (read_start,
337                                           read_duration,
338                                           stretch,
339                                           shift);
340                 (*x)->set_master_sources (region->get_master_sources());
341         }
342
343   out:
344
345         if (gain_buffer) {
346                 delete [] gain_buffer;
347         }
348
349         if (buffers) {
350                 for (uint32_t i = 0; i < channels; ++i) {
351                         delete buffers[i];
352                 }
353                 delete [] buffers;
354         }
355
356         if (ret || tsr.cancel) {
357                 for (SourceList::iterator si = nsrcs.begin(); si != nsrcs.end(); ++si) {
358                         (*si)->mark_for_remove ();
359                 }
360         }
361         
362         tsr.done = true;
363
364         return ret;
365 }
366
367
368
369
370