2 terminatorX - realtime audio scratching software
3 Copyright (C) 1999-2003 Alexander König
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 Description: This implements the new virtual turntable class. It replaces
22 the old turntable.c from terminatorX 3.2 and earlier. The lowpass
23 filter is based on some sample code by Paul Kellett
24 <paul.kellett@maxim.abel.co.uk>
26 08 Dec 1999 - Switched to the new audiofile class
30 #include "tX_global.h"
34 #include "tX_mastergui.h"
35 #include "tX_sequencer.h"
42 #include "tX_loaddlg.h"
44 #define USE_PREFETCH 1
47 #define my_prefetch(base, index); __asm__ __volatile__ ("prefetch index(%0)\n" : : "r" (base));
48 #define my_prefetchw(base, index); __asm__ __volatile__ ("prefetchw index(%0)\n" : : "r" (base));
50 #define my_prefetch(base, index); /* NOP */;
51 #define my_prefetchw(base, index); /* NOP */;
54 extern void build_vtt_gui(vtt_class *);
55 extern void gui_set_name(vtt_class *vtt, char *newname);
56 extern void gui_set_filename(vtt_class *vtt, char *newname);
57 extern void delete_gui(vtt_class *vtt);
58 extern void gui_update_display(vtt_class *vtt);
59 extern void gui_clear_master_button(vtt_class *vtt);
60 extern void cleanup_vtt(vtt_class *vtt);
61 extern int vg_get_current_page(vtt_class *vtt);
62 extern f_prec gui_get_audio_x_zoom(vtt_class *vtt);
63 extern void gui_set_audio_x_zoom(vtt_class *vtt, f_prec);
65 int vtt_class::last_sample_rate=44100;
66 int vtt_class::vtt_amount=0;
67 list <vtt_class *> vtt_class::main_list;
68 list <vtt_class *> vtt_class::render_list;
69 int16_t* vtt_class::mix_out_buffer=NULL;
70 f_prec * vtt_class::mix_buffer=NULL;
71 f_prec * vtt_class::mix_buffer_end=NULL;
72 int vtt_class::solo_ctr=0;
74 int vtt_class::samples_in_mix_buffer=0;
75 pthread_mutex_t vtt_class::render_lock=PTHREAD_MUTEX_INITIALIZER;
76 f_prec vtt_class::master_volume=1.0;
77 f_prec vtt_class::res_master_volume=1.0;
79 vtt_class * vtt_class::sync_master=NULL;
80 int vtt_class::master_triggered=0;
81 int vtt_class::master_triggered_at=0;
82 vtt_class * vtt_class::focused_vtt=NULL;
83 f_prec vtt_class::mix_max_l=0;
84 f_prec vtt_class::mix_max_r=0;
85 f_prec vtt_class::vol_channel_adjust=1.0;
86 int vtt_class::mix_buffer_size=0;
88 #define GAIN_AUTO_ADJUST 0.8
90 vtt_class :: vtt_class (int do_create_gui)
93 cleanup_required=false;
95 sprintf (name, "Turntable %i", vtt_amount);
96 strcpy(filename, "NONE");
105 audiofile_pitch_correction=1.0;
107 ec_output_buffer=NULL;
126 lp_setup(lp_gain, lp_reso, lp_freq);
137 main_list.push_back(this);
139 /* "connecting" the seq-parameters */
141 sp_speed.set_vtt((void *) this);
142 sp_volume.set_vtt((void *) this);
143 sp_pitch.set_vtt((void *) this);
144 sp_pan.set_vtt((void *) this);
145 sp_trigger.set_vtt((void *) this);
146 sp_loop.set_vtt((void *) this);
147 sp_sync_client.set_vtt((void *) this);
148 sp_sync_cycles.set_vtt((void *) this);
149 sp_lp_enable.set_vtt((void *) this);
150 sp_lp_gain.set_vtt((void *) this);
151 sp_lp_reso.set_vtt((void *) this);
152 sp_lp_freq.set_vtt((void *) this);
153 sp_ec_enable.set_vtt((void *) this);
154 sp_ec_length.set_vtt((void *) this);
155 sp_ec_pan.set_vtt((void *) this);
156 sp_ec_volume.set_vtt((void *) this);
157 sp_ec_feedback.set_vtt((void *) this);
158 sp_mute.set_vtt((void *) this);
159 sp_spin.set_vtt((void *) this);
164 lp_fx=new vtt_fx_lp();
165 lp_fx->set_vtt((void *) this);
166 fx_list.push_back(lp_fx);
168 ec_fx=new vtt_fx_ec();
169 ec_fx->set_vtt((void *) this);
170 fx_list.push_back(ec_fx);
175 lp_fx->set_panel_widget(gui.lp_panel->get_widget());
176 ec_fx->set_panel_widget(gui.ec_panel->get_widget());
181 set_master_volume(globals.volume);
182 set_output_buffer_size(samples_in_mix_buffer/2);
185 audiofile_pitch_correction=1.0;
193 control_hidden=false;
200 vtt_class :: ~vtt_class()
205 main_list.remove(this);
206 if (audiofile) delete audiofile;
207 //if (buffer) free(buffer);
208 if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt Destructor");
211 if (mix_solo) solo_ctr--;
213 while (fx_list.size())
215 effect=(*fx_list.begin());
216 fx_list.remove(effect);
220 if (sync_master==this) {
227 void vtt_class :: set_name(char *newname)
229 strcpy(name, newname);
230 gui_set_name(this, name);
233 tX_audio_error vtt_class :: load_file(char *fname)
236 int was_playing=is_playing;
238 if (is_playing) stop();
240 if (audiofile) delete(audiofile);
248 audiofile=new tx_audiofile();
249 res=audiofile->load(fname);
251 if (res==TX_AUDIO_SUCCESS) {
252 buffer=audiofile->get_buffer();
253 double file_rate=audiofile->get_sample_rate();
254 audiofile_pitch_correction=file_rate/((double) last_sample_rate);
256 samples_in_buffer=audiofile->get_no_samples();
257 pos_i_max=samples_in_buffer-1;
258 maxpos=audiofile->get_no_samples();
259 strcpy(filename, fname);
260 if (was_playing) trigger();
261 // printf("Successfully loaded %s, %08x, %i\n", fname, buffer, samples_in_buffer);
266 gui_update_display(this);
268 ec_set_length(ec_length);
273 int vtt_class :: set_output_buffer_size(int newsize)
275 list <vtt_fx *> :: iterator effect;
277 if (ec_output_buffer) tX_freemem(ec_output_buffer, "ec_output_buffer", "vtt set_output_buffer_size()");
278 tX_malloc(ec_output_buffer, "ec_output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
280 if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt set_output_buffer_size()");
281 tX_malloc(output_buffer, "output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
283 end_of_outputbuffer = output_buffer + newsize; //size_t(sizeof(float)*(newsize));
285 samples_in_outputbuffer=newsize;
286 inv_samples_in_outputbuffer=1.0/samples_in_outputbuffer;
288 for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
290 (*effect)->reconnect_buffer();
293 if (output_buffer) return(0);
297 void vtt_class :: set_volume(f_prec newvol)
303 void vtt_class :: recalc_volume()
305 res_volume=rel_volume*res_master_volume;
306 f_prec ec_res_volume=res_volume*ec_volume;
310 res_volume_left=(1.0-pan)*res_volume;
311 res_volume_right=res_volume;
315 res_volume_left=res_volume;
316 res_volume_right=(1.0+pan)*res_volume;
320 res_volume_left=res_volume_right=res_volume;
325 ec_volume_left=(1.0-ec_pan)*ec_res_volume;
326 ec_volume_right=ec_res_volume;
330 ec_volume_left=ec_res_volume;
331 ec_volume_right=(1.0+ec_pan)*ec_res_volume;
335 ec_volume_left=ec_volume_right=ec_res_volume;
337 // printf("vtt_volume: %f, %f, l: %f, r: %f\n", rel_volume, res_volume, res_volume_left, res_volume_right);
340 void vtt_class :: set_pan(f_prec newpan)
346 void vtt_class :: set_pitch(f_prec newpitch)
352 void vtt_class :: recalc_pitch()
354 res_pitch=globals.pitch*rel_pitch;
355 res_pitch*=audiofile_pitch_correction;
357 ec_set_length(ec_length);
360 void vtt_class :: set_autotrigger(int newstate)
362 autotrigger=newstate;
365 void vtt_class :: set_loop(int newstate)
370 void vtt_class :: set_mute(int newstate)
376 void vtt_class :: set_mix_mute(int newstate)
382 void vtt_class :: set_mix_solo(int newstate)
384 if (mix_solo && !newstate)
390 else if (!mix_solo && newstate)
399 list <vtt_class *> :: iterator vtt;
401 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++)
407 void vtt_class :: lp_set_enable (int newstate)
413 void vtt_class :: lp_reset()
418 void vtt_class :: lp_set_gain (f_prec gain)
421 lp_resgain=lp_gain*lp_autogain;
424 void vtt_class :: lp_set_reso(f_prec reso)
428 lp_b=reso*(1.0+(1.0/lp_a));
429 lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
430 lp_resgain=lp_gain*lp_autogain;
433 void vtt_class :: lp_set_freq(f_prec freq)
438 lp_b=lp_reso*(1.0+(1.0/lp_a));
441 void vtt_class :: lp_setup(f_prec gain, f_prec reso, f_prec freq)
447 lp_b=reso*(1.0+(1.0/lp_a));
449 lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
450 lp_resgain=lp_gain*lp_autogain;
453 void vtt_class :: ec_set_enable(int newstate)
460 void vtt_class :: ec_set_pan(f_prec pan)
467 /* Max length is 1.0 */
469 void vtt_class :: ec_set_length(f_prec length)
476 ec_res_length=length*samples_in_buffer;
480 ec_res_length=length*samples_in_buffer/res_pitch;
483 if (ec_res_length<0) ec_res_length*=-1;
485 if (ec_res_length>=EC_MAX_BUFFER)
487 ec_res_length=EC_MAX_BUFFER*length;
490 delay=(int )floor(ec_res_length);
492 ec_delay=&ec_buffer[delay];
495 void vtt_class :: ec_set_feedback(f_prec feedback)
497 ec_feedback=feedback;
501 void vtt_class :: ec_set_volume(f_prec volume)
507 void vtt_class :: ec_clear_buffer()
511 for (ptr=ec_buffer; ptr<=ec_delay; ptr++) {
515 memset(ec_buffer, 0, sizeof(ec_buffer));
519 void vtt_class :: render()
521 list <vtt_fx *> :: iterator effect;
524 if (sense_cycles>0) {
526 if (sense_cycles==0) sp_speed.receive_input_value(0);
531 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
532 if ((*effect)->isEnabled()) (*effect)->run();
536 extern void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plugin);
538 vtt_fx_ladspa * vtt_class :: add_effect (LADSPA_Plugin *plugin)
540 vtt_fx_ladspa *new_effect;
542 new_effect = new vtt_fx_ladspa (plugin, this);
543 pthread_mutex_lock(&render_lock);
544 fx_list.push_back(new_effect);
545 if (is_playing) new_effect->activate();
546 pthread_mutex_unlock(&render_lock);
547 vg_create_fx_gui(this, new_effect, plugin);
552 void vtt_class :: calc_speed()
558 if (speed != speed_target) {
560 speed_step=speed_target-speed_real;
561 speed_step/=globals.vtt_inertia;
564 if (speed_target != speed_real) {
565 speed_real+=speed_step;
566 if ((speed_step<0) && (speed_real<speed_target)) speed_real=speed_target;
567 else if ((speed_step>0) && (speed_real>speed_target)) speed_real=speed_target;
571 if ((speed_last==0) && (speed_real !=0)) {
576 if ((speed_last!=0) && (speed_real==0)) {
582 speed_last = speed_real;
584 if (res_mute != res_mute_old) {
586 fade_out=1; fade_in=0;
589 fade_in=1; fade_out=0;
592 res_mute_old=res_mute;
594 if (res_mute) do_mute=1;
598 void vtt_class :: render_scratch()
619 for (sample =0,out=output_buffer, fade_vol=0.0; sample < samples_in_outputbuffer;sample++, out++, fade_vol+=inv_samples_in_outputbuffer) {
620 if ((speed_real!=0) || (fade_out)) {
631 master_triggered_at=sample;
637 } else if (pos_f<0) {
644 master_triggered_at=sample;
652 pos_a_f=floor(pos_f);
653 pos_i=(unsigned int) pos_a_f;
655 amount_b=pos_f-pos_a_f;
656 amount_a=1.0-amount_b;
662 sample_a=(f_prec) *ptr;
664 if (pos_i == pos_i_max) {
668 sample_b=(f_prec) *ptr;
671 sample_res=(sample_a*amount_a)+(sample_b*amount_b);
674 sample_res*=fade_vol;
675 } else if (fade_out) {
676 sample_res*=1.0-fade_vol;
687 void vtt_class :: forward_turntable()
698 if ((speed_real==0) && (!fade_out)) return;
701 /* following code is problematic as adding speed_real*n is
702 different from adding speed_real n times to pos_f.
704 well it speeds things up quite a bit and double precision
705 seems to do a satisfying job.
707 #define pos_f_test to prove that.
710 pos_f_tmp=pos_f+speed_real*samples_in_outputbuffer;
712 if ((pos_f_tmp > 0) && (pos_f_tmp < maxpos)) {
721 /* now the slow way ;) */
723 for (sample =0; sample < samples_in_outputbuffer; sample++) {
730 if (is_sync_master) {
732 master_triggered_at=sample;
738 } else if (pos_f<0) {
742 if (is_sync_master) {
744 master_triggered_at=sample;
754 diff=pos_f_tmp-pos_f;
755 if (diff!=0) printf("fast: %f, slow: %f, diff: %f, tt: %s\n", pos_f_tmp, pos_f, diff, name);
761 The following lowpass filter is based on some sample code by
762 Paul Kellett <paul.kellett@maxim.abel.co.uk>
765 void vtt_class :: render_lp()
769 for (sample = output_buffer; sample<end_of_outputbuffer; sample++) {
770 lp_buf0 = lp_a * lp_buf0 + lp_freq * ((*sample)*lp_resgain + lp_b * (lp_buf0 - lp_buf1));
771 lp_buf1 = lp_a * lp_buf1 + lp_freq * lp_buf0;
777 void vtt_class :: render_ec()
783 for (i=0, sample = output_buffer, ec_sample=ec_output_buffer; i<samples_in_outputbuffer; i++, ec_sample++,sample++, ec_ptr++) {
784 if (ec_ptr>ec_delay) ec_ptr=ec_buffer;
785 *ec_sample=(*ec_ptr) *ec_feedback;
786 *ec_ptr=*sample+*ec_sample;
790 int vtt_class :: set_mix_buffer_size(int no_samples)
792 list <vtt_class *> :: iterator vtt;
795 // printf("vtt_class::set_mix_buffer_size(), mix_buffer: %12x, mix_out: %12x, samples: %i\n", mix_buffer, mix_out_buffer, no_samples);
797 if (mix_buffer) tX_freemem(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()");
798 samples_in_mix_buffer=no_samples*2;
800 tX_malloc(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()", sizeof(float)*samples_in_mix_buffer, (float *));
801 mix_buffer_end=mix_buffer+samples_in_mix_buffer;
803 // printf("mix_buffer: %12x\n", mix_buffer);
804 // printf("mix_samples: %i, out_samples: %i", samples_in_mix_buffer, no_samples);
806 if (mix_out_buffer) tX_freemem(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()");
807 tX_malloc(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()", sizeof(int16_t)*samples_in_mix_buffer + 4, (int16_t *));
809 // printf("mix_out_buffer: %12x\n", mix_out_buffer);
811 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
812 res|=(*vtt)->set_output_buffer_size(no_samples);
815 if ((!mix_buffer) || (!mix_out_buffer) || res) return(1);
817 mix_buffer_size=no_samples;
822 int16_t * vtt_class :: render_all_turntables()
824 list <vtt_class *> :: iterator vtt, next;
831 pthread_mutex_lock(&render_lock);
833 if (render_list.size()==0) {
834 memset((void *) mix_out_buffer, 0, sizeof(int16_t)*samples_in_mix_buffer);
835 /* We need to memset mix_buffer, too, as the JACK backend
836 acesses this directly.
838 memset((void *) mix_buffer, 0, sizeof(float)*samples_in_mix_buffer);
840 vtt=render_list.begin();
842 max=(*vtt)->max_value;
845 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
846 temp=(*vtt)->output_buffer[sample];
847 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_left;
849 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_right;
852 if (temp>max) max=temp;
853 else if (temp<min) min=temp;
857 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
859 if ((*vtt)->ec_enable) {
860 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
861 temp=(*vtt)->ec_output_buffer[sample];
863 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
865 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
870 if (master_triggered) {
871 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
872 if ((*vtt)->is_sync_client) {
873 if ((*vtt)->sync_countdown) {
874 (*vtt)->sync_countdown--;
876 (*vtt)->sync_countdown=(*vtt)->sync_cycles;
877 (*vtt)->trigger(false);
883 vtt=render_list.begin();
884 for (vtt++; vtt!=render_list.end(); vtt++) {
886 max=(*vtt)->max_value;
889 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
890 temp=(*vtt)->output_buffer[sample];
891 mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_left;
893 mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_right;
896 if (temp>max) max=temp;
897 else if (temp<min) min=temp;
901 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
903 if ((*vtt)->ec_enable) {
904 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
905 temp=(*vtt)->ec_output_buffer[sample];
907 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
909 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
920 for (sample=0; sample<samples_in_mix_buffer; sample+=2) {
921 temp=mix_buffer[sample];
924 #define FL_SHRT_MAX 32767.0
925 #define FL_SHRT_MIN -32768.0
926 if(temp < FL_SHRT_MIN) temp = FL_SHRT_MIN;
927 else if (temp > FL_SHRT_MAX) temp = FL_SHRT_MAX;
930 mix_out_buffer[sample]=(int16_t) temp;
932 if (temp>max) max=temp;
933 else if (temp<min) min=temp;
937 if (min>max) mix_max_l=min; else mix_max_l=max;
944 for (sample=1; sample<samples_in_mix_buffer; sample+=2) {
945 temp=mix_buffer[sample];
948 if(temp < FL_SHRT_MIN) temp = FL_SHRT_MIN;
949 else if (temp > FL_SHRT_MAX) temp = FL_SHRT_MAX;
952 mix_out_buffer[sample]=(int16_t) temp;
954 if (temp>max) max=temp;
955 else if (temp<min) min=temp;
959 if (min>max) mix_max_r=min; else mix_max_r=max;
964 vtt=render_list.begin();
965 while (vtt!=render_list.end()) {
969 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
972 pthread_mutex_unlock(&render_lock);
974 return(mix_out_buffer);
977 void vtt_class :: forward_all_turntables()
979 list <vtt_class *> :: iterator vtt, next;
981 if (render_list.size()>0)
983 vtt=render_list.begin();
984 (*vtt)->forward_turntable();
986 if (master_triggered)
988 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
990 if ((*vtt)->is_sync_client)
992 if ((*vtt)->sync_countdown)
994 (*vtt)->sync_countdown--;
998 (*vtt)->sync_countdown=(*vtt)->sync_cycles;
1005 vtt=render_list.begin();
1006 for (vtt++; vtt!=render_list.end(); vtt++)
1008 (*vtt)->forward_turntable();
1013 vtt=render_list.begin();
1014 while (vtt!=render_list.end())
1019 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
1024 void vtt_class :: retrigger()
1026 if (res_pitch>=0) pos_f=0;
1031 speed_real=res_pitch;
1032 speed_target=res_pitch;
1037 if (is_sync_master) {
1039 master_triggered_at=0;
1043 int vtt_class :: trigger(bool need_lock)
1045 list <vtt_fx *> :: iterator effect;
1047 if (!buffer) return 1;
1052 if (need_lock) pthread_mutex_lock(&render_lock);
1054 cleanup_required=false;
1056 /* activating plugins */
1057 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
1058 (*effect)->activate();
1061 if (is_sync_master) {
1062 render_list.push_front(this);
1064 render_list.push_back(this);
1067 if (need_lock) pthread_mutex_unlock(&render_lock);
1073 /* call this only when owning render_lock. */
1074 int vtt_class :: stop_nolock()
1076 list <vtt_fx *> :: iterator effect;
1082 render_list.remove(this);
1087 cleanup_required=true;
1089 /* deactivating plugins */
1090 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
1091 (*effect)->deactivate();
1097 int vtt_class :: stop()
1101 pthread_mutex_lock(&render_lock);
1103 pthread_mutex_unlock(&render_lock);
1108 void vtt_class :: set_sync_master(int master)
1111 if (sync_master) sync_master->set_sync_master(0);
1115 if (sync_master==this) sync_master=0;
1117 gui_clear_master_button(this);
1121 void vtt_class :: set_sync_client(int slave, int cycles)
1123 tX_debug("vtt_class::set_sync_client() setting %i, %i.", slave, cycles);
1124 is_sync_client=slave;
1126 // sync_countdown=cycles;
1130 void vtt_class :: set_sync_client_ug(int slave, int cycles)
1132 set_sync_client(slave, cycles);
1135 void vtt_class :: set_master_volume(f_prec new_volume)
1137 list <vtt_class *> :: iterator vtt;
1139 master_volume=new_volume;
1140 globals.volume=new_volume;
1142 if (main_list.size()>0) {
1143 vol_channel_adjust=sqrt((f_prec) main_list.size());
1144 res_master_volume=master_volume/vol_channel_adjust;
1147 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1148 (*vtt)->recalc_volume();
1152 void vtt_class :: set_master_pitch(f_prec new_pitch)
1154 list <vtt_class *> :: iterator vtt;
1156 globals.pitch=new_pitch;
1157 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1158 (*vtt)->recalc_pitch();
1162 void vtt_class :: focus_no(int no)
1164 list <vtt_class *> :: iterator vtt;
1169 for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++) {
1176 void vtt_class :: focus_next()
1178 list <vtt_class *> :: iterator vtt;
1181 if (main_list.size()) {
1182 focused_vtt=(*main_list.begin());
1187 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1188 if ((*vtt)==focused_vtt) {
1189 /* Ok, we found ourselves.. */
1192 while ((vtt!=main_list.end()) && ((*vtt)->audio_hidden) ) {
1196 if (vtt==main_list.end()) {
1197 /* No other "focusable" after this vtt so we're looking for the next */
1199 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1200 if (! (*vtt)->audio_hidden) {
1205 /* When we get here there's no "focusable" vtt at all... damn */
1215 focused_vtt=(*main_list.begin());
1218 void vtt_class :: set_scratch(int newstate)
1221 sp_spin.receive_input_value(0);
1223 sense_cycles=globals.sense_cycles;
1225 sp_spin.receive_input_value(1);
1231 void vtt_class :: unfocus()
1236 void vtt_class :: set_x_input_parameter(tX_seqpar *sp)
1241 void vtt_class :: set_y_input_parameter(tX_seqpar *sp)
1246 void vtt_class :: xy_input(f_prec x_value, f_prec y_value)
1248 if (x_par) x_par->handle_mouse_input(x_value*globals.mouse_speed);
1249 if (y_par) y_par->handle_mouse_input(y_value*globals.mouse_speed);
1252 #define store(data); if (fwrite((void *) &data, sizeof(data), 1, output)!=1) res+=1;
1254 int vtt_class :: save(FILE *rc, gzFile rz, char *indent) {
1255 list <vtt_fx *> :: iterator effect;
1256 char tmp_xml_buffer[4096];
1260 tX_store("%s<turntable>\n", indent);
1261 strcat(indent, "\t");
1263 store_string("name", name);
1265 store_string("audiofile", filename);
1267 store_string("audiofile", "");
1269 store_bool("sync_master", is_sync_master);
1270 store_bool("autotrigger", autotrigger);
1271 store_bool_sp("loop", loop, sp_loop);
1273 store_bool_sp("sync_client", is_sync_client, sp_sync_client);
1274 store_int_sp("sync_cycles", sync_cycles, sp_sync_cycles);
1276 store_float_sp("volume", rel_volume, sp_volume);
1277 store_float_sp("pitch", rel_pitch, sp_pitch);
1278 store_bool_sp("mute", mute, sp_mute);
1279 store_float_sp("pan", pan, sp_pan);
1281 store_bool_sp("lowpass_enable", lp_enable, sp_lp_enable);
1282 store_float_sp("lowpass_gain", lp_gain, sp_lp_gain);
1283 store_float_sp("lowpass_reso", lp_reso, sp_lp_reso);
1284 store_float_sp("lowpass_freq", lp_freq, sp_lp_freq);
1286 store_bool_sp("echo_enable", ec_enable, sp_ec_enable);
1287 store_float_sp("echo_length", ec_length, sp_ec_length);
1288 store_float_sp("echo_feedback", ec_feedback, sp_ec_feedback);
1289 store_float_sp("echo_pan", ec_pan, sp_ec_pan);
1290 store_float_sp("echo_volume", ec_volume, sp_ec_volume);
1292 store_id("speed", sp_speed.get_persistence_id());
1293 store_id("trigger", sp_trigger.get_persistence_id());
1294 store_id("spin", sp_spin.get_persistence_id());
1298 store_int("x_axis_mapping", x_par->get_persistence_id());
1302 store_int("y_axis_mapping", y_par->get_persistence_id());
1305 store_bool("audio_panel_hidden", audio_hidden);
1306 store_bool("control_panel_hidden", control_hidden);
1307 store_bool("main_panel_hidden", gui.main_panel->is_hidden());
1308 store_bool("trigger_panel_hidden", gui.trigger_panel->is_hidden());
1309 store_bool("lowpass_panel_hidden", gui.lp_panel->is_hidden());
1310 store_bool("echo_panel_hidden", gui.ec_panel->is_hidden());
1312 store_bool("mix_mute", mix_mute);
1313 store_bool("mix_solo", mix_solo);
1315 store_float("audio_x_zoom", gui_get_audio_x_zoom(this));
1317 tX_store("%s<fx>\n", indent);
1318 strcat(indent, "\t");
1320 for (effect=fx_list.begin(); effect!=fx_list.end(); effect++) {
1321 (*effect)->save(rc, rz, indent);
1323 indent[strlen(indent)-1]=0;
1324 tX_store("%s</fx>\n", indent);
1326 indent[strlen(indent)-1]=0;
1327 tX_store("%s</turntable>\n", indent);
1332 #define TX_XML_SETFILE_VERSION "1.0"
1334 int vtt_class :: save_all(FILE* rc, gzFile rz) {
1336 list <vtt_class *> :: iterator vtt;
1339 tX_seqpar :: create_persistence_ids();
1341 tX_store("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n");
1342 tX_store("<terminatorXset version=\"%s\">\n", TX_XML_SETFILE_VERSION);
1344 strcpy(indent, "\t");
1346 //store_int(vtt_amount); obsolete
1348 store_float_sp("master_volume", master_volume, sp_master_volume);
1349 store_float_sp("master_pitch", globals.pitch, sp_master_pitch);
1351 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1352 res+=(*vtt)->save(rc, rz, indent);
1355 sequencer.save(rc, rz, indent);
1357 tX_store("</terminatorXset>\n");
1362 int vtt_class :: load(xmlDocPtr doc, xmlNodePtr node) {
1372 char tmp_xml_buffer[4096];
1374 for (xmlNodePtr cur=node->xmlChildrenNode; cur != NULL; cur = cur->next) {
1375 if (cur->type == XML_ELEMENT_NODE) {
1378 restore_string_ac("name", buffer, set_name(buffer));
1379 restore_string("audiofile", filename);
1380 restore_bool("sync_master", is_sync_master);
1381 restore_bool("autotrigger", autotrigger);
1382 restore_bool_id("loop", loop, sp_loop, nop);
1383 restore_bool_id("sync_client", is_sync_client, sp_sync_client, set_sync_client(is_sync_client, sync_cycles));
1384 restore_int_id("sync_cycles", sync_cycles, sp_sync_cycles, set_sync_client(is_sync_client, sync_cycles));
1385 restore_float_id("volume", rel_volume, sp_volume, recalc_volume());
1386 restore_float_id("pitch", rel_pitch, sp_pitch, recalc_pitch());
1387 restore_bool_id("mute", mute, sp_mute, set_mute(mute));
1388 restore_float_id("pan", pan, sp_pan, set_pan(pan));
1390 restore_bool_id("lowpass_enable", lp_enable, sp_lp_enable, lp_set_enable(lp_enable));
1391 restore_float_id("lowpass_gain", lp_gain, sp_lp_gain, lp_set_gain(lp_gain));
1392 restore_float_id("lowpass_reso", lp_reso, sp_lp_reso, lp_set_reso(lp_reso));
1393 restore_float_id("lowpass_freq", lp_freq, sp_lp_freq, lp_set_freq(lp_freq));
1395 restore_bool_id("echo_enable", ec_enable, sp_ec_enable, ec_set_enable(ec_enable));
1396 restore_float_id("echo_length", ec_length, sp_ec_length, ec_set_length(ec_length));
1397 restore_float_id("echo_feedback", ec_feedback, sp_ec_feedback, ec_set_feedback(ec_feedback));
1398 restore_float_id("echo_pan", ec_pan, sp_ec_pan, ec_set_pan(ec_pan));
1399 restore_float_id("echo_volume", ec_volume, sp_ec_volume, ec_set_volume(ec_volume));
1401 restore_id("speed", sp_speed);
1402 restore_id("trigger", sp_trigger);
1403 restore_id("spin", sp_spin);
1405 restore_int("x_axis_mapping", xpar_id);
1406 restore_int("y_axis_mapping", ypar_id);
1408 restore_bool("mix_mute", mix_mute);
1409 restore_bool("mix_solo", mix_solo);
1411 restore_bool("audio_panel_hidden", audio_hidden);
1412 restore_bool("control_panel_hidden", control_hidden);
1413 restore_bool_ac("main_panel_hidden", hidden, gui.main_panel->hide(hidden));
1414 restore_bool_ac("trigger_panel_hidden", hidden, gui.trigger_panel->hide(hidden));
1415 restore_bool_ac("lowpass_panel_hidden", hidden, gui.lp_panel->hide(hidden));
1416 restore_bool_ac("echo_panel_hidden", hidden, gui.ec_panel->hide(hidden));
1417 restore_float_ac("audio_x_zoom", tmp, gui_set_audio_x_zoom(this,tmp));
1418 vg_adjust_zoom(gui.zoom, this);
1420 if (xmlStrcmp(cur->name, (xmlChar *) "fx")==0) {
1424 for (xmlNodePtr cur=fx->xmlChildrenNode; cur != NULL; cur = cur->next) {
1425 if (cur->type == XML_ELEMENT_NODE) {
1428 if (xmlStrcmp(cur->name, (xmlChar *) "cutoff")==0) {
1429 for (unsigned int t=0; t<fx_list.size(); t++) effect_down(lp_fx);
1431 } else if (xmlStrcmp(cur->name, (xmlChar *) "lowpass")==0) {
1432 for (unsigned int t=0; t<fx_list.size(); t++) effect_down(ec_fx);
1434 } else if (xmlStrcmp(cur->name, (xmlChar *) "ladspa_plugin")==0) {
1435 xmlNodePtr pluginNode=cur;
1439 for (xmlNodePtr cur=pluginNode->xmlChildrenNode; cur!=NULL; cur = cur->next) {
1441 if (cur->type == XML_ELEMENT_NODE) {
1444 restore_int("ladspa_id", ladspa_id);
1445 if (elementFound) break;
1449 if (ladspa_id!=-1) {
1450 LADSPA_Plugin *plugin=LADSPA_Plugin::getPluginByUniqueID(ladspa_id);
1452 vtt_fx_ladspa *ladspa_effect=add_effect(plugin);
1453 ladspa_effect->load(doc, pluginNode);
1455 sprintf(buffer,"The terminatorX set file you are loading makes use of a LADSPA plugin that is not installed on this machine. The plugin's ID is [%i].", ladspa_id);
1456 tx_note(buffer, true);
1459 tX_warning("ladspa_plugin section without a ladspa_id element.");
1463 tX_warning("unhandled element %s in fx section.", cur->name);
1470 tX_warning("unhandled element %s in turntable secion.", cur->name);
1482 set_x_input_parameter(tX_seqpar :: get_sp_by_persistence_id(xpar_id));
1484 else set_x_input_parameter(NULL);
1487 set_y_input_parameter(tX_seqpar :: get_sp_by_persistence_id(ypar_id));
1489 else set_y_input_parameter(NULL);
1491 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.mute), mix_mute);
1492 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.solo), mix_solo);
1497 void vtt_class :: delete_all()
1499 while (main_list.size()) {
1500 delete((*main_list.begin()));
1503 /* Take care of the master events.. */
1504 sequencer.delete_all_events(tX_sequencer::DELETE_ALL);
1506 /* Now reset master settings ot the default: */
1507 set_master_pitch(1.0);
1508 set_master_volume(1.0);
1510 sp_master_pitch.do_exec(1.0);
1511 sp_master_pitch.do_update_graphics();
1513 sp_master_volume.do_exec(1.0);
1514 sp_master_volume.do_update_graphics();
1516 /* Remove master MIDI mappings... */
1517 sp_master_pitch.bound_midi_event.type=tX_midievent::NONE;
1518 sp_master_volume.bound_midi_event.type=tX_midievent::NONE;
1523 int vtt_class :: load_all(xmlDocPtr doc, char *fname) {
1524 xmlNodePtr root=xmlDocGetRootElement(doc);
1532 tX_error("no root element? What kind of XML document is this?");
1536 if (xmlStrcmp(root->name, (const xmlChar *) "terminatorXset")) {
1537 tX_error("this is not a terminatorXset file.")
1541 if (xmlGetProp(root,(xmlChar *) "version")==NULL) {
1542 tX_error("the set file lacks a version attribute.");
1546 if (xmlStrcmp(xmlGetProp(root, (xmlChar *) "version"), (xmlChar *) TX_XML_SETFILE_VERSION)) {
1547 tX_warning("this set file is version %s - while this releases uses version %s - trying to load anyway.", xmlGetProp(root, (xmlChar *) "version"), TX_XML_SETFILE_VERSION);
1550 /* delete current tables... */
1555 /* counting turntables.. */
1556 for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1557 if (cur->type == XML_ELEMENT_NODE) {
1558 if (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0) {
1564 tX_debug("Found %i turntables in set.", table_ctr);
1566 ld_create_loaddlg(TX_LOADDLG_MODE_MULTI, table_ctr);
1567 ld_set_setname(fname);
1570 for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1571 if (cur->type == XML_ELEMENT_NODE) {
1574 restore_float_id("master_volume", master_volume, sp_master_volume, set_master_volume(master_volume));
1575 restore_float_id("master_pitch", globals.pitch, sp_master_pitch, set_master_pitch(globals.pitch));
1577 if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0)) {
1579 vtt_class *vtt=new vtt_class(1);
1580 vtt->load(doc, cur);
1582 tX_debug("loading a turntable..");
1584 if (strlen(vtt->filename)) {
1585 strcpy(fn_buff, vtt->filename);
1586 ld_set_filename(fn_buff);
1588 restmp=(int) vtt->load_file(fn_buff);
1592 gtk_box_pack_start(GTK_BOX(control_parent), vtt->gui.control_box, TRUE, TRUE, 0);
1593 gtk_box_pack_start(GTK_BOX(audio_parent), vtt->gui.audio_box, TRUE, TRUE, 0);
1594 if (vtt->audio_hidden) vtt->hide_audio(vtt->audio_hidden);
1595 if (vtt->control_hidden) vtt->hide_control(vtt->control_hidden);
\r
1597 if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "sequencer")==0)) {
1599 sequencer.load(doc, cur);
1601 if (!elementFound) {
1602 tX_warning("unhandled element %s in setfile %s", cur->name, fname);
1607 sp_master_volume.do_update_graphics();
1608 sp_master_pitch.do_update_graphics();
1615 void add_vtt(GtkWidget *ctrl, GtkWidget *audio, char *fn)
1618 new_tt = new vtt_class(1);
1619 gtk_box_pack_start(GTK_BOX(ctrl), new_tt->gui.control_box, TRUE, TRUE, 0);
1620 gtk_box_pack_start(GTK_BOX(audio), new_tt->gui.audio_box, TRUE, TRUE, 0);
1621 if (fn) new_tt->load_file(fn);
1624 extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt);
1625 extern void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt);
1627 //#define debug_fx_stack(); for (i=fx_list.begin(); i != fx_list.end(); i++) puts((*i)->get_info_string());
1628 #define debug_fx_stack();
1630 void vtt_class :: effect_up(vtt_fx *effect)
1632 list <vtt_fx *> :: iterator i;
1633 list <vtt_fx *> :: iterator previous;
1638 if ((*fx_list.begin())==effect) return;
1640 for (previous=i=fx_list.begin(); i != fx_list.end(); i++) {
1641 if ((*i) == effect) {
1649 pthread_mutex_lock(&render_lock);
1650 fx_list.remove(effect);
1651 fx_list.insert(previous, effect);
1652 pthread_mutex_unlock(&render_lock);
1654 vg_move_fx_panel_up(effect->get_panel_widget(), this);
1660 void vtt_class :: effect_down(vtt_fx *effect)
1662 list <vtt_fx *> :: iterator i;
1667 for (i=fx_list.begin(); i != fx_list.end(); i++) {
1668 if ((*i) == effect) {
1674 if ((ok) && (i!=fx_list.end())) {
1676 if (i==fx_list.end()) return;
1679 pthread_mutex_lock(&render_lock);
1680 fx_list.remove(effect);
1682 fx_list.insert(i, effect);
1683 vg_move_fx_panel_down(effect->get_panel_widget(), this);
1684 pthread_mutex_unlock(&render_lock);
1690 void vtt_class :: effect_remove(vtt_fx_ladspa *effect)
1692 pthread_mutex_lock(&render_lock);
1693 fx_list.remove(effect);
1694 pthread_mutex_unlock(&render_lock);
1699 extern void gui_hide_control_panel(vtt_class *vtt, bool hide);
1700 extern void gui_hide_audio_panel(vtt_class *vtt, bool hide);
1702 void vtt_class :: hide_audio(bool hide) {
1704 gui_hide_audio_panel(this, hide);
1707 void vtt_class :: hide_control(bool hide) {
1708 control_hidden=hide;
1709 gui_hide_control_panel(this, hide);
1712 void vtt_class :: set_sample_rate(int samplerate) {
1713 list <vtt_class *> :: iterator vtt;
1714 double sr=(double) samplerate;
1716 last_sample_rate=samplerate;
1718 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1719 if ((*vtt)->audiofile) {
1720 double file_rate=(*vtt)->audiofile->get_sample_rate();
1721 (*vtt)->audiofile_pitch_correction=file_rate/sr;
1723 (*vtt)->audiofile_pitch_correction=1.0;
1725 (*vtt)->recalc_pitch();
1728 int no_samples=(int) (sr*0.001); // Forcing 1 ms blocksize
1730 set_mix_buffer_size(no_samples);
1733 void vtt_class :: adjust_to_master_pitch(int master_cycles, int cycles, bool create_event) {
1734 if (!sync_master) return;
1735 if (this==sync_master) return;
1736 if (!sync_master->audiofile) return;
1737 if (!audiofile) return;
1739 double master_time=((double) master_cycles)/sync_master->rel_pitch*sync_master->audiofile->get_no_samples()/((double) sync_master->audiofile->get_sample_rate());
1740 double my_rel_pitch=((audiofile->get_no_samples()/((double) audiofile->get_sample_rate()))*((double) cycles))/master_time;
1743 sp_pitch.do_exec(my_rel_pitch);
1744 sp_pitch.record_value(my_rel_pitch);
1746 sp_pitch.do_exec(my_rel_pitch);
1749 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());
1751 sp_pitch.update_graphics();