2 terminatorX - realtime audio scratching software
3 Copyright (C) 1999-2004 Alexander König
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 Description: This implements the new virtual turntable class. It replaces
22 the old turntable.c from terminatorX 3.2 and earlier. The lowpass
23 filter is based on some sample code by Paul Kellett
24 <paul.kellett@maxim.abel.co.uk>
26 08 Dec 1999 - Switched to the new audiofile class
30 #include "tX_global.h"
34 #include "tX_mastergui.h"
35 #include "tX_sequencer.h"
42 #include "tX_loaddlg.h"
44 #define USE_PREFETCH 1
47 #define my_prefetch(base, index); __asm__ __volatile__ ("prefetch index(%0)\n" : : "r" (base));
48 #define my_prefetchw(base, index); __asm__ __volatile__ ("prefetchw index(%0)\n" : : "r" (base));
50 #define my_prefetch(base, index); /* NOP */;
51 #define my_prefetchw(base, index); /* NOP */;
54 extern void build_vtt_gui(vtt_class *);
55 extern void gui_set_name(vtt_class *vtt, char *newname);
56 extern void gui_set_filename(vtt_class *vtt, char *newname);
57 extern void delete_gui(vtt_class *vtt);
58 extern void gui_update_display(vtt_class *vtt);
59 extern void gui_clear_master_button(vtt_class *vtt);
60 extern void cleanup_vtt(vtt_class *vtt);
61 extern int vg_get_current_page(vtt_class *vtt);
62 extern f_prec gui_get_audio_x_zoom(vtt_class *vtt);
63 extern void gui_set_audio_x_zoom(vtt_class *vtt, f_prec);
65 int vtt_class::last_sample_rate=44100;
66 int vtt_class::vtt_amount=0;
67 list <vtt_class *> vtt_class::main_list;
68 list <vtt_class *> vtt_class::render_list;
69 int16_t* vtt_class::mix_out_buffer=NULL;
70 f_prec * vtt_class::mix_buffer=NULL;
71 f_prec * vtt_class::mix_buffer_end=NULL;
72 int vtt_class::solo_ctr=0;
74 int vtt_class::samples_in_mix_buffer=0;
75 pthread_mutex_t vtt_class::render_lock=PTHREAD_MUTEX_INITIALIZER;
76 f_prec vtt_class::master_volume=1.0;
77 f_prec vtt_class::res_master_volume=1.0;
79 vtt_class * vtt_class::sync_master=NULL;
80 int vtt_class::master_triggered=0;
81 int vtt_class::master_triggered_at=0;
82 vtt_class * vtt_class::focused_vtt=NULL;
83 f_prec vtt_class::mix_max_l=0;
84 f_prec vtt_class::mix_max_r=0;
85 f_prec vtt_class::vol_channel_adjust=1.0;
86 int vtt_class::mix_buffer_size=0;
88 #define GAIN_AUTO_ADJUST 0.8
90 vtt_class :: vtt_class (int do_create_gui)
93 cleanup_required=false;
95 sprintf (name, "Turntable %i", vtt_amount);
96 strcpy(filename, "NONE");
105 audiofile_pitch_correction=1.0;
107 ec_output_buffer=NULL;
127 lp_setup(lp_gain, lp_reso, lp_freq);
138 main_list.push_back(this);
140 /* "connecting" the seq-parameters */
142 sp_speed.set_vtt((void *) this);
143 sp_volume.set_vtt((void *) this);
144 sp_pitch.set_vtt((void *) this);
145 sp_pan.set_vtt((void *) this);
146 sp_trigger.set_vtt((void *) this);
147 sp_loop.set_vtt((void *) this);
148 sp_sync_client.set_vtt((void *) this);
149 sp_sync_cycles.set_vtt((void *) this);
150 sp_lp_enable.set_vtt((void *) this);
151 sp_lp_gain.set_vtt((void *) this);
152 sp_lp_reso.set_vtt((void *) this);
153 sp_lp_freq.set_vtt((void *) this);
154 sp_ec_enable.set_vtt((void *) this);
155 sp_ec_length.set_vtt((void *) this);
156 sp_ec_pan.set_vtt((void *) this);
157 sp_ec_volume.set_vtt((void *) this);
158 sp_ec_feedback.set_vtt((void *) this);
159 sp_mute.set_vtt((void *) this);
160 sp_spin.set_vtt((void *) this);
165 lp_fx=new vtt_fx_lp();
166 lp_fx->set_vtt((void *) this);
167 fx_list.push_back(lp_fx);
169 ec_fx=new vtt_fx_ec();
170 ec_fx->set_vtt((void *) this);
171 fx_list.push_back(ec_fx);
176 lp_fx->set_panel_widget(gui.lp_panel->get_widget());
177 ec_fx->set_panel_widget(gui.ec_panel->get_widget());
182 set_master_volume(globals.volume);
183 set_output_buffer_size(samples_in_mix_buffer/2);
186 audiofile_pitch_correction=1.0;
194 control_hidden=false;
201 vtt_class :: ~vtt_class()
204 vtt_fx_stereo_ladspa *stereo_effect;
207 main_list.remove(this);
208 if (audiofile) delete audiofile;
209 if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt Destructor");
210 if (output_buffer2) tX_freemem(output_buffer2, "output_buffer2", "vtt Destructor");
214 if (mix_solo) solo_ctr--;
216 while (fx_list.size()) {
217 effect=(*fx_list.begin());
218 fx_list.remove(effect);
222 while (stereo_fx_list.size()) {
223 stereo_effect=(*stereo_fx_list.begin());
224 stereo_fx_list.remove(stereo_effect);
225 delete stereo_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();
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 *));
288 if (output_buffer2) tX_freemem(output_buffer2, "output_buffer2", "vtt set_output_buffer2_size()");
289 tX_malloc(output_buffer2, "output_buffer2", "vtt set_output_buffer2_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++) {
297 (*effect)->reconnect_buffer();
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;
315 res_volume_left=(1.0-pan)*res_volume;
316 res_volume_right=res_volume;
317 } else if (pan<0.0) {
318 res_volume_left=res_volume;
319 res_volume_right=(1.0+pan)*res_volume;
321 res_volume_left=res_volume_right=res_volume;
325 ec_volume_left=(1.0-ec_pan)*ec_res_volume;
326 ec_volume_right=ec_res_volume;
327 } else if (ec_pan<0.0) {
328 ec_volume_left=ec_res_volume;
329 ec_volume_right=(1.0+ec_pan)*ec_res_volume;
331 ec_volume_left=ec_volume_right=ec_res_volume;
335 void vtt_class :: set_pan(f_prec newpan)
341 void vtt_class :: set_pitch(f_prec newpitch)
347 void vtt_class :: recalc_pitch()
349 res_pitch=globals.pitch*rel_pitch;
350 res_pitch*=audiofile_pitch_correction;
352 ec_set_length(ec_length);
355 void vtt_class :: set_autotrigger(int newstate)
357 autotrigger=newstate;
360 void vtt_class :: set_loop(int newstate)
365 void vtt_class :: set_mute(int newstate)
371 void vtt_class :: set_mix_mute(int newstate)
377 void vtt_class :: set_mix_solo(int newstate)
379 if (mix_solo && !newstate) {
383 } else if (!mix_solo && newstate) {
391 list <vtt_class *> :: iterator vtt;
393 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++)
399 void vtt_class :: lp_set_enable (int newstate)
405 void vtt_class :: lp_reset()
410 void vtt_class :: lp_set_gain (f_prec gain)
413 lp_resgain=lp_gain*lp_autogain;
416 void vtt_class :: lp_set_reso(f_prec reso)
420 lp_b=reso*(1.0+(1.0/lp_a));
421 lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
422 lp_resgain=lp_gain*lp_autogain;
425 void vtt_class :: lp_set_freq(f_prec freq)
430 lp_b=lp_reso*(1.0+(1.0/lp_a));
433 void vtt_class :: lp_setup(f_prec gain, f_prec reso, f_prec freq)
439 lp_b=reso*(1.0+(1.0/lp_a));
441 lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
442 lp_resgain=lp_gain*lp_autogain;
445 void vtt_class :: ec_set_enable(int newstate)
452 void vtt_class :: ec_set_pan(f_prec pan)
459 /* Max length is 1.0 */
461 void vtt_class :: ec_set_length(f_prec length)
467 ec_res_length=length*samples_in_buffer;
469 ec_res_length=length*samples_in_buffer/res_pitch;
472 if (ec_res_length<0) ec_res_length*=-1;
474 if (ec_res_length>=EC_MAX_BUFFER) {
475 ec_res_length=EC_MAX_BUFFER*length;
478 delay=(int )floor(ec_res_length);
480 ec_delay=&ec_buffer[delay];
483 void vtt_class :: ec_set_feedback(f_prec feedback)
485 ec_feedback=feedback;
489 void vtt_class :: ec_set_volume(f_prec volume)
495 void vtt_class :: ec_clear_buffer()
497 memset(ec_buffer, 0, sizeof(ec_buffer));
501 #ifdef BIG_ENDIAN_MACHINE
502 #define fastabs(x) fabs(x)
504 // found this on musicdsp.org
505 // posted by <tobybear@web.de>
506 // proabably wont work on bigendian so we
507 // use fabs() instead.
508 inline float fastabs(float f)
510 int i=((*(int*)&f)&0x7fffffff);
511 return (*(float*)&i);
515 void vtt_class :: render()
517 list <vtt_fx *> :: iterator effect;
520 if (sense_cycles>0) {
522 if (sense_cycles==0) sp_speed.receive_input_value(0);
527 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
528 if ((*effect)->isEnabled()) (*effect)->run();
531 if (stereo_fx_list.size()>0) {
533 memcpy((void *) output_buffer2, (void *) output_buffer, sizeof(float)*((int)samples_in_outputbuffer));
535 // apply stereo effects.
536 list <vtt_fx_stereo_ladspa *> :: iterator stereo_effect;
538 for (stereo_effect=stereo_fx_list.begin(); stereo_effect != stereo_fx_list.end(); stereo_effect++) {
539 if ((*stereo_effect)->isEnabled()) (*stereo_effect)->run();
542 for (int sample=0; sample<samples_in_outputbuffer; sample++) {
543 output_buffer[sample]*=res_volume_left;
544 output_buffer2[sample]*=res_volume_right;
547 for (int sample=0; sample<samples_in_outputbuffer; sample++) {
548 output_buffer2[sample]=output_buffer[sample]*res_volume_right;
549 output_buffer[sample]*=res_volume_left;
554 for (int sample=0; sample<samples_in_outputbuffer; sample++) {
555 f_prec temp=ec_output_buffer[sample];
556 output_buffer[sample]+=temp*ec_volume_left;
557 output_buffer2[sample]+=temp*ec_volume_right;
561 // find max signal for vu meters...
562 for (int sample=0; sample<samples_in_outputbuffer; sample++) {
563 f_prec lmax=fastabs(output_buffer[sample]);
564 f_prec rmax=fastabs(output_buffer2[sample]);
566 if (lmax>max_value) max_value=lmax;
567 if (rmax>max_value2) max_value2=rmax;
571 extern void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plugin);
573 vtt_fx_ladspa * vtt_class :: add_effect (LADSPA_Plugin *plugin)
575 vtt_fx_ladspa *new_effect;
577 new_effect = new vtt_fx_ladspa (plugin, this);
578 pthread_mutex_lock(&render_lock);
579 fx_list.push_back(new_effect);
580 if (is_playing) new_effect->activate();
581 pthread_mutex_unlock(&render_lock);
582 vg_create_fx_gui(this, new_effect, plugin);
587 vtt_fx_stereo_ladspa * vtt_class :: add_stereo_effect (LADSPA_Stereo_Plugin *plugin)
589 vtt_fx_stereo_ladspa *new_effect;
591 new_effect = new vtt_fx_stereo_ladspa(plugin, this);
592 pthread_mutex_lock(&render_lock);
593 stereo_fx_list.push_back(new_effect);
594 if (is_playing) new_effect->activate();
595 pthread_mutex_unlock(&render_lock);
596 vg_create_fx_gui(this, new_effect, plugin);
601 void vtt_class :: calc_speed()
607 if (speed != speed_target) {
609 speed_step=speed_target-speed_real;
610 speed_step/=globals.vtt_inertia;
613 if (speed_target != speed_real) {
614 speed_real+=speed_step;
615 if ((speed_step<0) && (speed_real<speed_target)) speed_real=speed_target;
616 else if ((speed_step>0) && (speed_real>speed_target)) speed_real=speed_target;
620 if ((speed_last==0) && (speed_real !=0)) {
625 if ((speed_last!=0) && (speed_real==0)) {
631 speed_last = speed_real;
633 if (res_mute != res_mute_old) {
635 fade_out=1; fade_in=0;
638 fade_in=1; fade_out=0;
641 res_mute_old=res_mute;
643 if (res_mute) do_mute=1;
647 void vtt_class :: render_scratch()
668 for (sample =0,out=output_buffer, fade_vol=0.0; sample < samples_in_outputbuffer;sample++, out++, fade_vol+=inv_samples_in_outputbuffer) {
669 if ((speed_real!=0) || (fade_out)) {
680 master_triggered_at=sample;
686 } else if (pos_f<0) {
693 master_triggered_at=sample;
701 pos_a_f=floor(pos_f);
702 pos_i=(unsigned int) pos_a_f;
704 amount_b=pos_f-pos_a_f;
705 amount_a=1.0-amount_b;
711 sample_a=(f_prec) *ptr;
713 if (pos_i == pos_i_max) {
717 sample_b=(f_prec) *ptr;
720 sample_res=(sample_a*amount_a)+(sample_b*amount_b);
722 // scale to 0 db := 1.0f
723 sample_res/=FL_SHRT_MAX;
726 sample_res*=fade_vol;
727 } else if (fade_out) {
728 sample_res*=1.0-fade_vol;
739 void vtt_class :: forward_turntable()
750 if ((speed_real==0) && (!fade_out)) return;
752 /* following code is problematic as adding speed_real*n is
753 different from adding speed_real n times to pos_f.
755 well it speeds things up quite a bit and double precision
756 seems to do a satisfying job.
758 #define pos_f_test to prove that.
761 pos_f_tmp=pos_f+speed_real*samples_in_outputbuffer;
763 if ((pos_f_tmp > 0) && (pos_f_tmp < maxpos)) {
772 /* now the slow way ;) */
774 for (sample =0; sample < samples_in_outputbuffer; sample++) {
781 if (is_sync_master) {
783 master_triggered_at=sample;
789 } else if (pos_f<0) {
793 if (is_sync_master) {
795 master_triggered_at=sample;
805 diff=pos_f_tmp-pos_f;
806 if (diff!=0) printf("fast: %f, slow: %f, diff: %f, tt: %s\n", pos_f_tmp, pos_f, diff, name);
812 The following lowpass filter is based on some sample code by
813 Paul Kellett <paul.kellett@maxim.abel.co.uk>
816 void vtt_class :: render_lp()
820 for (sample = output_buffer; sample<end_of_outputbuffer; sample++) {
821 lp_buf0 = lp_a * lp_buf0 + lp_freq * ((*sample)*lp_resgain + lp_b * (lp_buf0 - lp_buf1));
822 lp_buf1 = lp_a * lp_buf1 + lp_freq * lp_buf0;
828 void vtt_class :: render_ec()
834 for (i=0, sample = output_buffer, ec_sample=ec_output_buffer; i<samples_in_outputbuffer; i++, ec_sample++,sample++, ec_ptr++) {
835 if (ec_ptr>ec_delay) ec_ptr=ec_buffer;
836 *ec_sample=(*ec_ptr) *ec_feedback;
837 *ec_ptr=*sample+*ec_sample;
841 int vtt_class :: set_mix_buffer_size(int no_samples)
843 list <vtt_class *> :: iterator vtt;
846 if (mix_buffer) tX_freemem(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()");
847 samples_in_mix_buffer=no_samples*2;
849 tX_malloc(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()", sizeof(float)*samples_in_mix_buffer, (float *));
850 mix_buffer_end=mix_buffer+samples_in_mix_buffer;
852 if (mix_out_buffer) tX_freemem(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()");
853 tX_malloc(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()", sizeof(int16_t)*samples_in_mix_buffer + 4, (int16_t *));
855 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
856 res|=(*vtt)->set_output_buffer_size(no_samples);
859 if ((!mix_buffer) || (!mix_out_buffer) || res) return 1;
861 mix_buffer_size=no_samples;
866 int16_t * vtt_class :: render_all_turntables()
868 list <vtt_class *> :: iterator vtt, next;
872 pthread_mutex_lock(&render_lock);
874 if (render_list.size()==0) {
875 memset((void *) mix_out_buffer, 0, sizeof(int16_t)*samples_in_mix_buffer);
876 /* We need to memset mix_buffer, too, as the JACK backend
877 acesses this directly.
879 memset((void *) mix_buffer, 0, sizeof(float)*samples_in_mix_buffer);
881 vtt=render_list.begin();
884 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
885 mix_buffer[mix_sample++]=(*vtt)->output_buffer[sample]*FL_SHRT_MAX;
886 mix_buffer[mix_sample++]=(*vtt)->output_buffer2[sample]*FL_SHRT_MAX;
889 if (master_triggered) {
890 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
891 if ((*vtt)->is_sync_client) {
892 if ((*vtt)->sync_countdown) {
893 (*vtt)->sync_countdown--;
895 (*vtt)->sync_countdown=(*vtt)->sync_cycles;
896 (*vtt)->trigger(false);
902 vtt=render_list.begin();
904 for (vtt++; vtt!=render_list.end(); vtt++) {
907 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++) {
908 mix_buffer[mix_sample++]+=(*vtt)->output_buffer[sample]*FL_SHRT_MAX;
909 mix_buffer[mix_sample++]+=(*vtt)->output_buffer2[sample]*FL_SHRT_MAX;
915 for (sample=0; sample<samples_in_mix_buffer; sample++) {
916 f_prec temp=mix_buffer[sample];
918 if(temp < FL_SHRT_MIN) {
919 temp = mix_buffer[sample] = FL_SHRT_MIN;
920 } else if (temp > FL_SHRT_MAX) {
921 temp = mix_buffer[sample] = FL_SHRT_MAX;
924 mix_out_buffer[sample]=(int16_t) temp;
928 if (temp>mix_max_r) mix_max_r=temp;
930 if (temp>mix_max_l) mix_max_l=temp;
937 vtt=render_list.begin();
938 while (vtt!=render_list.end()) {
942 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
945 pthread_mutex_unlock(&render_lock);
947 return(mix_out_buffer);
950 void vtt_class :: forward_all_turntables()
952 list <vtt_class *> :: iterator vtt, next;
954 if (render_list.size()>0) {
955 vtt=render_list.begin();
956 (*vtt)->forward_turntable();
958 if (master_triggered) {
959 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
960 if ((*vtt)->is_sync_client){
961 if ((*vtt)->sync_countdown) {
962 (*vtt)->sync_countdown--;
964 (*vtt)->sync_countdown=(*vtt)->sync_cycles;
971 vtt=render_list.begin();
972 for (vtt++; vtt!=render_list.end(); vtt++) {
973 (*vtt)->forward_turntable();
978 vtt=render_list.begin();
979 while (vtt!=render_list.end()) {
983 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
988 void vtt_class :: retrigger()
990 if (res_pitch>=0) pos_f=0;
995 speed_real=res_pitch;
996 speed_target=res_pitch;
1002 if (is_sync_master) {
1004 master_triggered_at=0;
1008 int vtt_class :: trigger(bool need_lock)
1010 if (!buffer) return 1;
1015 if (need_lock) pthread_mutex_lock(&render_lock);
1017 cleanup_required=false;
1019 /* activating plugins */
1020 for (list <vtt_fx *> :: iterator effect=fx_list.begin(); effect != fx_list.end(); effect++) {
1021 (*effect)->activate();
1024 for (list <vtt_fx_stereo_ladspa *> :: iterator effect=stereo_fx_list.begin(); effect != stereo_fx_list.end(); effect++) {
1025 (*effect)->activate();
1028 if (is_sync_master) {
1029 render_list.push_front(this);
1031 render_list.push_back(this);
1034 if (need_lock) pthread_mutex_unlock(&render_lock);
1040 /* call this only when owning render_lock. */
1041 int vtt_class :: stop_nolock()
1043 list <vtt_fx *> :: iterator effect;
1049 render_list.remove(this);
1055 cleanup_required=true;
1057 /* deactivating plugins */
1058 for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
1059 (*effect)->deactivate();
1065 int vtt_class :: stop()
1069 pthread_mutex_lock(&render_lock);
1071 pthread_mutex_unlock(&render_lock);
1076 void vtt_class :: set_sync_master(int master)
1079 if (sync_master) sync_master->set_sync_master(0);
1083 if (sync_master==this) sync_master=0;
1085 gui_clear_master_button(this);
1089 void vtt_class :: set_sync_client(int slave, int cycles)
1091 tX_debug("vtt_class::set_sync_client() setting %i, %i.", slave, cycles);
1092 is_sync_client=slave;
1094 // sync_countdown=cycles;
1098 void vtt_class :: set_sync_client_ug(int slave, int cycles)
1100 set_sync_client(slave, cycles);
1103 void vtt_class :: set_master_volume(f_prec new_volume)
1105 list <vtt_class *> :: iterator vtt;
1107 master_volume=new_volume;
1108 globals.volume=new_volume;
1110 if (main_list.size()>0) {
1111 vol_channel_adjust=sqrt((f_prec) main_list.size());
1112 res_master_volume=master_volume/vol_channel_adjust;
1115 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1116 (*vtt)->recalc_volume();
1120 void vtt_class :: set_master_pitch(f_prec new_pitch)
1122 list <vtt_class *> :: iterator vtt;
1124 globals.pitch=new_pitch;
1125 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1126 (*vtt)->recalc_pitch();
1130 void vtt_class :: focus_no(int no)
1132 list <vtt_class *> :: iterator vtt;
1137 for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++) {
1144 void vtt_class :: focus_next()
1146 list <vtt_class *> :: iterator vtt;
1149 if (main_list.size()) {
1150 focused_vtt=(*main_list.begin());
1155 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1156 if ((*vtt)==focused_vtt) {
1157 /* Ok, we found ourselves.. */
1160 while ((vtt!=main_list.end()) && ((*vtt)->audio_hidden) ) {
1164 if (vtt==main_list.end()) {
1165 /* No other "focusable" after this vtt so we're looking for the next */
1167 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1168 if (! (*vtt)->audio_hidden) {
1173 /* When we get here there's no "focusable" vtt at all... damn */
1183 focused_vtt=(*main_list.begin());
1186 void vtt_class :: set_scratch(int newstate)
1189 sp_spin.receive_input_value(0);
1191 sense_cycles=globals.sense_cycles;
1193 sp_spin.receive_input_value(1);
1199 void vtt_class :: unfocus()
1204 void vtt_class :: set_x_input_parameter(tX_seqpar *sp)
1209 void vtt_class :: set_y_input_parameter(tX_seqpar *sp)
1214 void vtt_class :: xy_input(f_prec x_value, f_prec y_value)
1216 if (x_par) x_par->handle_mouse_input(x_value*globals.mouse_speed);
1217 if (y_par) y_par->handle_mouse_input(y_value*globals.mouse_speed);
1220 #define store(data); if (fwrite((void *) &data, sizeof(data), 1, output)!=1) res+=1;
1222 int vtt_class :: save(FILE *rc, gzFile rz, char *indent) {
1223 char tmp_xml_buffer[4096];
1227 tX_store("%s<turntable>\n", indent);
1228 strcat(indent, "\t");
1230 store_string("name", name);
1232 store_string("audiofile", filename);
1234 store_string("audiofile", "");
1236 store_bool("sync_master", is_sync_master);
1237 store_bool("autotrigger", autotrigger);
1238 store_bool_sp("loop", loop, sp_loop);
1240 store_bool_sp("sync_client", is_sync_client, sp_sync_client);
1241 store_int_sp("sync_cycles", sync_cycles, sp_sync_cycles);
1243 store_float_sp("volume", rel_volume, sp_volume);
1244 store_float_sp("pitch", rel_pitch, sp_pitch);
1245 store_bool_sp("mute", mute, sp_mute);
1246 store_float_sp("pan", pan, sp_pan);
1248 store_bool_sp("lowpass_enable", lp_enable, sp_lp_enable);
1249 store_float_sp("lowpass_gain", lp_gain, sp_lp_gain);
1250 store_float_sp("lowpass_reso", lp_reso, sp_lp_reso);
1251 store_float_sp("lowpass_freq", lp_freq, sp_lp_freq);
1253 store_bool_sp("echo_enable", ec_enable, sp_ec_enable);
1254 store_float_sp("echo_length", ec_length, sp_ec_length);
1255 store_float_sp("echo_feedback", ec_feedback, sp_ec_feedback);
1256 store_float_sp("echo_pan", ec_pan, sp_ec_pan);
1257 store_float_sp("echo_volume", ec_volume, sp_ec_volume);
1259 store_id("speed", sp_speed.get_persistence_id());
1260 store_id("trigger", sp_trigger.get_persistence_id());
1261 store_id("spin", sp_spin.get_persistence_id());
1264 store_int("x_axis_mapping", x_par->get_persistence_id());
1268 store_int("y_axis_mapping", y_par->get_persistence_id());
1271 store_bool("audio_panel_hidden", audio_hidden);
1272 store_bool("control_panel_hidden", control_hidden);
1273 store_bool("main_panel_hidden", gui.main_panel->is_hidden());
1274 store_bool("trigger_panel_hidden", gui.trigger_panel->is_hidden());
1275 store_bool("lowpass_panel_hidden", gui.lp_panel->is_hidden());
1276 store_bool("echo_panel_hidden", gui.ec_panel->is_hidden());
1277 store_bool("mix_mute", mix_mute);
1278 store_bool("mix_solo", mix_solo);
1279 store_float("audio_x_zoom", gui_get_audio_x_zoom(this));
1281 tX_store("%s<fx>\n", indent);
1282 strcat(indent, "\t");
1284 for (list <vtt_fx *> :: iterator effect=fx_list.begin(); effect!=fx_list.end(); effect++) {
1285 (*effect)->save(rc, rz, indent);
1287 indent[strlen(indent)-1]=0;
1288 tX_store("%s</fx>\n", indent);
1290 tX_store("%s<stereo_fx>\n", indent);
1291 strcat(indent, "\t");
1293 for (list <vtt_fx_stereo_ladspa *> :: iterator effect=stereo_fx_list.begin(); effect!=stereo_fx_list.end(); effect++) {
1294 (*effect)->save(rc, rz, indent);
1296 indent[strlen(indent)-1]=0;
1297 tX_store("%s</stereo_fx>\n", indent);
1299 indent[strlen(indent)-1]=0;
1300 tX_store("%s</turntable>\n", indent);
1305 #define TX_XML_SETFILE_VERSION "1.0"
1307 int vtt_class :: save_all(FILE* rc, gzFile rz) {
1309 list <vtt_class *> :: iterator vtt;
1312 tX_seqpar :: create_persistence_ids();
1314 tX_store("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n");
1315 tX_store("<terminatorXset version=\"%s\">\n", TX_XML_SETFILE_VERSION);
1317 strcpy(indent, "\t");
1319 store_float_sp("master_volume", master_volume, sp_master_volume);
1320 store_float_sp("master_pitch", globals.pitch, sp_master_pitch);
1322 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1323 res+=(*vtt)->save(rc, rz, indent);
1326 sequencer.save(rc, rz, indent);
1328 tX_store("</terminatorXset>\n");
1333 int vtt_class :: load(xmlDocPtr doc, xmlNodePtr node) {
1343 char tmp_xml_buffer[4096];
1345 for (xmlNodePtr cur=node->xmlChildrenNode; cur != NULL; cur = cur->next) {
1346 if (cur->type == XML_ELEMENT_NODE) {
1349 restore_string_ac("name", buffer, set_name(buffer));
1350 restore_string("audiofile", filename);
1351 restore_bool("sync_master", is_sync_master);
1352 restore_bool("autotrigger", autotrigger);
1353 restore_bool_id("loop", loop, sp_loop, nop);
1354 restore_bool_id("sync_client", is_sync_client, sp_sync_client, set_sync_client(is_sync_client, sync_cycles));
1355 restore_int_id("sync_cycles", sync_cycles, sp_sync_cycles, set_sync_client(is_sync_client, sync_cycles));
1356 restore_float_id("volume", rel_volume, sp_volume, recalc_volume());
1357 restore_float_id("pitch", rel_pitch, sp_pitch, recalc_pitch());
1358 restore_bool_id("mute", mute, sp_mute, set_mute(mute));
1359 restore_float_id("pan", pan, sp_pan, set_pan(pan));
1361 restore_bool_id("lowpass_enable", lp_enable, sp_lp_enable, lp_set_enable(lp_enable));
1362 restore_float_id("lowpass_gain", lp_gain, sp_lp_gain, lp_set_gain(lp_gain));
1363 restore_float_id("lowpass_reso", lp_reso, sp_lp_reso, lp_set_reso(lp_reso));
1364 restore_float_id("lowpass_freq", lp_freq, sp_lp_freq, lp_set_freq(lp_freq));
1366 restore_bool_id("echo_enable", ec_enable, sp_ec_enable, ec_set_enable(ec_enable));
1367 restore_float_id("echo_length", ec_length, sp_ec_length, ec_set_length(ec_length));
1368 restore_float_id("echo_feedback", ec_feedback, sp_ec_feedback, ec_set_feedback(ec_feedback));
1369 restore_float_id("echo_pan", ec_pan, sp_ec_pan, ec_set_pan(ec_pan));
1370 restore_float_id("echo_volume", ec_volume, sp_ec_volume, ec_set_volume(ec_volume));
1372 restore_id("speed", sp_speed);
1373 restore_id("trigger", sp_trigger);
1374 restore_id("spin", sp_spin);
1376 restore_int("x_axis_mapping", xpar_id);
1377 restore_int("y_axis_mapping", ypar_id);
1379 restore_bool("mix_mute", mix_mute);
1380 restore_bool("mix_solo", mix_solo);
1382 restore_bool("audio_panel_hidden", audio_hidden);
1383 restore_bool("control_panel_hidden", control_hidden);
1384 restore_bool_ac("main_panel_hidden", hidden, gui.main_panel->hide(hidden));
1385 restore_bool_ac("trigger_panel_hidden", hidden, gui.trigger_panel->hide(hidden));
1386 restore_bool_ac("lowpass_panel_hidden", hidden, gui.lp_panel->hide(hidden));
1387 restore_bool_ac("echo_panel_hidden", hidden, gui.ec_panel->hide(hidden));
1388 restore_float_ac("audio_x_zoom", tmp, gui_set_audio_x_zoom(this,tmp));
1389 vg_adjust_zoom(gui.zoom, this);
1391 if ((xmlStrcmp(cur->name, (xmlChar *) "fx")==0) ||
1392 (xmlStrcmp(cur->name, (xmlChar *) "stereo_fx")==0)) {
1393 bool stereo=(xmlStrcmp(cur->name, (xmlChar *) "stereo_fx")==0);
1397 for (xmlNodePtr cur=fx->xmlChildrenNode; cur != NULL; cur = cur->next) {
1398 if (cur->type == XML_ELEMENT_NODE) {
1401 if ((xmlStrcmp(cur->name, (xmlChar *) "cutoff")==0) && !stereo) {
1402 for (unsigned int t=0; t<fx_list.size(); t++) effect_down(lp_fx);
1404 } else if ((xmlStrcmp(cur->name, (xmlChar *) "lowpass")==0) && !stereo) {
1405 for (unsigned int t=0; t<fx_list.size(); t++) effect_down(ec_fx);
1407 } else if (xmlStrcmp(cur->name, (xmlChar *) "ladspa_plugin")==0) {
1408 xmlNodePtr pluginNode=cur;
1412 for (xmlNodePtr cur=pluginNode->xmlChildrenNode; cur!=NULL; cur = cur->next) {
1414 if (cur->type == XML_ELEMENT_NODE) {
1417 restore_int("ladspa_id", ladspa_id);
1418 if (elementFound) break;
1422 if (ladspa_id!=-1) {
1423 LADSPA_Plugin *plugin=LADSPA_Plugin::getPluginByUniqueID(ladspa_id);
1424 if (!plugin) plugin=LADSPA_Stereo_Plugin::getPluginByUniqueID(ladspa_id);
1427 vtt_fx_ladspa *ladspa_effect=NULL;
1429 if (plugin->is_stereo()) {
1430 ladspa_effect=add_stereo_effect((LADSPA_Stereo_Plugin *) plugin);
1432 sprintf(buffer,"Trying to load mono plugin into stereo queue [%i].", ladspa_id);
1433 tx_note(buffer, true, GTK_WINDOW(gtk_widget_get_toplevel(ld_loaddlg)));
1436 ladspa_effect=add_effect(plugin);
1438 sprintf(buffer,"Trying to load stereo plugin into mono queue [%i].", ladspa_id);
1439 tx_note(buffer, true, GTK_WINDOW(gtk_widget_get_toplevel(ld_loaddlg)));
1443 ladspa_effect->load(doc, pluginNode);
1445 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);
1446 tx_note(buffer, true, GTK_WINDOW(gtk_widget_get_toplevel(ld_loaddlg)));
1449 tX_warning("ladspa_plugin section without a ladspa_id element.");
1453 tX_warning("unhandled element %s in fx section.", cur->name);
1460 tX_warning("unhandled element %s in turntable secion.", cur->name);
1472 set_x_input_parameter(tX_seqpar::get_sp_by_persistence_id(xpar_id));
1474 else set_x_input_parameter(NULL);
1477 set_y_input_parameter(tX_seqpar::get_sp_by_persistence_id(ypar_id));
1479 else set_y_input_parameter(NULL);
1481 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.mute), mix_mute);
1482 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gui.solo), mix_solo);
1487 void vtt_class :: delete_all()
1489 while (main_list.size()) {
1490 delete((*main_list.begin()));
1493 /* Take care of the master events.. */
1494 sequencer.delete_all_events(tX_sequencer::DELETE_ALL);
1496 /* Now reset master settings ot the default: */
1497 set_master_pitch(1.0);
1498 set_master_volume(1.0);
1500 sp_master_pitch.do_exec(1.0);
1501 sp_master_pitch.do_update_graphics();
1503 sp_master_volume.do_exec(1.0);
1504 sp_master_volume.do_update_graphics();
1506 /* Remove master MIDI mappings... */
1507 sp_master_pitch.bound_midi_event.type=tX_midievent::NONE;
1508 sp_master_volume.bound_midi_event.type=tX_midievent::NONE;
1513 int vtt_class :: load_all(xmlDocPtr doc, char *fname) {
1514 xmlNodePtr root=xmlDocGetRootElement(doc);
1522 tX_error("no root element? What kind of XML document is this?");
1526 if (xmlStrcmp(root->name, (const xmlChar *) "terminatorXset")) {
1527 tX_error("this is not a terminatorXset file.")
1531 if (xmlGetProp(root,(xmlChar *) "version")==NULL) {
1532 tX_error("the set file lacks a version attribute.");
1536 if (xmlStrcmp(xmlGetProp(root, (xmlChar *) "version"), (xmlChar *) TX_XML_SETFILE_VERSION)) {
1537 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);
1540 /* delete current tables... */
1545 /* counting turntables.. */
1546 for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1547 if (cur->type == XML_ELEMENT_NODE) {
1548 if (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0) {
1554 tX_debug("Found %i turntables in set.", table_ctr);
1556 ld_create_loaddlg(TX_LOADDLG_MODE_MULTI, table_ctr);
1557 ld_set_setname(fname);
1560 for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1561 if (cur->type == XML_ELEMENT_NODE) {
1564 restore_float_id("master_volume", master_volume, sp_master_volume, set_master_volume(master_volume));
1565 restore_float_id("master_pitch", globals.pitch, sp_master_pitch, set_master_pitch(globals.pitch));
1567 if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0)) {
1569 vtt_class *vtt=new vtt_class(1);
1570 vtt->load(doc, cur);
1572 if (strlen(vtt->filename)) {
1573 strcpy(fn_buff, vtt->filename);
1574 ld_set_filename(fn_buff);
1576 restmp=(int) vtt->load_file(fn_buff);
1580 gtk_box_pack_start(GTK_BOX(control_parent), vtt->gui.control_box, TRUE, TRUE, 0);
1581 gtk_box_pack_start(GTK_BOX(audio_parent), vtt->gui.audio_box, TRUE, TRUE, 0);
1582 if (vtt->audio_hidden) vtt->hide_audio(vtt->audio_hidden);
1583 if (vtt->control_hidden) vtt->hide_control(vtt->control_hidden);
1585 if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "sequencer")==0)) {
1587 sequencer.load(doc, cur);
1589 if (!elementFound) {
1590 tX_warning("unhandled element %s in setfile %s", cur->name, fname);
1595 sp_master_volume.do_update_graphics();
1596 sp_master_pitch.do_update_graphics();
1603 void add_vtt(GtkWidget *ctrl, GtkWidget *audio, char *fn)
1606 new_tt = new vtt_class(1);
1607 gtk_box_pack_start(GTK_BOX(ctrl), new_tt->gui.control_box, TRUE, TRUE, 0);
1608 gtk_box_pack_start(GTK_BOX(audio), new_tt->gui.audio_box, TRUE, TRUE, 0);
1609 if (fn) new_tt->load_file(fn);
1612 extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt, bool stereo);
1613 extern void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt, bool stereo);
1615 //#define debug_fx_stack(); for (i=list->begin(); i != list->end(); i++) puts((*i)->get_info_string());
1616 #define debug_fx_stack();
1618 void vtt_class :: effect_up(vtt_fx *effect)
1620 list <vtt_fx *> :: iterator i;
1621 list <vtt_fx *> :: iterator previous;
1622 list <vtt_fx *> *list;
1625 if (effect->is_stereo()) {
1626 list=(std::list <vtt_fx *> *) &stereo_fx_list;
1633 if ((*list->begin())==effect) return;
1635 for (previous=i=list->begin(); i != list->end(); i++) {
1636 if ((*i) == effect) {
1644 pthread_mutex_lock(&render_lock);
1645 list->remove(effect);
1646 list->insert(previous, effect);
1647 pthread_mutex_unlock(&render_lock);
1649 vg_move_fx_panel_up(effect->get_panel_widget(), this, effect->is_stereo());
1655 void vtt_class :: effect_down(vtt_fx *effect)
1657 list <vtt_fx *> :: iterator i;
1658 list <vtt_fx *> *list;
1661 if (effect->is_stereo()) {
1662 list=(std::list <vtt_fx *> *) &stereo_fx_list;
1669 for (i=list->begin(); i != list->end(); i++) {
1670 if ((*i) == effect) {
1676 if ((ok) && (i!=list->end())) {
1678 if (i==list->end()) return;
1681 pthread_mutex_lock(&render_lock);
1682 list->remove(effect);
1684 list->insert(i, effect);
1685 vg_move_fx_panel_down(effect->get_panel_widget(), this, effect->is_stereo());
1686 pthread_mutex_unlock(&render_lock);
1692 void vtt_class :: effect_remove(vtt_fx_ladspa *effect)
1694 pthread_mutex_lock(&render_lock);
1695 if (effect->is_stereo()) {
1696 stereo_fx_list.remove((vtt_fx_stereo_ladspa *) effect);
1698 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();