Adding the "Pitch Adjust" feature - Alex
authorterminatorX <>
Sun, 6 Apr 2003 22:28:02 +0000 (22:28 +0000)
committerterminatorX <>
Sun, 6 Apr 2003 22:28:02 +0000 (22:28 +0000)
src/tX_glade_interface.cc
src/tX_glade_interface.h
src/tX_seqpar.h
src/tX_vtt.cc
src/tX_vtt.h
src/tX_vttgui.cc
src/tX_vttgui.h
terminatorX.glade

index 1adbbbbc65c56fdb06e315341d53519c7a50bd22..9a676555d99a59c37cdc90e348a25b7cbf4bb120 100644 (file)
@@ -709,3 +709,100 @@ create_tx_options (void)
   return tx_options;
 }
 
+GtkWidget*
+create_tx_adjust (void)
+{
+  GtkWidget *tx_adjust;
+  GtkWidget *dialog_vbox2;
+  GtkWidget *vbox1;
+  GtkWidget *label34;
+  GtkWidget *hbox3;
+  GtkWidget *label35;
+  GtkObject *master_cycles_adj;
+  GtkWidget *master_cycles;
+  GtkWidget *label36;
+  GtkObject *cycles_adj;
+  GtkWidget *cycles;
+  GtkWidget *create_event;
+  GtkWidget *dialog_action_area2;
+  GtkWidget *cancel;
+  GtkWidget *ok;
+
+  tx_adjust = gtk_dialog_new ();
+  gtk_window_set_title (GTK_WINDOW (tx_adjust), "Compute Pitch");
+
+  dialog_vbox2 = GTK_DIALOG (tx_adjust)->vbox;
+  gtk_widget_show (dialog_vbox2);
+
+  vbox1 = gtk_vbox_new (FALSE, 4);
+  gtk_widget_show (vbox1);
+  gtk_box_pack_start (GTK_BOX (dialog_vbox2), vbox1, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (vbox1), 4);
+
+  label34 = gtk_label_new ("To compute the pitch value, please specify with how many cycles of the master turntable this turntable should be re-triggered:");
+  gtk_widget_show (label34);
+  gtk_box_pack_start (GTK_BOX (vbox1), label34, FALSE, FALSE, 0);
+  gtk_label_set_justify (GTK_LABEL (label34), GTK_JUSTIFY_LEFT);
+  gtk_label_set_line_wrap (GTK_LABEL (label34), TRUE);
+
+  hbox3 = gtk_hbox_new (FALSE, 4);
+  gtk_widget_show (hbox3);
+  gtk_box_pack_start (GTK_BOX (vbox1), hbox3, FALSE, FALSE, 0);
+
+  label35 = gtk_label_new ("Master Cycles:");
+  gtk_widget_show (label35);
+  gtk_box_pack_start (GTK_BOX (hbox3), label35, FALSE, FALSE, 0);
+  gtk_label_set_justify (GTK_LABEL (label35), GTK_JUSTIFY_LEFT);
+
+  master_cycles_adj = gtk_adjustment_new (1, 1, 100, 1, 10, 10);
+  master_cycles = gtk_spin_button_new (GTK_ADJUSTMENT (master_cycles_adj), 1, 0);
+  gtk_widget_show (master_cycles);
+  gtk_box_pack_start (GTK_BOX (hbox3), master_cycles, TRUE, TRUE, 0);
+
+  label36 = gtk_label_new ("Cycles:");
+  gtk_widget_show (label36);
+  gtk_box_pack_start (GTK_BOX (hbox3), label36, FALSE, FALSE, 0);
+  gtk_label_set_justify (GTK_LABEL (label36), GTK_JUSTIFY_LEFT);
+
+  cycles_adj = gtk_adjustment_new (1, 1, 100, 1, 10, 10);
+  cycles = gtk_spin_button_new (GTK_ADJUSTMENT (cycles_adj), 1, 0);
+  gtk_widget_show (cycles);
+  gtk_box_pack_start (GTK_BOX (hbox3), cycles, TRUE, TRUE, 0);
+
+  create_event = gtk_check_button_new_with_mnemonic ("Record a sequencer event");
+  gtk_widget_show (create_event);
+  gtk_box_pack_start (GTK_BOX (vbox1), create_event, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (create_event), TRUE);
+
+  dialog_action_area2 = GTK_DIALOG (tx_adjust)->action_area;
+  gtk_widget_show (dialog_action_area2);
+  gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area2), GTK_BUTTONBOX_END);
+
+  cancel = gtk_button_new_from_stock ("gtk-cancel");
+  gtk_widget_show (cancel);
+  gtk_dialog_add_action_widget (GTK_DIALOG (tx_adjust), cancel, GTK_RESPONSE_CANCEL);
+  GTK_WIDGET_SET_FLAGS (cancel, GTK_CAN_DEFAULT);
+
+  ok = gtk_button_new_from_stock ("gtk-ok");
+  gtk_widget_show (ok);
+  gtk_dialog_add_action_widget (GTK_DIALOG (tx_adjust), ok, GTK_RESPONSE_OK);
+  GTK_WIDGET_SET_FLAGS (ok, GTK_CAN_DEFAULT);
+
+  /* Store pointers to all widgets, for use by lookup_widget(). */
+  GLADE_HOOKUP_OBJECT_NO_REF (tx_adjust, tx_adjust, "tx_adjust");
+  GLADE_HOOKUP_OBJECT_NO_REF (tx_adjust, dialog_vbox2, "dialog_vbox2");
+  GLADE_HOOKUP_OBJECT (tx_adjust, vbox1, "vbox1");
+  GLADE_HOOKUP_OBJECT (tx_adjust, label34, "label34");
+  GLADE_HOOKUP_OBJECT (tx_adjust, hbox3, "hbox3");
+  GLADE_HOOKUP_OBJECT (tx_adjust, label35, "label35");
+  GLADE_HOOKUP_OBJECT (tx_adjust, master_cycles, "master_cycles");
+  GLADE_HOOKUP_OBJECT (tx_adjust, label36, "label36");
+  GLADE_HOOKUP_OBJECT (tx_adjust, cycles, "cycles");
+  GLADE_HOOKUP_OBJECT (tx_adjust, create_event, "create_event");
+  GLADE_HOOKUP_OBJECT_NO_REF (tx_adjust, dialog_action_area2, "dialog_action_area2");
+  GLADE_HOOKUP_OBJECT (tx_adjust, cancel, "cancel");
+  GLADE_HOOKUP_OBJECT (tx_adjust, ok, "ok");
+
+  return tx_adjust;
+}
+
index ab7f80dfb0de11d2a24558206e8438f4a3419285..d2bbaab4b1acb8cb184065cabc06c3c5ecdb1f06 100644 (file)
@@ -3,3 +3,4 @@
  */
 
 GtkWidget* create_tx_options (void);
