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++)
818 res|=(*vtt)->set_output_buffer_size(no_samples);
821 if ((!mix_buffer) || (!mix_out_buffer) || res) return(1);
823 mix_buffer_size=no_samples;
828 int16_t * vtt_class :: render_all_turntables()
830 list <vtt_class *> :: iterator vtt, next;
837 pthread_mutex_lock(&render_lock);
839 if (render_list.size()==0)
841 for (sample=0; sample<samples_in_mix_buffer; sample++)
843 mix_out_buffer[sample]=0;
848 vtt=render_list.begin();
850 max=(*vtt)->max_value;
853 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
855 temp=(*vtt)->output_buffer[sample];
856 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_left;
858 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_right;
861 if (temp>max) max=temp;
862 else if (temp<min) min=temp;
866 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
868 if ((*vtt)->ec_enable)
870 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
872 temp=(*vtt)->ec_output_buffer[sample];
874 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
876 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
881 if (master_triggered)
883 pthread_mutex_unlock(&render_lock);
884 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
886 if ((*vtt)->is_sync_client)
888 if ((*vtt)->sync_countdown)
890 (*vtt)->sync_countdown--;
894 (*vtt)->sync_countdown=(*vtt)->sync_cycles;
899 pthread_mutex_lock(&render_lock);
902 vtt=render_list.begin();
903 for (vtt++; vtt!=render_list.end(); vtt++)
906 max=(*vtt)->max_value;
909 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
911 temp=(*vtt)->output_buffer[sample];
912 mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_left;
914 mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_right;
917 if (temp>max) max=temp;
918 else if (temp<min) min=temp;
922 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
924 if ((*vtt)->ec_enable)
926 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
928 temp=(*vtt)->ec_output_buffer[sample];
930 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
932 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
943 for (sample=0; sample<samples_in_mix_buffer; sample+=2)
945 temp=mix_buffer[sample];
948 #define FL_SHRT_MAX 32767.0
949 #define FL_SHRT_MIN -32768.0
950 if(temp < FL_SHRT_MIN) temp = FL_SHRT_MIN;
951 else if (temp > FL_SHRT_MAX) temp = FL_SHRT_MAX;
954 mix_out_buffer[sample]=(int16_t) temp;
956 if (temp>max) max=temp;
957 else if (temp<min) min=temp;
961 if (min>max) mix_max_l=min; else mix_max_l=max;
968 for (sample=1; sample<samples_in_mix_buffer; sample+=2)
970 temp=mix_buffer[sample];
973 if(temp < FL_SHRT_MIN) temp = FL_SHRT_MIN;
974 else if (temp > FL_SHRT_MAX) temp = FL_SHRT_MAX;
977 mix_out_buffer[sample]=(int16_t) temp;
979 if (temp>max) max=temp;
980 else if (temp<min) min=temp;
984 if (min>max) mix_max_r=min; else mix_max_r=max;
989 vtt=render_list.begin();
990 while (vtt!=render_list.end())
995 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
998 pthread_mutex_unlock(&render_lock);
1000 return(mix_out_buffer);
1003 void vtt_class :: forward_all_turntables()
1005 list <vtt_class *> :: iterator vtt, next;
1007 if (render_list.size()>0)
1009 vtt=render_list.begin();
1010 (*vtt)->forward_turntable();
1012 if (master_triggered)
1014 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1016 if ((*vtt)->is_sync_client)
1018 if ((*vtt)->sync_countdown)
1020 (*vtt)->sync_countdown--;
1024 (*vtt)->sync_countdown=(*vtt)->sync_cycles;
1031 vtt=render_list.begin();
1032 for (vtt++; vtt!=render_list.end(); vtt++)
1034 (*vtt)->forward_turntable();
1039 vtt=render_list.begin();
1040 while (vtt!=render_list.end())
1045 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
1051 int vtt_class :: trigger()
1053 list <vtt_fx *> :: iterator effect;
1055 if (!buffer) return (1);
1057 if (!is_playing) pthread_mutex_lock(&render_lock);
1059 if (res_pitch>=0) pos_f=0;
1063 speed_real=res_pitch;
1064 speed_target=res_pitch;
1067 /* activating plugins */
1068 for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
1070 (*effect)->activate();
1078 master_triggered_at=0;
1087 render_list.push_front(this);
1091 render_list.push_back(this);
1093 pthread_mutex_unlock(&render_lock);
1098 static bool do_unlock=true;
1100 int vtt_class :: stop_nolock()
1102 list <vtt_fx *> :: iterator effect;
1104 if ((!is_playing) && do_unlock) {
1105 pthread_mutex_unlock(&render_lock);
1108 render_list.remove(this);
1117 /* deactivating plugins */
1118 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
1119 (*effect)->deactivate();
1125 int vtt_class :: stop()
1129 pthread_mutex_lock(&render_lock);
1137 pthread_mutex_unlock(&render_lock);
1142 void vtt_class :: set_sync_master(int master)
1146 if (sync_master) sync_master->set_sync_master(0);
1152 if (sync_master==this) sync_master=0;
1154 gui_clear_master_button(this);
1158 void vtt_class :: set_sync_client(int slave, int cycles)
1160 is_sync_client=slave;
1162 // sync_countdown=cycles;
1166 void vtt_class :: set_sync_client_ug(int slave, int cycles)
1168 set_sync_client(slave, cycles);
1171 void vtt_class :: set_master_volume(f_prec new_volume)
1173 list <vtt_class *> :: iterator vtt;
1175 master_volume=new_volume;
1176 globals.volume=new_volume;
1178 if (main_list.size()>0)
1180 vol_channel_adjust=sqrt((f_prec) main_list.size());
1181 res_master_volume=master_volume/vol_channel_adjust;
1184 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1186 (*vtt)->recalc_volume();
1190 void vtt_class :: set_master_pitch(f_prec new_pitch)
1192 list <vtt_class *> :: iterator vtt;
1194 globals.pitch=new_pitch;
1195 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1197 (*vtt)->recalc_pitch();
1201 void vtt_class :: enable_saturate (int newstate)
1203 do_saturate=newstate;
1206 void vtt_class :: focus_no(int no)
1208 list <vtt_class *> :: iterator vtt;
1211 for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++)
1220 void vtt_class :: focus_next()
1222 list <vtt_class *> :: iterator vtt;
1226 if (main_list.size())
1228 focused_vtt=(*main_list.begin());
1233 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1234 if ((*vtt)==focused_vtt) {
1235 /* Ok, we found ourselves.. */
1238 while ((vtt!=main_list.end()) && ((*vtt)->audio_hidden) ) {
1242 if (vtt==main_list.end()) {
1243 /* No other "focusable" after this vtt so we're looking for the next */
1245 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1246 if (! (*vtt)->audio_hidden) {
1251 /* When we get here there's no "focusable" vtt at all... damn */
1261 focused_vtt=(*main_list.begin());
1264 void vtt_class :: set_scratch(int newstate)
1268 sp_spin.receive_input_value(0);
1270 sense_cycles=globals.sense_cycles;
1274 sp_spin.receive_input_value(1);
1280 void vtt_class :: unfocus()
1285 void vtt_class :: set_x_input_parameter(tX_seqpar *sp)
1290 void vtt_class :: set_y_input_parameter(tX_seqpar *sp)
1295 void vtt_class :: xy_input(f_prec x_value, f_prec y_value)
1297 if (x_par) x_par->handle_mouse_input(x_value*globals.mouse_speed);
1298 if (y_par) y_par->handle_mouse_input(y_value*globals.mouse_speed);
1301 #define store(data); if (fwrite((void *) &data, sizeof(data), 1, output)!=1) res+=1;
1303 int vtt_class :: save(FILE *rc, gzFile rz, char *indent) {
1304 list <vtt_fx *> :: iterator effect;
1305 char tmp_xml_buffer[4096];
1309 tX_store("%s<turntable>\n", indent);
1310 strcat(indent, "\t");
1312 store_string("name", name);
1314 store_string("audiofile", filename);
1316 store_string("audiofile", "");
1318 store_bool("sync_master", is_sync_master);
1319 store_bool("autotrigger", autotrigger);
1320 store_bool_sp("loop", loop, sp_loop);
1322 store_bool_sp("sync_client", is_sync_client, sp_sync_client);
1323 store_int_sp("sync_cycles", sync_cycles, sp_sync_cycles);
1325 store_float_sp("volume", rel_volume, sp_volume);
1326 store_float_sp("pitch", rel_pitch, sp_pitch);
1327 store_bool_sp("mute", mute, sp_mute);
1328 store_float_sp("pan", pan, sp_pan);
1330 store_bool_sp("lowpass_enable", lp_enable, sp_lp_enable);
1331 store_float_sp("lowpass_gain", lp_gain, sp_lp_gain);
1332 store_float_sp("lowpass_reso", lp_reso, sp_lp_reso);
1333 store_float_sp("lowpass_freq", lp_freq, sp_lp_freq);
1335 store_bool_sp("echo_enable", ec_enable, sp_ec_enable);
1336 store_float_sp("echo_length", ec_length, sp_ec_length);
1337 store_float_sp("echo_feedback", ec_feedback, sp_ec_feedback);
1338 store_float_sp("echo_pan", ec_pan, sp_ec_pan);
1339 store_float_sp("echo_volume", ec_volume, sp_ec_volume);
1341 store_id("speed", sp_speed.get_persistence_id());
1342 store_id("trigger", sp_trigger.get_persistence_id());
1343 store_id("spin", sp_spin.get_persistence_id());
1347 store_int("x_axis_mapping", x_par->get_persistence_id());
1351 store_int("y_axis_mapping", y_par->get_persistence_id());
1354 store_bool("audio_panel_hidden", audio_hidden);
1355 store_bool("control_panel_hidden", control_hidden);
1356 store_bool("main_panel_hidden", gui.main_panel->is_hidden());
1357 store_bool("trigger_panel_hidden", gui.trigger_panel->is_hidden());
1358 store_bool("lowpass_panel_hidden", gui.lp_panel->is_hidden());
1359 store_bool("echo_panel_hidden", gui.ec_panel->is_hidden());
1361 store_bool("mix_mute", mix_mute);
1362 store_bool("mix_solo", mix_solo);
1364 store_float("audio_x_zoom", gui_get_audio_x_zoom(this));
1366 tX_store("%s<fx>\n", indent);
1367 strcat(indent, "\t");
1369 for (effect=fx_list.begin(); effect!=fx_list.end(); effect++) {
1370 (*effect)->save(rc, rz, indent);
1372 indent[strlen(indent)-1]=0;
1373 tX_store("%s</fx>\n", indent);
1375 indent[strlen(indent)-1]=0;
1376 tX_store("%s</turntable>\n", indent);
1381 #define TX_XML_SETFILE_VERSION "1.0"
1383 int vtt_class :: save_all(FILE* rc, gzFile rz) {
1385 list <vtt_class *> :: iterator vtt;
1388 tX_seqpar :: create_persistence_ids();
1390 tX_store("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n");
1391 tX_store("<terminatorXset version=\"%s\">\n", TX_XML_SETFILE_VERSION);
1393 strcpy(indent, "\t");
1395 //store_int(vtt_amount); obsolete
1397 store_float_sp("master_volume", master_volume, sp_master_volume);
1398 store_float_sp("master_pitch", globals.pitch, sp_master_pitch);
1400 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1401 res+=(*vtt)->save(rc, rz, indent);
1404 sequencer.save(rc, rz, indent);
1406 tX_store("</terminatorXset>\n");
1411 int vtt_class :: load(xmlDocPtr doc, xmlNodePtr node) {
1421 char tmp_xml_buffer[4096];
1423 for (xmlNodePtr cur=node->xmlChildrenNode; cur != NULL; cur = cur->next) {
1424 if (cur->type == XML_ELEMENT_NODE) {
1427 restore_string_ac("name", buffer, set_name(buffer));
1428 restore_string("audiofile", filename);
1429 restore_bool("sync_master", is_sync_master);
1430 restore_bool("autotrigger", autotrigger);
1431 restore_bool_id("loop", loop, sp_loop, nop);
1432 restore_bool_id("sync_client", is_sync_client, sp_sync_client, set_sync_client(is_sync_client, sync_cycles));
1433 restore_int_id("sync_cycles", sync_cycles, sp_sync_cycles, set_sync_client(is_sync_client, sync_cycles));
1434 restore_float_id("volume", rel_volume, sp_volume, recalc_volume());
1435 restore_float_id("pitch", rel_pitch, sp_pitch, recalc_pitch());
1436 restore_bool_id("mute", mute, sp_mute, set_mute(mute));
1437 restore_float_id("pan", pan, sp_pan, set_pan(pan));
1439 restore_bool_id("lowpass_enable", lp_enable, sp_lp_enable, lp_set_enable(lp_enable));
1440 restore_float_id("lowpass_gain", lp_gain, sp_lp_gain, lp_set_gain(lp_gain));
1441 restore_float_id("lowpass_reso", lp_reso, sp_lp_reso, lp_set_reso(lp_reso));
1442 restore_float_id("lowpass_freq", lp_freq, sp_lp_freq, lp_set_freq(lp_freq));
1444 restore_bool_id("echo_enable", ec_enable, sp_ec_enable, ec_set_enable(ec_enable));
1445 restore_float_id("echo_length", ec_length, sp_ec_length, ec_set_length(ec_length));
1446 restore_float_id("echo_feedback", ec_feedback, sp_ec_feedback, ec_set_feedback(ec_feedback));
1447 restore_float_id("echo_pan", ec_pan, sp_ec_pan, ec_set_pan(ec_pan));
1448 restore_float_id("echo_volume", ec_volume, sp_ec_volume, ec_set_volume(ec_volume));
1450 restore_id("speed", sp_speed);
1451 restore_id("trigger", sp_trigger);
1452 restore_id("spin", sp_spin);
1454 restore_int("x_axis_mapping", xpar_id);
1455 restore_int("y_axis_mapping", ypar_id);
1457 restore_bool("mix_mute", mix_mute);
1458 restore_bool("mix_solo", mix_solo);
1460 restore_bool("audio_panel_hidden", audio_hidden);
1461 restore_bool("control_panel_hidden", control_hidden);
1462 restore_bool_ac("main_panel_hidden", hidden, gui.main_panel->hide(hidden));
1463 restore_bool_ac("trigger_panel_hidden", hidden, gui.trigger_panel->hide(hidden));
1464 restore_bool_ac("lowpass_panel_hidden", hidden, gui.lp_panel->hide(hidden));
1465 restore_bool_ac("echo_panel_hidden", hidden, gui.ec_panel->hide(hidden));
1466 restore_float_ac("audio_x_zoom", tmp, gui_set_audio_x_zoom(this,tmp));
1467 vg_adjust_zoom(gui.zoom, this);
1469 if (xmlStrcmp(cur->name, (xmlChar *) "fx")==0) {
1473 for (xmlNodePtr cur=fx->xmlChildrenNode; cur != NULL; cur = cur->next) {
1474 if (cur->type == XML_ELEMENT_NODE) {
1477 if (xmlStrcmp(cur->name, (xmlChar *) "cutoff")==0) {
1478 for (unsigned int t=0; t<fx_list.size(); t++) effect_down(lp_fx);
1480 } else if (xmlStrcmp(cur->name, (xmlChar *) "lowpass")==0) {
1481 for (unsigned int t=0; t<fx_list.size(); t++) effect_down(ec_fx);
1483 } else if (xmlStrcmp(cur->name, (xmlChar *) "ladspa_plugin")==0) {
1484 xmlNodePtr pluginNode=cur;
1488 for (xmlNodePtr cur=pluginNode->xmlChildrenNode; cur!=NULL; cur = cur->next) {
1490 if (cur->type == XML_ELEMENT_NODE) {
1493 restore_int("ladspa_id", ladspa_id);
1494 if (elementFound) break;
1498 if (ladspa_id!=-1) {
1499 LADSPA_Plugin *plugin=LADSPA_Plugin::getPluginByUniqueID(ladspa_id);
1501 vtt_fx_ladspa *ladspa_effect=add_effect(plugin);
1502 ladspa_effect->load(doc, pluginNode);
1504 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);
1505 tx_note(buffer, true);
1508 tX_warning("ladspa_plugin section without a ladspa_id element.");
1512 tX_warning("unhandled element %s in fx section.", cur->name);
1519 tX_warning("unhandled element %s in turntable secion.", cur->name);
1531 set_x_input_parameter(tX_seqpar :: get_sp_by_persistence_id(xpar_id));
1533 else set_x_input_parameter(NULL);
1536 set_y_input_parameter(tX_seqpar :: get_sp_by_persistence_id(ypar_id));
1538 else set_y_input_parameter(NULL);
1540 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.mute), mix_mute);
1541 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.solo), mix_solo);
1546 void vtt_class :: delete_all()
1548 while (main_list.size()) {
1549 delete((*main_list.begin()));
1552 /* Take care of the master events.. */
1553 sequencer.delete_all_events(tX_sequencer::DELETE_ALL);
1555 /* Now reset master settings ot the default: */
1556 set_master_pitch(1.0);
1557 set_master_volume(1.0);
1559 sp_master_pitch.do_exec(1.0);
1560 sp_master_pitch.do_update_graphics();
1562 sp_master_volume.do_exec(1.0);
1563 sp_master_volume.do_update_graphics();
1569 int vtt_class :: load_all(xmlDocPtr doc, char *fname) {
1570 xmlNodePtr root=xmlDocGetRootElement(doc);
1578 tX_error("no root element? What kind of XML document is this?");
1582 if (xmlStrcmp(root->name, (const xmlChar *) "terminatorXset")) {
1583 tX_error("this is not a terminatorXset file.")
1587 if (xmlGetProp(root,(xmlChar *) "version")==NULL) {
1588 tX_error("the set file lacks a version attribute.");
1592 if (xmlStrcmp(xmlGetProp(root, (xmlChar *) "version"), (xmlChar *) TX_XML_SETFILE_VERSION)) {
1593 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);
1596 /* delete current tables... */
1601 /* counting turntables.. */
1602 for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1603 if (cur->type == XML_ELEMENT_NODE) {
1604 if (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0) {
1610 tX_debug("Found %i turntables in set.", table_ctr);
1612 ld_create_loaddlg(TX_LOADDLG_MODE_MULTI, table_ctr);
1613 ld_set_setname(fname);
1616 for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1617 if (cur->type == XML_ELEMENT_NODE) {
1620 restore_float_id("master_volume", master_volume, sp_master_volume, set_master_volume(master_volume));
1621 restore_float_id("master_pitch", globals.pitch, sp_master_pitch, set_master_pitch(globals.pitch));
1623 if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0)) {
1625 vtt_class *vtt=new vtt_class(1);
1626 vtt->load(doc, cur);
1628 tX_debug("loading a turntable..");
1630 if (strlen(vtt->filename)) {
1631 strcpy(fn_buff, vtt->filename);
1632 ld_set_filename(fn_buff);
1634 restmp=(int) vtt->load_file(fn_buff);
1638 gtk_box_pack_start(GTK_BOX(control_parent), vtt->gui.control_box, TRUE, TRUE, 0);
1639 gtk_box_pack_start(GTK_BOX(audio_parent), vtt->gui.audio_box, TRUE, TRUE, 0);
1640 if (vtt->audio_hidden) vtt->hide_audio(vtt->audio_hidden);
1641 if (vtt->control_hidden) vtt->hide_control(vtt->control_hidden);
\r
1643 if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "sequencer")==0)) {
1645 sequencer.load(doc, cur);
1647 if (!elementFound) {
1648 tX_warning("unhandled element %s in setfile %s", cur->name, fname);
1658 void add_vtt(GtkWidget *ctrl, GtkWidget *audio, char *fn)
1661 hmmpg = new vtt_class(1);
1662 gtk_box_pack_start(GTK_BOX(ctrl), hmmpg->gui.control_box, TRUE, TRUE, 0);
1663 gtk_box_pack_start(GTK_BOX(audio), hmmpg->gui.audio_box, TRUE, TRUE, 0);
1664 if (fn) hmmpg->load_file(fn);
1667 extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt);
1668 extern void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt);
1670 //#define debug_fx_stack(); for (i=fx_list.begin(); i != fx_list.end(); i++) puts((*i)->get_info_string());
1671 #define debug_fx_stack();
1673 void vtt_class :: effect_up(vtt_fx *effect)
1675 list <vtt_fx *> :: iterator i;
1676 list <vtt_fx *> :: iterator previous;
1681 if ((*fx_list.begin())==effect) return;
1683 for (previous=i=fx_list.begin(); i != fx_list.end(); i++)
1695 pthread_mutex_lock(&render_lock);
1696 fx_list.remove(effect);
1697 fx_list.insert(previous, effect);
1698 pthread_mutex_unlock(&render_lock);
1700 vg_move_fx_panel_up(effect->get_panel_widget(), this);
1706 void vtt_class :: effect_down(vtt_fx *effect)
1708 list <vtt_fx *> :: iterator i;
1713 for (i=fx_list.begin(); i != fx_list.end(); i++)
1722 if ((ok) && (i!=fx_list.end()))
1725 if (i==fx_list.end()) return;
1728 pthread_mutex_lock(&render_lock);
1729 fx_list.remove(effect);
1731 fx_list.insert(i, effect);
1732 vg_move_fx_panel_down(effect->get_panel_widget(), this);
1733 pthread_mutex_unlock(&render_lock);
1739 void vtt_class :: effect_remove(vtt_fx_ladspa *effect)
1741 pthread_mutex_lock(&render_lock);
1742 fx_list.remove(effect);
1743 pthread_mutex_unlock(&render_lock);
1748 extern void gui_hide_control_panel(vtt_class *vtt, bool hide);
1749 extern void gui_hide_audio_panel(vtt_class *vtt, bool hide);
1751 void vtt_class :: hide_audio(bool hide) {
1753 gui_hide_audio_panel(this, hide);
1756 void vtt_class :: hide_control(bool hide) {
1757 control_hidden=hide;
1758 gui_hide_control_panel(this, hide);
1761 void vtt_class :: set_sample_rate(int samplerate) {
1762 list <vtt_class *> :: iterator vtt;
1763 double sr=(double) samplerate;
1765 last_sample_rate=samplerate;
1767 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1768 if ((*vtt)->audiofile) {
1769 double file_rate=(*vtt)->audiofile->get_sample_rate();
1770 (*vtt)->audiofile_pitch_correction=file_rate/sr;
1772 (*vtt)->audiofile_pitch_correction=1.0;
1774 (*vtt)->recalc_pitch();
1777 int no_samples=(int) (sr*0.001); // Forcing 1 ms blocksize
1779 set_mix_buffer_size(no_samples);
1782 void vtt_class :: adjust_to_master_pitch(int master_cycles, int cycles, bool create_event) {
1783 if (!sync_master) return;
1784 if (this==sync_master) return;
1785 if (!sync_master->audiofile) return;
1786 if (!audiofile) return;
1788 double master_time=((double) master_cycles)/sync_master->rel_pitch*sync_master->audiofile->get_no_samples()/((double) sync_master->audiofile->get_sample_rate());
1789 double my_rel_pitch=((audiofile->get_no_samples()/((double) audiofile->get_sample_rate()))*((double) cycles))/master_time;
1792 sp_pitch.do_exec(my_rel_pitch);
1793 sp_pitch.record_value(my_rel_pitch);
1795 sp_pitch.do_exec(my_rel_pitch);
1798 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());
1800 sp_pitch.update_graphics();