X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_timefx.cc;h=c623a3fe1336737bd354bb02711cba2099ed4821;hb=df28a71252f4593c65ec03611586dfc8a62a834f;hp=d4d02ea1c4acf6ba44d601815e5a4e84e5591dc8;hpb=33c61757fc8352fdb1280bca28b54d1adee183ff;p=ardour.git diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc index d4d02ea1c4..c623a3fe13 100644 --- a/gtk2_ardour/editor_timefx.cc +++ b/gtk2_ardour/editor_timefx.cc @@ -29,6 +29,13 @@ #include "pbd/memento_command.h" #include "pbd/stateful_diff_command.h" +#include "ardour/audioregion.h" +#include "ardour/midi_stretch.h" +#include "ardour/pitch.h" +#include "ardour/region.h" +#include "ardour/session.h" +#include "ardour/stretch.h" + #include #include "audio_region_view.h" @@ -37,21 +44,12 @@ #include "region_selection.h" #include "time_fx_dialog.h" -#include "ardour/session.h" -#include "ardour/region.h" -#include "ardour/audioplaylist.h" -#include "ardour/audio_track.h" -#include "ardour/audioregion.h" -#include "ardour/stretch.h" -#include "ardour/midi_stretch.h" -#include "ardour/pitch.h" - #ifdef USE_RUBBERBAND -#include "rubberband/RubberBandStretcher.h" +#include using namespace RubberBand; #endif -#include "i18n.h" +#include "pbd/i18n.h" using namespace std; using namespace ARDOUR; @@ -78,6 +76,7 @@ Editor::time_stretch (RegionSelection& regions, float fraction) } if ((aret = time_fx (audio, fraction, false)) != 0) { + commit_reversible_command (); return aret; } @@ -106,7 +105,7 @@ Editor::time_stretch (RegionSelection& regions, float fraction) stretch.run (*i); playlist->replace_region (regions.front()->region(), stretch.results[0], - regions.front()->region()->position()); + regions.front()->region()->position()); midi_playlists_affected.insert (playlist); } @@ -134,6 +133,8 @@ Editor::pitch_shift (RegionSelection& regions, float fraction) if (ret == 0) { commit_reversible_command (); + } else { + abort_reversible_command (); } return ret; @@ -145,9 +146,17 @@ Editor::pitch_shift (RegionSelection& regions, float fraction) int Editor::time_fx (RegionList& regions, float val, bool pitching) { - delete current_timefx; + if (regions.empty()) { + return 0; + } + + const samplecnt_t oldlen = (samplecnt_t) (regions.front()->length()); + const samplecnt_t newlen = (samplecnt_t) (regions.front()->length() * val); + const samplecnt_t pos = regions.front()->position (); - current_timefx = new TimeFXDialog (*this, pitching); + delete current_timefx; + current_timefx = new TimeFXDialog (*this, pitching, oldlen, newlen, pos); + current_timefx->regions = regions; switch (current_timefx->run ()) { case RESPONSE_ACCEPT: @@ -158,35 +167,14 @@ Editor::time_fx (RegionList& regions, float val, bool pitching) } current_timefx->status = 0; - current_timefx->regions = regions; - - if (pitching) { - - float cents = current_timefx->pitch_octave_adjustment.get_value() * 1200.0; - float pitch_fraction; - cents += current_timefx->pitch_semitone_adjustment.get_value() * 100.0; - cents += current_timefx->pitch_cent_adjustment.get_value(); - - if (cents == 0.0) { - // user didn't change anything - current_timefx->hide (); - return 0; - } - - // one octave == 1200 cents - // adding one octave doubles the frequency - // ratio is 2^^octaves - - pitch_fraction = pow(2, cents/1200); - - current_timefx->request.time_fraction = 1.0; - current_timefx->request.pitch_fraction = pitch_fraction; - - } else { - - current_timefx->request.time_fraction = val; - current_timefx->request.pitch_fraction = 1.0; + current_timefx->request.time_fraction = current_timefx->get_time_fraction (); + current_timefx->request.pitch_fraction = current_timefx->get_pitch_fraction (); + if (current_timefx->request.time_fraction == 1.0 && + current_timefx->request.pitch_fraction == 1.0) { + /* nothing to do */ + current_timefx->hide (); + return 0; } #ifdef USE_RUBBERBAND @@ -220,7 +208,31 @@ Editor::time_fx (RegionList& regions, float val, bool pitching) } } - switch (rb_current_opt) { + int rb_mode = rb_current_opt; + + if (pitching /*&& rb_current_opt == 6*/) { + /* The timefx dialog does not show the "stretch_opts_selector" + * when pitch-shifting. So the most recently used option from + * "Time Stretch" would be used (if any). That may even be + * "resample without preserving pitch", which would be invalid. + * + * TODO: also show stretch_opts_selector when pitching (except the option + * to not preserve pitch) and use separate rb_current_opt when pitching. + * + * Actually overhaul this the dialog and processing opts below and use rubberband's + * "Crispness" levels: + * -c 0 equivalent to --no-transients --no-lamination --window-long + * -c 1 equivalent to --detector-soft --no-lamination --window-long (for piano) + * -c 2 equivalent to --no-transients --no-lamination + * -c 3 equivalent to --no-transients + * -c 4 equivalent to --bl-transients + * -c 5 default processing options + * -c 6 equivalent to --no-lamination --window-short (may be good for drums) + */ + rb_mode = 4; + } + + switch (rb_mode) { case 0: transients = NoTransients; peaklock = false; longwin = true; shortwin = false; break; @@ -240,7 +252,7 @@ Editor::time_fx (RegionList& regions, float val, bool pitching) transients = NoTransients; precise = true; preserve_formants = false; - current_timefx->request.pitch_fraction = 1/val; + current_timefx->request.pitch_fraction = 1.0 / current_timefx->request.time_fraction; shortwin = true; // peaklock = false; break; @@ -287,6 +299,8 @@ Editor::time_fx (RegionList& regions, float val, bool pitching) current_timefx->first_delete = current_timefx->signal_delete_event().connect (sigc::mem_fun (current_timefx, &TimeFXDialog::delete_in_progress)); + current_timefx->start_updates (); + if (pthread_create_and_store ("timefx", ¤t_timefx->request.thread, timefx_thread, current_timefx)) { current_timefx->hide (); error << _("timefx cannot be started - thread creation error") << endmsg; @@ -299,20 +313,22 @@ Editor::time_fx (RegionList& regions, float val, bool pitching) gtk_main_iteration (); } + pthread_join (current_timefx->request.thread, 0); + current_timefx->hide (); return current_timefx->status; } void -Editor::do_timefx (TimeFXDialog& dialog) +Editor::do_timefx () { boost::shared_ptr playlist; boost::shared_ptr new_region; set > playlists_affected; - uint32_t const N = dialog.regions.size (); + uint32_t const N = current_timefx->regions.size (); - for (RegionList::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ++i) { + for (RegionList::iterator i = current_timefx->regions.begin(); i != current_timefx->regions.end(); ++i) { boost::shared_ptr playlist = (*i)->playlist(); if (playlist) { @@ -320,7 +336,7 @@ Editor::do_timefx (TimeFXDialog& dialog) } } - for (RegionList::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ++i) { + for (RegionList::iterator i = current_timefx->regions.begin(); i != current_timefx->regions.end(); ++i) { boost::shared_ptr region = boost::dynamic_pointer_cast (*i); @@ -328,30 +344,30 @@ Editor::do_timefx (TimeFXDialog& dialog) continue; } - if (dialog.request.cancel) { + if (current_timefx->request.cancel) { /* we were cancelled */ /* XXX what to do about playlists already affected ? */ - dialog.status = 1; + current_timefx->status = 1; return; } Filter* fx; - if (dialog.pitching) { - fx = new Pitch (*_session, dialog.request); + if (current_timefx->pitching) { + fx = new Pitch (*_session, current_timefx->request); } else { #ifdef USE_RUBBERBAND - fx = new RBStretch (*_session, dialog.request); + fx = new RBStretch (*_session, current_timefx->request); #else - fx = new STStretch (*_session, dialog.request); + fx = new STStretch (*_session, current_timefx->request); #endif } current_timefx->descend (1.0 / N); if (fx->run (region, current_timefx)) { - dialog.status = -1; - dialog.request.done = true; + current_timefx->status = -1; + current_timefx->request.done = true; delete fx; return; } @@ -371,8 +387,8 @@ Editor::do_timefx (TimeFXDialog& dialog) _session->add_command (new StatefulDiffCommand (*p)); } - dialog.status = 0; - dialog.request.done = true; + current_timefx->status = 0; + current_timefx->request.done = true; } void* @@ -384,16 +400,18 @@ Editor::timefx_thread (void *arg) pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); - tsd->editor.do_timefx (*tsd); - - /* GACK! HACK! sleep for a bit so that our request buffer for the GUI - event loop doesn't die before any changes we made are processed - by the GUI ... - */ + tsd->editor.do_timefx (); - struct timespec t = { 2, 0 }; - nanosleep (&t, 0); + /* GACK! HACK! sleep for a bit so that our request buffer for the GUI + event loop doesn't die before any changes we made are processed + by the GUI ... + */ +#ifdef PLATFORM_WINDOWS + Glib::usleep(2 * G_USEC_PER_SEC); +#else + struct timespec t = { 2, 0 }; + nanosleep (&t, 0); +#endif return 0; } -