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 cleanup_required=false;
103 sprintf (name, "Turntable %i", vtt_amount);
104 strcpy(filename, "NONE");
113 audiofile_pitch_correction=1.0;
115 ec_output_buffer=NULL;
134 lp_setup(lp_gain, lp_reso, lp_freq);
145 main_list.push_back(this);
147 /* "connecting" the seq-parameters */
149 sp_speed.set_vtt((void *) this);
150 sp_volume.set_vtt((void *) this);
151 sp_pitch.set_vtt((void *) this);
152 sp_pan.set_vtt((void *) this);
153 sp_trigger.set_vtt((void *) this);
154 sp_loop.set_vtt((void *) this);
155 sp_sync_client.set_vtt((void *) this);
156 sp_sync_cycles.set_vtt((void *) this);
157 sp_lp_enable.set_vtt((void *) this);
158 sp_lp_gain.set_vtt((void *) this);
159 sp_lp_reso.set_vtt((void *) this);
160 sp_lp_freq.set_vtt((void *) this);
161 sp_ec_enable.set_vtt((void *) this);
162 sp_ec_length.set_vtt((void *) this);
163 sp_ec_pan.set_vtt((void *) this);
164 sp_ec_volume.set_vtt((void *) this);
165 sp_ec_feedback.set_vtt((void *) this);
166 sp_mute.set_vtt((void *) this);
167 sp_spin.set_vtt((void *) this);
172 lp_fx=new vtt_fx_lp();
173 lp_fx->set_vtt((void *) this);
174 fx_list.push_back(lp_fx);
176 ec_fx=new vtt_fx_ec();
177 ec_fx->set_vtt((void *) this);
178 fx_list.push_back(ec_fx);
183 lp_fx->set_panel_widget(gui.lp_panel->get_widget());
184 ec_fx->set_panel_widget(gui.ec_panel->get_widget());
189 set_master_volume(globals.volume);
190 set_output_buffer_size(samples_in_mix_buffer/2);
193 audiofile_pitch_correction=1.0;
201 control_hidden=false;
208 vtt_class :: ~vtt_class()
213 main_list.remove(this);
214 if (audiofile) delete audiofile;
215 //if (buffer) free(buffer);
216 if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt Destructor");
219 if (mix_solo) solo_ctr--;
221 while (fx_list.size())
223 effect=(*fx_list.begin());
224 fx_list.remove(effect);
228 if (sync_master==this) {
235 void vtt_class :: set_name(char *newname)
237 strcpy(name, newname);
238 gui_set_name(this, name);
241 tX_audio_error vtt_class :: load_file(char *fname)
244 int was_playing=is_playing;
246 if (is_playing) stop();
248 if (audiofile) delete(audiofile);
256 audiofile=new tx_audiofile();
257 res=audiofile->load(fname);
259 if (res==TX_AUDIO_SUCCESS) {
260 buffer=audiofile->get_buffer();
261 double file_rate=audiofile->get_sample_rate();
262 audiofile_pitch_correction=file_rate/((double) last_sample_rate);
264 samples_in_buffer=audiofile->get_no_samples();
265 pos_i_max=samples_in_buffer-1;
266 maxpos=audiofile->get_no_samples();
267 strcpy(filename, fname);
268 if (was_playing) trigger();
269 // printf("Successfully loaded %s, %08x, %i\n", fname, buffer, samples_in_buffer);
274 gui_update_display(this);
276 ec_set_length(ec_length);
281 int vtt_class :: set_output_buffer_size(int newsize)
283 list <vtt_fx *> :: iterator effect;
285 if (ec_output_buffer) tX_freemem(ec_output_buffer, "ec_output_buffer", "vtt set_output_buffer_size()");
286 tX_malloc(ec_output_buffer, "ec_output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
288 if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt set_output_buffer_size()");
289 tX_malloc(output_buffer, "output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
291 end_of_outputbuffer = output_buffer + newsize; //size_t(sizeof(float)*(newsize));
293 samples_in_outputbuffer=newsize;
294 inv_samples_in_outputbuffer=1.0/samples_in_outputbuffer;
296 for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
298 (*effect)->reconnect_buffer();
301 if (output_buffer) return(0);
305 void vtt_class :: set_volume(f_prec newvol)
311 void vtt_class :: recalc_volume()
313 res_volume=rel_volume*res_master_volume;
314 f_prec ec_res_volume=res_volume*ec_volume;
318 res_volume_left=(1.0-pan)*res_volume;
319 res_volume_right=res_volume;
323 res_volume_left=res_volume;
324 res_volume_right=(1.0+pan)*res_volume;
328 res_volume_left=res_volume_right=res_volume;
333 ec_volume_left=(1.0-ec_pan)*ec_res_volume;
334 ec_volume_right=ec_res_volume;
338 ec_volume_left=ec_res_volume;
339 ec_volume_right=(1.0+ec_pan)*ec_res_volume;
343 ec_volume_left=ec_volume_right=ec_res_volume;
345 // printf("vtt_volume: %f, %f, l: %f, r: %f\n", rel_volume, res_volume, res_volume_left, res_volume_right);
348 void vtt_class :: set_pan(f_prec newpan)
354 void vtt_class :: set_pitch(f_prec newpitch)
360 void vtt_class :: recalc_pitch()
362 res_pitch=globals.pitch*rel_pitch;
363 res_pitch*=audiofile_pitch_correction;
365 ec_set_length(ec_length);
368 void vtt_class :: set_autotrigger(int newstate)
370 autotrigger=newstate;
373 void vtt_class :: set_loop(int newstate)
378 void vtt_class :: set_mute(int newstate)
384 void vtt_class :: set_mix_mute(int newstate)
390 void vtt_class :: set_mix_solo(int newstate)
392 if (mix_solo && !newstate)
398 else if (!mix_solo && newstate)
407 list <vtt_class *> :: iterator vtt;
409 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++)
415 void vtt_class :: lp_set_enable (int newstate)
421 void vtt_class :: lp_reset()
426 void vtt_class :: lp_set_gain (f_prec gain)
429 lp_resgain=lp_gain*lp_autogain;
432 void vtt_class :: lp_set_reso(f_prec reso)
436 lp_b=reso*(1.0+(1.0/lp_a));
437 lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
438 lp_resgain=lp_gain*lp_autogain;
441 void vtt_class :: lp_set_freq(f_prec freq)
446 lp_b=lp_reso*(1.0+(1.0/lp_a));
449 void vtt_class :: lp_setup(f_prec gain, f_prec reso, f_prec freq)
455 lp_b=reso*(1.0+(1.0/lp_a));
457 lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
458 lp_resgain=lp_gain*lp_autogain;
461 void vtt_class :: ec_set_enable(int newstate)
468 void vtt_class :: ec_set_pan(f_prec pan)
475 /* Max length is 1.0 */
477 void vtt_class :: ec_set_length(f_prec length)
484 ec_res_length=length*samples_in_buffer;
488 ec_res_length=length*samples_in_buffer/res_pitch;
491 if (ec_res_length<0) ec_res_length*=-1;
493 if (ec_res_length>=EC_MAX_BUFFER)
495 ec_res_length=EC_MAX_BUFFER*length;
498 delay=(int )floor(ec_res_length);
500 ec_delay=&ec_buffer[delay];
503 void vtt_class :: ec_set_feedback(f_prec feedback)
505 ec_feedback=feedback;
509 void vtt_class :: ec_set_volume(f_prec volume)
515 void vtt_class :: ec_clear_buffer()
519 for (ptr=ec_buffer; ptr<=ec_delay; ptr++) {
525 void vtt_class :: render()
527 list <vtt_fx *> :: iterator effect;
530 if (sense_cycles>0) {
532 if (sense_cycles==0) sp_speed.receive_input_value(0);
537 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
538 if ((*effect)->isEnabled()) (*effect)->run();
542 extern void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plugin);
544 vtt_fx_ladspa * vtt_class :: add_effect (LADSPA_Plugin *plugin)
546 vtt_fx_ladspa *new_effect;
548 new_effect = new vtt_fx_ladspa (plugin, this);
549 pthread_mutex_lock(&render_lock);
550 fx_list.push_back(new_effect);
551 if (is_playing) new_effect->activate();
552 pthread_mutex_unlock(&render_lock);
553 vg_create_fx_gui(this, new_effect, plugin);
558 void vtt_class :: calc_speed()
564 if (speed != speed_target) {
566 speed_step=speed_target-speed_real;
567 speed_step/=globals.vtt_inertia;
570 if (speed_target != speed_real) {
571 speed_real+=speed_step;
572 if ((speed_step<0) && (speed_real<speed_target)) speed_real=speed_target;
573 else if ((speed_step>0) && (speed_real>speed_target)) speed_real=speed_target;
577 if ((speed_last==0) && (speed_real !=0)) {
582 if ((speed_last!=0) && (speed_real==0)) {
588 speed_last = speed_real;
590 if (res_mute != res_mute_old) {
592 fade_out=1; fade_in=0;
595 fade_in=1; fade_out=0;
598 res_mute_old=res_mute;
600 if (res_mute) do_mute=1;
604 void vtt_class :: render_scratch()
625 for (sample =0,out=output_buffer, fade_vol=0.0; sample < samples_in_outputbuffer;sample++, out++, fade_vol+=inv_samples_in_outputbuffer) {
626 if ((speed_real!=0) || (fade_out)) {
637 master_triggered_at=sample;
643 } else if (pos_f<0) {
650 master_triggered_at=sample;
658 pos_a_f=floor(pos_f);
659 pos_i=(unsigned int) pos_a_f;
661 amount_b=pos_f-pos_a_f;
662 amount_a=1.0-amount_b;
668 sample_a=(f_prec) *ptr;
670 if (pos_i == pos_i_max) {
674 sample_b=(f_prec) *ptr;
677 sample_res=(sample_a*amount_a)+(sample_b*amount_b);
680 sample_res*=fade_vol;
681 } else if (fade_out) {
682 sample_res*=1.0-fade_vol;
693 void vtt_class :: forward_turntable()
704 if ((speed_real==0) && (!fade_out)) return;
707 /* following code is problematic as adding speed_real*n is
708 different from adding speed_real n times to pos_f.
710 well it speeds things up quite a bit and double precision
711 seems to do a satisfying job.
713 #define pos_f_test to prove that.
716 pos_f_tmp=pos_f+speed_real*samples_in_outputbuffer;
718 if ((pos_f_tmp > 0) && (pos_f_tmp < maxpos)) {
727 /* now the slow way ;) */
729 for (sample =0; sample < samples_in_outputbuffer; sample++) {
736 if (is_sync_master) {
738 master_triggered_at=sample;
744 } else if (pos_f<0) {
748 if (is_sync_master) {
750 master_triggered_at=sample;
760 diff=pos_f_tmp-pos_f;
761 if (diff!=0) printf("fast: %f, slow: %f, diff: %f, tt: %s\n", pos_f_tmp, pos_f, diff, name);
767 The following lowpass filter is based on some sample code by
768 Paul Kellett <paul.kellett@maxim.abel.co.uk>
771 void vtt_class :: render_lp()
775 for (sample = output_buffer; sample<end_of_outputbuffer; sample++) {
776 lp_buf0 = lp_a * lp_buf0 + lp_freq * ((*sample)*lp_resgain + lp_b * (lp_buf0 - lp_buf1));
777 lp_buf1 = lp_a * lp_buf1 + lp_freq * lp_buf0;
783 void vtt_class :: render_ec()
789 for (i=0, sample = output_buffer, ec_sample=ec_output_buffer; i<samples_in_outputbuffer; i++, ec_sample++,sample++, ec_ptr++) {
790 if (ec_ptr>ec_delay) ec_ptr=ec_buffer;
791 *ec_sample=(*ec_ptr) *ec_feedback;
792 *ec_ptr=*sample+*ec_sample;
796 int vtt_class :: set_mix_buffer_size(int no_samples)
798 list <vtt_class *> :: iterator vtt;
801 // printf("vtt_class::set_mix_buffer_size(), mix_buffer: %12x, mix_out: %12x, samples: %i\n", mix_buffer, mix_out_buffer, no_samples);
803 if (mix_buffer) tX_freemem(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()");
804 samples_in_mix_buffer=no_samples*2;
806 tX_malloc(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()", sizeof(float)*samples_in_mix_buffer, (float *));
807 mix_buffer_end=mix_buffer+samples_in_mix_buffer;
809 // printf("mix_buffer: %12x\n", mix_buffer);
810 // printf("mix_samples: %i, out_samples: %i", samples_in_mix_buffer, no_samples);
812 if (mix_out_buffer) tX_freemem(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()");
813 tX_malloc(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()", sizeof(int16_t)*samples_in_mix_buffer + 4, (int16_t *));
815 // printf("mix_out_buffer: %12x\n", mix_out_buffer);
817 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) {
840 memset((void *) mix_out_buffer, 0, sizeof(int16_t)*samples_in_mix_buffer);
841 /* We need to memset mix_buffer, too, as the JACK backend
842 acesses this directly.
844 memset((void *) mix_buffer, 0, sizeof(float)*samples_in_mix_buffer);
846 vtt=render_list.begin();
848 max=(*vtt)->max_value;
851 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
852 temp=(*vtt)->output_buffer[sample];
853 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_left;
855 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_right;
858 if (temp>max) max=temp;
859 else if (temp<min) min=temp;
863 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
865 if ((*vtt)->ec_enable) {
866 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
867 temp=(*vtt)->ec_output_buffer[sample];
869 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
871 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
876 if (master_triggered) {
877 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
878 if ((*vtt)->is_sync_client) {
879 if ((*vtt)->sync_countdown) {
880 (*vtt)->sync_countdown--;
882 (*vtt)->sync_countdown=(*vtt)->sync_cycles;
883 (*vtt)->trigger(false);
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();
1030 void vtt_class :: retrigger()
1032 if (res_pitch>=0) pos_f=0;
1037 speed_real=res_pitch;
1038 speed_target=res_pitch;
1043 if (is_sync_master) {
1045 master_triggered_at=0;
1049 int vtt_class :: trigger(bool need_lock)
1051 list <vtt_fx *> :: iterator effect;
1053 if (!buffer) return 1;
1058 if (need_lock) pthread_mutex_lock(&render_lock);
1060 cleanup_required=false;
1062 /* activating plugins */
1063 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
1064 (*effect)->activate();
1067 if (is_sync_master) {
1068 render_list.push_front(this);
1070 render_list.push_back(this);
1073 if (need_lock) pthread_mutex_unlock(&render_lock);
1079 /* call this only when owning render_lock. */
1080 int vtt_class :: stop_nolock()
1082 list <vtt_fx *> :: iterator effect;
1088 render_list.remove(this);
1093 cleanup_required=true;
1095 /* deactivating plugins */
1096 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
1097 (*effect)->deactivate();
1103 int vtt_class :: stop()
1107 pthread_mutex_lock(&render_lock);
1109 pthread_mutex_unlock(&render_lock);
1114 void vtt_class :: set_sync_master(int master)
1117 if (sync_master) sync_master->set_sync_master(0);
1121 if (sync_master==this) sync_master=0;
1123 gui_clear_master_button(this);
1127 void vtt_class :: set_sync_client(int slave, int cycles)
1129 tX_debug("vtt_class::set_sync_client() setting %i, %i.", slave, cycles);
1130 is_sync_client=slave;
1132 // sync_countdown=cycles;
1136 void vtt_class :: set_sync_client_ug(int slave, int cycles)
1138 set_sync_client(slave, cycles);
1141 void vtt_class :: set_master_volume(f_prec new_volume)
1143 list <vtt_class *> :: iterator vtt;
1145 master_volume=new_volume;
1146 globals.volume=new_volume;
1148 if (main_list.size()>0) {
1149 vol_channel_adjust=sqrt((f_prec) main_list.size());
1150 res_master_volume=master_volume/vol_channel_adjust;
1153 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1154 (*vtt)->recalc_volume();
1158 void vtt_class :: set_master_pitch(f_prec new_pitch)
1160 list <vtt_class *> :: iterator vtt;
1162 globals.pitch=new_pitch;
1163 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1164 (*vtt)->recalc_pitch();
1168 void vtt_class :: focus_no(int no)
1170 list <vtt_class *> :: iterator vtt;
1175 for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++) {
1182 void vtt_class :: focus_next()
1184 list <vtt_class *> :: iterator vtt;
1187 if (main_list.size()) {
1188 focused_vtt=(*main_list.begin());
1193 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1194 if ((*vtt)==focused_vtt) {
1195 /* Ok, we found ourselves.. */
1198 while ((vtt!=main_list.end()) && ((*vtt)->audio_hidden) ) {
1202 if (vtt==main_list.end()) {
1203 /* No other "focusable" after this vtt so we're looking for the next */
1205 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1206 if (! (*vtt)->audio_hidden) {
1211 /* When we get here there's no "focusable" vtt at all... damn */
1221 focused_vtt=(*main_list.begin());
1224 void vtt_class :: set_scratch(int newstate)
1227 sp_spin.receive_input_value(0);
1229 sense_cycles=globals.sense_cycles;
1231 sp_spin.receive_input_value(1);
1237 void vtt_class :: unfocus()
1242 void vtt_class :: set_x_input_parameter(tX_seqpar *sp)
1247 void vtt_class :: set_y_input_parameter(tX_seqpar *sp)
1252 void vtt_class :: xy_input(f_prec x_value, f_prec y_value)
1254 if (x_par) x_par->handle_mouse_input(x_value*globals.mouse_speed);
1255 if (y_par) y_par->handle_mouse_input(y_value*globals.mouse_speed);
1258 #define store(data); if (fwrite((void *) &data, sizeof(data), 1, output)!=1) res+=1;
1260 int vtt_class :: save(FILE *rc, gzFile rz, char *indent) {
1261 list <vtt_fx *> :: iterator effect;
1262 char tmp_xml_buffer[4096];
1266 tX_store("%s<turntable>\n", indent);
1267 strcat(indent, "\t");
1269 store_string("name", name);
1271 store_string("audiofile", filename);
1273 store_string("audiofile", "");
1275 store_bool("sync_master", is_sync_master);
1276 store_bool("autotrigger", autotrigger);
1277 store_bool_sp("loop", loop, sp_loop);
1279 store_bool_sp("sync_client", is_sync_client, sp_sync_client);
1280 store_int_sp("sync_cycles", sync_cycles, sp_sync_cycles);
1282 store_float_sp("volume", rel_volume, sp_volume);
1283 store_float_sp("pitch", rel_pitch, sp_pitch);
1284 store_bool_sp("mute", mute, sp_mute);
1285 store_float_sp("pan", pan, sp_pan);
1287 store_bool_sp("lowpass_enable", lp_enable, sp_lp_enable);
1288 store_float_sp("lowpass_gain", lp_gain, sp_lp_gain);
1289 store_float_sp("lowpass_reso", lp_reso, sp_lp_reso);
1290 store_float_sp("lowpass_freq", lp_freq, sp_lp_freq);
1292 store_bool_sp("echo_enable", ec_enable, sp_ec_enable);
1293 store_float_sp("echo_length", ec_length, sp_ec_length);
1294 store_float_sp("echo_feedback", ec_feedback, sp_ec_feedback);
1295 store_float_sp("echo_pan", ec_pan, sp_ec_pan);
1296 store_float_sp("echo_volume", ec_volume, sp_ec_volume);
1298 store_id("speed", sp_speed.get_persistence_id());
1299 store_id("trigger", sp_trigger.get_persistence_id());
1300 store_id("spin", sp_spin.get_persistence_id());
1304 store_int("x_axis_mapping", x_par->get_persistence_id());
1308 store_int("y_axis_mapping", y_par->get_persistence_id());
1311 store_bool("audio_panel_hidden", audio_hidden);
1312 store_bool("control_panel_hidden", control_hidden);
1313 store_bool("main_panel_hidden", gui.main_panel->is_hidden());
1314 store_bool("trigger_panel_hidden", gui.trigger_panel->is_hidden());
1315 store_bool("lowpass_panel_hidden", gui.lp_panel->is_hidden());
1316 store_bool("echo_panel_hidden", gui.ec_panel->is_hidden());
1318 store_bool("mix_mute", mix_mute);
1319 store_bool("mix_solo", mix_solo);
1321 store_float("audio_x_zoom", gui_get_audio_x_zoom(this));
1323 tX_store("%s<fx>\n", indent);
1324 strcat(indent, "\t");
1326 for (effect=fx_list.begin(); effect!=fx_list.end(); effect++) {
1327 (*effect)->save(rc, rz, indent);
1329 indent[strlen(indent)-1]=0;
1330 tX_store("%s</fx>\n", indent);
1332 indent[strlen(indent)-1]=0;
1333 tX_store("%s</turntable>\n", indent);
1338 #define TX_XML_SETFILE_VERSION "1.0"
1340 int vtt_class :: save_all(FILE* rc, gzFile rz) {
1342 list <vtt_class *> :: iterator vtt;
1345 tX_seqpar :: create_persistence_ids();
1347 tX_store("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n");
1348 tX_store("<terminatorXset version=\"%s\">\n", TX_XML_SETFILE_VERSION);
1350 strcpy(indent, "\t");
1352 //store_int(vtt_amount); obsolete
1354 store_float_sp("master_volume", master_volume, sp_master_volume);
1355 store_float_sp("master_pitch", globals.pitch, sp_master_pitch);
1357 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1358 res+=(*vtt)->save(rc, rz, indent);
1361 sequencer.save(rc, rz, indent);
1363 tX_store("</terminatorXset>\n");
1368 int vtt_class :: load(xmlDocPtr doc, xmlNodePtr node) {
1378 char tmp_xml_buffer[4096];
1380 for (xmlNodePtr cur=node->xmlChildrenNode; cur != NULL; cur = cur->next) {
1381 if (cur->type == XML_ELEMENT_NODE) {
1384 restore_string_ac("name", buffer, set_name(buffer));
1385 restore_string("audiofile", filename);
1386 restore_bool("sync_master", is_sync_master);
1387 restore_bool("autotrigger", autotrigger);
1388 restore_bool_id("loop", loop, sp_loop, nop);
1389 restore_bool_id("sync_client", is_sync_client, sp_sync_client, set_sync_client(is_sync_client, sync_cycles));
1390 restore_int_id("sync_cycles", sync_cycles, sp_sync_cycles, set_sync_client(is_sync_client, sync_cycles));
1391 restore_float_id("volume", rel_volume, sp_volume, recalc_volume());
1392 restore_float_id("pitch", rel_pitch, sp_pitch, recalc_pitch());
1393 restore_bool_id("mute", mute, sp_mute, set_mute(mute));
1394 restore_float_id("pan", pan, sp_pan, set_pan(pan));
1396 restore_bool_id("lowpass_enable", lp_enable, sp_lp_enable, lp_set_enable(lp_enable));
1397 restore_float_id("lowpass_gain", lp_gain, sp_lp_gain, lp_set_gain(lp_gain));
1398 restore_float_id("lowpass_reso", lp_reso, sp_lp_reso, lp_set_reso(lp_reso));
1399 restore_float_id("lowpass_freq", lp_freq, sp_lp_freq, lp_set_freq(lp_freq));
1401 restore_bool_id("echo_enable", ec_enable, sp_ec_enable, ec_set_enable(ec_enable));
1402 restore_float_id("echo_length", ec_length, sp_ec_length, ec_set_length(ec_length));
1403 restore_float_id("echo_feedback", ec_feedback, sp_ec_feedback, ec_set_feedback(ec_feedback));
1404 restore_float_id("echo_pan", ec_pan, sp_ec_pan, ec_set_pan(ec_pan));
1405 restore_float_id("echo_volume", ec_volume, sp_ec_volume, ec_set_volume(ec_volume));
1407 restore_id("speed", sp_speed);
1408 restore_id("trigger", sp_trigger);
1409 restore_id("spin", sp_spin);
1411 restore_int("x_axis_mapping", xpar_id);
1412 restore_int("y_axis_mapping", ypar_id);
1414 restore_bool("mix_mute", mix_mute);
1415 restore_bool("mix_solo", mix_solo);
1417 restore_bool("audio_panel_hidden", audio_hidden);
1418 restore_bool("control_panel_hidden", control_hidden);
1419 restore_bool_ac("main_panel_hidden", hidden, gui.main_panel->hide(hidden));
1420 restore_bool_ac("trigger_panel_hidden", hidden, gui.trigger_panel->hide(hidden));
1421 restore_bool_ac("lowpass_panel_hidden", hidden, gui.lp_panel->hide(hidden));
1422 restore_bool_ac("echo_panel_hidden", hidden, gui.ec_panel->hide(hidden));
1423 restore_float_ac("audio_x_zoom", tmp, gui_set_audio_x_zoom(this,tmp));
1424 vg_adjust_zoom(gui.zoom, this);
1426 if (xmlStrcmp(cur->name, (xmlChar *) "fx")==0) {
1430 for (xmlNodePtr cur=fx->xmlChildrenNode; cur != NULL; cur = cur->next) {
1431 if (cur->type == XML_ELEMENT_NODE) {
1434 if (xmlStrcmp(cur->name, (xmlChar *) "cutoff")==0) {
1435 for (unsigned int t=0; t<fx_list.size(); t++) effect_down(lp_fx);
1437 } else if (xmlStrcmp(cur->name, (xmlChar *) "lowpass")==0) {
1438 for (unsigned int t=0; t<fx_list.size(); t++) effect_down(ec_fx);
1440 } else if (xmlStrcmp(cur->name, (xmlChar *) "ladspa_plugin")==0) {
1441 xmlNodePtr pluginNode=cur;
1445 for (xmlNodePtr cur=pluginNode->xmlChildrenNode; cur!=NULL; cur = cur->next) {
1447 if (cur->type == XML_ELEMENT_NODE) {
1450 restore_int("ladspa_id", ladspa_id);
1451 if (elementFound) break;
1455 if (ladspa_id!=-1) {
1456 LADSPA_Plugin *plugin=LADSPA_Plugin::getPluginByUniqueID(ladspa_id);
1458 vtt_fx_ladspa *ladspa_effect=add_effect(plugin);
1459 ladspa_effect->load(doc, pluginNode);
1461 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);
1462 tx_note(buffer, true);
1465 tX_warning("ladspa_plugin section without a ladspa_id element.");
1469 tX_warning("unhandled element %s in fx section.", cur->name);
1476 tX_warning("unhandled element %s in turntable secion.", cur->name);
1488 set_x_input_parameter(tX_seqpar :: get_sp_by_persistence_id(xpar_id));
1490 else set_x_input_parameter(NULL);
1493 set_y_input_parameter(tX_seqpar :: get_sp_by_persistence_id(ypar_id));
1495 else set_y_input_parameter(NULL);
1497 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.mute), mix_mute);
1498 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.solo), mix_solo);
1503 void vtt_class :: delete_all()
1505 while (main_list.size()) {
1506 delete((*main_list.begin()));
1509 /* Take care of the master events.. */
1510 sequencer.delete_all_events(tX_sequencer::DELETE_ALL);
1512 /* Now reset master settings ot the default: */
1513 set_master_pitch(1.0);
1514 set_master_volume(1.0);
1516 sp_master_pitch.do_exec(1.0);
1517 sp_master_pitch.do_update_graphics();
1519 sp_master_volume.do_exec(1.0);
1520 sp_master_volume.do_update_graphics();
1522 /* Remove master MIDI mappings... */
1523 sp_master_pitch.bound_midi_event.type=tX_midievent::NONE;
1524 sp_master_volume.bound_midi_event.type=tX_midievent::NONE;
1529 int vtt_class :: load_all(xmlDocPtr doc, char *fname) {
1530 xmlNodePtr root=xmlDocGetRootElement(doc);
1538 tX_error("no root element? What kind of XML document is this?");
1542 if (xmlStrcmp(root->name, (const xmlChar *) "terminatorXset")) {
1543 tX_error("this is not a terminatorXset file.")
1547 if (xmlGetProp(root,(xmlChar *) "version")==NULL) {
1548 tX_error("the set file lacks a version attribute.");
1552 if (xmlStrcmp(xmlGetProp(root, (xmlChar *) "version"), (xmlChar *) TX_XML_SETFILE_VERSION)) {
1553 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);
1556 /* delete current tables... */
1561 /* counting turntables.. */
1562 for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1563 if (cur->type == XML_ELEMENT_NODE) {
1564 if (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0) {
1570 tX_debug("Found %i turntables in set.", table_ctr);
1572 ld_create_loaddlg(TX_LOADDLG_MODE_MULTI, table_ctr);
1573 ld_set_setname(fname);
1576 for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1577 if (cur->type == XML_ELEMENT_NODE) {
1580 restore_float_id("master_volume", master_volume, sp_master_volume, set_master_volume(master_volume));
1581 restore_float_id("master_pitch", globals.pitch, sp_master_pitch, set_master_pitch(globals.pitch));
1583 if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0)) {
1585 vtt_class *vtt=new vtt_class(1);
1586 vtt->load(doc, cur);
1588 tX_debug("loading a turntable..");
1590 if (strlen(vtt->filename)) {
1591 strcpy(fn_buff, vtt->filename);
1592 ld_set_filename(fn_buff);
1594 restmp=(int) vtt->load_file(fn_buff);
1598 gtk_box_pack_start(GTK_BOX(control_parent), vtt->gui.control_box, TRUE, TRUE, 0);
1599 gtk_box_pack_start(GTK_BOX(audio_parent), vtt->gui.audio_box, TRUE, TRUE, 0);
1600 if (vtt->audio_hidden) vtt->hide_audio(vtt->audio_hidden);
1601 if (vtt->control_hidden) vtt->hide_control(vtt->control_hidden);
\r
1603 if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "sequencer")==0)) {
1605 sequencer.load(doc, cur);
1607 if (!elementFound) {
1608 tX_warning("unhandled element %s in setfile %s", cur->name, fname);
1613 sp_master_volume.do_update_graphics();
1614 sp_master_pitch.do_update_graphics();
1621 void add_vtt(GtkWidget *ctrl, GtkWidget *audio, char *fn)
1624 new_tt = new vtt_class(1);
1625 gtk_box_pack_start(GTK_BOX(ctrl), new_tt->gui.control_box, TRUE, TRUE, 0);
1626 gtk_box_pack_start(GTK_BOX(audio), new_tt->gui.audio_box, TRUE, TRUE, 0);
1627 if (fn) new_tt->load_file(fn);
1630 extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt);
1631 extern void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt);
1633 //#define debug_fx_stack(); for (i=fx_list.begin(); i != fx_list.end(); i++) puts((*i)->get_info_string());
1634 #define debug_fx_stack();
1636 void vtt_class :: effect_up(vtt_fx *effect)
1638 list <vtt_fx *> :: iterator i;
1639 list <vtt_fx *> :: iterator previous;
1644 if ((*fx_list.begin())==effect) return;
1646 for (previous=i=fx_list.begin(); i != fx_list.end(); i++) {
1647 if ((*i) == effect) {
1655 pthread_mutex_lock(&render_lock);
1656 fx_list.remove(effect);
1657 fx_list.insert(previous, effect);
1658 pthread_mutex_unlock(&render_lock);
1660 vg_move_fx_panel_up(effect->get_panel_widget(), this);
1666 void vtt_class :: effect_down(vtt_fx *effect)
1668 list <vtt_fx *> :: iterator i;
1673 for (i=fx_list.begin(); i != fx_list.end(); i++) {
1674 if ((*i) == effect) {
1680 if ((ok) && (i!=fx_list.end())) {
1682 if (i==fx_list.end()) return;
1685 pthread_mutex_lock(&render_lock);
1686 fx_list.remove(effect);
1688 fx_list.insert(i, effect);
1689 vg_move_fx_panel_down(effect->get_panel_widget(), this);
1690 pthread_mutex_unlock(&render_lock);
1696 void vtt_class :: effect_remove(vtt_fx_ladspa *effect)
1698 pthread_mutex_lock(&render_lock);
1699 fx_list.remove(effect);
1700 pthread_mutex_unlock(&render_lock);
1705 extern void gui_hide_control_panel(vtt_class *vtt, bool hide);
1706 extern void gui_hide_audio_panel(vtt_class *vtt, bool hide);
1708 void vtt_class :: hide_audio(bool hide) {
1710 gui_hide_audio_panel(this, hide);
1713 void vtt_class :: hide_control(bool hide) {
1714 control_hidden=hide;
1715 gui_hide_control_panel(this, hide);
1718 void vtt_class :: set_sample_rate(int samplerate) {
1719 list <vtt_class *> :: iterator vtt;
1720 double sr=(double) samplerate;
1722 last_sample_rate=samplerate;
1724 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1725 if ((*vtt)->audiofile) {
1726 double file_rate=(*vtt)->audiofile->get_sample_rate();
1727 (*vtt)->audiofile_pitch_correction=file_rate/sr;
1729 (*vtt)->audiofile_pitch_correction=1.0;
1731 (*vtt)->recalc_pitch();
1734 int no_samples=(int) (sr*0.001); // Forcing 1 ms blocksize
1736 set_mix_buffer_size(no_samples);
1739 void vtt_class :: adjust_to_master_pitch(int master_cycles, int cycles, bool create_event) {
1740 if (!sync_master) return;
1741 if (this==sync_master) return;
1742 if (!sync_master->audiofile) return;
1743 if (!audiofile) return;
1745 double master_time=((double) master_cycles)/sync_master->rel_pitch*sync_master->audiofile->get_no_samples()/((double) sync_master->audiofile->get_sample_rate());
1746 double my_rel_pitch=((audiofile->get_no_samples()/((double) audiofile->get_sample_rate()))*((double) cycles))/master_time;
1749 sp_pitch.do_exec(my_rel_pitch);
1750 sp_pitch.record_value(my_rel_pitch);
1752 sp_pitch.do_exec(my_rel_pitch);
1755 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());
1757 sp_pitch.update_graphics();