View Issue Details

IDProjectCategoryView StatusLast Update
0003075ardourfeaturespublic2015-09-18 15:11
Reportercolinf Assigned Tocth103  
PrioritynormalSeverityminorReproducibilityN/A
Status closedResolutionfixed 
Product VersionSVN/2.0-ongoing 
Summary0003075: 'Tape' style region stretching
DescriptionIt'd be nice to have the option to stretch regions without preserving pitch: i.e. to speed them up or slow them down as if on an analogue tape recorder.

I assume that RubberBand can do this easily: I'll have a go at working out how when I get a moment.
TagsNo tags attached.

Activities

2010-08-12 18:58

 

timefx-tape-mode-2.X.patch (3,332 bytes)   
Index: gtk2_ardour/editor_timefx.cc
===================================================================
--- gtk2_ardour/editor_timefx.cc	(revision 7608)
+++ gtk2_ardour/editor_timefx.cc	(working copy)
@@ -125,7 +125,7 @@
 
 		set_popdown_strings (stretch_opts_selector, editor.rb_opt_strings);
 		/* set default */
-		stretch_opts_selector.set_active_text (editor.rb_opt_strings[4]);
+		stretch_opts_selector.set_active_text (editor.rb_opt_strings[editor.rb_current_opt]);
 
 		opts_box.pack_start (precise_button, false, false);
 		opts_box.pack_start (stretch_opts_label, false, false);
@@ -268,20 +268,41 @@
 	
 	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 */
-
-		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;
 	};
 
 
Index: gtk2_ardour/editor.cc
===================================================================
--- gtk2_ardour/editor.cc	(revision 7608)
+++ gtk2_ardour/editor.cc	(working copy)
@@ -163,6 +163,7 @@
 	N_("Unpitched percussion with stable notes"),
 	N_("Crisp monophonic instrumental"),
 	N_("Unpitched solo percussion"),
+	N_("Resample (don't preserve pitch)"),
 	0
 };
 #endif
@@ -297,6 +298,7 @@
 	edit_point_strings = I18N (_edit_point_strings);
 #ifdef USE_RUBBERBAND
 	rb_opt_strings = I18N (_rb_opt_strings);
+	rb_current_opt = 4;
 #endif
 	
 	snap_threshold = 5.0;
Index: gtk2_ardour/editor.h
===================================================================
--- gtk2_ardour/editor.h	(revision 7608)
+++ gtk2_ardour/editor.h	(working copy)
@@ -171,6 +171,7 @@
 
 #ifdef USE_RUBBERBAND
 	std::vector<std::string> rb_opt_strings;
+	int rb_current_opt;
 #endif
 
 	//global waveform options
timefx-tape-mode-2.X.patch (3,332 bytes)   

2010-08-12 19:09

 

timefx-tape-mode-3.0.patch (3,785 bytes)   
Index: gtk2_ardour/editor_timefx.cc
===================================================================
--- gtk2_ardour/editor_timefx.cc	(revision 7608)
+++ gtk2_ardour/editor_timefx.cc	(working copy)
@@ -171,21 +171,42 @@
 
 	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 */
-
-		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;
Index: gtk2_ardour/time_fx_dialog.cc
===================================================================
--- gtk2_ardour/time_fx_dialog.cc	(revision 7608)
+++ gtk2_ardour/time_fx_dialog.cc	(working copy)
@@ -145,7 +145,7 @@
 
 		set_popdown_strings (stretch_opts_selector, editor.rb_opt_strings);
 		/* set default */
-		stretch_opts_selector.set_active_text (editor.rb_opt_strings[4]);
+		stretch_opts_selector.set_active_text (editor.rb_opt_strings[editor.rb_current_opt]);
 		table->attach (stretch_opts_selector, 2, 3, 0, 1, Gtk::FILL, Gtk::EXPAND & Gtk::FILL, 0, 0);
 
 		table->attach (precise_button, 1, 3, 1, 2, Gtk::FILL, Gtk::EXPAND, 0, 0);
Index: gtk2_ardour/editor.cc
===================================================================
--- gtk2_ardour/editor.cc	(revision 7608)
+++ gtk2_ardour/editor.cc	(working copy)
@@ -201,6 +201,7 @@
 	N_("Unpitched percussion with stable notes"),
 	N_("Crisp monophonic instrumental"),
 	N_("Unpitched solo percussion"),
+	N_("Resample (don't preserve pitch)"),
 	0
 };
 #endif
@@ -329,6 +330,7 @@
 	edit_point_strings = I18N (_edit_point_strings);
 #ifdef USE_RUBBERBAND
 	rb_opt_strings = I18N (_rb_opt_strings);
+	rb_current_opt = 4;
 #endif
 
 	snap_threshold = 5.0;
Index: gtk2_ardour/editor.h
===================================================================
--- gtk2_ardour/editor.h	(revision 7608)
+++ gtk2_ardour/editor.h	(working copy)
@@ -221,6 +221,7 @@
 
 #ifdef USE_RUBBERBAND
 	std::vector<std::string> rb_opt_strings;
+	int rb_current_opt;
 #endif
 
 	/* things that need to be public to be used in the main menubar */
timefx-tape-mode-3.0.patch (3,785 bytes)   

colinf

2010-08-12 19:20

updater   ~0008816

Pair of patches attached for 2.X and 3.0, doing this in a rather simplistic way by just setting the pitch_fraction to 1/time_fraction. I don't think librubberband has any special handling of this case, so it'll actually do a time stretch with a ratio of 1:1 as well as the resampling. This shouldn't make any difference to the end result, but I did have to mess around with the other parameters to try to get the best results: stretching constant-amplitude sine waves seemed prone to producing spurious transients at region start and end with most combinations.

The pair of patches actually also address another annoyance I found in the timefx dialog, which is that the chosen stretch mode always reset to "Crisp monophonic instrumental" every time the stretch tool is used. The chosen stretch mode is remembered, and pre-selected the next time the dialog is shown.

cth103

2010-08-13 16:55

administrator   ~0008825

Won't be applied to 2.X I don't think, but applied to 3.0. Thanks!

colinf

2015-09-18 15:11

updater   ~0017249

Closing old issues: these have long since been fixed.

Issue History

Date Modified Username Field Change
2010-04-21 14:55 colinf New Issue
2010-08-12 18:58 colinf File Added: timefx-tape-mode-2.X.patch
2010-08-12 19:09 colinf File Added: timefx-tape-mode-3.0.patch
2010-08-12 19:20 colinf Note Added: 0008816
2010-08-13 16:55 cth103 cost => 0.00
2010-08-13 16:55 cth103 Note Added: 0008825
2010-08-13 16:55 cth103 Status new => resolved
2010-08-13 16:55 cth103 Resolution open => fixed
2010-08-13 16:55 cth103 Assigned To => cth103
2015-09-18 15:11 colinf Note Added: 0017249
2015-09-18 15:11 colinf Status resolved => closed