X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_timefx.cc;h=03094d0a52c75d2b5f89e7a93246c5124ca09abe;hb=fef66431656638bebf6cdd40f49496369c21437b;hp=3dda9e87e9dff431d1aa1a7feacaf31a3dae78cc;hpb=bc89fe0147c04b67141936d109c00dfd4d69cc4b;p=ardour.git diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc index 3dda9e87e9..03094d0a52 100644 --- a/gtk2_ardour/editor_timefx.cc +++ b/gtk2_ardour/editor_timefx.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2000 Paul Davis + Copyright (C) 2000 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 @@ -23,30 +23,30 @@ #include -#include -#include -#include +#include "pbd/error.h" +#include "pbd/pthread_utils.h" +#include "pbd/memento_command.h" +#include "pbd/stateful_diff_command.h" -#include #include -#include "editor.h" -#include "audio_time_axis.h" #include "audio_region_view.h" +#include "audio_time_axis.h" +#include "editor.h" #include "region_selection.h" +#include "time_fx_dialog.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include +#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 +#include "rubberband/RubberBandStretcher.h" using namespace RubberBand; #endif @@ -55,141 +55,15 @@ using namespace RubberBand; using namespace std; using namespace ARDOUR; using namespace PBD; -using namespace sigc; using namespace Gtk; using namespace Gtkmm2ext; -Editor::TimeFXDialog::TimeFXDialog (Editor& e, bool pitch) - : ArdourDialog (X_("time fx dialog")), - editor (e), - pitching (pitch), - pitch_octave_adjustment (0.0, -4.0, 4.0, 1, 2.0), - pitch_semitone_adjustment (0.0, -12.0, 12.0, 1.0, 4.0), - pitch_cent_adjustment (0.0, -499.0, 500.0, 5.0, 15.0), - pitch_octave_spinner (pitch_octave_adjustment), - pitch_semitone_spinner (pitch_semitone_adjustment), - pitch_cent_spinner (pitch_cent_adjustment), - quick_button (_("Quick but Ugly")), - antialias_button (_("Skip Anti-aliasing")), - stretch_opts_label (_("Contents:")), - precise_button (_("Strict Linear")), - preserve_formants_button(_("Preserve Formants")) -{ - set_modal (true); - set_position (Gtk::WIN_POS_MOUSE); - set_name (N_("TimeFXDialog")); - - WindowTitle title(Glib::get_application_name()); - if (pitching) { - title += _("Pitch Shift"); - } else { - title += _("Time Stretch"); - } - set_title(title.get_string()); - - cancel_button = add_button (_("Cancel"), Gtk::RESPONSE_CANCEL); - - get_vbox()->set_spacing (5); - get_vbox()->set_border_width (12); - - if (pitching) { - - upper_button_box.set_spacing (5); - upper_button_box.set_border_width (5); - - Gtk::Label* l; - - l = manage (new Label (_("Octaves"))); - upper_button_box.pack_start (*l, false, false); - upper_button_box.pack_start (pitch_octave_spinner, false, false); - - l = manage (new Label (_("Semitones (12TET)"))); - upper_button_box.pack_start (*l, false, false); - upper_button_box.pack_start (pitch_semitone_spinner, false, false); - - l = manage (new Label (_("Cents"))); - upper_button_box.pack_start (*l, false, false); - upper_button_box.pack_start (pitch_cent_spinner, false, false); - - pitch_cent_spinner.set_digits (1); - - upper_button_box.pack_start (preserve_formants_button, false, false); - - - add_button (_("Shift"), Gtk::RESPONSE_ACCEPT); - - get_vbox()->pack_start (upper_button_box, false, false); - - } else { - -#ifdef USE_RUBBERBAND - opts_box.set_spacing (5); - opts_box.set_border_width (5); - vector strings; - - set_popdown_strings (stretch_opts_selector, editor.rb_opt_strings); - /* set default */ - stretch_opts_selector.set_active_text (editor.rb_opt_strings[4]); - - opts_box.pack_start (precise_button, false, false); - opts_box.pack_start (stretch_opts_label, false, false); - opts_box.pack_start (stretch_opts_selector, false, false); - - get_vbox()->pack_start (opts_box, false, false); - -#else - upper_button_box.set_homogeneous (true); - upper_button_box.set_spacing (5); - upper_button_box.set_border_width (5); - - upper_button_box.pack_start (quick_button, true, true); - upper_button_box.pack_start (antialias_button, true, true); - - quick_button.set_name (N_("TimeFXButton")); - antialias_button.set_name (N_("TimeFXButton")); - - get_vbox()->pack_start (upper_button_box, false, false); - -#endif - add_button (_("Stretch/Shrink"), Gtk::RESPONSE_ACCEPT); - } - - get_vbox()->pack_start (progress_bar); - - progress_bar.set_name (N_("TimeFXProgress")); - - show_all_children (); -} - -gint -Editor::TimeFXDialog::update_progress () -{ - progress_bar.set_fraction (request.progress); - return !request.done; -} - -void -Editor::TimeFXDialog::cancel_in_progress () -{ - status = -2; - request.cancel = true; - first_cancel.disconnect(); -} - -gint -Editor::TimeFXDialog::delete_in_progress (GdkEventAny* ev) -{ - status = -2; - request.cancel = true; - first_delete.disconnect(); - return TRUE; -} - +/** @return -1 in case of error, 1 if operation was cancelled by the user, 0 if everything went ok */ int Editor::time_stretch (RegionSelection& regions, float fraction) { // FIXME: kludge, implement stretching of selection of both types - + if (regions.front()->region()->data_type() == DataType::AUDIO) { // Audio, pop up timefx dialog return time_fx (regions, fraction, false); @@ -198,20 +72,19 @@ Editor::time_stretch (RegionSelection& regions, float fraction) RouteTimeAxisView* rtv = dynamic_cast (®ions.front()->get_time_axis_view()); if (!rtv) return -1; - + boost::shared_ptr playlist - = rtv->track()->diskstream()->playlist(); + = rtv->track()->playlist(); ARDOUR::TimeFXRequest request; request.time_fraction = fraction; - MidiStretch stretch(*session, request); + MidiStretch stretch(*_session, request); begin_reversible_command ("midi stretch"); stretch.run(regions.front()->region()); - XMLNode &before = playlist->get_state(); + playlist->clear_changes (); playlist->replace_region (regions.front()->region(), stretch.results[0], regions.front()->region()->position()); - XMLNode &after = playlist->get_state(); - session->add_command (new MementoCommand(*playlist, &before, &after)); + _session->add_command (new StatefulDiffCommand (playlist)); commit_reversible_command (); } @@ -224,12 +97,11 @@ Editor::pitch_shift (RegionSelection& regions, float fraction) return time_fx (regions, fraction, true); } +/** @return -1 in case of error, 1 if operation was cancelled by the user, 0 if everything went ok */ int Editor::time_fx (RegionSelection& regions, float val, bool pitching) { - if (current_timefx != 0) { - delete current_timefx; - } + delete current_timefx; current_timefx = new TimeFXDialog (*this, pitching); @@ -262,12 +134,12 @@ Editor::time_fx (RegionSelection& regions, float val, bool pitching) // 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; @@ -293,39 +165,56 @@ Editor::time_fx (RegionSelection& regions, float val, bool pitching) BandLimitedTransients, Transients } transients = Transients; - + precise = current_timefx->precise_button.get_active(); preserve_formants = current_timefx->preserve_formants_button.get_active(); - - txt = current_timefx->stretch_opts_selector.get_active_text (); - if (txt == rb_opt_strings[0]) { - transients = NoTransients; peaklock = false; longwin = true; shortwin = false; - } else if (txt == rb_opt_strings[1]) { - transients = NoTransients; peaklock = false; longwin = false; shortwin = false; - } else if (txt == rb_opt_strings[2]) { - transients = NoTransients; peaklock = true; longwin = false; shortwin = false; - } else if (txt == rb_opt_strings[3]) { - transients = BandLimitedTransients; peaklock = true; longwin = false; shortwin = false; - } else if (txt == rb_opt_strings[5]) { - transients = Transients; peaklock = false; longwin = false; shortwin = true; - } else { - /* default/4 */ + txt = current_timefx->stretch_opts_selector.get_active_text (); - transients = Transients; peaklock = true; longwin = false; shortwin = false; + for (int i = 0; i <= 6; i++) { + if (txt == rb_opt_strings[i]) { + rb_current_opt = i; + break; + } + } + + switch (rb_current_opt) { + case 0: + transients = NoTransients; peaklock = false; longwin = true; shortwin = false; + break; + case 1: + transients = NoTransients; peaklock = false; longwin = false; shortwin = false; + break; + case 2: + transients = NoTransients; peaklock = true; longwin = false; shortwin = false; + break; + case 3: + transients = BandLimitedTransients; peaklock = true; longwin = false; shortwin = false; + break; + case 5: + transients = Transients; peaklock = false; longwin = false; shortwin = true; + break; + case 6: + transients = NoTransients; + precise = true; + preserve_formants = false; + current_timefx->request.pitch_fraction = 1/val; + shortwin = true; + // peaklock = false; + break; + default: + /* default/4 */ + transients = Transients; peaklock = true; longwin = false; shortwin = false; + break; }; + if (realtime) options |= RubberBandStretcher::OptionProcessRealTime; + if (precise) options |= RubberBandStretcher::OptionStretchPrecise; + if (preserve_formants) options |= RubberBandStretcher::OptionFormantPreserved; + if (!peaklock) options |= RubberBandStretcher::OptionPhaseIndependent; + if (longwin) options |= RubberBandStretcher::OptionWindowLong; + if (shortwin) options |= RubberBandStretcher::OptionWindowShort; - if (realtime) options |= RubberBandStretcher::OptionProcessRealTime; - if (precise) options |= RubberBandStretcher::OptionStretchPrecise; - if (preserve_formants) options |= RubberBandStretcher::OptionFormantPreserved; - - if (!peaklock) options |= RubberBandStretcher::OptionPhaseIndependent; - if (longwin) options |= RubberBandStretcher::OptionWindowLong; - if (shortwin) options |= RubberBandStretcher::OptionWindowShort; - - - switch (transients) { case NoTransients: options |= RubberBandStretcher::OptionTransientsSmooth; @@ -346,18 +235,18 @@ Editor::time_fx (RegionSelection& regions, float val, bool pitching) current_timefx->request.progress = 0.0f; current_timefx->request.done = false; current_timefx->request.cancel = false; - + /* re-connect the cancel button and delete events */ - + current_timefx->first_cancel.disconnect(); current_timefx->first_delete.disconnect(); - - current_timefx->first_cancel = current_timefx->cancel_button->signal_clicked().connect - (mem_fun (current_timefx, &TimeFXDialog::cancel_in_progress)); - current_timefx->first_delete = current_timefx->signal_delete_event().connect - (mem_fun (current_timefx, &TimeFXDialog::delete_in_progress)); - if (pthread_create_and_store ("timefx", ¤t_timefx->request.thread, 0, timefx_thread, current_timefx)) { + current_timefx->first_cancel = current_timefx->cancel_button->signal_clicked().connect + (sigc::mem_fun (current_timefx, &TimeFXDialog::cancel_in_progress)); + current_timefx->first_delete = current_timefx->signal_delete_event().connect + (sigc::mem_fun (current_timefx, &TimeFXDialog::delete_in_progress)); + + 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; return -1; @@ -365,14 +254,14 @@ Editor::time_fx (RegionSelection& regions, float val, bool pitching) pthread_detach (current_timefx->request.thread); - sigc::connection c = Glib::signal_timeout().connect (mem_fun (current_timefx, &TimeFXDialog::update_progress), 100); + sigc::connection c = Glib::signal_timeout().connect (sigc::mem_fun (current_timefx, &TimeFXDialog::update_progress), 100); while (!current_timefx->request.done && !current_timefx->request.cancel) { gtk_main_iteration (); } c.disconnect (); - + current_timefx->hide (); return current_timefx->status; } @@ -384,7 +273,7 @@ Editor::do_timefx (TimeFXDialog& dialog) boost::shared_ptr playlist; boost::shared_ptr new_region; bool in_command = false; - + for (RegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) { AudioRegionView* arv = dynamic_cast(*i); @@ -396,7 +285,7 @@ Editor::do_timefx (TimeFXDialog& dialog) TimeAxisView* tv = &(arv->get_time_axis_view()); RouteTimeAxisView* rtv; RegionSelection::iterator tmp; - + tmp = i; ++tmp; @@ -409,8 +298,8 @@ Editor::do_timefx (TimeFXDialog& dialog) i = tmp; continue; } - - if ((playlist = t->diskstream()->playlist()) == 0) { + + if ((playlist = t->playlist()) == 0) { i = tmp; continue; } @@ -424,9 +313,13 @@ Editor::do_timefx (TimeFXDialog& dialog) Filter* fx; if (dialog.pitching) { - fx = new Pitch (*session, dialog.request); + fx = new Pitch (*_session, dialog.request); } else { - fx = new Stretch (*session, dialog.request); +#ifdef USE_RUBBERBAND + fx = new RBStretch (*_session, dialog.request); +#else + fx = new STStretch (*_session, dialog.request); +#endif } if (fx->run (region)) { @@ -440,14 +333,13 @@ Editor::do_timefx (TimeFXDialog& dialog) new_region = fx->results.front(); if (!in_command) { - begin_reversible_command (dialog.pitching ? _("pitch shift") : _("time stretch")); + _session->begin_reversible_command (dialog.pitching ? _("pitch shift") : _("time stretch")); in_command = true; } - XMLNode &before = playlist->get_state(); + playlist->clear_changes (); playlist->replace_region (region, new_region, region->position()); - XMLNode &after = playlist->get_state(); - session->add_command (new MementoCommand(*playlist, &before, &after)); + _session->add_command (new StatefulDiffCommand (playlist)); } i = tmp; @@ -455,7 +347,7 @@ Editor::do_timefx (TimeFXDialog& dialog) } if (in_command) { - commit_reversible_command (); + _session->commit_reversible_command (); } dialog.status = 0; @@ -465,7 +357,7 @@ Editor::do_timefx (TimeFXDialog& dialog) void* Editor::timefx_thread (void *arg) { - PBD::notify_gui_about_thread_creation (pthread_self(), X_("TimeFX")); + SessionEvent::create_per_thread_pool ("timefx events", 64); TimeFXDialog* tsd = static_cast(arg);