23 #include <rubberband/RubberBandStretcher.h>
70 error <<
"RBEffect::run() passed a non-audio region! WTF?" <<
endmsg;
84 cerr <<
"RBEffect: source region: position = " << region->
position()
85 <<
", start = " << region->
start()
86 <<
", length = " << region->
length()
89 <<
", stretch " << region->
stretch()
90 <<
", shift " << region->
shift() << endl;
158 RubberBandStretcher stretcher
160 (RubberBandStretcher::Options)
tsr.
opts, stretch, shift);
165 stretcher.setExpectedInputDuration(read_duration);
166 stretcher.setDebugLevel(1);
172 if (stretch == 1.0) {
173 snprintf (suffix,
sizeof (suffix),
"@%d", (
int) floor (shift * 100.0
f));
174 }
else if (shift == 1.0) {
175 snprintf (suffix,
sizeof (suffix),
"@%d", (
int) floor (stretch * 100.0
f));
177 snprintf (suffix,
sizeof (suffix),
"@%d-%d",
178 (
int) floor (stretch * 100.0
f),
179 (
int) floor (shift * 100.0f));
192 gain_buffer =
new gain_t[bufsize];
193 buffers =
new float *[channels];
195 for (uint32_t i = 0; i < channels; ++i) {
196 buffers[i] =
new float[bufsize];
206 while (pos < read_duration && !
tsr.
cancel) {
210 for (uint32_t i = 0; i < channels; ++i) {
213 this_time = min(bufsize, read_duration - pos);
216 this_position = read_start + pos -
227 if (this_read != this_time) {
229 (
_(
"tempoize: error reading data from %1 at %2 (wanted %3, got %4)"),
230 region->
name(), this_position, this_time, this_read) <<
endmsg;
238 progress->
set_progress (((
float) done / read_duration) * 0.25);
240 stretcher.study(buffers, this_read, pos == read_duration);
246 while (pos < read_duration && !
tsr.
cancel) {
250 for (uint32_t i = 0; i < channels; ++i) {
253 this_time = min(bufsize, read_duration - pos);
256 this_position = read_start + pos -
267 if (this_read != this_time) {
269 (
_(
"tempoize: error reading data from %1 at %2 (wanted %3, got %4)"),
278 progress->
set_progress (0.25 + ((
float) done / read_duration) * 0.75);
280 stretcher.process(buffers, this_read, pos == read_duration);
284 while ((avail = stretcher.available()) > 0) {
286 this_read = min (bufsize, avail);
288 stretcher.retrieve(buffers, this_read);
290 for (uint32_t i = 0; i < nsrcs.size(); ++i) {
297 if (asrc->
write(buffers[i], this_read) != this_read) {
305 while ((avail = stretcher.available()) >= 0) {
309 stretcher.retrieve(buffers, this_read);
311 for (uint32_t i = 0; i < nsrcs.size(); ++i) {
318 if (asrc->
write(buffers[i], this_read) !=
326 }
catch (runtime_error& err) {
332 new_name = region->
name();
333 at = new_name.find (
'@');
337 if (at != string::npos && at > 2) {
338 new_name = new_name.substr (0, at - 1);
343 ret =
finish (region, nsrcs, new_name);
349 (*x)->set_ancestral_data (read_start,
371 delete [] gain_buffer;
374 for (uint32_t i = 0; i < channels; ++i) {
381 for (SourceList::iterator si = nsrcs.begin(); si != nsrcs.end(); ++si) {
382 (*si)->mark_for_remove ();
const SourceList & master_sources() const
void x_scale(double factor)
int make_new_sources(boost::shared_ptr< ARDOUR::Region >, ARDOUR::SourceList &, std::string suffix="")
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
int run(boost::shared_ptr< ARDOUR::Region >, Progress *progress=0)
LIBPBD_API Transmitter error
std::ostream & endmsg(std::ostream &ostr)
framecnt_t frame_rate() const
LIBARDOUR_API PBD::PropertyDescriptor< float > stretch
ARDOUR::Session & session
boost::shared_ptr< AutomationList > envelope()
framecnt_t ancestral_length() const
LIBARDOUR_API PBD::PropertyDescriptor< float > shift
virtual framecnt_t master_read_at(Sample *buf, Sample *mixdown_buf, float *gain_buf, framepos_t position, framecnt_t cnt, uint32_t chan_n=0) const
framepos_t position() const
std::vector< boost::shared_ptr< ARDOUR::Region > > results
uint32_t n_channels() const
virtual framecnt_t write(Sample *src, framecnt_t cnt)
framecnt_t length() const
framepos_t ancestral_start() const
int finish(boost::shared_ptr< ARDOUR::Region >, ARDOUR::SourceList &, std::string region_name="")
RBEffect(ARDOUR::Session &, TimeFXRequest &)
std::vector< boost::shared_ptr< Source > > SourceList
std::string string_compose(const std::string &fmt, const T1 &o1)