X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Frb_effect.cc;h=bc127e2d816f025727653ebf4e163dbe881212f7;hb=cf52d6e4b40111eb04b244ec054055a4ec15dbe0;hp=3cda2eb7064189ce319b57dd3ec34143b466946d;hpb=1d516ac95a61d12dadaaf75c46f792d8e4308578;p=ardour.git diff --git a/libs/ardour/rb_effect.cc b/libs/ardour/rb_effect.cc index 3cda2eb706..bc127e2d81 100644 --- a/libs/ardour/rb_effect.cc +++ b/libs/ardour/rb_effect.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2004-2007 Paul Davis + Copyright (C) 2004-2007 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,17 +20,19 @@ #include #include +#include + #include "pbd/error.h" -#include "rubberband/RubberBandStretcher.h" -#include "ardour/types.h" -#include "ardour/stretch.h" +#include "ardour/audioregion.h" +#include "ardour/audiosource.h" #include "ardour/pitch.h" -#include "ardour/audiofilesource.h" +#include "ardour/progress.h" #include "ardour/session.h" -#include "ardour/audioregion.h" +#include "ardour/stretch.h" +#include "ardour/types.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace std; using namespace ARDOUR; @@ -42,7 +44,7 @@ Pitch::Pitch (Session& s, TimeFXRequest& req) { } -Stretch::Stretch (Session& s, TimeFXRequest& req) +RBStretch::RBStretch (Session& s, TimeFXRequest& req) : RBEffect (s, req) { } @@ -52,7 +54,7 @@ RBEffect::RBEffect (Session& s, TimeFXRequest& req) , tsr (req) { - tsr.progress = 0.0f; + } RBEffect::~RBEffect () @@ -60,7 +62,7 @@ RBEffect::~RBEffect () } int -RBEffect::run (boost::shared_ptr r) +RBEffect::run (boost::shared_ptr r, Progress* progress) { boost::shared_ptr region = boost::dynamic_pointer_cast (r); @@ -70,20 +72,18 @@ RBEffect::run (boost::shared_ptr r) } SourceList nsrcs; - nframes_t done; int ret = -1; - const nframes_t bufsize = 256; + const framecnt_t bufsize = 256; gain_t* gain_buffer = 0; Sample** buffers = 0; char suffix[32]; string new_name; string::size_type at; - nframes_t pos = 0; - int avail = 0; + boost::shared_ptr result; cerr << "RBEffect: source region: position = " << region->position() << ", start = " << region->start() - << ", length = " << region->length() + << ", length = " << region->length() << ", ancestral_start = " << region->ancestral_start() << ", ancestral_length = " << region->ancestral_length() << ", stretch " << region->stretch() @@ -91,33 +91,33 @@ RBEffect::run (boost::shared_ptr r) /* We have two cases to consider: - + 1. The region has not been stretched before. - + In this case, we just want to read region->length() frames from region->start(). - + We will create a new region of region->length() * tsr.time_fraction frames. The new region will have its start set to 0 (because it has a new audio file that begins at the start of the stretched area) and its ancestral_start set to region->start() (so that we know where to begin reading if we want to stretch it again). - + 2. The region has been stretched before. - + The region starts at region->start() frames into its (possibly previously stretched) source file. But we don't want to read from its source file; we want to read from the file it was originally stretched from. - + The region's source begins at region->ancestral_start() frames into its master source file. Thus, we need to start reading at region->ancestral_start() + (region->start() / region->stretch()) frames into the master source. This value will also become the ancestral_start for the new region. - + We cannot use region->ancestral_length() to establish how many frames to read, because it won't be up to date if the region has been trimmed since it was last stretched. We @@ -125,10 +125,10 @@ RBEffect::run (boost::shared_ptr r) stretch them by tsr.time_fraction * region->stretch(), for a new region of region->length() * tsr.time_fraction frames. - + Case 1 is of course a special case of 2, where region->ancestral_start() == 0 and region->stretch() == 1. - + When we ask to read from a region, we supply a position on the global timeline. The read function calculates the offset into the source as (position - region->position()) + @@ -138,28 +138,28 @@ RBEffect::run (boost::shared_ptr r) n frames into the master source, we need to provide n - region->start() + region->position() as our position argument to master_read_at(). - + Note that region->ancestral_length() is not used. - + I hope this is clear. */ double stretch = region->stretch() * tsr.time_fraction; double shift = region->shift() * tsr.pitch_fraction; - nframes_t read_start = region->ancestral_start() + - nframes_t(region->start() / (double)region->stretch()); + framecnt_t read_start = region->ancestral_start() + + framecnt_t(region->start() / (double)region->stretch()); - nframes_t read_duration = - nframes_t(region->length() / (double)region->stretch()); + framecnt_t read_duration = + framecnt_t(region->length() / (double)region->stretch()); uint32_t channels = region->n_channels(); RubberBandStretcher stretcher (session.frame_rate(), channels, (RubberBandStretcher::Options) tsr.opts, stretch, shift); - - tsr.progress = 0.0f; + + progress->set_progress (0); tsr.done = false; stretcher.setExpectedInputDuration(read_duration); @@ -174,13 +174,17 @@ RBEffect::run (boost::shared_ptr r) } else if (shift == 1.0) { snprintf (suffix, sizeof (suffix), "@%d", (int) floor (stretch * 100.0f)); } else { - snprintf (suffix, sizeof (suffix), "@%d-%d", + snprintf (suffix, sizeof (suffix), "@%d-%d", (int) floor (stretch * 100.0f), (int) floor (shift * 100.0f)); } /* create new sources */ + framepos_t pos = 0; + framecnt_t avail = 0; + framecnt_t done = 0; + if (make_new_sources (region, nsrcs, suffix)) { goto out; } @@ -198,23 +202,17 @@ RBEffect::run (boost::shared_ptr r) /* study first, process afterwards. */ - pos = 0; - avail = 0; - done = 0; - - try { + try { while (pos < read_duration && !tsr.cancel) { - - nframes_t this_read = 0; + + framecnt_t this_read = 0; for (uint32_t i = 0; i < channels; ++i) { - - this_read = 0; - nframes_t this_time; + framepos_t this_time; this_time = min(bufsize, read_duration - pos); - - nframes_t this_position; + + framepos_t this_position; this_position = read_start + pos - region->start() + region->position(); @@ -225,7 +223,7 @@ RBEffect::run (boost::shared_ptr r) this_position, this_time, i); - + if (this_read != this_time) { error << string_compose (_("tempoize: error reading data from %1 at %2 (wanted %3, got %4)"), @@ -233,32 +231,31 @@ RBEffect::run (boost::shared_ptr r) goto out; } } - + pos += this_read; done += this_read; - tsr.progress = ((float) done / read_duration) * 0.25; + progress->set_progress (((float) done / read_duration) * 0.25); stretcher.study(buffers, this_read, pos == read_duration); } - + done = 0; pos = 0; while (pos < read_duration && !tsr.cancel) { - - nframes_t this_read = 0; - + + framecnt_t this_read = 0; + for (uint32_t i = 0; i < channels; ++i) { - - this_read = 0; - nframes_t this_time; + + framepos_t this_time; this_time = min(bufsize, read_duration - pos); - nframes_t this_position; + framepos_t this_position; this_position = read_start + pos - region->start() + region->position(); - + this_read = region->master_read_at (buffers[i], buffers[i], @@ -266,7 +263,7 @@ RBEffect::run (boost::shared_ptr r) this_position, this_time, i); - + if (this_read != this_time) { error << string_compose (_("tempoize: error reading data from %1 at %2 (wanted %3, got %4)"), @@ -278,18 +275,18 @@ RBEffect::run (boost::shared_ptr r) pos += this_read; done += this_read; - tsr.progress = 0.25 + ((float) done / read_duration) * 0.75; + progress->set_progress (0.25 + ((float) done / read_duration) * 0.75); stretcher.process(buffers, this_read, pos == read_duration); - int avail = 0; + framecnt_t avail = 0; while ((avail = stretcher.available()) > 0) { - this_read = min(bufsize, uint32_t(avail)); + this_read = min (bufsize, avail); stretcher.retrieve(buffers, this_read); - + for (uint32_t i = 0; i < nsrcs.size(); ++i) { boost::shared_ptr asrc = boost::dynamic_pointer_cast(nsrcs[i]); @@ -307,7 +304,7 @@ RBEffect::run (boost::shared_ptr r) while ((avail = stretcher.available()) >= 0) { - uint32_t this_read = min(bufsize, uint32_t(avail)); + framecnt_t this_read = min (bufsize, avail); stretcher.retrieve(buffers, this_read); @@ -317,7 +314,7 @@ RBEffect::run (boost::shared_ptr r) if (!asrc) { continue; } - + if (asrc->write(buffers[i], this_read) != this_read) { error << string_compose (_("error writing tempo-adjusted data to %1"), nsrcs[i]->name()) << endmsg; @@ -327,7 +324,7 @@ RBEffect::run (boost::shared_ptr r) } } catch (runtime_error& err) { - error << _("timefx code failure. please notify ardour-developers.") << endmsg; + error << string_compose (_("programming error: %1"), X_("timefx code failure")) << endmsg; error << err.what() << endmsg; goto out; } @@ -354,6 +351,19 @@ RBEffect::run (boost::shared_ptr r) stretch, shift); (*x)->set_master_sources (region->master_sources()); + /* multiply the old (possibly previously stretched) region length by the extra + stretch this time around to get its new length. this is a non-music based edit atm. + */ + (*x)->set_length ((*x)->length() * tsr.time_fraction, 0); + } + + /* stretch region gain envelope */ + /* XXX: assuming we've only processed one input region into one result here */ + + if (tsr.time_fraction != 1) { + result = boost::dynamic_pointer_cast (results.front()); + assert (result); + result->envelope()->x_scale (tsr.time_fraction); } out: @@ -372,8 +382,6 @@ RBEffect::run (boost::shared_ptr r) (*si)->mark_for_remove (); } } - - tsr.done = true; return ret; } @@ -381,4 +389,4 @@ RBEffect::run (boost::shared_ptr r) - +