+GtkWidget* create_tx_adjust (void);
index 4de2f593488d3c7f4cae58fc3761a07bcad56661..b18cf47241dc79bd5fca96a69b50effd8efb9d1b 100644 (file)
@@ -225,8 +225,8 @@ class tX_seqpar_vtt_pitch : public tX_seqpar_update_active_forward
        public:
        tX_seqpar_vtt_pitch();
        virtual float get_value();
-       private:        
        virtual void do_exec(const float value);
+       private:        
        virtual void do_update_graphics();      
         virtual const char *get_name(); 
 };
@@ -446,8 +446,4 @@ class tX_seqpar_vttfx_int : public tX_seqpar_vttfx
 
        static GtkSignalFunc gtk_callback(GtkWidget*, tX_seqpar_vttfx_int *);
 };
-#endif 
-
-
-
-
+#endif
index 69339868c531d30959ef96205d143d7a3825d187..04fa6fdb44032a870979ea2839b3ffa6b282da48 100644 (file)
@@ -179,7 +179,7 @@ vtt_class :: vtt_class (int do_create_gui)
        set_output_buffer_size(samples_in_mix_buffer/2);
        
        audiofile = NULL;
-       audiofile_pitch_correction=0;
+       audiofile_pitch_correction=1.0;
        mix_solo=0;
        mix_mute=0;
        res_mute=mute;
@@ -236,7 +236,7 @@ tX_audio_error vtt_class :: load_file(char *fname)
        if (res==TX_AUDIO_SUCCESS) {
                buffer=audiofile->get_buffer();
                double file_rate=audiofile->get_sample_rate();
-               audiofile_pitch_correction=file_rate/44100.0;
+               audiofile_pitch_correction=file_rate/((double) last_sample_rate);
                recalc_pitch();
                samples_in_buffer=audiofile->get_no_samples();
                maxpos=audiofile->get_no_samples();
@@ -330,9 +330,7 @@ void vtt_class :: set_pan(f_prec newpan)
 void vtt_class :: set_pitch(f_prec newpitch)
 {
        rel_pitch=newpitch;
-       res_pitch=globals.pitch*rel_pitch;
-       speed=res_pitch;
-       ec_set_length(ec_length);
+       recalc_pitch();
 }
 
 void vtt_class :: recalc_pitch()
@@ -341,6 +339,7 @@ void vtt_class :: recalc_pitch()
        res_pitch*=audiofile_pitch_correction;
        speed=res_pitch;
        ec_set_length(ec_length);
+       tX_debug("setting pitch: rel: %lf -> res: %lf", rel_pitch, res_pitch);
 }
 
 void vtt_class :: set_autotrigger(int newstate)
