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"
43 #define tX_freemem(ptr, varname, comment); fprintf(stderr, "** free() [%s] at %08x. %s.\n", varname, ptr, comment); free(ptr);
44 #define tX_malloc(ptr, varname, comment, size, type); fprintf(stderr, "**[1/2] malloc() [%s]. Size: %i. %s.\n", varname, size, comment); ptr=type malloc(size); fprintf(stderr, "**[2/2] malloc() [%s]. ptr: %08x.\n", varname, ptr);
46 #define tX_freemem(ptr, varname, comment); free(ptr);
47 #define tX_malloc(ptr, varname, comment, size, type); ptr=type malloc(size);
50 #include "tX_loaddlg.h"
52 #define USE_PREFETCH 1
55 #define my_prefetch(base, index); __asm__ __volatile__ ("prefetch index(%0)\n" : : "r" (base));
56 #define my_prefetchw(base, index); __asm__ __volatile__ ("prefetchw index(%0)\n" : : "r" (base));
58 #define my_prefetch(base, index); /* NOP */;
59 #define my_prefetchw(base, index); /* NOP */;
62 extern void build_vtt_gui(vtt_class *);
63 extern void gui_set_name(vtt_class *vtt, char *newname);
64 extern void gui_set_filename(vtt_class *vtt, char *newname);
65 extern void delete_gui(vtt_class *vtt);
66 extern void gui_update_display(vtt_class *vtt);
67 extern void gui_clear_master_button(vtt_class *vtt);
68 extern void cleanup_vtt(vtt_class *vtt);
69 extern int vg_get_current_page(vtt_class *vtt);
70 extern f_prec gui_get_audio_x_zoom(vtt_class *vtt);
71 extern void gui_set_audio_x_zoom(vtt_class *vtt, f_prec);
73 int vtt_class::last_sample_rate=44100;
74 int vtt_class::vtt_amount=0;
75 list <vtt_class *> vtt_class::main_list;
76 list <vtt_class *> vtt_class::render_list;
77 int16_t* vtt_class::mix_out_buffer=NULL;
78 f_prec * vtt_class::mix_buffer=NULL;
79 f_prec * vtt_class::mix_buffer_end=NULL;
80 int vtt_class::solo_ctr=0;
82 int vtt_class::samples_in_mix_buffer=0;
83 pthread_mutex_t vtt_class::render_lock=PTHREAD_MUTEX_INITIALIZER;
84 f_prec vtt_class::master_volume=1.0;
85 f_prec vtt_class::res_master_volume=1.0;
86 f_prec vtt_class::saturate_fac=0.1;
87 int vtt_class::do_saturate=0;
88 vtt_class * vtt_class::sync_master=NULL;
89 int vtt_class::master_triggered=0;
90 int vtt_class::master_triggered_at=0;
91 vtt_class * vtt_class::focused_vtt=NULL;
92 f_prec vtt_class::mix_max_l=0;
93 f_prec vtt_class::mix_max_r=0;
94 f_prec vtt_class::vol_channel_adjust=1.0;
95 int vtt_class::mix_buffer_size=0;
97 #define GAIN_AUTO_ADJUST 0.8
99 vtt_class :: vtt_class (int do_create_gui)
102 sprintf (name, "Turntable %i", vtt_amount);
103 strcpy(filename, "NONE");
112 audiofile_pitch_correction=1.0;
114 ec_output_buffer=NULL;
133 lp_setup(lp_gain, lp_reso, lp_freq);
144 main_list.push_back(this);
146 /* "connecting" the seq-parameters */
148 sp_speed.set_vtt((void *) this);
149 sp_volume.set_vtt((void *) this);
150 sp_pitch.set_vtt((void *) this);
151 sp_pan.set_vtt((void *) this);
152 sp_trigger.set_vtt((void *) this);
153 sp_loop.set_vtt((void *) this);
154 sp_sync_client.set_vtt((void *) this);
155 sp_sync_cycles.set_vtt((void *) this);
156 sp_lp_enable.set_vtt((void *) this);
157 sp_lp_gain.set_vtt((void *) this);
158 sp_lp_reso.set_vtt((void *) this);
159 sp_lp_freq.set_vtt((void *) this);
160 sp_ec_enable.set_vtt((void *) this);
161 sp_ec_length.set_vtt((void *) this);
162 sp_ec_pan.set_vtt((void *) this);
163 sp_ec_volume.set_vtt((void *) this);
164 sp_ec_feedback.set_vtt((void *) this);
165 sp_mute.set_vtt((void *) this);
166 sp_spin.set_vtt((void *) this);
171 lp_fx=new vtt_fx_lp();
172 lp_fx->set_vtt((void *) this);
173 fx_list.push_back(lp_fx);
175 ec_fx=new vtt_fx_ec();
176 ec_fx->set_vtt((void *) this);
177 fx_list.push_back(ec_fx);
182 lp_fx->set_panel_widget(gui.lp_panel->get_widget());
183 ec_fx->set_panel_widget(gui.ec_panel->get_widget());
188 set_master_volume(globals.volume);
189 set_output_buffer_size(samples_in_mix_buffer/2);
192 audiofile_pitch_correction=1.0;
200 control_hidden=false;
207 vtt_class :: ~vtt_class()
212 main_list.remove(this);
213 if (audiofile) delete audiofile;
214 //if (buffer) free(buffer);
215 if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt Destructor");
218 if (mix_solo) solo_ctr--;
220 while (fx_list.size())
222 effect=(*fx_list.begin());
223 fx_list.remove(effect);
227 if (sync_master==this) {
234 void vtt_class :: set_name(char *newname)
236 strcpy(name, newname);
237 gui_set_name(this, name);
240 tX_audio_error vtt_class :: load_file(char *fname)
243 int was_playing=is_playing;
245 if (is_playing) stop();
247 if (audiofile) delete(audiofile);
255 audiofile=new tx_audiofile();
256 res=audiofile->load(fname);
258 if (res==TX_AUDIO_SUCCESS) {
259 buffer=audiofile->get_buffer();
260 double file_rate=audiofile->get_sample_rate();
261 audiofile_pitch_correction=file_rate/((double) last_sample_rate);
263 samples_in_buffer=audiofile->get_no_samples();
264 pos_i_max=samples_in_buffer-1;
265 maxpos=audiofile->get_no_samples();
266 strcpy(filename, fname);
267 if (was_playing) trigger();
268 // printf("Successfully loaded %s, %08x, %i\n", fname, buffer, samples_in_buffer);
273 gui_update_display(this);
275 ec_set_length(ec_length);
280 int vtt_class :: set_output_buffer_size(int newsize)
282 list <vtt_fx *> :: iterator effect;
284 if (ec_output_buffer) tX_freemem(ec_output_buffer, "ec_output_buffer", "vtt set_output_buffer_size()");
285 tX_malloc(ec_output_buffer, "ec_output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
287 if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt set_output_buffer_size()");
288 tX_malloc(output_buffer, "output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
290 end_of_outputbuffer = output_buffer + newsize; //size_t(sizeof(float)*(newsize));
292 samples_in_outputbuffer=newsize;
293 inv_samples_in_outputbuffer=1.0/samples_in_outputbuffer;
295 for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
297 (*effect)->reconnect_buffer();
300 if (output_buffer) return(0);
304 void vtt_class :: set_volume(f_prec newvol)
310 void vtt_class :: recalc_volume()
312 res_volume=rel_volume*res_master_volume;
313 f_prec ec_res_volume=res_volume*ec_volume;
317 res_volume_left=(1.0-pan)*res_volume;
318 res_volume_right=res_volume;
322 res_volume_left=res_volume;
323 res_volume_right=(1.0+pan)*res_volume;
327 res_volume_left=res_volume_right=res_volume;
332 ec_volume_left=(1.0-ec_pan)*ec_res_volume;
333 ec_volume_right=ec_res_volume;
337 ec_volume_left=ec_res_volume;
338 ec_volume_right=(1.0+ec_pan)*ec_res_volume;
342 ec_volume_left=ec_volume_right=ec_res_volume;
344 // printf("vtt_volume: %f, %f, l: %f, r: %f\n", rel_volume, res_volume, res_volume_left, res_volume_right);
347 void vtt_class :: set_pan(f_prec newpan)
353 void vtt_class :: set_pitch(f_prec newpitch)
359 void vtt_class :: recalc_pitch()
361 res_pitch=globals.pitch*rel_pitch;
362 res_pitch*=audiofile_pitch_correction;
364 ec_set_length(ec_length);
367 void vtt_class :: set_autotrigger(int newstate)
369 autotrigger=newstate;
372 void vtt_class :: set_loop(int newstate)
377 void vtt_class :: set_mute(int newstate)
383 void vtt_class :: set_mix_mute(int newstate)
389 void vtt_class :: set_mix_solo(int newstate)
391 if (mix_solo && !newstate)
397 else if (!mix_solo && newstate)
406 list <vtt_class *> :: iterator vtt;
408 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++)
414 void vtt_class :: lp_set_enable (int newstate)
420 void vtt_class :: lp_reset()
425 void vtt_class :: lp_set_gain (f_prec gain)
428 lp_resgain=lp_gain*lp_autogain;
431 void vtt_class :: lp_set_reso(f_prec reso)
435 lp_b=reso*(1.0+(1.0/lp_a));
436 lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
437 lp_resgain=lp_gain*lp_autogain;
440 void vtt_class :: lp_set_freq(f_prec freq)
445 lp_b=lp_reso*(1.0+(1.0/lp_a));
448 void vtt_class :: lp_setup(f_prec gain, f_prec reso, f_prec freq)
454 lp_b=reso*(1.0+(1.0/lp_a));
456 lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
457 lp_resgain=lp_gain*lp_autogain;
460 void vtt_class :: ec_set_enable(int newstate)
467 void vtt_class :: ec_set_pan(f_prec pan)
474 /* Max length is 1.0 */
476 void vtt_class :: ec_set_length(f_prec length)
483 ec_res_length=length*samples_in_buffer;
487 ec_res_length=length*samples_in_buffer/res_pitch;
490 if (ec_res_length<0) ec_res_length*=-1;
492 if (ec_res_length>=EC_MAX_BUFFER)
494 ec_res_length=EC_MAX_BUFFER*length;
497 delay=(int )floor(ec_res_length);
499 ec_delay=&ec_buffer[delay];
502 void vtt_class :: ec_set_feedback(f_prec feedback)
504 ec_feedback=feedback;
508 void vtt_class :: ec_set_volume(f_prec volume)
514 void vtt_class :: ec_clear_buffer()
518 for (ptr=ec_buffer; ptr<=ec_delay; ptr++) {
524 void vtt_class :: render()
526 list <vtt_fx *> :: iterator effect;
529 if (sense_cycles>0) {
531 if (sense_cycles==0) sp_speed.receive_input_value(0);
536 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
537 if ((*effect)->isEnabled()) (*effect)->run();
541 extern void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plugin);
543 vtt_fx_ladspa * vtt_class :: add_effect (LADSPA_Plugin *plugin)
545 vtt_fx_ladspa *new_effect;
547 new_effect = new vtt_fx_ladspa (plugin, this);
548 pthread_mutex_lock(&render_lock);
549 fx_list.push_back(new_effect);
550 if (is_playing) new_effect->activate();
551 pthread_mutex_unlock(&render_lock);
552 vg_create_fx_gui(this, new_effect, plugin);
557 void vtt_class :: calc_speed()
563 if (speed != speed_target) {
565 speed_step=speed_target-speed_real;
566 speed_step/=globals.vtt_inertia;
569 if (speed_target != speed_real) {
570 speed_real+=speed_step;
571 if ((speed_step<0) && (speed_real<speed_target)) speed_real=speed_target;
572 else if ((speed_step>0) && (speed_real>speed_target)) speed_real=speed_target;
576 if ((speed_last==0) && (speed_real !=0)) {
581 if ((speed_last!=0) && (speed_real==0)) {
587 speed_last = speed_real;
589 if (res_mute != res_mute_old) {
591 fade_out=1; fade_in=0;
594 fade_in=1; fade_out=0;
597 res_mute_old=res_mute;
599 if (res_mute) do_mute=1;
603 void vtt_class :: render_scratch()
624 for (sample =0,out=output_buffer, fade_vol=0.0; sample < samples_in_outputbuffer;sample++, out++, fade_vol+=inv_samples_in_outputbuffer) {
625 if ((speed_real!=0) || (fade_out)) {
636 master_triggered_at=sample;
642 } else if (pos_f<0) {
649 master_triggered_at=sample;
657 pos_a_f=floor(pos_f);
658 pos_i=(unsigned int) pos_a_f;
660 amount_b=pos_f-pos_a_f;
661 amount_a=1.0-amount_b;
667 sample_a=(f_prec) *ptr;
669 if (pos_i == pos_i_max) {
673 sample_b=(f_prec) *ptr;
676 sample_res=(sample_a*amount_a)+(sample_b*amount_b);
679 sample_res*=fade_vol;
680 } else if (fade_out) {
681 sample_res*=1.0-fade_vol;
692 void vtt_class :: forward_turntable()
703 if ((speed_real==0) && (!fade_out)) return;
706 /* following code is problematic as adding speed_real*n is
707 different from adding speed_real n times to pos_f.
709 well it speeds things up quite a bit and double precision
710 seems to do a satisfying job.
712 #define pos_f_test to prove that.
715 pos_f_tmp=pos_f+speed_real*samples_in_outputbuffer;
717 if ((pos_f_tmp > 0) && (pos_f_tmp < maxpos)) {
726 /* now the slow way ;) */
728 for (sample =0; sample < samples_in_outputbuffer; sample++) {
735 if (is_sync_master) {
737 master_triggered_at=sample;
743 } else if (pos_f<0) {
747 if (is_sync_master) {
749 master_triggered_at=sample;
759 diff=pos_f_tmp-pos_f;
760 if (diff!=0) printf("fast: %f, slow: %f, diff: %f, tt: %s\n", pos_f_tmp, pos_f, diff, name);
766 The following lowpass filter is based on some sample code by
767 Paul Kellett <paul.kellett@maxim.abel.co.uk>
770 void vtt_class :: render_lp()
774 for (sample = output_buffer; sample<end_of_outputbuffer; sample++) {
775 lp_buf0 = lp_a * lp_buf0 + lp_freq * ((*sample)*lp_resgain + lp_b * (lp_buf0 - lp_buf1));
776 lp_buf1 = lp_a * lp_buf1 + lp_freq * lp_buf0;
782 void vtt_class :: render_ec()
788 for (i=0, sample = output_buffer, ec_sample=ec_output_buffer; i<samples_in_outputbuffer; i++, ec_sample++,sample++, ec_ptr++) {
789 if (ec_ptr>ec_delay) ec_ptr=ec_buffer;
790 *ec_sample=(*ec_ptr) *ec_feedback;
791 *ec_ptr=*sample+*ec_sample;
795 int vtt_class :: set_mix_buffer_size(int no_samples)
797 list <vtt_class *> :: iterator vtt;
800 // printf("vtt_class::set_mix_buffer_size(), mix_buffer: %12x, mix_out: %12x, samples: %i\n", mix_buffer, mix_out_buffer, no_samples);
802 if (mix_buffer) tX_freemem(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()");
803 samples_in_mix_buffer=no_samples*2;
805 tX_malloc(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()", sizeof(float)*samples_in_mix_buffer, (float *));
806 mix_buffer_end=mix_buffer+samples_in_mix_buffer;
808 // printf("mix_buffer: %12x\n", mix_buffer);
809 // printf("mix_samples: %i, out_samples: %i", samples_in_mix_buffer, no_samples);
811 if (mix_out_buffer) tX_freemem(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()");
812 tX_malloc(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()", sizeof(int16_t)*samples_in_mix_buffer + 4, (int16_t *));
814 // printf("mix_out_buffer: %12x\n", mix_out_buffer);
816 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
817 res|=(*vtt)->set_output_buffer_size(no_samples);
820 if ((!mix_buffer) || (!mix_out_buffer) || res) return(1);
822 mix_buffer_size=no_samples;
827 int16_t * vtt_class :: render_all_turntables()
829 list <vtt_class *> :: iterator vtt, next;
836 pthread_mutex_lock(&render_lock);
838 if (render_list.size()==0) {
839 for (sample=0; sample<samples_in_mix_buffer; sample++) {
840 mix_out_buffer[sample]=0;
843 vtt=render_list.begin();
845 max=(*vtt)->max_value;
848 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
849 temp=(*vtt)->output_buffer[sample];
850 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_left;
852 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_right;
855 if (temp>max) max=temp;
856 else if (temp<min) min=temp;
860 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
862 if ((*vtt)->ec_enable) {
863 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
864 temp=(*vtt)->ec_output_buffer[sample];
866 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
868 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
873 if (master_triggered) {
874 pthread_mutex_unlock(&render_lock);
875 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
876 if ((*vtt)->is_sync_client) {
877 if ((*vtt)->sync_countdown) {
878 (*vtt)->sync_countdown--;
880 (*vtt)->sync_countdown=(*vtt)->sync_cycles;
885 pthread_mutex_lock(&render_lock);
888 vtt=render_list.begin();
889 for (vtt++; vtt!=render_list.end(); vtt++) {
891 max=(*vtt)->max_value;
894 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
895 temp=(*vtt)->output_buffer[sample];
896 mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_left;
898 mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_right;
901 if (temp>max) max=temp;
902 else if (temp<min) min=temp;
906 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
908 if ((*vtt)->ec_enable) {
909 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
910 temp=(*vtt)->ec_output_buffer[sample];
912 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
914 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
925 for (sample=0; sample<samples_in_mix_buffer; sample+=2) {
926 temp=mix_buffer[sample];
929 #define FL_SHRT_MAX 32767.0
930 #define FL_SHRT_MIN -32768.0
931 if(temp < FL_SHRT_MIN) temp = FL_SHRT_MIN;
932 else if (temp > FL_SHRT_MAX) temp = FL_SHRT_MAX;
935 mix_out_buffer[sample]=(int16_t) temp;
937 if (temp>max) max=temp;
938 else if (temp<min) min=temp;
942 if (min>max) mix_max_l=min; else mix_max_l=max;
949 for (sample=1; sample<samples_in_mix_buffer; sample+=2) {
950 temp=mix_buffer[sample];
953 if(temp < FL_SHRT_MIN) temp = FL_SHRT_MIN;
954 else if (temp > FL_SHRT_MAX) temp = FL_SHRT_MAX;
957 mix_out_buffer[sample]=(int16_t) temp;
959 if (temp>max) max=temp;
960 else if (temp<min) min=temp;
964 if (min>max) mix_max_r=min; else mix_max_r=max;
969 vtt=render_list.begin();
970 while (vtt!=render_list.end()) {
974 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
977 pthread_mutex_unlock(&render_lock);
979 return(mix_out_buffer);
982 void vtt_class :: forward_all_turntables()
984 list <vtt_class *> :: iterator vtt, next;
986 if (render_list.size()>0)
988 vtt=render_list.begin();
989 (*vtt)->forward_turntable();
991 if (master_triggered)
993 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
995 if ((*vtt)->is_sync_client)
997 if ((*vtt)->sync_countdown)
999 (*vtt)->sync_countdown--;
1003 (*vtt)->sync_countdown=(*vtt)->sync_cycles;
1010 vtt=render_list.begin();
1011 for (vtt++; vtt!=render_list.end(); vtt++)
1013 (*vtt)->forward_turntable();
1018 vtt=render_list.begin();
1019 while (vtt!=render_list.end())
1024 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
1030 int vtt_class :: trigger()
1032 list <vtt_fx *> :: iterator effect;
1034 if (!buffer) return (1);
1036 if (!is_playing) pthread_mutex_lock(&render_lock);
1038 if (res_pitch>=0) pos_f=0;
1042 speed_real=res_pitch;
1043 speed_target=res_pitch;
1046 /* activating plugins */
1047 for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
1049 (*effect)->activate();
1057 master_triggered_at=0;
1066 render_list.push_front(this);
1070 render_list.push_back(this);
1072 pthread_mutex_unlock(&render_lock);
1077 static bool do_unlock=true;
1079 int vtt_class :: stop_nolock()
1081 list <vtt_fx *> :: iterator effect;
1083 if ((!is_playing) && do_unlock) {
1084 pthread_mutex_unlock(&render_lock);
1087 render_list.remove(this);
1096 /* deactivating plugins */
1097 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
1098 (*effect)->deactivate();
1104 int vtt_class :: stop()
1108 pthread_mutex_lock(&render_lock);
1116 pthread_mutex_unlock(&render_lock);
1121 void vtt_class :: set_sync_master(int master)
1125 if (sync_master) sync_master->set_sync_master(0);
1131 if (sync_master==this) sync_master=0;
1133 gui_clear_master_button(this);
1137 void vtt_class :: set_sync_client(int slave, int cycles)
1139 is_sync_client=slave;
1141 // sync_countdown=cycles;
1145 void vtt_class :: set_sync_client_ug(int slave, int cycles)
1147 set_sync_client(slave, cycles);
1150 void vtt_class :: set_master_volume(f_prec new_volume)
1152 list <vtt_class *> :: iterator vtt;
1154 master_volume=new_volume;
1155 globals.volume=new_volume;
1157 if (main_list.size()>0)
1159 vol_channel_adjust=sqrt((f_prec) main_list.size());
1160 res_master_volume=master_volume/vol_channel_adjust;
1163 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1165 (*vtt)->recalc_volume();
1169 void vtt_class :: set_master_pitch(f_prec new_pitch)
1171 list <vtt_class *> :: iterator vtt;
1173 globals.pitch=new_pitch;
1174 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1176 (*vtt)->recalc_pitch();
1180 void vtt_class :: enable_saturate (int newstate)
1182 do_saturate=newstate;
1185 void vtt_class :: focus_no(int no)
1187 list <vtt_class *> :: iterator vtt;
1192 for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++)
1200 void vtt_class :: focus_next()
1202 list <vtt_class *> :: iterator vtt;
1206 if (main_list.size())
1208 focused_vtt=(*main_list.begin());
1213 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1214 if ((*vtt)==focused_vtt) {
1215 /* Ok, we found ourselves.. */
1218 while ((vtt!=main_list.end()) && ((*vtt)->audio_hidden) ) {
1222 if (vtt==main_list.end()) {
1223 /* No other "focusable" after this vtt so we're looking for the next */
1225 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1226 if (! (*vtt)->audio_hidden) {
1231 /* When we get here there's no "focusable" vtt at all... damn */
1241 focused_vtt=(*main_list.begin());
1244 void vtt_class :: set_scratch(int newstate)
1248 sp_spin.receive_input_value(0);
1250 sense_cycles=globals.sense_cycles;
1254 sp_spin.receive_input_value(1);
1260 void vtt_class :: unfocus()
1265 void vtt_class :: set_x_input_parameter(tX_seqpar *sp)
1270 void vtt_class :: set_y_input_parameter(tX_seqpar *sp)
1275 void vtt_class :: xy_input(f_prec x_value, f_prec y_value)
1277 if (x_par) x_par->handle_mouse_input(x_value*globals.mouse_speed);
1278 if (y_par) y_par->handle_mouse_input(y_value*globals.mouse_speed);
1281 #define store(data); if (fwrite((void *) &data, sizeof(data), 1, output)!=1) res+=1;
1283 int vtt_class :: save(FILE *rc, gzFile rz, char *indent) {
1284 list <vtt_fx *> :: iterator effect;
1285 char tmp_xml_buffer[4096];
1289 tX_store("%s<turntable>\n", indent);
1290 strcat(indent, "\t");
1292 store_string("name", name);
1294 store_string("audiofile", filename);
1296 store_string("audiofile", "");
1298 store_bool("sync_master", is_sync_master);
1299 store_bool("autotrigger", autotrigger);
1300 store_bool_sp("loop", loop, sp_loop);
1302 store_bool_sp("sync_client", is_sync_client, sp_sync_client);
1303 store_int_sp("sync_cycles", sync_cycles, sp_sync_cycles);
1305 store_float_sp("volume", rel_volume, sp_volume);
1306 store_float_sp("pitch", rel_pitch, sp_pitch);
1307 store_bool_sp("mute", mute, sp_mute);
1308 store_float_sp("pan", pan, sp_pan);
1310 store_bool_sp("lowpass_enable", lp_enable, sp_lp_enable);
1311 store_float_sp("lowpass_gain", lp_gain, sp_lp_gain);
1312 store_float_sp("lowpass_reso", lp_reso, sp_lp_reso);
1313 store_float_sp("lowpass_freq", lp_freq, sp_lp_freq);
1315 store_bool_sp("echo_enable", ec_enable, sp_ec_enable);
1316 store_float_sp("echo_length", ec_length, sp_ec_length);
1317 store_float_sp("echo_feedback", ec_feedback, sp_ec_feedback);
1318 store_float_sp("echo_pan", ec_pan, sp_ec_pan);
1319 store_float_sp("echo_volume", ec_volume, sp_ec_volume);
1321 store_id("speed", sp_speed.get_persistence_id());
1322 store_id("trigger", sp_trigger.get_persistence_id());
1323 store_id("spin", sp_spin.get_persistence_id());
1327 store_int("x_axis_mapping", x_par->get_persistence_id());
1331 store_int("y_axis_mapping", y_par->get_persistence_id());
1334 store_bool("audio_panel_hidden", audio_hidden);
1335 store_bool("control_panel_hidden", control_hidden);
1336 store_bool("main_panel_hidden", gui.main_panel->is_hidden());
1337 store_bool("trigger_panel_hidden", gui.trigger_panel->is_hidden());
1338 store_bool("lowpass_panel_hidden", gui.lp_panel->is_hidden());
1339 store_bool("echo_panel_hidden", gui.ec_panel->is_hidden());
1341 store_bool("mix_mute", mix_mute);
1342 store_bool("mix_solo", mix_solo);
1344 store_float("audio_x_zoom", gui_get_audio_x_zoom(this));
1346 tX_store("%s<fx>\n", indent);
1347 strcat(indent, "\t");
1349 for (effect=fx_list.begin(); effect!=fx_list.end(); effect++) {
1350 (*effect)->save(rc, rz, indent);
1352 indent[strlen(indent)-1]=0;
1353 tX_store("%s</fx>\n", indent);
1355 indent[strlen(indent)-1]=0;
1356 tX_store("%s</turntable>\n", indent);
1361 #define TX_XML_SETFILE_VERSION "1.0"
1363 int vtt_class :: save_all(FILE* rc, gzFile rz) {
1365 list <vtt_class *> :: iterator vtt;
1368 tX_seqpar :: create_persistence_ids();
1370 tX_store("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n");
1371 tX_store("<terminatorXset version=\"%s\">\n", TX_XML_SETFILE_VERSION);
1373 strcpy(indent, "\t");
1375 //store_int(vtt_amount); obsolete
1377 store_float_sp("master_volume", master_volume, sp_master_volume);
1378 store_float_sp("master_pitch", globals.pitch, sp_master_pitch);
1380 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1381 res+=(*vtt)->save(rc, rz, indent);
1384 sequencer.save(rc, rz, indent);
1386 tX_store("</terminatorXset>\n");
1391 int vtt_class :: load(xmlDocPtr doc, xmlNodePtr node) {
1401 char tmp_xml_buffer[4096];
1403 for (xmlNodePtr cur=node->xmlChildrenNode; cur != NULL; cur = cur->next) {
1404 if (cur->type == XML_ELEMENT_NODE) {
1407 restore_string_ac("name", buffer, set_name(buffer));
1408 restore_string("audiofile", filename);
1409 restore_bool("sync_master", is_sync_master);
1410 restore_bool("autotrigger", autotrigger);
1411 restore_bool_id("loop", loop, sp_loop, nop);
1412 restore_bool_id("sync_client", is_sync_client, sp_sync_client, set_sync_client(is_sync_client, sync_cycles));
1413 restore_int_id("sync_cycles", sync_cycles, sp_sync_cycles, set_sync_client(is_sync_client, sync_cycles));
1414 restore_float_id("volume", rel_volume, sp_volume, recalc_volume());
1415 restore_float_id("pitch", rel_pitch, sp_pitch, recalc_pitch());
1416 restore_bool_id("mute", mute, sp_mute, set_mute(mute));
1417 restore_float_id("pan", pan, sp_pan, set_pan(pan));
1419 restore_bool_id("lowpass_enable", lp_enable, sp_lp_enable, lp_set_enable(lp_enable));
1420 restore_float_id("lowpass_gain", lp_gain, sp_lp_gain, lp_set_gain(lp_gain));
1421 restore_float_id("lowpass_reso", lp_reso, sp_lp_reso, lp_set_reso(lp_reso));
1422 restore_float_id("lowpass_freq", lp_freq, sp_lp_freq, lp_set_freq(lp_freq));
1424 restore_bool_id("echo_enable", ec_enable, sp_ec_enable, ec_set_enable(ec_enable));
1425 restore_float_id("echo_length", ec_length, sp_ec_length, ec_set_length(ec_length));
1426 restore_float_id("echo_feedback", ec_feedback, sp_ec_feedback, ec_set_feedback(ec_feedback));
1427 restore_float_id("echo_pan", ec_pan, sp_ec_pan, ec_set_pan(ec_pan));
1428 restore_float_id("echo_volume", ec_volume, sp_ec_volume, ec_set_volume(ec_volume));
1430 restore_id("speed", sp_speed);
1431 restore_id("trigger", sp_trigger);
1432 restore_id("spin", sp_spin);
1434 restore_int("x_axis_mapping", xpar_id);
1435 restore_int("y_axis_mapping", ypar_id);
1437 restore_bool("mix_mute", mix_mute);
1438 restore_bool("mix_solo", mix_solo);
1440 restore_bool("audio_panel_hidden", audio_hidden);
1441 restore_bool("control_panel_hidden", control_hidden);
1442 restore_bool_ac("main_panel_hidden", hidden, gui.main_panel->hide(hidden));
1443 restore_bool_ac("trigger_panel_hidden", hidden, gui.trigger_panel->hide(hidden));
1444 restore_bool_ac("lowpass_panel_hidden", hidden, gui.lp_panel->hide(hidden));
1445 restore_bool_ac("echo_panel_hidden", hidden, gui.ec_panel->hide(hidden));
1446 restore_float_ac("audio_x_zoom", tmp, gui_set_audio_x_zoom(this,tmp));
1447 vg_adjust_zoom(gui.zoom, this);
1449 if (xmlStrcmp(cur->name, (xmlChar *) "fx")==0) {
1453 for (xmlNodePtr cur=fx->xmlChildrenNode; cur != NULL; cur = cur->next) {
1454 if (cur->type == XML_ELEMENT_NODE) {
1457 if (xmlStrcmp(cur->name, (xmlChar *) "cutoff")==0) {
1458 for (unsigned int t=0; t<fx_list.size(); t++) effect_down(lp_fx);
1460 } else if (xmlStrcmp(cur->name, (xmlChar *) "lowpass")==0) {
1461 for (unsigned int t=0; t<fx_list.size(); t++) effect_down(ec_fx);
1463 } else if (xmlStrcmp(cur->name, (xmlChar *) "ladspa_plugin")==0) {
1464 xmlNodePtr pluginNode=cur;
1468 for (xmlNodePtr cur=pluginNode->xmlChildrenNode; cur!=NULL; cur = cur->next) {
1470 if (cur->type == XML_ELEMENT_NODE) {
1473 restore_int("ladspa_id", ladspa_id);
1474 if (elementFound) break;
1478 if (ladspa_id!=-1) {
1479 LADSPA_Plugin *plugin=LADSPA_Plugin::getPluginByUniqueID(ladspa_id);
1481 vtt_fx_ladspa *ladspa_effect=add_effect(plugin);
1482 ladspa_effect->load(doc, pluginNode);
1484 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);
1485 tx_note(buffer, true);
1488 tX_warning("ladspa_plugin section without a ladspa_id element.");
1492 tX_warning("unhandled element %s in fx section.", cur->name);
1499 tX_warning("unhandled element %s in turntable secion.", cur->name);
1511 set_x_input_parameter(tX_seqpar :: get_sp_by_persistence_id(xpar_id));
1513 else set_x_input_parameter(NULL);
1516 set_y_input_parameter(tX_seqpar :: get_sp_by_persistence_id(ypar_id));
1518 else set_y_input_parameter(NULL);
1520 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.mute), mix_mute);
1521 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.solo), mix_solo);
1526 void vtt_class :: delete_all()
1528 while (main_list.size()) {
1529 delete((*main_list.begin()));
1532 /* Take care of the master events.. */
1533 sequencer.delete_all_events(tX_sequencer::DELETE_ALL);
1535 /* Now reset master settings ot the default: */
1536 set_master_pitch(1.0);
1537 set_master_volume(1.0);
1539 sp_master_pitch.do_exec(1.0);
1540 sp_master_pitch.do_update_graphics();
1542 sp_master_volume.do_exec(1.0);
1543 sp_master_volume.do_update_graphics();
1545 /* Remove master MIDI mappings... */
1546 sp_master_pitch.bound_midi_event.type=tX_midievent::NONE;
1547 sp_master_volume.bound_midi_event.type=tX_midievent::NONE;
1553 int vtt_class :: load_all(xmlDocPtr doc, char *fname) {
1554 xmlNodePtr root=xmlDocGetRootElement(doc);
1562 tX_error("no root element? What kind of XML document is this?");
1566 if (xmlStrcmp(root->name, (const xmlChar *) "terminatorXset")) {
1567 tX_error("this is not a terminatorXset file.")
1571 if (xmlGetProp(root,(xmlChar *) "version")==NULL) {
1572 tX_error("the set file lacks a version attribute.");
1576 if (xmlStrcmp(xmlGetProp(root, (xmlChar *) "version"), (xmlChar *) TX_XML_SETFILE_VERSION)) {
1577 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);
1580 /* delete current tables... */
1585 /* counting turntables.. */
1586 for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1587 if (cur->type == XML_ELEMENT_NODE) {
1588 if (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0) {
1594 tX_debug("Found %i turntables in set.", table_ctr);
1596 ld_create_loaddlg(TX_LOADDLG_MODE_MULTI, table_ctr);
1597 ld_set_setname(fname);
1600 for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1601 if (cur->type == XML_ELEMENT_NODE) {
1604 restore_float_id("master_volume", master_volume, sp_master_volume, set_master_volume(master_volume));
1605 restore_float_id("master_pitch", globals.pitch, sp_master_pitch, set_master_pitch(globals.pitch));
1607 if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0)) {
1609 vtt_class *vtt=new vtt_class(1);
1610 vtt->load(doc, cur);
1612 tX_debug("loading a turntable..");
1614 if (strlen(vtt->filename)) {
1615 strcpy(fn_buff, vtt->filename);
1616 ld_set_filename(fn_buff);
1618 restmp=(int) vtt->load_file(fn_buff);
1622 gtk_box_pack_start(GTK_BOX(control_parent), vtt->gui.control_box, TRUE, TRUE, 0);
1623 gtk_box_pack_start(GTK_BOX(audio_parent), vtt->gui.audio_box, TRUE, TRUE, 0);
1624 if (vtt->audio_hidden) vtt->hide_audio(vtt->audio_hidden);
1625 if (vtt->control_hidden) vtt->hide_control(vtt->control_hidden);
\r
1627 if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "sequencer")==0)) {
1629 sequencer.load(doc, cur);
1631 if (!elementFound) {
1632 tX_warning("unhandled element %s in setfile %s", cur->name, fname);
1637 sp_master_volume.do_update_graphics();
1638 sp_master_pitch.do_update_graphics();
1645 void add_vtt(GtkWidget *ctrl, GtkWidget *audio, char *fn)
1648 hmmpg = new vtt_class(1);
1649 gtk_box_pack_start(GTK_BOX(ctrl), hmmpg->gui.control_box, TRUE, TRUE, 0);
1650 gtk_box_pack_start(GTK_BOX(audio), hmmpg->gui.audio_box, TRUE, TRUE, 0);
1651 if (fn) hmmpg->load_file(fn);
1654 extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt);
1655 extern void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt);
1657 //#define debug_fx_stack(); for (i=fx_list.begin(); i != fx_list.end(); i++) puts((*i)->get_info_string());
1658 #define debug_fx_stack();
1660 void vtt_class :: effect_up(vtt_fx *effect)
1662 list <vtt_fx *> :: iterator i;
1663 list <vtt_fx *> :: iterator previous;
1668 if ((*fx_list.begin())==effect) return;
1670 for (previous=i=fx_list.begin(); i != fx_list.end(); i++)
1682 pthread_mutex_lock(&render_lock);
1683 fx_list.remove(effect);
1684 fx_list.insert(previous, effect);
1685 pthread_mutex_unlock(&render_lock);
1687 vg_move_fx_panel_up(effect->get_panel_widget(), this);
1693 void vtt_class :: effect_down(vtt_fx *effect)
1695 list <vtt_fx *> :: iterator i;
1700 for (i=fx_list.begin(); i != fx_list.end(); i++)
1709 if ((ok) && (i!=fx_list.end()))
1712 if (i==fx_list.end()) return;
1715 pthread_mutex_lock(&render_lock);
1716 fx_list.remove(effect);
1718 fx_list.insert(i, effect);
1719 vg_move_fx_panel_down(effect->get_panel_widget(), this);
1720 pthread_mutex_unlock(&render_lock);
1726 void vtt_class :: effect_remove(vtt_fx_ladspa *effect)
1728 pthread_mutex_lock(&render_lock);
1729 fx_list.remove(effect);
1730 pthread_mutex_unlock(&render_lock);
1735 extern void gui_hide_control_panel(vtt_class *vtt, bool hide);
1736 extern void gui_hide_audio_panel(vtt_class *vtt, bool hide);
1738 void vtt_class :: hide_audio(bool hide) {
1740 gui_hide_audio_panel(this, hide);
1743 void vtt_class :: hide_control(bool hide) {
1744 control_hidden=hide;
1745 gui_hide_control_panel(this, hide);
1748 void vtt_class :: set_sample_rate(int samplerate) {
1749 list <vtt_class *> :: iterator vtt;
1750 double sr=(double) samplerate;
1752 last_sample_rate=samplerate;
1754 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1755 if ((*vtt)->audiofile) {
1756 double file_rate=(*vtt)->audiofile->get_sample_rate();
1757 (*vtt)->audiofile_pitch_correction=file_rate/sr;
1759 (*vtt)->audiofile_pitch_correction=1.0;
1761 (*vtt)->recalc_pitch();
1764 int no_samples=(int) (sr*0.001); // Forcing 1 ms blocksize
1766 set_mix_buffer_size(no_samples);
1769 void vtt_class :: adjust_to_master_pitch(int master_cycles, int cycles, bool create_event) {
1770 if (!sync_master) return;
1771 if (this==sync_master) return;
1772 if (!sync_master->audiofile) return;
1773 if (!audiofile) return;
1775 double master_time=((double) master_cycles)/sync_master->rel_pitch*sync_master->audiofile->get_no_samples()/((double) sync_master->audiofile->get_sample_rate());
1776 double my_rel_pitch=((audiofile->get_no_samples()/((double) audiofile->get_sample_rate()))*((double) cycles))/master_time;
1779 sp_pitch.do_exec(my_rel_pitch);
1780 sp_pitch.record_value(my_rel_pitch);
1782 sp_pitch.do_exec(my_rel_pitch);
1785 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());
1787 sp_pitch.update_graphics();