Mostly ALSA fixing - Alex
[terminatorX.git] / terminatorX / src / tX_vtt.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2003  Alexander K├Ânig
4  
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.
9  
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.
14  
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.
18  
19     File: tX_vtt.cc
20  
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>
25                  
26     08 Dec 1999 - Switched to the new audiofile class            
27 */    
28
29 #include "tX_vtt.h"
30 #include "tX_global.h"
31 #include <stdio.h>
32 #include "malloc.h"
33 #include <math.h>
34 #include "tX_mastergui.h"
35 #include "tX_sequencer.h"
36 #include <glib.h>
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #ifdef USE_3DNOW
43 #include "3dnow.h"
44 #endif
45
46 #ifdef DEBUG
47 #define tX_freemem(ptr, varname, comment); fprintf(stderr, "** free() [%s] at %08x. %s.\n", varname, ptr, comment); free(ptr);
48 #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);
49 #else
50 #define tX_freemem(ptr, varname, comment); free(ptr);
51 #define tX_malloc(ptr, varname, comment, size, type); ptr=type malloc(size);
52 #endif
53
54 #include "tX_loaddlg.h"
55
56 #define USE_PREFETCH 1
57
58 #ifdef USE_PREFETCH
59 #define my_prefetch(base, index); __asm__  __volatile__ ("prefetch index(%0)\n" : : "r" (base));
60 #define my_prefetchw(base, index); __asm__  __volatile__ ("prefetchw index(%0)\n" : : "r" (base));
61 #else
62 #define my_prefetch(base, index);  /* NOP */;
63 #define my_prefetchw(base, index); /* NOP */;
64 #endif
65
66 extern void build_vtt_gui(vtt_class *);
67 extern void gui_set_name(vtt_class *vtt, char *newname);
68 extern void gui_set_filename(vtt_class *vtt, char *newname);
69 extern void delete_gui(vtt_class *vtt);
70 extern void gui_update_display(vtt_class *vtt);
71 extern void gui_clear_master_button(vtt_class *vtt);
72 extern void cleanup_vtt(vtt_class *vtt);
73 extern int vg_get_current_page(vtt_class *vtt);
74 extern f_prec gui_get_audio_x_zoom(vtt_class *vtt);
75 extern void gui_set_audio_x_zoom(vtt_class *vtt, f_prec);
76
77 int vtt_class::last_sample_rate=44100;
78 int vtt_class::vtt_amount=0;
79 list <vtt_class *> vtt_class::main_list;
80 list <vtt_class *> vtt_class::render_list;
81 int16_t* vtt_class::mix_out_buffer=NULL;
82 f_prec * vtt_class::mix_buffer=NULL;
83 f_prec * vtt_class::mix_buffer_end=NULL;
84 int vtt_class::solo_ctr=0;
85
86 int vtt_class::samples_in_mix_buffer=0;
87 pthread_mutex_t vtt_class::render_lock=PTHREAD_MUTEX_INITIALIZER;
88 f_prec vtt_class::master_volume=1.0;
89 f_prec vtt_class::res_master_volume=1.0;
90 f_prec vtt_class::saturate_fac=0.1;
91 int vtt_class::do_saturate=0;
92 vtt_class * vtt_class::sync_master=NULL;
93 int vtt_class::master_triggered=0;
94 int vtt_class::master_triggered_at=0;
95 vtt_class * vtt_class::focused_vtt=NULL;
96 f_prec vtt_class::mix_max_l=0;
97 f_prec vtt_class::mix_max_r=0;
98 f_prec vtt_class::vol_channel_adjust=1.0;
99 int vtt_class::mix_buffer_size=0;
100
101 #define GAIN_AUTO_ADJUST 0.8
102
103 vtt_class :: vtt_class (int do_create_gui)
104 {       
105         vtt_amount++;
106         sprintf (name, "Turntable %i", vtt_amount);
107         strcpy(filename, "NONE");
108         buffer=NULL;
109         samples_in_buffer=0;
110         
111         set_volume(1);
112         set_pitch(1);
113         
114         autotrigger=1;
115         loop=1;
116         
117         is_playing=0;
118         is_sync_master=0;
119         is_sync_client=0;
120         sync_cycles=0,
121         sync_countdown=0;
122         
123         lp_enable=0;
124         lp_reso=0.8;
125         lp_freq=0.3;
126         lp_gain=1;
127         lp_setup(lp_gain, lp_reso, lp_freq);
128         lp_reset();
129         
130         ec_enable=0;
131         ec_length=0.5;
132         ec_feedback=0.3;
133         ec_clear_buffer();
134         ec_set_length(0.5);
135         ec_set_pan(0);
136         ec_set_volume(1);
137         
138         main_list.push_back(this);
139
140         /* "connecting" the seq-parameters */
141         
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);
161
162         x_par = &sp_speed;
163         y_par = &sp_lp_freq;
164         
165         lp_fx=new vtt_fx_lp();
166         lp_fx->set_vtt((void *) this);
167         fx_list.push_back(lp_fx);
168
169         ec_fx=new vtt_fx_ec();
170         ec_fx->set_vtt((void *) this);
171         fx_list.push_back(ec_fx);
172         
173         if (do_create_gui)
174         {       
175                 build_vtt_gui(this);
176                 lp_fx->set_panel_widget(gui.lp_panel->get_widget());    
177                 ec_fx->set_panel_widget(gui.ec_panel->get_widget());
178         }
179         else have_gui=0;
180                 
181         set_pan(0);     
182         set_master_volume(globals.volume);
183         set_output_buffer_size(samples_in_mix_buffer/2);
184         
185         audiofile = NULL;
186         audiofile_pitch_correction=0;
187         mix_solo=0;
188         mix_mute=0;
189         res_mute=mute;
190         res_mute_old=0;
191         
192         audio_hidden=false;
193         control_hidden=false;\r
194 }
195
196 vtt_class :: ~vtt_class()
197 {
198         vtt_fx *effect;
199         stop();
200
201         main_list.remove(this);
202         if (audiofile) delete audiofile;
203         //if (buffer) free(buffer);
204         if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt Destructor");
205         vtt_amount--;
206         
207         while (fx_list.size())
208         { 
209                 effect=(*fx_list.begin());
210                 fx_list.remove(effect);
211                 delete effect;
212         }
213         
214         delete_gui(this);
215 }
216
217 void vtt_class :: set_name(char *newname)
218 {
219         strcpy(name, newname);
220         gui_set_name(this, name);       
221 }
222
223 tX_audio_error vtt_class :: load_file(char *fname)
224 {
225         tX_audio_error res;
226         int was_playing=is_playing;
227         
228         if (is_playing) stop();
229
230         if (audiofile) delete(audiofile);
231         
232         buffer=NULL;
233         samples_in_buffer=0;
234         maxpos=0;
235         strcpy(filename,"");
236
237         audiofile=new tx_audiofile();
238         res=audiofile->load(fname);     
239         
240         if (res==TX_AUDIO_SUCCESS) {
241                 buffer=audiofile->get_buffer();
242                 double file_rate=audiofile->get_sample_rate();
243                 audiofile_pitch_correction=file_rate/44100.0;
244                 recalc_pitch();
245                 samples_in_buffer=audiofile->get_no_samples();
246                 maxpos=audiofile->get_no_samples();
247                 strcpy(filename, fname);
248                 if (was_playing) trigger();
249 //              printf("Successfully loaded %s, %08x, %i\n", fname, buffer, samples_in_buffer);
250         }
251         
252         if (have_gui)
253         {
254                 gui_update_display(this);
255         }
256         ec_set_length(ec_length);
257         
258         return(res);
259 }
260
261 int vtt_class :: set_output_buffer_size(int newsize)
262 {
263         list <vtt_fx *> :: iterator effect;
264
265         if (ec_output_buffer) tX_freemem(ec_output_buffer, "ec_output_buffer", "vtt set_output_buffer_size()");
266         tX_malloc(ec_output_buffer, "ec_output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
267
268         if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt set_output_buffer_size()");
269         tX_malloc(output_buffer, "output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
270
271         end_of_outputbuffer = output_buffer + newsize; //size_t(sizeof(float)*(newsize));
272         
273         samples_in_outputbuffer=newsize;
274         inv_samples_in_outputbuffer=1.0/samples_in_outputbuffer;
275
276         for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
277         {
278                 (*effect)->reconnect_buffer();
279         }
280         
281         if (output_buffer) return(0);   
282         else return(0);
283 }
284
285 void vtt_class :: set_volume(f_prec newvol)
286 {
287         rel_volume=newvol;
288         recalc_volume();
289 }
290
291 void vtt_class :: recalc_volume()
292 {
293         res_volume=rel_volume*res_master_volume;
294         f_prec ec_res_volume=res_volume*ec_volume;
295         
296         if (pan>0.0)
297         {
298                 res_volume_left=(1.0-pan)*res_volume;
299                 res_volume_right=res_volume;
300         }
301         else if (pan<0.0)
302         {
303                 res_volume_left=res_volume;
304                 res_volume_right=(1.0+pan)*res_volume;
305         }
306         else
307         {
308                 res_volume_left=res_volume_right=res_volume;
309         }
310         
311         if (ec_pan>0.0)
312         {
313                 ec_volume_left=(1.0-ec_pan)*ec_res_volume;
314                 ec_volume_right=ec_res_volume;
315         }
316         else if (ec_pan<0.0)
317         {
318                 ec_volume_left=ec_res_volume;
319                 ec_volume_right=(1.0+ec_pan)*ec_res_volume;
320         }
321         else
322         {
323                 ec_volume_left=ec_volume_right=ec_res_volume;
324         }       
325 //      printf("vtt_volume: %f, %f, l: %f, r: %f\n", rel_volume, res_volume, res_volume_left, res_volume_right);
326         
327 #ifdef USE_3DNOW
328         mm_res_volume.s[0]=mm_res_volume.s[1]=res_volume;
329 #endif  
330 }
331
332 void vtt_class :: set_pan(f_prec newpan)
333 {
334         pan=newpan;
335         recalc_volume();
336 }
337
338 void vtt_class :: set_pitch(f_prec newpitch)
339 {
340         rel_pitch=newpitch;
341         res_pitch=globals.pitch*rel_pitch;
342         speed=res_pitch;
343         ec_set_length(ec_length);
344 }
345
346 void vtt_class :: recalc_pitch()
347 {
348         res_pitch=globals.pitch*rel_pitch;
349         res_pitch*=audiofile_pitch_correction;
350         speed=res_pitch;
351         ec_set_length(ec_length);
352 }
353
354 void vtt_class :: set_autotrigger(int newstate)
355 {
356         autotrigger=newstate;
357 }
358
359 void vtt_class :: set_loop(int newstate)
360 {
361         loop=newstate;
362 }
363
364 void vtt_class :: set_mute(int newstate)
365 {
366         mute=newstate;
367         calc_mute();
368 }
369
370 void vtt_class :: set_mix_mute(int newstate)
371 {
372         mix_mute=newstate;
373         calc_mute();
374 }
375
376 void vtt_class :: set_mix_solo(int newstate)
377 {
378         if (mix_solo && !newstate)
379         {
380                 /* turning it off */
381                 mix_solo=0;
382                 solo_ctr--;
383         }
384         else if (!mix_solo && newstate)
385         {
386                 /* turning it on */
387                 mix_solo=1;
388                 solo_ctr++;
389         }
390         calc_mute();
391
392         /* locking ? */
393         list <vtt_class *> :: iterator vtt;
394         
395         for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++)
396         {
397                 (*vtt)->calc_mute();
398         }
399 }
400
401 void vtt_class :: lp_set_enable (int newstate)
402 {
403         lp_enable=newstate;
404         lp_reset();
405 }
406
407 void vtt_class :: lp_reset()
408 {
409         lp_buf0=lp_buf1=0;
410 }
411
412 void vtt_class :: lp_set_gain (f_prec gain)
413 {
414         lp_gain=gain;
415         lp_resgain=lp_gain*lp_autogain;
416 }
417
418 void vtt_class :: lp_set_reso(f_prec reso)
419 {
420         lp_reso=reso;
421         
422         lp_b=reso*(1.0+(1.0/lp_a));
423         lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
424         lp_resgain=lp_gain*lp_autogain;
425 }
426
427 void vtt_class :: lp_set_freq(f_prec freq)
428 {
429         lp_freq=freq;
430         
431         lp_a=0.9999-freq;
432         lp_b=lp_reso*(1.0+(1.0/lp_a));
433 }
434
435 void vtt_class :: lp_setup(f_prec gain, f_prec reso, f_prec freq)
436 {
437         lp_freq=freq;
438         lp_reso=reso;
439         
440         lp_a=1.0-freq;
441         lp_b=reso*(1.0+(1.0/lp_a));
442         
443         lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
444         lp_resgain=lp_gain*lp_autogain;
445 }
446
447 void vtt_class :: ec_set_enable(int newstate)
448 {
449         ec_enable=newstate;
450         ec_clear_buffer();
451 }
452
453
454 void vtt_class :: ec_set_pan(f_prec pan)
455 {
456         ec_pan=pan;
457
458         recalc_volume();
459 }
460
461 /* Max length is 1.0 */
462
463 void vtt_class :: ec_set_length(f_prec length)
464 {
465         int delay;
466
467         ec_length=length;
468         if (res_pitch==0) 
469         {
470                 ec_res_length=length*samples_in_buffer;
471         }
472         else
473         {
474                 ec_res_length=length*samples_in_buffer/res_pitch;       
475         }
476         
477         if (ec_res_length<0) ec_res_length*=-1;
478         
479         if (ec_res_length>=EC_MAX_BUFFER)
480         {
481                 ec_res_length=EC_MAX_BUFFER*length;
482         }
483         
484         delay=(int )floor(ec_res_length);
485         delay-=2;
486         ec_delay=&ec_buffer[delay];
487 }
488
489 void vtt_class :: ec_set_feedback(f_prec feedback)
490 {
491         ec_feedback=feedback;
492 }
493
494
495 void vtt_class :: ec_set_volume(f_prec volume)
496 {
497         ec_volume=volume;
498         recalc_volume();
499 }
500
501 void vtt_class :: ec_clear_buffer()
502 {
503         f_prec *ptr;
504         
505         for (ptr=ec_buffer; ptr<=ec_delay; ptr++)
506         {
507                 *ptr=0.0;
508         }
509         ec_ptr=ec_buffer;
510 }
511
512 void vtt_class :: render()
513 {
514         list <vtt_fx *> :: iterator effect;
515
516         if (do_scratch)
517         {
518                 if (sense_cycles>0)
519                 {
520                         sense_cycles--;
521                         if (sense_cycles==0) sp_speed.receive_input_value(0);
522                 }
523         }
524         render_scratch();
525         
526         for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
527         {
528                 if ((*effect)->isEnabled()) (*effect)->run();
529         }
530 }
531
532 extern void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plugin);
533
534 vtt_fx_ladspa * vtt_class :: add_effect (LADSPA_Plugin *plugin)
535 {
536         vtt_fx_ladspa *new_effect;
537         
538         new_effect = new vtt_fx_ladspa (plugin, this);
539         pthread_mutex_lock(&render_lock);
540         fx_list.push_back(new_effect);
541         if (is_playing) new_effect->activate();
542         pthread_mutex_unlock(&render_lock);
543         vg_create_fx_gui(this, new_effect, plugin);
544         
545         return new_effect;
546 }
547
548 void vtt_class :: calc_speed()
549 {
550         do_mute=0;
551         fade_out=0;
552         fade_in=0;
553
554         if (speed != speed_target)
555         {
556                 speed_target=speed;
557                 speed_step=speed_target-speed_real;
558                 speed_step/=10.0;
559         }
560                         
561         if (speed_target != speed_real)
562         {
563                 speed_real+=speed_step;
564                 if ((speed_step<0) && (speed_real<speed_target)) speed_real=speed_target;
565                 else
566                 if ((speed_step>0) && (speed_real>speed_target)) speed_real=speed_target;                       
567         }
568         
569         if (fade)
570         {
571                 if ((speed_last==0) && (speed_real !=0))
572                 {
573                         fade_in=1;
574                         fade=NEED_FADE_OUT;
575                 }
576         }
577         else
578         {
579                 if ((speed_last!=0) && (speed_real==0))
580                 {
581                         fade_out=1;
582                         fade=NEED_FADE_IN;
583                 }
584         }
585
586         speed_last = speed_real;
587
588         if (res_mute != res_mute_old)
589         {
590                 if (res_mute)
591                 {
592                         fade_out=1; fade_in=0;
593                         fade=NEED_FADE_IN;
594                 }
595                 else
596                 {
597                         fade_in=1; fade_out=0;
598                         fade=NEED_FADE_OUT;
599                 }
600                 res_mute_old=res_mute;
601         }
602         else
603         {
604                 if (res_mute) do_mute=1;
605         }       
606 }
607
608 void vtt_class :: render_scratch()
609 {
610         int16_t *ptr;
611         
612         int sample;
613         
614         f_prec pos_a_f;
615         
616         f_prec amount_a;
617         f_prec amount_b;
618
619         f_prec sample_a;
620         f_prec sample_b;
621         
622         f_prec sample_res;
623         
624         f_prec *out;
625         f_prec fade_vol;        
626
627         calc_speed();
628                                         
629         for (sample =0,out=output_buffer, fade_vol=0.0; sample < samples_in_outputbuffer;sample++, out++, fade_vol+=inv_samples_in_outputbuffer)
630         {
631                 if ((speed_real!=0) || (fade_out))
632                 {
633
634                         pos_f+=speed_real;
635
636                         if (pos_f>maxpos)
637                         {
638                                 pos_f-=maxpos;
639                                 if (res_pitch>0)
640                                 {
641                                         if (loop)
642                                         {
643                                         if (is_sync_master)
644                                         {
645                                                 master_triggered=1;
646                                                 master_triggered_at=sample;
647                                         }
648                                         }
649                                         else
650                                         {
651                                                 want_stop=1;
652                                         }
653                                         
654                                 }
655                         }
656                         else if (pos_f<0)
657                         {
658                                 pos_f+=maxpos;
659                                 if (res_pitch<0)
660                                 {
661                                         if (loop)
662                                         {
663                                         if (is_sync_master)
664                                         {
665                                                 master_triggered=1;
666                                                 master_triggered_at=sample;
667                                         }
668                                         }
669                                         else
670                                         {
671                                                 want_stop=1;
672                                         }
673                                 }
674                         }
675                                 
676                         pos_a_f=floor(pos_f);
677                         pos_i=(unsigned int) pos_a_f;
678                                                                 
679                         amount_b=pos_f-pos_a_f;                         
680                         amount_a=1.0-amount_b;                          
681                                 
682                         if (do_mute)
683                         {
684                                 *out=0.0;
685                         }
686                         else
687                         {
688                                 ptr=&buffer[pos_i];
689                                 sample_a=(f_prec) *ptr;
690                         
691                                 if (pos_i == samples_in_buffer) 
692                                 {
693                                         sample_b=*buffer;
694                                 }
695                                 else
696                                 {
697                                         ptr++;
698                                         sample_b=(f_prec) *ptr;
699                                 }
700                                 
701                                 sample_res=(sample_a*amount_a)+(sample_b*amount_b);
702                                                                 
703                                 if (fade_in)
704                                 {
705                                         sample_res*=fade_vol;
706                                 }
707                                 else
708                                 if (fade_out)
709                                 {
710                                         sample_res*=1.0-fade_vol;
711                                 }
712  
713                                 *out=sample_res;
714                         }
715                 }
716                 else
717                 {
718                                 *out=0;
719                 }
720         }
721 }       
722
723 void vtt_class :: forward_turntable()
724 {
725         int sample;
726         double pos_f_tmp;
727 #ifdef pos_f_test
728         int show=0;
729         double diff;
730 #endif
731
732         calc_speed();
733
734         if ((speed_real==0) && (!fade_out)) return;
735         
736         
737         /* following code is problematic as adding speed_real*n is
738           different from adding speed_real n times to pos_f.
739           
740           well it speeds things up quite a bit and double precision
741           seems to do a satisfying job.
742           
743           #define pos_f_test to prove that.
744         */
745         
746         pos_f_tmp=pos_f+speed_real*samples_in_outputbuffer;
747         
748         if ((pos_f_tmp > 0) && (pos_f_tmp < maxpos))
749         {
750 #ifdef pos_f_test
751                 show=1;
752 #else   
753                 pos_f=pos_f_tmp;
754                 return;
755 #endif          
756         }
757                                 
758         /* now the slow way ;) */
759         
760         for (sample =0; sample < samples_in_outputbuffer; sample++)
761         {
762                         pos_f+=speed_real;
763
764                         if (pos_f>maxpos)
765                         {
766                                 pos_f-=maxpos;
767                                 if (res_pitch>0)
768                                 {
769                                         if (loop)
770                                         {
771                                         if (is_sync_master)
772                                         {
773                                                 master_triggered=1;
774                                                 master_triggered_at=sample;
775                                         }
776                                         }
777                                         else
778                                         {
779                                                 want_stop=1;
780                                         }
781                                         
782                                 }
783                         }
784                         else if (pos_f<0)
785                         {
786                                 pos_f+=maxpos;
787                                 if (res_pitch<0)
788                                 {
789                                         if (loop)
790                                         {
791                                         if (is_sync_master)
792                                         {
793                                                 master_triggered=1;
794                                                 master_triggered_at=sample;
795                                         }
796                                         }
797                                         else
798                                         {
799                                                 want_stop=1;
800                                         }
801                                 }
802                         }
803                 
804         }
805 #ifdef pos_f_test
806         if (show)
807         {
808                 diff=pos_f_tmp-pos_f;
809                 if (diff!=0) printf("fast: %f, slow: %f, diff: %f, tt: %s\n", pos_f_tmp, pos_f, diff, name);
810         }
811 #endif  
812 }       
813
814 /*
815         The following lowpass filter is based on some sample code by
816         Paul Kellett <paul.kellett@maxim.abel.co.uk>
817 */
818
819 void vtt_class :: render_lp()
820 {
821         f_prec *sample;
822                 
823         for (sample = output_buffer; sample<end_of_outputbuffer; sample++)
824         {
825                 lp_buf0 = lp_a * lp_buf0 + lp_freq * ((*sample)*lp_resgain + lp_b * (lp_buf0 - lp_buf1));
826                 lp_buf1 = lp_a * lp_buf1 + lp_freq * lp_buf0;
827                 
828                 *sample=lp_buf1;
829         }
830 }
831
832 void vtt_class :: render_ec()
833 {
834         f_prec *sample;
835         f_prec *ec_sample;
836         int i;
837
838         for (i=0, sample = output_buffer, ec_sample=ec_output_buffer; i<samples_in_outputbuffer; i++, ec_sample++,sample++, ec_ptr++)
839         {
840                 if (ec_ptr>ec_delay) ec_ptr=ec_buffer;
841                 *ec_sample=(*ec_ptr) *ec_feedback;
842                 *ec_ptr=*sample+*ec_sample;
843         }       
844 }
845
846 int vtt_class :: set_mix_buffer_size(int no_samples)
847 {
848         list <vtt_class *> :: iterator vtt;
849         int res=0;
850         
851 //      printf("vtt_class::set_mix_buffer_size(), mix_buffer: %12x, mix_out: %12x, samples: %i\n", mix_buffer, mix_out_buffer, no_samples);
852         
853         if (mix_buffer) tX_freemem(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()");
854         samples_in_mix_buffer=no_samples*2;
855
856         tX_malloc(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()", sizeof(float)*samples_in_mix_buffer, (float *));
857         mix_buffer_end=mix_buffer+samples_in_mix_buffer;
858
859 //      printf("mix_buffer: %12x\n", mix_buffer);
860 //      printf("mix_samples: %i, out_samples: %i", samples_in_mix_buffer, no_samples);
861         
862         if (mix_out_buffer) tX_freemem(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()");
863         tX_malloc(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()", sizeof(int16_t)*samples_in_mix_buffer + 4, (int16_t *));
864
865 //      printf("mix_out_buffer: %12x\n", mix_out_buffer);
866         
867         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
868         {
869                 res|=(*vtt)->set_output_buffer_size(no_samples);
870         }
871         
872         if ((!mix_buffer) || (!mix_out_buffer) || res) return(1);
873         
874         mix_buffer_size=no_samples;
875         
876         return(0);
877 }
878
879 int16_t * vtt_class :: render_all_turntables()
880 {
881         list <vtt_class *> :: iterator vtt, next;
882         int sample;
883         int mix_sample;
884         f_prec temp;
885
886 #ifdef USE_3DNOW
887         mmx_t *mix;
888         mmx_t *vtt_buffer;
889         int32_t *mix_int;
890 #endif
891
892 #ifdef USE_FLASH
893         f_prec max;
894         f_prec min;
895 #ifdef USE_3DNOW
896         mmx_t mm_max;
897         mmx_t mm_min;
898         mmx_t mm_volume;
899         mmx_t mm_src1;
900         mmx_t mm_src2;
901
902 #ifndef OVERRIDE_MOVQ_AUTODETECT
903 #ifndef GCC_VERSION
904 #define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
905 #endif /* GCC_VERSION */
906
907 #if (GCC_VERSION < 2096)
908 #warning "*************************"
909 #warning "* gcc < 2.96            *"
910 #warning "* assuming working movq *"
911 #warning "*************************"
912 #undef GCC_MOVQ_BUG_WORKAROUND
913 #else
914 #warning "*************************"
915 #warning "* gcc >= 2.96           *"
916 #warning "* using movq-workaround *"
917 #warning "*************************"
918 #define GCC_MOVQ_BUG_WORKAROUND 1
919 #endif /* GCC < 2.96 */
920 #endif /* OVERRIDE MOVQ AUTODETECVT */
921         
922 #ifdef GCC_MOVQ_BUG_WORKAROUND
923         /* REQUIRED DUE TO GCC BUG (2.96-3.0.2) */
924         mmx_t *mm_src1_ptr=&mm_src1;
925         mmx_t *mm_src2_ptr=&mm_src2;
926         mmx_t *mm_volume_ptr=&mm_volume;
927         mmx_t *mm_max_ptr=&mm_max;
928         mmx_t *mm_min_ptr=&mm_min;
929         
930 #define MM_VAR_ACC(var) (* var ## _ptr)
931 #define MM_VAR_MOVQ(var) * var ## _ptr
932 #else
933 #define MM_VAR_ACC(var) var
934 #define MM_VAR_MOVQ(var) var
935 #endif  
936         int32_t *temp_int=&mm_max.d[1];
937 #endif  
938 #endif  
939         
940         pthread_mutex_lock(&render_lock);
941         
942         if (render_list.size()==0)
943         {
944                 for (sample=0; sample<samples_in_mix_buffer; sample++)
945                 {
946                         mix_out_buffer[sample]=0;
947                 }
948         }
949         else
950         {
951                         vtt=render_list.begin();
952                         (*vtt)->render();                       
953                         max=(*vtt)->max_value;
954                         min=max;
955
956 #ifndef USE_3DNOW
957                         for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
958                         {                               
959                                 temp=(*vtt)->output_buffer[sample];
960                                 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_left;
961                                 mix_sample++;
962                                 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_right;
963                                 mix_sample++;
964                                 
965                                 if (temp>max) max=temp;
966                                 else if (temp<min) min=temp;
967                         }
968 #else
969                         MM_VAR_ACC(mm_volume).s[0]=(*vtt)->res_volume_left;
970                         MM_VAR_ACC(mm_volume).s[1]=(*vtt)->res_volume_right;
971
972                         MM_VAR_ACC(mm_max).s[1]=MM_VAR_ACC(mm_max).s[0]=max;
973                         MM_VAR_ACC(mm_min).s[1]=MM_VAR_ACC(mm_min).s[0]=min;
974                         
975                         movq_m2r(MM_VAR_MOVQ(mm_max), mm1);
976                         movq_m2r(MM_VAR_MOVQ(mm_min), mm2);
977                                                         
978                         movq_m2r(MM_VAR_MOVQ(mm_volume), mm0);
979                         
980                         mix=(mmx_t*)mix_buffer;
981                         
982                         for (f_prec* src=(*vtt)->output_buffer; mix < (mmx_t*) mix_buffer_end;)
983                         {
984                                 /* first sample */
985                                 MM_VAR_ACC(mm_src1).s[0]=*src;
986                                 MM_VAR_ACC(mm_src1).s[1]=*src;
987                                         
988                                 /* sample * l/r volume */
989                                 movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
990                                 pfmul_r2r(mm0, mm3);
991                                 movq_r2m(mm3, *mix);
992                                         
993                                 /* next sample */
994                                 src++, mix++;
995                                 MM_VAR_ACC(mm_src2).s[0]=*src;
996                                 MM_VAR_ACC(mm_src2).s[1]=*src;
997                                         
998                                 /* sample * l/r volume */
999                                 movq_m2r(MM_VAR_MOVQ(mm_src2), mm3);
1000                                 pfmul_r2r(mm0, mm3);
1001                                 movq_r2m(mm3, *mix);
1002                                         
1003                                 /* calculating min/max */
1004                                 MM_VAR_ACC(mm_src1).s[1]=MM_VAR_ACC(mm_src2).s[0];
1005                                 movq_m2r(mm_src1, mm3);
1006                                 pfmax_r2r(mm3, mm1);
1007                                 pfmin_r2r(mm3, mm2);
1008                                 
1009                                 src++, mix++;
1010                         }
1011
1012                         movq_r2m(mm1, MM_VAR_MOVQ(mm_max));
1013                         movq_r2m(mm2, MM_VAR_MOVQ(mm_min));
1014                         
1015                         femms();
1016                         
1017                         if (MM_VAR_ACC(mm_max).s[0]>MM_VAR_ACC(mm_max).s[1]) max=MM_VAR_ACC(mm_max).s[0]; else max=MM_VAR_ACC(mm_max).s[1];
1018                         if (MM_VAR_ACC(mm_min).s[0]<MM_VAR_ACC(mm_min).s[0]) min=MM_VAR_ACC(mm_min).s[0]; else min=MM_VAR_ACC(mm_min).s[1];
1019 #endif                  
1020                         
1021                         min*=-1.0;
1022                         if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
1023
1024                         if ((*vtt)->ec_enable)
1025                         {
1026 #ifndef USE_3DNOW                       
1027                                 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
1028                                 {                               
1029                                         temp=(*vtt)->ec_output_buffer[sample];
1030                                         
1031                                         mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
1032                                         mix_sample++;
1033                                         mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
1034                                         mix_sample++;
1035                                 }
1036 #else
1037                                 MM_VAR_ACC(mm_volume).s[0]=(*vtt)->ec_volume_left;
1038                                 MM_VAR_ACC(mm_volume).s[1]=(*vtt)->ec_volume_right;
1039                                                 
1040                                 movq_m2r(MM_VAR_MOVQ(mm_volume), mm0);
1041                                 mix =(mmx_t*)mix_buffer;
1042
1043                                 for (f_prec* src=(*vtt)->ec_output_buffer; mix < (mmx_t*) mix_buffer_end; src++, mix++)
1044                                 {
1045                                         /* first sample */
1046                                         MM_VAR_ACC(mm_src1).s[0]=*src;
1047                                         MM_VAR_ACC(mm_src1).s[1]=*src;
1048                                 
1049                                         /* sample * l/r volume */
1050                                         movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
1051                                         pfmul_r2r(mm0, mm3);
1052                                 
1053                                         /* accumulating complete mix */
1054                                         movq_m2r(*mix, mm4);
1055                                         pfadd_r2r(mm4, mm3);
1056                                         movq_r2m(mm3, *mix);
1057                                 }
1058                                 femms();
1059 #endif                          
1060                         }
1061                         
1062                         if (master_triggered)
1063                         {
1064                                 pthread_mutex_unlock(&render_lock);
1065                                 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1066                                 {
1067                                         if ((*vtt)->is_sync_client)
1068                                         {
1069                                                 if ((*vtt)->sync_countdown)
1070                                                 {
1071                                                         (*vtt)->sync_countdown--;
1072                                                 }
1073                                                 else
1074                                                 {
1075                                                         (*vtt)->sync_countdown=(*vtt)->sync_cycles;
1076                                                         (*vtt)->trigger();
1077                                                 }
1078                                         }
1079                                 }
1080                                 pthread_mutex_lock(&render_lock);
1081                         }
1082                         
1083                         vtt=render_list.begin();
1084                         for (vtt++; vtt!=render_list.end(); vtt++)
1085                         {
1086                                 (*vtt)->render();                                       
1087                                 max=(*vtt)->max_value;
1088                                 min=max;
1089
1090 #ifndef USE_3DNOW
1091                                 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
1092                                 {                               
1093                                         temp=(*vtt)->output_buffer[sample];
1094                                         mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_left;
1095                                         mix_sample++;                                   
1096                                         mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_right;
1097                                         mix_sample++;
1098                                 
1099                                         if (temp>max) max=temp;
1100                                         else if (temp<min) min=temp;
1101                                 }
1102 #else
1103                                 MM_VAR_ACC(mm_volume).s[0]=(*vtt)->res_volume_left;
1104                                 MM_VAR_ACC(mm_volume).s[1]=(*vtt)->res_volume_right;
1105
1106                                 MM_VAR_ACC(mm_max).s[1]=MM_VAR_ACC(mm_max).s[0]=max;
1107                                 MM_VAR_ACC(mm_min).s[1]=MM_VAR_ACC(mm_min).s[0]=min;
1108                         
1109                                 movq_m2r(MM_VAR_MOVQ(mm_max), mm1);
1110                                 movq_m2r(MM_VAR_MOVQ(mm_min), mm2);
1111                                                         
1112                                 movq_m2r(MM_VAR_MOVQ(mm_volume), mm0);
1113                                 mix=(mmx_t*)mix_buffer;
1114
1115                                 for (f_prec* src=(*vtt)->output_buffer; mix < (mmx_t*) mix_buffer_end;)
1116                                 {
1117                                         /* first sample */
1118                                         MM_VAR_ACC(mm_src1).s[0]=*src;
1119                                         MM_VAR_ACC(mm_src1).s[1]=*src;
1120                                         
1121                                         /* sample * l/r volume */
1122                                         movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
1123                                         pfmul_r2r(mm0, mm3);
1124                                         
1125                                         /* accumulating complete mix */
1126                                         movq_m2r(*mix, mm4);
1127                                         pfadd_r2r(mm4, mm3);
1128                                         movq_r2m(mm3, *mix);
1129                                         
1130                                         /* next sample */
1131                                         src++, mix++;
1132                                         MM_VAR_ACC(mm_src2).s[0]=*src;
1133                                         MM_VAR_ACC(mm_src2).s[1]=*src;
1134                                         
1135                                         /* sample * l/r volume */
1136                                         movq_m2r(MM_VAR_MOVQ(mm_src2), mm3);
1137                                         pfmul_r2r(mm0, mm3);
1138
1139                                         /* accumulating complete mix */
1140                                         movq_m2r(*mix, mm4);
1141                                         pfadd_r2r(mm4, mm3);
1142                                         movq_r2m(mm3, *mix);
1143                                         
1144                                         /* calculating min/max */
1145                                         MM_VAR_ACC(mm_src1).s[1]=MM_VAR_ACC(mm_src2).s[0];
1146                                         movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
1147                                         pfmax_r2r(mm3, mm1);
1148                                         pfmin_r2r(mm3, mm2);
1149                                         
1150                                         src++, mix++;
1151                                 }
1152
1153                                 movq_r2m(mm1, MM_VAR_MOVQ(mm_max));
1154                                 movq_r2m(mm2, MM_VAR_MOVQ(mm_min));
1155                                 
1156                                 femms();
1157         
1158                                 if (MM_VAR_ACC(mm_max).s[0]>MM_VAR_ACC(mm_max).s[1]) max=MM_VAR_ACC(mm_max).s[0]; else max=MM_VAR_ACC(mm_max).s[1];
1159                                 if (MM_VAR_ACC(mm_min).s[0]<MM_VAR_ACC(mm_min).s[0]) min=MM_VAR_ACC(mm_min).s[0]; else min=MM_VAR_ACC(mm_min).s[1];
1160 #endif
1161                                 
1162                                 min*=-1.0;
1163                                 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
1164                                 
1165                                 if ((*vtt)->ec_enable)
1166                                 {
1167 #ifndef USE_3DNOW
1168                                         for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
1169                                         {                               
1170                                                 temp=(*vtt)->ec_output_buffer[sample];
1171                                                 
1172                                                 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
1173                                                 mix_sample++;
1174                                                 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
1175                                                 mix_sample++;
1176                                         }
1177 #else
1178                                         MM_VAR_ACC(mm_volume).s[0]=(*vtt)->ec_volume_left;
1179                                         MM_VAR_ACC(mm_volume).s[1]=(*vtt)->ec_volume_right;
1180                                                 
1181                                         movq_m2r(MM_VAR_MOVQ(mm_volume), mm0);
1182                                         mix =(mmx_t*)mix_buffer;
1183
1184                                         for (f_prec* src=(*vtt)->ec_output_buffer; mix < (mmx_t*) mix_buffer_end; src++, mix++)
1185                                         {
1186                                                 /* first sample */
1187                                                 MM_VAR_ACC(mm_src1).s[0]=*src;
1188                                                 MM_VAR_ACC(mm_src1).s[1]=*src;
1189                                 
1190                                                 /* sample * l/r volume */
1191                                                 movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
1192                                                 pfmul_r2r(mm0, mm3);
1193                                 
1194                                                 /* accumulating complete mix */
1195                                                 movq_m2r(*mix, mm4);
1196                                                 pfadd_r2r(mm4, mm3);
1197                                                 movq_r2m(mm3, *mix);
1198                                         }
1199
1200                                         femms();
1201 #endif                                  
1202                                 }
1203                         }
1204                         
1205                         /* left */
1206                         
1207                         max=mix_max_l;
1208                         min=max;
1209
1210                         for (sample=0; sample<samples_in_mix_buffer; sample+=2)
1211                         {                               
1212                                 temp=mix_buffer[sample];
1213
1214 #ifndef TX_DO_CLIP
1215 #define FL_SHRT_MAX 32767.0
1216 #define FL_SHRT_MIN -32768.0
1217                                 if(temp < FL_SHRT_MIN) temp = FL_SHRT_MIN;
1218                                 else if (temp > FL_SHRT_MAX) temp = FL_SHRT_MAX;
1219 #endif                                  
1220
1221                                 mix_out_buffer[sample]=(int16_t) temp;
1222                         
1223                                 if (temp>max) max=temp;
1224                                 else if (temp<min) min=temp;
1225                         }
1226                         
1227                         min*=-1.0;
1228                         if (min>max) mix_max_l=min; else mix_max_l=max;         
1229                         
1230                         /* right */
1231                         
1232                         max=mix_max_r;
1233                         min=max;
1234
1235                         for (sample=1; sample<samples_in_mix_buffer; sample+=2)
1236                         {                               
1237                                 temp=mix_buffer[sample];
1238
1239 #ifndef TX_DO_CLIP
1240                                 if(temp < FL_SHRT_MIN) temp = FL_SHRT_MIN;
1241                                 else if (temp > FL_SHRT_MAX) temp = FL_SHRT_MAX;
1242 #endif
1243                                 
1244                                 mix_out_buffer[sample]=(int16_t) temp;
1245                         
1246                                 if (temp>max) max=temp;
1247                                 else if (temp<min) min=temp;
1248                         }
1249                         
1250                         min*=-1.0;
1251                         if (min>max) mix_max_r=min; else mix_max_r=max;         
1252                         
1253         }
1254         master_triggered=0;
1255                 
1256         vtt=render_list.begin();
1257         while (vtt!=render_list.end())
1258         {
1259                 next=vtt;
1260                 next++;
1261                 
1262                 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
1263                 vtt=next;
1264         }
1265         pthread_mutex_unlock(&render_lock);
1266         
1267         return(mix_out_buffer);
1268 }
1269
1270 void vtt_class :: forward_all_turntables()
1271 {
1272         list <vtt_class *> :: iterator vtt, next;
1273
1274         if (render_list.size()>0)
1275         {
1276                  vtt=render_list.begin();
1277                  (*vtt)->forward_turntable();                    
1278
1279                  if (master_triggered)
1280                  {
1281                          for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1282                          {
1283                                  if ((*vtt)->is_sync_client)
1284                                  {
1285                                          if ((*vtt)->sync_countdown)
1286                                          {
1287                                                  (*vtt)->sync_countdown--;
1288                                          }
1289                                          else
1290                                          {
1291                                                  (*vtt)->sync_countdown=(*vtt)->sync_cycles;
1292                                                  (*vtt)->trigger();
1293                                          }
1294                                  }
1295                          }
1296                  }
1297
1298                  vtt=render_list.begin();
1299                  for (vtt++; vtt!=render_list.end(); vtt++)
1300                  {
1301                          (*vtt)->forward_turntable();
1302                  }
1303                  
1304         }
1305         master_triggered=0;
1306         vtt=render_list.begin();
1307         while (vtt!=render_list.end())
1308         {
1309                 next=vtt;
1310                 next++;
1311                 
1312                 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
1313                 vtt=next;
1314         }
1315 }
1316
1317
1318 int vtt_class :: trigger()
1319 {
1320         list <vtt_fx *> :: iterator effect;
1321
1322         if (!buffer) return (1);
1323         
1324         if (!is_playing) pthread_mutex_lock(&render_lock);
1325         
1326         if (res_pitch>=0) pos_f=0;
1327         else pos_f=maxpos;
1328         fade=NEED_FADE_OUT;
1329         speed=res_pitch;
1330         speed_real=res_pitch;
1331         speed_target=res_pitch;
1332         want_stop=0;
1333
1334         /* activating plugins */
1335         for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
1336         {
1337                 (*effect)->activate();
1338         }
1339
1340
1341 #ifdef USE_FLASH
1342         max_value=0;
1343 #endif
1344         
1345         if (is_sync_master)
1346         {
1347                 master_triggered=1;
1348                 master_triggered_at=0;
1349         }
1350         
1351         if (!is_playing)
1352         {
1353                 is_playing=1;
1354         
1355                 if (is_sync_master) 
1356                 {
1357                         render_list.push_front(this);           
1358                 }               
1359                 else
1360                 {
1361                         render_list.push_back(this);
1362                 }
1363                 pthread_mutex_unlock(&render_lock);
1364         }
1365         return(0);
1366 }
1367
1368 int vtt_class :: stop_nolock()
1369 {
1370         list <vtt_fx *> :: iterator effect;
1371
1372         if (!is_playing) 
1373         {
1374                 pthread_mutex_unlock(&render_lock);
1375                 return(1);
1376         }
1377         render_list.remove(this);
1378         want_stop=0;
1379
1380         is_playing=0;
1381
1382 #ifdef USE_FLASH
1383         max_value=0;
1384 #endif
1385         cleanup_vtt(this);
1386         sync_countdown=0;
1387         
1388         /* deactivating plugins */
1389         for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
1390         {
1391                 (*effect)->deactivate();
1392         }
1393         
1394         return(0);
1395 }
1396
1397 int vtt_class :: stop()
1398 {
1399         int res;
1400         
1401         pthread_mutex_lock(&render_lock);
1402
1403         res=stop_nolock();
1404
1405         pthread_mutex_unlock(&render_lock);
1406
1407         return(res);
1408 }
1409
1410 void vtt_class :: set_sync_master(int master)
1411 {
1412         if (master)
1413         {
1414                 if (sync_master) sync_master->set_sync_master(0);
1415                 sync_master=this;
1416                 is_sync_master=1;
1417         }
1418         else
1419         {
1420                 if (sync_master==this) sync_master=0;
1421                 is_sync_master=0;
1422                 gui_clear_master_button(this);
1423         }
1424 }
1425
1426 void vtt_class :: set_sync_client(int slave, int cycles)
1427 {
1428         is_sync_client=slave;
1429         sync_cycles=cycles;
1430 //      sync_countdown=cycles; 
1431         sync_countdown=0;
1432 }
1433
1434 void vtt_class :: set_sync_client_ug(int slave, int cycles)
1435 {
1436         set_sync_client(slave, cycles);
1437 }
1438
1439 void vtt_class :: set_master_volume(f_prec new_volume)
1440 {
1441         list <vtt_class *> :: iterator vtt;
1442
1443         master_volume=new_volume;
1444         globals.volume=new_volume;
1445         
1446         if (main_list.size()>0)
1447         {
1448                 vol_channel_adjust=sqrt((f_prec) main_list.size());
1449                 res_master_volume=master_volume/vol_channel_adjust;             
1450         }
1451                 
1452         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1453         {
1454                 (*vtt)->recalc_volume();
1455         }
1456 }
1457
1458 void vtt_class :: set_master_pitch(f_prec new_pitch)
1459 {
1460         list <vtt_class *> :: iterator vtt;
1461         
1462         globals.pitch=new_pitch;
1463         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1464         {
1465                 (*vtt)->recalc_pitch();
1466         }
1467 }
1468
1469 void vtt_class :: enable_saturate (int newstate)
1470 {
1471         do_saturate=newstate;
1472 }
1473
1474 void vtt_class :: focus_no(int no)
1475 {
1476         list <vtt_class *> :: iterator vtt;
1477         int i;
1478
1479         for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++)
1480         {
1481                 if (i==no)
1482                 {
1483                         focused_vtt=(*vtt);
1484                 }
1485         }
1486 }
1487
1488 void vtt_class :: focus_next()
1489 {
1490         list <vtt_class *> :: iterator vtt;
1491         
1492         if (!focused_vtt)
1493         {
1494                 if (main_list.size())
1495                 {
1496                         focused_vtt=(*main_list.begin());
1497                 }
1498                 return;
1499         }
1500         
1501         for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1502                 if ((*vtt)==focused_vtt) {
1503                         /* Ok, we found ourselves.. */
1504                         
1505                         vtt++;
1506                         while ((vtt!=main_list.end()) && ((*vtt)->audio_hidden) ) {
1507                                 vtt++;
1508                         }
1509                         
1510                         if (vtt==main_list.end()) {
1511                                 /* No other "focusable" after this vtt so we're looking for the next */
1512                                 
1513                                 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1514                                         if (! (*vtt)->audio_hidden) {
1515                                                 focused_vtt=(*vtt);
1516                                                 return;
1517                                         }
1518                                 }
1519                                 /* When we get here there's no "focusable" vtt at all... damn */
1520                                 focused_vtt=NULL;
1521                                 return;
1522                         } else {
1523                                 focused_vtt=(*vtt);
1524                                 return;
1525                         }
1526                 }
1527         }
1528         
1529         focused_vtt=(*main_list.begin());
1530 }
1531
1532 void vtt_class :: set_scratch(int newstate)
1533 {
1534         if (newstate)
1535         {
1536                 sp_spin.receive_input_value(0);
1537                 do_scratch=1;
1538                 sense_cycles=globals.sense_cycles;
1539         }
1540         else
1541         {
1542                 sp_spin.receive_input_value(1);
1543                 do_scratch=0;
1544         }
1545 }
1546
1547
1548 void vtt_class :: unfocus()
1549 {
1550         focused_vtt=NULL;
1551 }
1552
1553 void vtt_class :: set_x_input_parameter(tX_seqpar *sp)
1554 {
1555         x_par = sp;
1556 }
1557
1558 void vtt_class :: set_y_input_parameter(tX_seqpar *sp)
1559 {
1560         y_par = sp;
1561 }
1562
1563 void vtt_class :: xy_input(f_prec x_value, f_prec y_value)
1564 {
1565         if (x_par) x_par->handle_mouse_input(x_value*globals.mouse_speed);
1566         if (y_par) y_par->handle_mouse_input(y_value*globals.mouse_speed);
1567 }
1568
1569 #define store(data); if (fwrite((void *) &data, sizeof(data), 1, output)!=1) res+=1;
1570
1571 int  vtt_class :: save(FILE *rc, char *indent) {
1572         list <vtt_fx *> :: iterator effect;
1573         char tmp_xml_buffer[4096];
1574         
1575         int res=0;
1576
1577         fprintf(rc, "%s<turntable>\n", indent);
1578         strcat(indent, "\t");
1579         
1580         store_string("name", name);
1581         if (buffer) {
1582                 store_string("audiofile", filename);
1583         } else {
1584                 store_string("audiofile", "");
1585         }
1586         store_bool("sync_master", is_sync_master);
1587         store_bool("autotrigger", autotrigger);
1588         store_bool_sp("loop", loop, sp_loop);
1589
1590         store_bool_sp("sync_client", is_sync_client, sp_sync_client);
1591         store_int_sp("sync_cycles", sync_cycles, sp_sync_cycles);
1592
1593         store_float_sp("volume", rel_volume, sp_volume);
1594         store_float_sp("pitch", rel_pitch, sp_pitch);   
1595         store_bool_sp("mute", mute, sp_mute);
1596         store_float_sp("pan", pan, sp_pan);
1597         
1598         store_bool_sp("lowpass_enable", lp_enable, sp_lp_enable);
1599         store_float_sp("lowpass_gain", lp_gain, sp_lp_gain);
1600         store_float_sp("lowpass_reso", lp_reso, sp_lp_reso);
1601         store_float_sp("lowpass_freq", lp_freq, sp_lp_freq);
1602
1603         store_bool_sp("echo_enable", ec_enable, sp_ec_enable);
1604         store_float_sp("echo_length", ec_length, sp_ec_length);
1605         store_float_sp("echo_feedback", ec_feedback, sp_ec_feedback);
1606         store_float_sp("echo_pan", ec_pan, sp_ec_pan);
1607         store_float_sp("echo_volume", ec_volume, sp_ec_volume);
1608         
1609         store_id("speed", sp_speed.get_persistence_id());
1610         store_id("trigger", sp_trigger.get_persistence_id());
1611         store_id("spin", sp_spin.get_persistence_id());
1612
1613         
1614         if (x_par) {
1615                 store_int("x_axis_mapping", x_par->get_persistence_id());
1616         }
1617         
1618         if (y_par) {
1619                 store_int("y_axis_mapping", y_par->get_persistence_id());
1620         }
1621
1622         store_bool("audio_panel_hidden", audio_hidden);
1623         store_bool("control_panel_hidden", control_hidden);
1624         store_bool("main_panel_hidden", gui.main_panel->is_hidden());
1625         store_bool("trigger_panel_hidden", gui.trigger_panel->is_hidden());
1626         store_bool("lowpass_panel_hidden", gui.lp_panel->is_hidden());
1627         store_bool("echo_panel_hidden", gui.ec_panel->is_hidden());
1628
1629         store_float("audio_x_zoom", gui_get_audio_x_zoom(this));
1630         
1631         fprintf(rc, "%s<fx>\n", indent);
1632         strcat(indent, "\t");
1633         
1634         for (effect=fx_list.begin(); effect!=fx_list.end(); effect++) {
1635                 (*effect)->save(rc, indent);
1636         }
1637         indent[strlen(indent)-1]=0;
1638         fprintf(rc, "%s</fx>\n", indent);
1639         
1640         indent[strlen(indent)-1]=0;
1641         fprintf(rc, "%s</turntable>\n", indent);
1642         
1643         return(res);
1644 }
1645
1646 #define TX_XML_SETFILE_VERSION "1.0"
1647
1648 int  vtt_class :: save_all(FILE* rc) {
1649         int res=0;
1650         list <vtt_class *> :: iterator vtt;
1651         char indent[256];
1652         
1653         tX_seqpar :: create_persistence_ids();
1654
1655         fprintf(rc, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n");
1656         fprintf(rc, "<terminatorXset version=\"%s\">\n", TX_XML_SETFILE_VERSION);
1657         
1658         strcpy(indent, "\t");
1659
1660         //store_int(vtt_amount); obsolete
1661
1662         store_float_sp("master_volume", master_volume, sp_master_volume);
1663         store_float_sp("master_pitch", globals.pitch, sp_master_pitch);
1664
1665         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1666                 res+=(*vtt)->save(rc, indent);
1667         }
1668         
1669         sequencer.save(rc, indent);
1670         
1671         fprintf(rc, "</terminatorXset>\n");
1672         
1673         return(res);
1674 }
1675
1676 int vtt_class :: load(xmlDocPtr doc, xmlNodePtr node) {
1677         char buffer[1024];
1678         bool hidden;
1679         int xpar_id=-1;
1680         int ypar_id=-1;
1681         int elementFound;
1682         char *pid_attr;
1683         int pid;
1684         double dvalue;
1685         double tmp;
1686         char tmp_xml_buffer[4096];
1687         
1688         for (xmlNodePtr cur=node->xmlChildrenNode; cur != NULL; cur = cur->next) {
1689                 if (cur->type == XML_ELEMENT_NODE) {
1690                         elementFound=0;
1691                         
1692                         restore_string_ac("name", buffer, set_name(buffer));
1693                         restore_string("audiofile", filename);
1694                         restore_bool("sync_master", is_sync_master);
1695                         restore_bool("autotrigger", autotrigger);
1696                         restore_bool_id("loop", loop, sp_loop, nop);
1697                         restore_bool_id("sync_client", is_sync_client, sp_sync_client, set_sync_client(is_sync_client, sync_cycles));
1698                         restore_int_id("sync_cycles", sync_cycles, sp_sync_cycles, set_sync_client(is_sync_client, sync_cycles));
1699                         restore_float_id("volume", rel_volume, sp_volume, recalc_volume());
1700                         restore_float_id("pitch", rel_pitch, sp_pitch, recalc_pitch());
1701                         restore_bool_id("mute", mute, sp_mute, set_mute(mute));
1702                         restore_float_id("pan", pan, sp_pan, set_pan(pan));
1703         
1704                         restore_bool_id("lowpass_enable", lp_enable, sp_lp_enable, lp_set_enable(lp_enable));
1705                         restore_float_id("lowpass_gain", lp_gain, sp_lp_gain, lp_set_gain(lp_gain)); 
1706                         restore_float_id("lowpass_reso", lp_reso, sp_lp_reso, lp_set_reso(lp_reso));
1707                         restore_float_id("lowpass_freq", lp_freq, sp_lp_freq, lp_set_freq(lp_freq));
1708         
1709                         restore_bool_id("echo_enable", ec_enable, sp_ec_enable, ec_set_enable(ec_enable));      
1710                         restore_float_id("echo_length", ec_length, sp_ec_length, ec_set_length(ec_length));
1711                         restore_float_id("echo_feedback", ec_feedback, sp_ec_feedback, ec_set_feedback(ec_feedback));
1712                         restore_float_id("echo_pan", ec_pan, sp_ec_pan, ec_set_pan(ec_pan));
1713                         restore_float_id("echo_volume", ec_volume, sp_ec_volume, ec_set_volume(ec_volume));             
1714                 
1715                         restore_id("speed", sp_speed);  
1716                         restore_id("trigger", sp_trigger);
1717                         restore_id("spin", sp_spin);
1718         
1719                         restore_int("x_axis_mapping", xpar_id);
1720                         restore_int("y_axis_mapping", ypar_id);
1721         
1722                         restore_bool("audio_panel_hidden", audio_hidden);
1723                         restore_bool("control_panel_hidden", control_hidden);
1724                         restore_bool_ac("main_panel_hidden", hidden, gui.main_panel->hide(hidden));
1725                         restore_bool_ac("trigger_panel_hidden", hidden, gui.trigger_panel->hide(hidden));
1726                         restore_bool_ac("lowpass_panel_hidden", hidden, gui.lp_panel->hide(hidden));                    
1727                         restore_bool_ac("echo_panel_hidden", hidden, gui.ec_panel->hide(hidden));
1728                         restore_float_ac("audio_x_zoom", tmp, gui_set_audio_x_zoom(this,tmp));
1729                         vg_adjust_zoom(gui.zoom, this);
1730                         
1731                         if (xmlStrcmp(cur->name, (xmlChar *) "fx")==0) {
1732                                 xmlNodePtr fx=cur;
1733                                 elementFound=1;
1734                                 
1735                                 for (xmlNodePtr cur=fx->xmlChildrenNode; cur != NULL; cur = cur->next) {
1736                                         if (cur->type == XML_ELEMENT_NODE) {
1737                                                 int elementFound=0;
1738                                                 
1739                                                 if (xmlStrcmp(cur->name, (xmlChar *) "cutoff")==0) {
1740                                                         for (unsigned int t=0; t<fx_list.size(); t++) effect_down(lp_fx);
1741                                                         elementFound=1;
1742                                                 } else if (xmlStrcmp(cur->name, (xmlChar *) "lowpass")==0) {
1743                                                         for (unsigned int t=0; t<fx_list.size(); t++) effect_down(ec_fx);
1744                                                         elementFound=1;                                                         
1745                                                 } else if (xmlStrcmp(cur->name, (xmlChar *) "ladspa_plugin")==0) {
1746                                                         xmlNodePtr pluginNode=cur;
1747                                                         int ladspa_id=-1;
1748                                                         elementFound=1;
1749                                                         
1750                                                         for (xmlNodePtr cur=pluginNode->xmlChildrenNode; cur!=NULL; cur = cur->next) {
1751                                                                 int elementFound;
1752                                                                 if (cur->type == XML_ELEMENT_NODE) {
1753                                                                         elementFound=0;
1754
1755                                                                         restore_int("ladspa_id", ladspa_id);
1756                                                                         if (elementFound) break;
1757                                                                 }
1758                                                         }
1759                                                         
1760                                                         if (ladspa_id!=-1) {
1761                                                                 LADSPA_Plugin *plugin=LADSPA_Plugin::getPluginByUniqueID(ladspa_id);
1762                                                                 if (plugin) {
1763                                                                         vtt_fx_ladspa *ladspa_effect=add_effect(plugin);
1764                                                                         ladspa_effect->load(doc, pluginNode);
1765                                                                 } else {
1766                                                                         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);
1767                                                                         tx_note(buffer, true);                                                  
1768                                                                 }
1769                                                         } else {
1770                                                                 tX_warning("ladspa_plugin section without a ladspa_id element.");
1771                                                         }
1772                                                         
1773                                                 } else {
1774                                                         tX_warning("unhandled element %s in fx section.", cur->name);
1775                                                 }
1776                                         }
1777                                 }
1778                         }
1779                         
1780                         if(!elementFound) {
1781                                 tX_warning("unhandled element %s in turntable secion.", cur->name);
1782                         }
1783                 }
1784         }
1785
1786         recalc_volume();
1787
1788         if (xpar_id>=0) {
1789                 set_x_input_parameter(tX_seqpar :: get_sp_by_persistence_id(xpar_id));
1790         }
1791         else set_x_input_parameter(NULL);
1792         
1793         if (ypar_id) {
1794                 set_y_input_parameter(tX_seqpar :: get_sp_by_persistence_id(ypar_id));
1795         }
1796         else set_y_input_parameter(NULL);
1797                 
1798         return 0;
1799 }
1800
1801 void vtt_class :: delete_all()
1802 {
1803         while (main_list.size()) {
1804                 delete((*main_list.begin()));
1805         }
1806 }
1807
1808
1809 int vtt_class :: load_all(xmlDocPtr doc, char *fname) {
1810         xmlNodePtr root=xmlDocGetRootElement(doc);
1811         int elementFound=0;
1812         char fn_buff[4096];
1813         double dvalue;
1814         int res=0;
1815         int restmp=0;
1816         char *pid_attr;
1817         int pid;
1818
1819         
1820         if (!root) {
1821                 tX_error("no root element? What kind of XML document is this?");
1822                 return 1;
1823         }
1824         
1825         if (xmlStrcmp(root->name, (const xmlChar *) "terminatorXset")) {
1826                 tX_error("this is not a terminatorXset file.")
1827                 return 2;
1828         }
1829         
1830         if (xmlGetProp(root,(xmlChar *) "version")==NULL) {
1831                 tX_error("the set file lacks a version attribute.");
1832                 return 3;
1833         }
1834         
1835         if (xmlStrcmp(xmlGetProp(root, (xmlChar *) "version"), (xmlChar *) TX_XML_SETFILE_VERSION)) {
1836                 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);
1837         }
1838         
1839         /* delete current tables... */
1840         delete_all();
1841
1842         int table_ctr=0;
1843         
1844         /* counting turntables.. */
1845         for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1846                 if (cur->type == XML_ELEMENT_NODE) {    
1847                         if (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0) {
1848                                 table_ctr++;
1849                         }
1850                 }
1851         }
1852
1853         tX_debug("Found %i turntables in set.",  table_ctr);
1854
1855         ld_create_loaddlg(TX_LOADDLG_MODE_MULTI, table_ctr);
1856         ld_set_setname(fname);
1857
1858         /* parsing all */
1859         for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1860                 if (cur->type == XML_ELEMENT_NODE) {                    
1861                         elementFound=0;
1862                 
1863                         restore_float_id("master_volume", master_volume, sp_master_volume, set_master_volume(master_volume));
1864                         restore_float_id("master_pitch", globals.pitch, sp_master_pitch, set_master_pitch(globals.pitch));
1865                         
1866                         if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0)) {
1867                                 elementFound=1;
1868                                 vtt_class *vtt=new vtt_class(1);
1869                                 vtt->load(doc, cur);
1870                                 
1871                                 tX_debug("loading a turntable..");
1872
1873                                 if (strlen(vtt->filename)) {
1874                                         strcpy(fn_buff, vtt->filename);
1875                                         ld_set_filename(fn_buff);
1876                                 
1877                                         restmp=(int) vtt->load_file(fn_buff);
1878                                         res+=restmp;
1879                                 }
1880         
1881                                 gtk_box_pack_start(GTK_BOX(control_parent), vtt->gui.control_box, TRUE, TRUE, 0);
1882                                 gtk_box_pack_start(GTK_BOX(audio_parent), vtt->gui.audio_box, TRUE, TRUE, 0);
1883                                 if (vtt->audio_hidden) vtt->hide_audio(vtt->audio_hidden);
1884                                 if (vtt->control_hidden) vtt->hide_control(vtt->control_hidden);\r
1885                         }
1886                         if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "sequencer")==0)) {
1887                                 elementFound=1;
1888                                 sequencer.load(doc, cur);
1889                         }
1890                         if (!elementFound) {
1891                                 tX_warning("unhandled element %s in setfile %s", cur->name, fname);
1892                         }
1893                 }
1894         }
1895         
1896         ld_destroy();
1897         
1898         return(res);
1899 }
1900
1901 void add_vtt(GtkWidget *ctrl, GtkWidget *audio, char *fn)
1902 {
1903         vtt_class *hmmpg;
1904         hmmpg = new vtt_class(1);
1905         gtk_box_pack_start(GTK_BOX(ctrl), hmmpg->gui.control_box, TRUE, TRUE, 0);
1906         gtk_box_pack_start(GTK_BOX(audio), hmmpg->gui.audio_box, TRUE, TRUE, 0);
1907         if (fn) hmmpg->load_file(fn);
1908 }
1909
1910 extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt);
1911 extern void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt);
1912
1913 //#define debug_fx_stack(); for (i=fx_list.begin(); i != fx_list.end(); i++) puts((*i)->get_info_string());
1914 #define debug_fx_stack();
1915
1916 void vtt_class :: effect_up(vtt_fx *effect)
1917 {
1918         list <vtt_fx *> :: iterator i;
1919         list <vtt_fx *> :: iterator previous;
1920         int ok=0;
1921         
1922         debug_fx_stack();
1923         
1924         if ((*fx_list.begin())==effect) return;
1925         
1926         for (previous=i=fx_list.begin(); i != fx_list.end(); i++)
1927         {
1928                 if ((*i) == effect)
1929                 {
1930                         ok=1;
1931                         break;
1932                 }
1933                 previous=i;
1934         }
1935         
1936         if (ok)
1937         {       
1938                 pthread_mutex_lock(&render_lock);
1939                 fx_list.remove(effect);
1940                 fx_list.insert(previous, effect);
1941                 pthread_mutex_unlock(&render_lock);
1942
1943                 vg_move_fx_panel_up(effect->get_panel_widget(), this);
1944         }
1945         
1946         debug_fx_stack();
1947 }
1948
1949 void vtt_class :: effect_down(vtt_fx *effect)
1950 {
1951         list <vtt_fx *> :: iterator i;
1952         int ok=0;
1953
1954         debug_fx_stack();
1955                 
1956         for (i=fx_list.begin(); i != fx_list.end(); i++)
1957         {
1958                 if ((*i) == effect)
1959                 {
1960                         ok=1;
1961                         break;
1962                 }
1963         }
1964         
1965         if ((ok) && (i!=fx_list.end()))
1966         {
1967                 i++;
1968                 if (i==fx_list.end()) return;
1969                 i++;
1970
1971                 pthread_mutex_lock(&render_lock);
1972                 fx_list.remove(effect);
1973                 
1974                 fx_list.insert(i, effect);
1975                 vg_move_fx_panel_down(effect->get_panel_widget(), this);
1976                 pthread_mutex_unlock(&render_lock);
1977         }
1978         
1979 debug_fx_stack();       
1980 }
1981
1982 void vtt_class ::  effect_remove(vtt_fx_ladspa *effect)
1983 {
1984         pthread_mutex_lock(&render_lock);
1985         fx_list.remove(effect);
1986         pthread_mutex_unlock(&render_lock);
1987         
1988         delete effect;
1989 }
1990
1991 extern void gui_hide_control_panel(vtt_class *vtt, bool hide);
1992 extern void gui_hide_audio_panel(vtt_class *vtt, bool hide);
1993
1994 void vtt_class :: hide_audio(bool hide) {
1995         audio_hidden=hide;
1996         gui_hide_audio_panel(this, hide);
1997 }
1998
1999 void vtt_class :: hide_control(bool hide) {
2000         control_hidden=hide;
2001         gui_hide_control_panel(this, hide);     
2002 }
2003
2004 void vtt_class :: set_sample_rate(int samplerate) {
2005         list <vtt_class *> :: iterator vtt;
2006         double sr=(double) samplerate;
2007
2008         last_sample_rate=samplerate;
2009         
2010         for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
2011                 if ((*vtt)->audiofile) {
2012                         double file_rate=(*vtt)->audiofile->get_sample_rate();
2013                         (*vtt)->audiofile_pitch_correction=file_rate/sr;
2014                 } else {
2015                         (*vtt)->audiofile_pitch_correction=1.0;
2016                 }
2017                 (*vtt)->recalc_pitch();
2018         }
2019         
2020         int no_samples=(int) (sr*0.001); // Forcing 1 ms blocksize
2021         
2022         set_mix_buffer_size(no_samples);        
2023 }