@@ -603,7 +602,7 @@ void vtt_class :: render_scratch()
        
        int sample;
        
-       f_prec pos_a_f;
+       d_prec pos_a_f;
        
        f_prec amount_a;
        f_prec amount_b;
@@ -1792,3 +1791,24 @@ void vtt_class :: set_sample_rate(int samplerate) {
        
        set_mix_buffer_size(no_samples);        
 }
+
+void vtt_class :: adjust_to_master_pitch(int master_cycles, int cycles, bool create_event) {
+       if (!sync_master) return;
+       if (this==sync_master) return;
+       if (!sync_master->audiofile) return;
+       if (!audiofile) return;
+       
+       double master_time=((double) master_cycles)/sync_master->rel_pitch*sync_master->audiofile->get_no_samples()/((double) sync_master->audiofile->get_sample_rate());
+       double my_rel_pitch=((audiofile->get_no_samples()/((double) audiofile->get_sample_rate()))*((double) cycles))/master_time;
+       
+       if (create_event) {
+               sp_pitch.do_exec(my_rel_pitch);
+               sp_pitch.record_value(my_rel_pitch);
+       } else {
+               sp_pitch.do_exec(my_rel_pitch);
+       }
+       
+       tX_debug("master_time: %lf, res_pitch: %lf - res time: %lf, (%lf, %lf)", master_time, my_rel_pitch, ((double) cycles)*my_rel_pitch*audiofile->get_no_samples()/((double) audiofile->get_sample_rate()), (double) sync_master->audiofile->get_sample_rate(),(double)  audiofile->get_sample_rate());
+       
+       sp_pitch.update_graphics();
+}
index 719979970e9cd3e0901a1db4bd749ef14ef6c1f5..42683ce6fdac6807e1b67598127e1442a4603339 100644 (file)
@@ -224,7 +224,7 @@ class vtt_class
        void recalc_volume();
        
        void set_pan(f_prec);
-       
+       void adjust_to_master_pitch(int master_cycles, int cycles, bool create_event);
        void set_pitch(f_prec);
        void recalc_pitch();
        
index ba9e8d686fcb71e088179718a7cfff24a41d6e15..58c556ec19b8817e222f8a21ec67e1b5091994d4 100644 (file)
@@ -49,6 +49,8 @@
 #include "tX_ladspa.h"
 #include "tX_ladspa_class.h"
 #include "tX_engine.h"
+#include "tX_glade_interface.h"
+#include "tX_glade_support.h"
 
 #ifdef USE_DIAL
 #include "tX_dial.h"
@@ -503,6 +505,52 @@ void vg_ycontrol_set(GtkWidget *wid, tX_seqpar *sp)
        vtt->set_y_input_parameter(sp);
 }
 
