~ubuntu-branches/ubuntu/dapper/terminatorx/dapper

« back to all changes in this revision

Viewing changes to src/tX_vtt.cc

  • Committer: Bazaar Package Importer
  • Author(s): Mike Furr
  • Date: 2004-04-26 21:20:09 UTC
  • Revision ID: james.westby@ubuntu.com-20040426212009-acjw8flkt05j945f
Tags: upstream-3.81
Import upstream version 3.81

Show diffs side-by-side

added added

removed removed

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