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;
87 vtt_class * vtt_class::sync_master=NULL;
88 int vtt_class::master_triggered=0;
89 int vtt_class::master_triggered_at=0;
90 vtt_class * vtt_class::focused_vtt=NULL;
91 f_prec vtt_class::mix_max_l=0;
92 f_prec vtt_class::mix_max_r=0;
93 f_prec vtt_class::vol_channel_adjust=1.0;
94 int vtt_class::mix_buffer_size=0;
96 #define GAIN_AUTO_ADJUST 0.8
98 vtt_class :: vtt_class (int do_create_gui)
101 sprintf (name, "Turntable %i", vtt_amount);
102 strcpy(filename, "NONE");
111 audiofile_pitch_correction=1.0;
113 ec_output_buffer=NULL;
132 lp_setup(lp_gain, lp_reso, lp_freq);
143 main_list.push_back(this);
145 /* "connecting" the seq-parameters */
147 sp_speed.set_vtt((void *) this);
148 sp_volume.set_vtt((void *) this);
149 sp_pitch.set_vtt((void *) this);
150 sp_pan.set_vtt((void *) this);
151 sp_trigger.set_vtt((void *) this);
152 sp_loop.set_vtt((void *) this);
153 sp_sync_client.set_vtt((void *) this);
154 sp_sync_cycles.set_vtt((void *) this);
155 sp_lp_enable.set_vtt((void *) this);
156 sp_lp_gain.set_vtt((void *) this);
157 sp_lp_reso.set_vtt((void *) this);
158 sp_lp_freq.set_vtt((void *) this);
159 sp_ec_enable.set_vtt((void *) this);
160 sp_ec_length.set_vtt((void *) this);
161 sp_ec_pan.set_vtt((void *) this);
162 sp_ec_volume.set_vtt((void *) this);
163 sp_ec_feedback.set_vtt((void *) this);
164 sp_mute.set_vtt((void *) this);
165 sp_spin.set_vtt((void *) this);
170 lp_fx=new vtt_fx_lp();
171 lp_fx->set_vtt((void *) this);
172 fx_list.push_back(lp_fx);
174 ec_fx=new vtt_fx_ec();
175 ec_fx->set_vtt((void *) this);
176 fx_list.push_back(ec_fx);
181 lp_fx->set_panel_widget(gui.lp_panel->get_widget());
182 ec_fx->set_panel_widget(gui.ec_panel->get_widget());
187 set_master_volume(globals.volume);
188 set_output_buffer_size(samples_in_mix_buffer/2);
191 audiofile_pitch_correction=1.0;
199 control_hidden=false;
206 vtt_class :: ~vtt_class()
211 main_list.remove(this);
212 if (audiofile) delete audiofile;
213 //if (buffer) free(buffer);
214 if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt Destructor");
217 if (mix_solo) solo_ctr--;
219 while (fx_list.size())
221 effect=(*fx_list.begin());
222 fx_list.remove(effect);
226 if (sync_master==this) {
233 void vtt_class :: set_name(char *newname)
235 strcpy(name, newname);
236 gui_set_name(this, name);
239 tX_audio_error vtt_class :: load_file(char *fname)
242 int was_playing=is_playing;
244 if (is_playing) stop();
246 if (audiofile) delete(audiofile);
254 audiofile=new tx_audiofile();
255 res=audiofile->load(fname);
257 if (res==TX_AUDIO_SUCCESS) {
258 buffer=audiofile->get_buffer();
259 double file_rate=audiofile->get_sample_rate();
260 audiofile_pitch_correction=file_rate/((double) last_sample_rate);
262 samples_in_buffer=audiofile->get_no_samples();
263 pos_i_max=samples_in_buffer-1;
264 maxpos=audiofile->get_no_samples();
265 strcpy(filename, fname);
266 if (was_playing) trigger();
267 // printf("Successfully loaded %s, %08x, %i\n", fname, buffer, samples_in_buffer);
272 gui_update_display(this);
274 ec_set_length(ec_length);
279 int vtt_class :: set_output_buffer_size(int newsize)
281 list <vtt_fx *> :: iterator effect;
283 if (ec_output_buffer) tX_freemem(ec_output_buffer, "ec_output_buffer", "vtt set_output_buffer_size()");
284 tX_malloc(ec_output_buffer, "ec_output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
286 if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt set_output_buffer_size()");
287 tX_malloc(output_buffer, "output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
289 end_of_outputbuffer = output_buffer + newsize; //size_t(sizeof(float)*(newsize));
291 samples_in_outputbuffer=newsize;
292 inv_samples_in_outputbuffer=1.0/samples_in_outputbuffer;
294 for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
296 (*effect)->reconnect_buffer();
299 if (output_buffer) return(0);
303 void vtt_class :: set_volume(f_prec newvol)
309 void vtt_class :: recalc_volume()
311 res_volume=rel_volume*res_master_volume;
312 f_prec ec_res_volume=res_volume*ec_volume;
316 res_volume_left=(1.0-pan)*res_volume;
317 res_volume_right=res_volume;
321 res_volume_left=res_volume;
322 res_volume_right=(1.0+pan)*res_volume;
326 res_volume_left=res_volume_right=res_volume;
331 ec_volume_left=(1.0-ec_pan)*ec_res_volume;
332 ec_volume_right=ec_res_volume;
336 ec_volume_left=ec_res_volume;
337 ec_volume_right=(1.0+ec_pan)*ec_res_volume;
341 ec_volume_left=ec_volume_right=ec_res_volume;
343 // printf("vtt_volume: %f, %f, l: %f, r: %f\n", rel_volume, res_volume, res_volume_left, res_volume_right);
346 void vtt_class :: set_pan(f_prec newpan)
352 void vtt_class :: set_pitch(f_prec newpitch)
358 void vtt_class :: recalc_pitch()
360 res_pitch=globals.pitch*rel_pitch;
361 res_pitch*=audiofile_pitch_correction;
363 ec_set_length(ec_length);
366 void vtt_class :: set_autotrigger(int newstate)
368 autotrigger=newstate;
371 void vtt_class :: set_loop(int newstate)
376 void vtt_class :: set_mute(int newstate)
382 void vtt_class :: set_mix_mute(int newstate)
388 void vtt_class :: set_mix_solo(int newstate)
390 if (mix_solo && !newstate)
396 else if (!mix_solo && newstate)
405 list <vtt_class *> :: iterator vtt;
407 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++)
413 void vtt_class :: lp_set_enable (int newstate)
419 void vtt_class :: lp_reset()
424 void vtt_class :: lp_set_gain (f_prec gain)
427 lp_resgain=lp_gain*lp_autogain;
430 void vtt_class :: lp_set_reso(f_prec reso)
434 lp_b=reso*(1.0+(1.0/lp_a));
435 lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
436 lp_resgain=lp_gain*lp_autogain;
439 void vtt_class :: lp_set_freq(f_prec freq)
444 lp_b=lp_reso*(1.0+(1.0/lp_a));
447 void vtt_class :: lp_setup(f_prec gain, f_prec reso, f_prec freq)
453 lp_b=reso*(1.0+(1.0/lp_a));
455 lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
456 lp_resgain=lp_gain*lp_autogain;
459 void vtt_class :: ec_set_enable(int newstate)
466 void vtt_class :: ec_set_pan(f_prec pan)
473 /* Max length is 1.0 */
475 void vtt_class :: ec_set_length(f_prec length)
482 ec_res_length=length*samples_in_buffer;
486 ec_res_length=length*samples_in_buffer/res_pitch;
489 if (ec_res_length<0) ec_res_length*=-1;
491 if (ec_res_length>=EC_MAX_BUFFER)
493 ec_res_length=EC_MAX_BUFFER*length;
496 delay=(int )floor(ec_res_length);
498 ec_delay=&ec_buffer[delay];
501 void vtt_class :: ec_set_feedback(f_prec feedback)
503 ec_feedback=feedback;
507 void vtt_class :: ec_set_volume(f_prec volume)
513 void vtt_class :: ec_clear_buffer()
517 for (ptr=ec_buffer; ptr<=ec_delay; ptr++) {
523 void vtt_class :: render()
525 list <vtt_fx *> :: iterator effect;
528 if (sense_cycles>0) {
530 if (sense_cycles==0) sp_speed.receive_input_value(0);
535 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
536 if ((*effect)->isEnabled()) (*effect)->run();
540 extern void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plugin);
542 vtt_fx_ladspa * vtt_class :: add_effect (LADSPA_Plugin *plugin)
544 vtt_fx_ladspa *new_effect;
546 new_effect = new vtt_fx_ladspa (plugin, this);
547 pthread_mutex_lock(&render_lock);
548 fx_list.push_back(new_effect);
549 if (is_playing) new_effect->activate();
550 pthread_mutex_unlock(&render_lock);
551 vg_create_fx_gui(this, new_effect, plugin);
556 void vtt_class :: calc_speed()
562 if (speed != speed_target) {
564 speed_step=speed_target-speed_real;
565 speed_step/=globals.vtt_inertia;
568 if (speed_target != speed_real) {
569 speed_real+=speed_step;
570 if ((speed_step<0) && (speed_real<speed_target)) speed_real=speed_target;
571 else if ((speed_step>0) && (speed_real>speed_target)) speed_real=speed_target;
575 if ((speed_last==0) && (speed_real !=0)) {
580 if ((speed_last!=0) && (speed_real==0)) {
586 speed_last = speed_real;
588 if (res_mute != res_mute_old) {
590 fade_out=1; fade_in=0;
593 fade_in=1; fade_out=0;
596 res_mute_old=res_mute;
598 if (res_mute) do_mute=1;
602 void vtt_class :: render_scratch()
623 for (sample =0,out=output_buffer, fade_vol=0.0; sample < samples_in_outputbuffer;sample++, out++, fade_vol+=inv_samples_in_outputbuffer) {
624 if ((speed_real!=0) || (fade_out)) {
635 master_triggered_at=sample;
641 } else if (pos_f<0) {
648 master_triggered_at=sample;
656 pos_a_f=floor(pos_f);
657 pos_i=(unsigned int) pos_a_f;
659 amount_b=pos_f-pos_a_f;
660 amount_a=1.0-amount_b;
666 sample_a=(f_prec) *ptr;
668 if (pos_i == pos_i_max) {
672 sample_b=(f_prec) *ptr;
675 sample_res=(sample_a*amount_a)+(sample_b*amount_b);
678 sample_res*=fade_vol;
679 } else if (fade_out) {
680 sample_res*=1.0-fade_vol;
691 void vtt_class :: forward_turntable()
702 if ((speed_real==0) && (!fade_out)) return;
705 /* following code is problematic as adding speed_real*n is
706 different from adding speed_real n times to pos_f.
708 well it speeds things up quite a bit and double precision
709 seems to do a satisfying job.
711 #define pos_f_test to prove that.
714 pos_f_tmp=pos_f+speed_real*samples_in_outputbuffer;
716 if ((pos_f_tmp > 0) && (pos_f_tmp < maxpos)) {
725 /* now the slow way ;) */
727 for (sample =0; sample < samples_in_outputbuffer; sample++) {
734 if (is_sync_master) {
736 master_triggered_at=sample;
742 } else if (pos_f<0) {
746 if (is_sync_master) {
748 master_triggered_at=sample;
758 diff=pos_f_tmp-pos_f;
759 if (diff!=0) printf("fast: %f, slow: %f, diff: %f, tt: %s\n", pos_f_tmp, pos_f, diff, name);
765 The following lowpass filter is based on some sample code by
766 Paul Kellett <paul.kellett@maxim.abel.co.uk>
769 void vtt_class :: render_lp()
773 for (sample = output_buffer; sample<end_of_outputbuffer; sample++) {
774 lp_buf0 = lp_a * lp_buf0 + lp_freq * ((*sample)*lp_resgain + lp_b * (lp_buf0 - lp_buf1));
775 lp_buf1 = lp_a * lp_buf1 + lp_freq * lp_buf0;
781 void vtt_class :: render_ec()
787 for (i=0, sample = output_buffer, ec_sample=ec_output_buffer; i<samples_in_outputbuffer; i++, ec_sample++,sample++, ec_ptr++) {
788 if (ec_ptr>ec_delay) ec_ptr=ec_buffer;
789 *ec_sample=(*ec_ptr) *ec_feedback;
790 *ec_ptr=*sample+*ec_sample;
794 int vtt_class :: set_mix_buffer_size(int no_samples)
796 list <vtt_class *> :: iterator vtt;
799 // printf("vtt_class::set_mix_buffer_size(), mix_buffer: %12x, mix_out: %12x, samples: %i\n", mix_buffer, mix_out_buffer, no_samples);
801 if (mix_buffer) tX_freemem(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()");
802 samples_in_mix_buffer=no_samples*2;
804 tX_malloc(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()", sizeof(float)*samples_in_mix_buffer, (float *));
805 mix_buffer_end=mix_buffer+samples_in_mix_buffer;
807 // printf("mix_buffer: %12x\n", mix_buffer);
808 // printf("mix_samples: %i, out_samples: %i", samples_in_mix_buffer, no_samples);
810 if (mix_out_buffer) tX_freemem(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()");
811 tX_malloc(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()", sizeof(int16_t)*samples_in_mix_buffer + 4, (int16_t *));
813 // printf("mix_out_buffer: %12x\n", mix_out_buffer);
815 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
816 res|=(*vtt)->set_output_buffer_size(no_samples);
819 if ((!mix_buffer) || (!mix_out_buffer) || res) return(1);
821 mix_buffer_size=no_samples;
826 int16_t * vtt_class :: render_all_turntables()
828 list <vtt_class *> :: iterator vtt, next;
835 pthread_mutex_lock(&render_lock);
837 if (render_list.size()==0) {
838 memset((void *) mix_out_buffer, 0, sizeof(int16_t)*samples_in_mix_buffer);
839 /* We need to memset mix_buffer, too, as the JACK backend
840 acesses this directly.
842 memset((void *) mix_buffer, 0, sizeof(float)*samples_in_mix_buffer);
844 vtt=render_list.begin();
846 max=(*vtt)->max_value;
849 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
850 temp=(*vtt)->output_buffer[sample];
851 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_left;
853 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_right;
856 if (temp>max) max=temp;
857 else if (temp<min) min=temp;
861 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
863 if ((*vtt)->ec_enable) {
864 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
865 temp=(*vtt)->ec_output_buffer[sample];
867 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
869 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
874 if (master_triggered) {
875 pthread_mutex_unlock(&render_lock);
876 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
877 if ((*vtt)->is_sync_client) {
878 if ((*vtt)->sync_countdown) {
879 (*vtt)->sync_countdown--;
881 (*vtt)->sync_countdown=(*vtt)->sync_cycles;
886 pthread_mutex_lock(&render_lock);
889 vtt=render_list.begin();
890 for (vtt++; vtt!=render_list.end(); vtt++) {
892 max=(*vtt)->max_value;
895 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
896 temp=(*vtt)->output_buffer[sample];
897 mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_left;
899 mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_right;
902 if (temp>max) max=temp;
903 else if (temp<min) min=temp;
907 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
909 if ((*vtt)->ec_enable) {
910 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
911 temp=(*vtt)->ec_output_buffer[sample];
913 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
915 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
926 for (sample=0; sample<samples_in_mix_buffer; sample+=2) {
927 temp=mix_buffer[sample];
930 #define FL_SHRT_MAX 32767.0
931 #define FL_SHRT_MIN -32768.0
932 if(temp < FL_SHRT_MIN) temp = FL_SHRT_MIN;
933 else if (temp > FL_SHRT_MAX) temp = FL_SHRT_MAX;
936 mix_out_buffer[sample]=(int16_t) temp;
938 if (temp>max) max=temp;
939 else if (temp<min) min=temp;
943 if (min>max) mix_max_l=min; else mix_max_l=max;
950 for (sample=1; sample<samples_in_mix_buffer; sample+=2) {
951 temp=mix_buffer[sample];
954 if(temp < FL_SHRT_MIN) temp = FL_SHRT_MIN;
955 else if (temp > FL_SHRT_MAX) temp = FL_SHRT_MAX;
958 mix_out_buffer[sample]=(int16_t) temp;
960 if (temp>max) max=temp;
961 else if (temp<min) min=temp;
965 if (min>max) mix_max_r=min; else mix_max_r=max;
970 vtt=render_list.begin();
971 while (vtt!=render_list.end()) {
975 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
978 pthread_mutex_unlock(&render_lock);
980 return(mix_out_buffer);
983 void vtt_class :: forward_all_turntables()
985 list <vtt_class *> :: iterator vtt, next;
987 if (render_list.size()>0)
989 vtt=render_list.begin();
990 (*vtt)->forward_turntable();
992 if (master_triggered)
994 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
996 if ((*vtt)->is_sync_client)
998 if ((*vtt)->sync_countdown)
1000 (*vtt)->sync_countdown--;
1004 (*vtt)->sync_countdown=(*vtt)->sync_cycles;
1011 vtt=render_list.begin();
1012 for (vtt++; vtt!=render_list.end(); vtt++)
1014 (*vtt)->forward_turntable();
1019 vtt=render_list.begin();
1020 while (vtt!=render_list.end())
1025 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
1031 int vtt_class :: trigger()
1033 list <vtt_fx *> :: iterator effect;
1035 if (!buffer) return (1);
1037 if (!is_playing) pthread_mutex_lock(&render_lock);
1039 if (res_pitch>=0) pos_f=0;
1043 speed_real=res_pitch;
1044 speed_target=res_pitch;
1047 /* activating plugins */
1048 for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
1050 (*effect)->activate();
1058 master_triggered_at=0;
1067 render_list.push_front(this);
1071 render_list.push_back(this);
1073 pthread_mutex_unlock(&render_lock);
1078 static bool do_unlock=true;
1080 int vtt_class :: stop_nolock()
1082 list <vtt_fx *> :: iterator effect;
1084 if ((!is_playing) && do_unlock) {
1085 pthread_mutex_unlock(&render_lock);
1088 render_list.remove(this);
1097 /* deactivating plugins */
1098 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
1099 (*effect)->deactivate();
1105 int vtt_class :: stop()
1109 pthread_mutex_lock(&render_lock);
1117 pthread_mutex_unlock(&render_lock);
1122 void vtt_class :: set_sync_master(int master)
1126 if (sync_master) sync_master->set_sync_master(0);
1132 if (sync_master==this) sync_master=0;
1134 gui_clear_master_button(this);
1138 void vtt_class :: set_sync_client(int slave, int cycles)
1140 tX_debug("vtt_class::set_sync_client() setting %i, %i.", slave, cycles);
1141 is_sync_client=slave;
1143 // sync_countdown=cycles;
1147 void vtt_class :: set_sync_client_ug(int slave, int cycles)
1149 set_sync_client(slave, cycles);
1152 void vtt_class :: set_master_volume(f_prec new_volume)
1154 list <vtt_class *> :: iterator vtt;
1156 master_volume=new_volume;
1157 globals.volume=new_volume;
1159 if (main_list.size()>0)
1161 vol_channel_adjust=sqrt((f_prec) main_list.size());
1162 res_master_volume=master_volume/vol_channel_adjust;
1165 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1167 (*vtt)->recalc_volume();
1171 void vtt_class :: set_master_pitch(f_prec new_pitch)
1173 list <vtt_class *> :: iterator vtt;
1175 globals.pitch=new_pitch;
1176 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1178 (*vtt)->recalc_pitch();
1182 void vtt_class :: focus_no(int no)
1184 list <vtt_class *> :: iterator vtt;
1189 for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++)
1197 void vtt_class :: focus_next()
1199 list <vtt_class *> :: iterator vtt;
1203 if (main_list.size())
1205 focused_vtt=(*main_list.begin());
1210 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1211 if ((*vtt)==focused_vtt) {
1212 /* Ok, we found ourselves.. */
1215 while ((vtt!=main_list.end()) && ((*vtt)->audio_hidden) ) {
1219 if (vtt==main_list.end()) {
1220 /* No other "focusable" after this vtt so we're looking for the next */
1222 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1223 if (! (*vtt)->audio_hidden) {
1228 /* When we get here there's no "focusable" vtt at all... damn */
1238 focused_vtt=(*main_list.begin());
1241 void vtt_class :: set_scratch(int newstate)
1245 sp_spin.receive_input_value(0);
1247 sense_cycles=globals.sense_cycles;
1251 sp_spin.receive_input_value(1);
1257 void vtt_class :: unfocus()
1262 void vtt_class :: set_x_input_parameter(tX_seqpar *sp)
1267 void vtt_class :: set_y_input_parameter(tX_seqpar *sp)
1272 void vtt_class :: xy_input(f_prec x_value, f_prec y_value)
1274 if (x_par) x_par->handle_mouse_input(x_value*globals.mouse_speed);
1275 if (y_par) y_par->handle_mouse_input(y_value*globals.mouse_speed);
1278 #define store(data); if (fwrite((void *) &data, sizeof(data), 1, output)!=1) res+=1;
1280 int vtt_class :: save(FILE *rc, gzFile rz, char *indent) {
1281 list <vtt_fx *> :: iterator effect;
1282 char tmp_xml_buffer[4096];
1286 tX_store("%s<turntable>\n", indent);
1287 strcat(indent, "\t");
1289 store_string("name", name);
1291 store_string("audiofile", filename);
1293 store_string("audiofile", "");
1295 store_bool("sync_master", is_sync_master);
1296 store_bool("autotrigger", autotrigger);
1297 store_bool_sp("loop", loop, sp_loop);
1299 store_bool_sp("sync_client", is_sync_client, sp_sync_client);
1300 store_int_sp("sync_cycles", sync_cycles, sp_sync_cycles);
1302 store_float_sp("volume", rel_volume, sp_volume);
1303 store_float_sp("pitch", rel_pitch, sp_pitch);
1304 store_bool_sp("mute", mute, sp_mute);
1305 store_float_sp("pan", pan, sp_pan);
1307 store_bool_sp("lowpass_enable", lp_enable, sp_lp_enable);
1308 store_float_sp("lowpass_gain", lp_gain, sp_lp_gain);
1309 store_float_sp("lowpass_reso", lp_reso, sp_lp_reso);
1310 store_float_sp("lowpass_freq", lp_freq, sp_lp_freq);
1312 store_bool_sp("echo_enable", ec_enable, sp_ec_enable);
1313 store_float_sp("echo_length", ec_length, sp_ec_length);
1314 store_float_sp("echo_feedback", ec_feedback, sp_ec_feedback);
1315 store_float_sp("echo_pan", ec_pan, sp_ec_pan);
1316 store_float_sp("echo_volume", ec_volume, sp_ec_volume);
1318 store_id("speed", sp_speed.get_persistence_id());
1319 store_id("trigger", sp_trigger.get_persistence_id());
1320 store_id("spin", sp_spin.get_persistence_id());
1324 store_int("x_axis_mapping", x_par->get_persistence_id());
1328 store_int("y_axis_mapping", y_par->get_persistence_id());
1331 store_bool("audio_panel_hidden", audio_hidden);
1332 store_bool("control_panel_hidden", control_hidden);
1333 store_bool("main_panel_hidden", gui.main_panel->is_hidden());
1334 store_bool("trigger_panel_hidden", gui.trigger_panel->is_hidden());
1335 store_bool("lowpass_panel_hidden", gui.lp_panel->is_hidden());
1336 store_bool("echo_panel_hidden", gui.ec_panel->is_hidden());
1338 store_bool("mix_mute", mix_mute);
1339 store_bool("mix_solo", mix_solo);
1341 store_float("audio_x_zoom", gui_get_audio_x_zoom(this));
1343 tX_store("%s<fx>\n", indent);
1344 strcat(indent, "\t");
1346 for (effect=fx_list.begin(); effect!=fx_list.end(); effect++) {
1347 (*effect)->save(rc, rz, indent);
1349 indent[strlen(indent)-1]=0;
1350 tX_store("%s</fx>\n", indent);
1352 indent[strlen(indent)-1]=0;
1353 tX_store("%s</turntable>\n", indent);
1358 #define TX_XML_SETFILE_VERSION "1.0"
1360 int vtt_class :: save_all(FILE* rc, gzFile rz) {
1362 list <vtt_class *> :: iterator vtt;
1365 tX_seqpar :: create_persistence_ids();
1367 tX_store("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n");
1368 tX_store("<terminatorXset version=\"%s\">\n", TX_XML_SETFILE_VERSION);
1370 strcpy(indent, "\t");
1372 //store_int(vtt_amount); obsolete
1374 store_float_sp("master_volume", master_volume, sp_master_volume);
1375 store_float_sp("master_pitch", globals.pitch, sp_master_pitch);
1377 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1378 res+=(*vtt)->save(rc, rz, indent);
1381 sequencer.save(rc, rz, indent);
1383 tX_store("</terminatorXset>\n");
1388 int vtt_class :: load(xmlDocPtr doc, xmlNodePtr node) {
1398 char tmp_xml_buffer[4096];
1400 for (xmlNodePtr cur=node->xmlChildrenNode; cur != NULL; cur = cur->next) {
1401 if (cur->type == XML_ELEMENT_NODE) {
1404 restore_string_ac("name", buffer, set_name(buffer));
1405 restore_string("audiofile", filename);
1406 restore_bool("sync_master", is_sync_master);
1407 restore_bool("autotrigger", autotrigger);
1408 restore_bool_id("loop", loop, sp_loop, nop);
1409 restore_bool_id("sync_client", is_sync_client, sp_sync_client, set_sync_client(is_sync_client, sync_cycles));
1410 restore_int_id("sync_cycles", sync_cycles, sp_sync_cycles, set_sync_client(is_sync_client, sync_cycles));
1411 restore_float_id("volume", rel_volume, sp_volume, recalc_volume());
1412 restore_float_id("pitch", rel_pitch, sp_pitch, recalc_pitch());
1413 restore_bool_id("mute", mute, sp_mute, set_mute(mute));
1414 restore_float_id("pan", pan, sp_pan, set_pan(pan));
1416 restore_bool_id("lowpass_enable", lp_enable, sp_lp_enable, lp_set_enable(lp_enable));
1417 restore_float_id("lowpass_gain", lp_gain, sp_lp_gain, lp_set_gain(lp_gain));
1418 restore_float_id("lowpass_reso", lp_reso, sp_lp_reso, lp_set_reso(lp_reso));
1419 restore_float_id("lowpass_freq", lp_freq, sp_lp_freq, lp_set_freq(lp_freq));
1421 restore_bool_id("echo_enable", ec_enable, sp_ec_enable, ec_set_enable(ec_enable));
1422 restore_float_id("echo_length", ec_length, sp_ec_length, ec_set_length(ec_length));
1423 restore_float_id("echo_feedback", ec_feedback, sp_ec_feedback, ec_set_feedback(ec_feedback));
1424 restore_float_id("echo_pan", ec_pan, sp_ec_pan, ec_set_pan(ec_pan));
1425 restore_float_id("echo_volume", ec_volume, sp_ec_volume, ec_set_volume(ec_volume));
1427 restore_id("speed", sp_speed);
1428 restore_id("trigger", sp_trigger);
1429 restore_id("spin", sp_spin);
1431 restore_int("x_axis_mapping", xpar_id);
1432 restore_int("y_axis_mapping", ypar_id);
1434 restore_bool("mix_mute", mix_mute);
1435 restore_bool("mix_solo", mix_solo);
1437 restore_bool("audio_panel_hidden", audio_hidden);
1438 restore_bool("control_panel_hidden", control_hidden);
1439 restore_bool_ac("main_panel_hidden", hidden, gui.main_panel->hide(hidden));
1440 restore_bool_ac("trigger_panel_hidden", hidden, gui.trigger_panel->hide(hidden));
1441 restore_bool_ac("lowpass_panel_hidden", hidden, gui.lp_panel->hide(hidden));
1442 restore_bool_ac("echo_panel_hidden", hidden, gui.ec_panel->hide(hidden));
1443 restore_float_ac("audio_x_zoom", tmp, gui_set_audio_x_zoom(this,tmp));
1444 vg_adjust_zoom(gui.zoom, this);
1446 if (xmlStrcmp(cur->name, (xmlChar *) "fx")==0) {
1450 for (xmlNodePtr cur=fx->xmlChildrenNode; cur != NULL; cur = cur->next) {
1451 if (cur->type == XML_ELEMENT_NODE) {
1454 if (xmlStrcmp(cur->name, (xmlChar *) "cutoff")==0) {
1455 for (unsigned int t=0; t<fx_list.size(); t++) effect_down(lp_fx);
1457 } else if (xmlStrcmp(cur->name, (xmlChar *) "lowpass")==0) {
1458 for (unsigned int t=0; t<fx_list.size(); t++) effect_down(ec_fx);
1460 } else if (xmlStrcmp(cur->name, (xmlChar *) "ladspa_plugin")==0) {
1461 xmlNodePtr pluginNode=cur;
1465 for (xmlNodePtr cur=pluginNode->xmlChildrenNode; cur!=NULL; cur = cur->next) {
1467 if (cur->type == XML_ELEMENT_NODE) {
1470 restore_int("ladspa_id", ladspa_id);
1471 if (elementFound) break;
1475 if (ladspa_id!=-1) {
1476 LADSPA_Plugin *plugin=LADSPA_Plugin::getPluginByUniqueID(ladspa_id);
1478 vtt_fx_ladspa *ladspa_effect=add_effect(plugin);
1479 ladspa_effect->load(doc, pluginNode);
1481 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);
1482 tx_note(buffer, true);
1485 tX_warning("ladspa_plugin section without a ladspa_id element.");
1489 tX_warning("unhandled element %s in fx section.", cur->name);
1496 tX_warning("unhandled element %s in turntable secion.", cur->name);
1508 set_x_input_parameter(tX_seqpar :: get_sp_by_persistence_id(xpar_id));
1510 else set_x_input_parameter(NULL);
1513 set_y_input_parameter(tX_seqpar :: get_sp_by_persistence_id(ypar_id));
1515 else set_y_input_parameter(NULL);
1517 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.mute), mix_mute);
1518 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.solo), mix_solo);
1523 void vtt_class :: delete_all()
1525 while (main_list.size()) {
1526 delete((*main_list.begin()));
1529 /* Take care of the master events.. */
1530 sequencer.delete_all_events(tX_sequencer::DELETE_ALL);
1532 /* Now reset master settings ot the default: */
1533 set_master_pitch(1.0);
1534 set_master_volume(1.0);
1536 sp_master_pitch.do_exec(1.0);
1537 sp_master_pitch.do_update_graphics();
1539 sp_master_volume.do_exec(1.0);
1540 sp_master_volume.do_update_graphics();
1542 /* Remove master MIDI mappings... */
1543 sp_master_pitch.bound_midi_event.type=tX_midievent::NONE;
1544 sp_master_volume.bound_midi_event.type=tX_midievent::NONE;
1550 int vtt_class :: load_all(xmlDocPtr doc, char *fname) {
1551 xmlNodePtr root=xmlDocGetRootElement(doc);
1559 tX_error("no root element? What kind of XML document is this?");
1563 if (xmlStrcmp(root->name, (const xmlChar *) "terminatorXset")) {
1564 tX_error("this is not a terminatorXset file.")
1568 if (xmlGetProp(root,(xmlChar *) "version")==NULL) {
1569 tX_error("the set file lacks a version attribute.");
1573 if (xmlStrcmp(xmlGetProp(root, (xmlChar *) "version"), (xmlChar *) TX_XML_SETFILE_VERSION)) {
1574 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);
1577 /* delete current tables... */
1582 /* counting turntables.. */
1583 for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1584 if (cur->type == XML_ELEMENT_NODE) {
1585 if (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0) {
1591 tX_debug("Found %i turntables in set.", table_ctr);
1593 ld_create_loaddlg(TX_LOADDLG_MODE_MULTI, table_ctr);
1594 ld_set_setname(fname);
1597 for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1598 if (cur->type == XML_ELEMENT_NODE) {
1601 restore_float_id("master_volume", master_volume, sp_master_volume, set_master_volume(master_volume));
1602 restore_float_id("master_pitch", globals.pitch, sp_master_pitch, set_master_pitch(globals.pitch));
1604 if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0)) {
1606 vtt_class *vtt=new vtt_class(1);
1607 vtt->load(doc, cur);
1609 tX_debug("loading a turntable..");
1611 if (strlen(vtt->filename)) {
1612 strcpy(fn_buff, vtt->filename);
1613 ld_set_filename(fn_buff);
1615 restmp=(int) vtt->load_file(fn_buff);
1619 gtk_box_pack_start(GTK_BOX(control_parent), vtt->gui.control_box, TRUE, TRUE, 0);
1620 gtk_box_pack_start(GTK_BOX(audio_parent), vtt->gui.audio_box, TRUE, TRUE, 0);
1621 if (vtt->audio_hidden) vtt->hide_audio(vtt->audio_hidden);
1622 if (vtt->control_hidden) vtt->hide_control(vtt->control_hidden);
\r
1624 if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "sequencer")==0)) {
1626 sequencer.load(doc, cur);
1628 if (!elementFound) {
1629 tX_warning("unhandled element %s in setfile %s", cur->name, fname);
1634 sp_master_volume.do_update_graphics();
1635 sp_master_pitch.do_update_graphics();
1642 void add_vtt(GtkWidget *ctrl, GtkWidget *audio, char *fn)
1645 hmmpg = new vtt_class(1);
1646 gtk_box_pack_start(GTK_BOX(ctrl), hmmpg->gui.control_box, TRUE, TRUE, 0);
1647 gtk_box_pack_start(GTK_BOX(audio), hmmpg->gui.audio_box, TRUE, TRUE, 0);
1648 if (fn) hmmpg->load_file(fn);
1651 extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt);
1652 extern void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt);
1654 //#define debug_fx_stack(); for (i=fx_list.begin(); i != fx_list.end(); i++) puts((*i)->get_info_string());
1655 #define debug_fx_stack();
1657 void vtt_class :: effect_up(vtt_fx *effect)
1659 list <vtt_fx *> :: iterator i;
1660 list <vtt_fx *> :: iterator previous;
1665 if ((*fx_list.begin())==effect) return;
1667 for (previous=i=fx_list.begin(); i != fx_list.end(); i++)
1679 pthread_mutex_lock(&render_lock);
1680 fx_list.remove(effect);
1681 fx_list.insert(previous, effect);
1682 pthread_mutex_unlock(&render_lock);
1684 vg_move_fx_panel_up(effect->get_panel_widget(), this);
1690 void vtt_class :: effect_down(vtt_fx *effect)
1692 list <vtt_fx *> :: iterator i;
1697 for (i=fx_list.begin(); i != fx_list.end(); i++)
1706 if ((ok) && (i!=fx_list.end()))
1709 if (i==fx_list.end()) return;
1712 pthread_mutex_lock(&render_lock);
1713 fx_list.remove(effect);
1715 fx_list.insert(i, effect);
1716 vg_move_fx_panel_down(effect->get_panel_widget(), this);
1717 pthread_mutex_unlock(&render_lock);
1723 void vtt_class :: effect_remove(vtt_fx_ladspa *effect)
1725 pthread_mutex_lock(&render_lock);
1726 fx_list.remove(effect);
1727 pthread_mutex_unlock(&render_lock);
1732 extern void gui_hide_control_panel(vtt_class *vtt, bool hide);
1733 extern void gui_hide_audio_panel(vtt_class *vtt, bool hide);
1735 void vtt_class :: hide_audio(bool hide) {
1737 gui_hide_audio_panel(this, hide);
1740 void vtt_class :: hide_control(bool hide) {
1741 control_hidden=hide;
1742 gui_hide_control_panel(this, hide);
1745 void vtt_class :: set_sample_rate(int samplerate) {
1746 list <vtt_class *> :: iterator vtt;
1747 double sr=(double) samplerate;
1749 last_sample_rate=samplerate;
1751 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1752 if ((*vtt)->audiofile) {
1753 double file_rate=(*vtt)->audiofile->get_sample_rate();
1754 (*vtt)->audiofile_pitch_correction=file_rate/sr;
1756 (*vtt)->audiofile_pitch_correction=1.0;
1758 (*vtt)->recalc_pitch();
1761 int no_samples=(int) (sr*0.001); // Forcing 1 ms blocksize
1763 set_mix_buffer_size(no_samples);
1766 void vtt_class :: adjust_to_master_pitch(int master_cycles, int cycles, bool create_event) {
1767 if (!sync_master) return;
1768 if (this==sync_master) return;
1769 if (!sync_master->audiofile) return;
1770 if (!audiofile) return;
1772 double master_time=((double) master_cycles)/sync_master->rel_pitch*sync_master->audiofile->get_no_samples()/((double) sync_master->audiofile->get_sample_rate());
1773 double my_rel_pitch=((audiofile->get_no_samples()/((double) audiofile->get_sample_rate()))*((double) cycles))/master_time;
1776 sp_pitch.do_exec(my_rel_pitch);
1777 sp_pitch.record_value(my_rel_pitch);
1779 sp_pitch.do_exec(my_rel_pitch);
1782 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());
1784 sp_pitch.update_graphics();