+gboolean vg_delete_pitch_adjust (GtkWidget *wid, vtt_class *vtt) {
+       vtt->gui.adjust_dialog=NULL;
+       return FALSE;
+}
+
+void vg_do_pitch_adjust (GtkWidget *wid, vtt_class *vtt) {
+       int master_cycles=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(vtt->gui.adjust_dialog, "master_cycles")));
+       int cycles=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(vtt->gui.adjust_dialog, "cycles")));
+       bool create_event=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(vtt->gui.adjust_dialog, "create_event")));
+
+       vtt->adjust_to_master_pitch(master_cycles, cycles, create_event);
+       
+       gtk_widget_destroy(vtt->gui.adjust_dialog);
+}
+
+void vg_cancel_pitch_adjust (GtkWidget *wid, vtt_class *vtt) {
+       gtk_widget_destroy(vtt->gui.adjust_dialog);
+}
+
+void vg_adjust_pitch_vtt(GtkWidget *wid, vtt_class *vtt) {
+       if (vtt->gui.adjust_dialog) {
+               gtk_widget_destroy(vtt->gui.adjust_dialog);
+               return;
+       }
+       
+       if (!vtt_class::sync_master) {
+               tx_note("No master turntable to adjust pitch to selected.", true);
+               return;
+       }
+       
+       if (vtt==vtt_class::sync_master) {
+               tx_note("This is the master turntable - cannot adjust a turntable to itself.", true);
+               return;
+       }
+       
+       vtt->gui.adjust_dialog=create_tx_adjust();
+       gtk_widget_show(vtt->gui.adjust_dialog);
+       
+       GtkWidget *ok_button=lookup_widget(vtt->gui.adjust_dialog, "ok");
+       GtkWidget *cancel_button=lookup_widget(vtt->gui.adjust_dialog, "cancel");
+       
+       g_signal_connect(G_OBJECT(ok_button), "clicked", GTK_SIGNAL_FUNC(vg_do_pitch_adjust), vtt);
+       g_signal_connect(G_OBJECT(vtt->gui.adjust_dialog), "destroy", GTK_SIGNAL_FUNC(vg_delete_pitch_adjust), vtt);
+       g_signal_connect(G_OBJECT(cancel_button), "clicked", GTK_SIGNAL_FUNC(vg_cancel_pitch_adjust), vtt);
+}
+
 void vg_mouse_mapping_pressed(GtkWidget *wid, vtt_class *vtt) {
        if (vtt->gui.mouse_mapping_menu) {
                gtk_widget_destroy(vtt->gui.mouse_mapping_menu);
@@ -682,6 +730,7 @@ void gui_connect_signals(vtt_class *vtt)
        connect_button(loop, loop_toggled);
        connect_button(sync_master, master_setup);
        connect_button(sync_client, client_setup);
+       connect_button(adjust_button, vg_adjust_pitch_vtt);
        connect_adj(cycles, client_setup_number);
        connect_press_button(fx_button, fx_button_pressed);
        
@@ -856,6 +905,10 @@ void build_vtt_gui(vtt_class *vtt)
        gui_set_tooltip(g->del, "Click here to annihilate this turntable. All events recorded for this turntable will be erased, too.");
        p->add_client_widget(g->del);
        
+       g->adjust_button=gtk_button_new_with_label("Pitch Adj.");
+       gui_set_tooltip(g->adjust_button, "Activate this button to adjust this turntable's speed to the master turntable's speed.");
+       p->add_client_widget(g->adjust_button);
+
        gtk_box_pack_start(GTK_BOX(g->control_subbox), p->get_widget(), WID_FIX);
                                
        p=new tX_panel("Trigger", g->control_subbox);
@@ -1034,6 +1087,8 @@ void build_vtt_gui(vtt_class *vtt)
        g->mouse_mapping_menu_x=NULL;
        g->mouse_mapping_menu_y=NULL;
        
+       g->adjust_dialog=NULL;
+       
        gui_set_name(vtt, vtt->name);
 }
 
index f89de78642123a22de98cf28ddd52cb73f71067f..ad1dc1735729f24b18788ff4a56680ec4ad4f769 100644 (file)
@@ -36,7 +36,8 @@ typedef struct vtt_gui
 {
        GtkWidget *control_box;
        GtkWidget *audio_box;
-
+       GtkWidget *adjust_dialog;
+       
        /* Control Box Widgets */
        GtkWidget *control_label;
        GtkWidget *control_minimize;
@@ -50,6 +51,7 @@ typedef struct vtt_gui
        GtkWidget *name;
        GtkWidget *show_audio;
        GtkWidget *del;
+       GtkWidget *adjust_button;
        GtkWidget *fx_button;
        
        /* Trigger */
index efea133c122b3500ce6d2da3bb3b45ac948af637..befcd866c078fbdc4691a1fe2fd06ce444bbf684 100644 (file)
   </child>
 </widget>
 
+<widget class="GtkDialog" id="tx_adjust">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">Compute Pitch</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="has_separator">True</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="dialog-vbox2">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child internal-child="action_area">
+       <widget class="GtkHButtonBox" id="dialog-action_area2">
+         <property name="visible">True</property>
+         <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+         <child>
+           <widget class="GtkButton" id="cancel">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="label">gtk-cancel</property>
+             <property name="use_stock">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="response_id">-6</property>
+           </widget>
+         </child>
+
+         <child>
+           <widget class="GtkButton" id="ok">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="label">gtk-ok</property>
+             <property name="use_stock">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="response_id">-5</property>
+           </widget>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">False</property>
+         <property name="fill">True</property>
+         <property name="pack_type">GTK_PACK_END</property>
+       </packing>
+      </child>
+
+      <child>
+       <widget class="GtkVBox" id="vbox1">
+         <property name="border_width">4</property>
+         <property name="visible">True</property>
+         <property name="homogeneous">False</property>
+         <property name="spacing">4</property>
+
+         <child>
+           <widget class="GtkLabel" id="label34">
+             <property name="visible">True</property>
+             <property name="label" translatable="yes">To compute the pitch value, please specify with how many cycles of the master turntable this turntable should be re-triggered:</property>
+             <property name="use_underline">False</property>
+             <property name="use_markup">False</property>
+             <property name="justify">GTK_JUSTIFY_LEFT</property>
+             <property name="wrap">True</property>
+             <property name="selectable">False</property>
+             <property name="xalign">0.5</property>
+             <property name="yalign">0.5</property>
+             <property name="xpad">0</property>
+             <property name="ypad">0</property>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">False</property>
+             <property name="fill">False</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkHBox" id="hbox3">
+             <property name="visible">True</property>
+             <property name="homogeneous">False</property>
+             <property name="spacing">4</property>
+
+             <child>
+               <widget class="GtkLabel" id="label35">
+                 <property name="visible">True</property>
+                 <property name="label" translatable="yes">Master Cycles:</property>
+                 <property name="use_underline">False</property>
+                 <property name="use_markup">False</property>
+                 <property name="justify">GTK_JUSTIFY_LEFT</property>
+                 <property name="wrap">False</property>
+                 <property name="selectable">False</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xpad">0</property>
+                 <property name="ypad">0</property>
+               </widget>
+               <packing>
+                 <property name="padding">0</property>
+                 <property name="expand">False</property>
+                 <property name="fill">False</property>
+               </packing>
+             </child>
+
+             <child>
+               <widget class="GtkSpinButton" id="master_cycles">
+                 <property name="visible">True</property>
+                 <property name="can_focus">True</property>
+                 <property name="climb_rate">1</property>
+                 <property name="digits">0</property>
+                 <property name="numeric">False</property>
+                 <property name="update_policy">GTK_UPDATE_ALWAYS</property>
+                 <property name="snap_to_ticks">False</property>
+                 <property name="wrap">False</property>
+                 <property name="adjustment">1 1 100 1 10 10</property>
+               </widget>
+               <packing>
+                 <property name="padding">0</property>
+                 <property name="expand">True</property>
+                 <property name="fill">True</property>
+               </packing>
+             </child>
+
+             <child>
+               <widget class="GtkLabel" id="label36">
+                 <property name="visible">True</property>
+                 <property name="label" translatable="yes">Cycles:</property>
+                 <property name="use_underline">False</property>
+                 <property name="use_markup">False</property>
+                 <property name="justify">GTK_JUSTIFY_LEFT</property>
+                 <property name="wrap">False</property>
+                 <property name="selectable">False</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xpad">0</property>
+                 <property name="ypad">0</property>
+               </widget>
+               <packing>
+                 <property name="padding">0</property>
+                 <property name="expand">False</property>
+                 <property name="fill">False</property>
+               </packing>
+             </child>
+
+             <child>
+               <widget class="GtkSpinButton" id="cycles">
+                 <property name="visible">True</property>
+                 <property name="can_focus">True</property>
+                 <property name="climb_rate">1</property>
+                 <property name="digits">0</property>
+                 <property name="numeric">False</property>
+                 <property name="update_policy">GTK_UPDATE_ALWAYS</property>
+                 <property name="snap_to_ticks">False</property>
+                 <property name="wrap">False</property>
+                 <property name="adjustment">1 1 100 1 10 10</property>
+               </widget>
+               <packing>
+                 <property name="padding">0</property>
+                 <property name="expand">True</property>
+                 <property name="fill">True</property>
+               </packing>
+             </child>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">False</property>
+             <property name="fill">False</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkCheckButton" id="create_event">
+             <property name="visible">True</property>
+             <property name="can_focus">True</property>
+             <property name="label" translatable="yes">Record a sequencer event</property>
+             <property name="use_underline">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="active">True</property>
+             <property name="inconsistent">False</property>
+             <property name="draw_indicator">True</property>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">False</property>
+             <property name="fill">False</property>
+           </packing>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">True</property>
+         <property name="fill">True</property>
+       </packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
 </glade-interface>