1b0591f0eebf73b456297d6040e6e63403780b25
[terminatorX.git] / terminatorX / src / turntable.c
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999  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: turntable.c
20
21     Description: This implements the virtual turntable. Contains
22     all audio related stuff.
23
24     I no longer have -DUSE_ALIASING as I don´t have time to maintain the same
25     code twice. Aliasing is now default. 
26     
27     Changes:    
28     
29     20 Mar 1999: Setting the buffer size in open_device() no
30                  happens before the DSP_RESET. This might
31                  help fighting latency with some audio drivers.
32                  
33     20 Mar 1999: If KEEP_DEV_OPEN is defined the audio device
34                  will be opened only once and is only closed
35                  by termination of the terminatorX-process via
36                  the OS. This helps if you have problems with
37                  memory fragmentation and the sounddriver fails
38                  to malloc the audiobuffers. If your sounddriver
39                  causes awfull clicks on opening the device this
40                  is nice too. Of course other processes can not access
41                  the audio device while terminatorX is running.
42                  see open_dev() and close_dev().
43                  
44     20 Mar 1999: Big endian support
45     
46     20 Mar 1999: Removed audio clicks. Use -DHANDLE_STOP to re-enable.
47                  This is not the solution I want as it produces
48                  what I consider corrupt audio.
49     
50     21 Mar 1999: do_mix is enabled automatically now if mix_data is
51                  available.
52                  
53     23 Mar 1999: new mixing routine allows to set the loop to scratch
54                  ratio. Old mixing (is faster) can be re-enabled
55                  via -DUSE_OLD_MIX. I consider this code as obsolete
56                  if nobody tells me he/she uses that switch I'll drop the
57                  old code.
58                  
59     07 Apr 1999: moved to gtk's pseudo C++              
60     
61     21 Apr 1999: applied new "NO_CLICK" strategy to render_block. 
62     
63     27 Apr 1999: <config.h> support
64     
65     09 May 1999: some render_block speedups.
66     
67     01 Jun 1999: fixed stdout-output. It's a good idea to use bigger
68                  buffersizes though..
69                  
70     02 Jun 1999: rehacked de-clicking code (fade_in/fade_out) for simplicity
71                  and reliability.
72                  
73     20 Jul 1999: implemented the lowpass filter - the code is
74                  based on Paul Kellett's "democode" in reso_lop.txt,
75                  that I found somewhere on the net.
76     
77     21 Jul 1999: moved the filter to render_block for speedups
78 */
79
80 #define GAIN_ADJUSTMENT_VALUE 0.8
81
82 #include "tX_gui.h"
83 #include "turntable.h"
84
85 #ifndef WIN32
86 #include <sys/types.h>
87 #include <sys/stat.h>
88 #include <sys/ioctl.h>
89 #include <unistd.h>
90 #endif
91
92 #include <fcntl.h>
93
94 #ifndef WIN32
95 #include <sys/soundcard.h>
96 #endif
97
98 #include <stdio.h>
99 #include <malloc.h>
100 #include "wav_file.h"
101 #include <math.h>
102
103 #include "endian.h"
104 #include "tX_types.h"
105 #include "tX_global.h"
106 #include "tX_engine.h"
107
108 /* For KEEP_DEV_OPEN */
109 #ifdef HAVE_CONFIG_H
110 #include <config.h>
111 #endif
112
113 #define NON_RT_BUFF 13
114
115 Virtual_TurnTable *vtt_new()
116 {
117         Virtual_TurnTable *vtt;
118         
119         vtt=(Virtual_TurnTable *) malloc(sizeof(Virtual_TurnTable));
120         
121         vtt->vol_scratch=globals.scratch_vol;
122         vtt->vol_loop=1.0-globals.scratch_vol;
123         
124         vtt->default_speed=globals.vtt_default_speed;
125         vtt->speed=globals.vtt_default_speed;
126         
127         vtt->last_block_recorded=0;
128         
129         vtt->dev_open=0;
130         vtt->devicefd=0;
131                 
132         vtt->mode=MODE_SCRATCH;
133
134 #ifdef TX_WRITER_THREAD
135         vtt->writer = 0;        
136         vtt->tmp_out=NULL;
137         vtt->writer_busy=0;
138         
139         pthread_mutex_init(&vtt->writer_locked, NULL);
140         pthread_mutex_init(&vtt->next_write, NULL);     
141 #endif
142
143         vtt->lowpass_q=globals.lowpass_reso;
144         
145         return(vtt);
146 }
147
148 int vtt_open_dev(Virtual_TurnTable *vtt, int use_rt_buffsize)
149 {
150 #ifdef USE_CONSOLE
151         if (verbose) puts("[VTT:open_dev] Trying to open device.");
152 #endif
153         int i=0;
154         int p;
155 #ifndef WIN32
156         
157 #ifdef KEEP_DEV_OPEN
158         if (vtt->dev_open) return(0);
159 #else   
160         if (vtt->dev_open) 
161         {
162 #ifdef USE_CONSOLE
163         puts("[VTT:open_dev] Error: Device already open.");
164 #endif
165                 return (1);
166         }
167 #endif
168
169         if (globals.use_stdout)
170         {
171                 vtt->devicefd=STDOUT_FILENO;
172                 vtt->dev_open=1;                
173                 vtt->deviceblocksize=1 << globals.buff_size;
174                 return(0);
175         }
176
177         vtt->devicefd = open(globals.audio_device, O_WRONLY, 0);
178         
179 #ifndef KEEP_DEV_OPEN
180         /* setting buffer size */       
181         if (use_rt_buffsize)
182         {
183 #endif  
184                 vtt->buff_cfg=(globals.buff_no<<16) | globals.buff_size;
185 #ifndef KEEP_DEV_OPEN           
186         }       
187         else
188         {
189                 /* somewhat more conservative buffersettings to
190                  reduce destortion in filedialogs */
191                 vtt->buff_cfg=(globals.buff_no<<16) | NON_RT_BUFF;      
192         }
193 #endif  
194                 p=vtt->buff_cfg;
195                 
196                 i = ioctl(vtt->devicefd, SNDCTL_DSP_SETFRAGMENT, &p);
197
198         ioctl(vtt->devicefd, SNDCTL_DSP_RESET, 0);              
199
200         /* 16 Bits */
201         
202         p =  16;
203
204         i +=  ioctl(vtt->devicefd, SOUND_PCM_WRITE_BITS, &p);
205
206         /* MONO */
207         
208         p =  1;
209         i += ioctl(vtt->devicefd, SOUND_PCM_WRITE_CHANNELS, &p);
210         
211         /* 44.1 khz */
212
213         p =  44100;
214         i += ioctl(vtt->devicefd, SOUND_PCM_WRITE_RATE, &p);
215                 
216         i += ioctl(vtt->devicefd, SNDCTL_DSP_GETBLKSIZE, &vtt->deviceblocksize);
217
218 #ifdef ENABLE_DEBUG_OUTPUT      
219         fprintf(stderr, "[vtt_open_dev()] Deviceblocksize: %i\n", vtt->deviceblocksize);
220 #endif
221         
222         ioctl(vtt->devicefd, SNDCTL_DSP_SYNC, 0);
223
224         vtt->dev_open=!i;
225
226 #endif // WIN32
227         return(i);
228 }
229
230 /* Virtual_TurnTable::close_dev() : Closes audio device */
231
232 int vtt_close_dev(Virtual_TurnTable *vtt)
233 {
234 #ifndef WIN32
235 #ifdef KEEP_DEV_OPEN
236         return(ioctl(vtt->devicefd, SNDCTL_DSP_POST, 0));
237 #else
238 #ifdef USE_CONSOLE
239         if (verbose) puts("[VTT:close_dev] Trying to close device.");
240 #endif
241         if (!vtt->dev_open)
242         {       
243 #ifdef USE_CONSOLE
244         puts("[VTT:close_dev] Error: Device not open.");
245 #endif  
246                 return(1);              
247         }
248
249         if (!globals.use_stdout)
250         {
251                 close(vtt->devicefd);
252         }
253         vtt->devicefd=0;
254         vtt->dev_open=0;
255         
256         return(0);
257 #endif
258 #endif // WIN32
259 }
260
261 #ifdef TX_WRITER_THREAD
262 void *vtt_block_writer(void *tt)
263 {
264         Virtual_TurnTable *vtt;
265         
266         vtt=(void *) tt;
267         
268         while (vtt->writer_busy)
269         {
270                 pthread_mutex_lock(&vtt->next_write);
271                 if (vtt->writer_busy)
272                 {
273                         pthread_mutex_lock(&vtt->writer_locked);                
274                         pthread_mutex_unlock(&vtt->next_write);
275                         write(vtt->devicefd, vtt->tmp_out, vtt->deviceblocksize);
276                         free(vtt->tmp_out);
277                         pthread_mutex_unlock(&vtt->writer_locked);
278                 }
279                 else
280                 {
281                         pthread_mutex_unlock(&vtt->next_write);
282                 }
283         }       
284         pthread_exit(NULL);
285 }
286 #endif
287
288 /* Virtual_TurnTable::play_block() : plays the given audio buffer size must
289    be deviceblocksize.
290 */
291
292 void vtt_play_block(Virtual_TurnTable *vtt, int16_t *buffer)
293 {
294 #ifdef BIG_ENDIAN_MACHINE
295 #ifndef BIG_ENDIAN_AUDIO
296         swapbuffer(vtt->buffer, vtt->samples_per_block);
297 #endif  
298 #else
299 #ifdef BIG_ENDIAN_AUDIO
300         swapbuffer(vtt->buffer, vtt->samples_per_block);
301 #endif
302 #endif
303
304 #ifdef TX_WRITER_THREAD 
305         vtt->tmp_out=(int16_t*) malloc(vtt->deviceblocksize);
306
307         pthread_mutex_lock(&vtt->writer_locked);
308         pthread_mutex_unlock(&vtt->next_write);
309         memcpy(vtt->tmp_out, buffer, vtt->deviceblocksize);
310         pthread_mutex_unlock(&vtt->writer_locked);
311         pthread_mutex_lock(&vtt->next_write);
312 #else
313         write(vtt->devicefd, buffer, vtt->deviceblocksize);
314 #endif  
315 }
316
317 /* Virtual_TurnTable::render_block() : "renders" one block of audio (scratch)
318    data into given buffer (size == deviceblocksize)
319 */
320
321 void vtt_render_block(Virtual_TurnTable *vtt, int16_t *buffer)
322 {       
323         int16_t *ptr;
324         
325         int sample;
326         int fade_in=0;
327         int fade_out=0;
328         int do_mute=0;
329         
330         f_prec next_speed;
331         f_prec true_pos_a;
332         
333 //      f_prec diff;    /* dropped diff for speed improvements now this value is stored tp amount_b */
334         f_prec amount_a;
335         f_prec amount_b;
336
337 #ifndef USE_TIME_DISPLAY        
338         unsigned int real_pos_a;
339 #endif
340
341         f_prec sample_a;
342         f_prec sample_b;
343         
344         f_prec sample_res;
345         
346 //      Now the lowpass vars:   
347         f_prec f=vtt->lowpass_freq;
348         f_prec adj=vtt->lowpass_gainadj;
349         f_prec buf0=vtt->lowpass_buf0;
350         f_prec buf1=vtt->lowpass_buf1;
351         f_prec a=vtt->lowpass_a;
352         f_prec b=vtt->lowpass_b;        
353         int lowpass=globals.lowpass_enable;
354         
355         real_pos_a=vtt->realpos;
356         
357         if (vtt->speed != vtt->target_speed)
358         {
359                 vtt->target_speed=vtt->speed;
360                 vtt->speed_step=vtt->target_speed-vtt->real_speed;
361                 vtt->speed_step/=10.0;
362         }
363                         
364         if (vtt->target_speed != vtt->real_speed)
365         {
366                 vtt->real_speed+=vtt->speed_step;
367                 if ((vtt->speed_step<0) && (vtt->real_speed<vtt->target_speed)) vtt->real_speed=vtt->target_speed;
368                 else
369                 if ((vtt->speed_step>0) && (vtt->real_speed>vtt->target_speed)) vtt->real_speed=vtt->target_speed;                      
370         }
371
372         if (vtt->fade)
373         {
374                 if ((vtt->last_speed==0) && (vtt->real_speed !=0))
375                 {
376                         fade_in=1;
377                         vtt->fade=NEED_FADE_OUT;
378                 }
379         }
380         else
381         {
382                 if ((vtt->last_speed!=0) && (vtt->real_speed==0))
383                 {
384                         fade_out=1;
385                         vtt->fade=NEED_FADE_IN;
386                 }
387         }
388
389         if (vtt->mute_scratch != vtt->old_mute)
390         {
391                 if (vtt->mute_scratch)
392                 {
393                         fade_out=1; fade_in=0;
394                         vtt->fade=NEED_FADE_IN;
395                 }
396                 else
397                 {
398                         fade_in=1; fade_out=0;
399                         vtt->fade=NEED_FADE_OUT;
400                 }
401                 vtt->old_mute=vtt->mute_scratch;
402         }
403         else
404         {
405                 if (vtt->mute_scratch) do_mute=1;
406         }
407                         
408         for (sample=0; sample < vtt->samples_per_block; sample++)
409         {
410                 if ((vtt->real_speed!=0) || (fade_out))
411                 {
412                         vtt->pos+=vtt->real_speed;
413                         if (vtt->pos>vtt->maxpos) vtt->pos-=vtt->maxpos;
414                         else if (vtt->pos<0) vtt->pos+=vtt->maxpos;
415                                 
416                         true_pos_a=floor(vtt->pos);
417                         real_pos_a=(unsigned int) true_pos_a;
418                                                                 
419                         amount_b=vtt->pos-true_pos_a;                           
420                         amount_a=1.0-amount_b;                          
421                                 
422                         if (do_mute)
423                         {
424                                 *buffer=0;
425                         }
426                         else
427                         {
428                                 ptr=&globals.scratch_data[real_pos_a];
429                                 sample_a=(f_prec) *ptr;
430                         
431                                 if (real_pos_a == globals.scratch_len) 
432                                 {
433                                         sample_b=*globals.scratch_data;
434                                 }
435                                 else
436                                 {
437                                         ptr++;
438                                         sample_b=(f_prec) *ptr;
439                                 }
440                                 
441                                 sample_res=(sample_a*amount_a)+(sample_b*amount_b);
442                                 
443                                 if (lowpass)
444                                 {
445                                         sample_res*=adj;
446                                         buf0 = a * buf0 + f * (sample_res + b * (buf0 - buf1));
447                                         buf1 = a * buf1 + f * buf0;
448                                         sample_res=buf1;
449                                 }
450                                 
451                                 if (fade_in)
452                                 {
453                                         sample_res*=(((f_prec)sample)/vtt->f_samples_per_block);
454                                 }
455                                 else
456                                 if (fade_out)
457                                 {
458                                         sample_res*=1.0-(((f_prec) sample)/vtt->f_samples_per_block);
459                                 }
460  
461                                 *buffer=(int16_t) sample_res;
462                         }
463                 }
464                 else
465                 {
466                                 *buffer=0;
467                 }
468                 buffer++;
469         }
470         vtt->realpos = real_pos_a;
471         vtt->last_speed = vtt->real_speed;
472         vtt->lowpass_buf0=buf0;
473         vtt->lowpass_buf1=buf1;
474 }
475
476 /* Virtual_TurnTable::needle_down() : Starts playback */
477
478 int vtt_needle_down(Virtual_TurnTable *vtt)
479 {
480         int result;
481         
482         vtt->pos=0;
483         vtt->maxpos=(f_prec) globals.scratch_size / 2.0;
484
485         vtt->mix_pos=globals.loop_data;
486         vtt->mix_max=globals.loop_data+(size_t) globals.loop_len;
487         vtt->store_pos=globals.rec_buffer;
488         vtt->fade=NEED_FADE_OUT;
489
490         vtt->speed=globals.vtt_default_speed;
491         vtt->real_speed=globals.vtt_default_speed;
492         vtt->target_speed=globals.vtt_default_speed;
493         vtt->speed_step=0;
494 #ifdef TX_WRITER_THREAD 
495         pthread_mutex_lock(&vtt->next_write);
496         
497         vtt->writer_busy=1;
498         if (!pthread_create(&vtt->writer, NULL, vtt_block_writer, (void *) vtt))
499         {
500                 puts("failed");
501         }
502 #endif  
503
504         vtt->lowpass_freq=0.99;
505         vtt_lowpass_conf(vtt, vtt->lowpass_freq, vtt->lowpass_q);
506         
507 #ifdef HANDLE_UNSTOP    
508         vtt->fade=0;
509 #endif
510
511         result = vtt_open_dev(vtt, 1);  
512         
513         if (result) 
514         {
515 #ifdef USE_CONSOLE
516                 puts("[VTT:needle_down] Error: Failed opening device. Fatal. Giving up.");
517 #endif          
518                 return(1);
519         }
520
521 #ifdef USE_CONSOLE
522         if (verbose) printf("[VTT:needle_down] Using Blocksize of %i Bytes.\n", deviceblocksize);
523 #endif
524         vtt->samples_per_block=vtt->deviceblocksize/sizeof(int16_t);
525         vtt->f_samples_per_block=(f_prec) vtt->samples_per_block;
526         
527         vtt->samplebuffer=(int16_t *) malloc(vtt->deviceblocksize);
528
529         if (!vtt->samplebuffer)
530         {
531 #ifdef USE_CONSOLE
532                 puts("[VTT:needle_down] Error. Failed to allocate sample_buffer. Fatal. Giving up.");
533 #endif
534                 return(1);
535         }
536         
537         vtt->store_pos=globals.rec_buffer;
538         vtt->mix_pos=globals.loop_data;
539         vtt->block_ctr=0;
540         vtt->block_max=globals.rec_size/vtt->deviceblocksize;
541
542         vtt->mute_scratch=0;
543         vtt->old_mute=0;
544         
545         return(0);
546 }
547
548 /* Virtual_TurnTable::needle_up() : Stops playback. */
549
550 void vtt_needle_up(Virtual_TurnTable *vtt)
551 {
552         int result;
553         void *ptr;
554
555 #ifdef TX_WRITER_THREAD 
556         vtt->writer_busy=0;
557         pthread_mutex_unlock(&vtt->next_write);
558         pthread_join(vtt->writer, &ptr);
559         vtt->writer=0;
560         vtt->tmp_out=NULL;
561 #endif  
562         
563         free(vtt->samplebuffer);        
564         
565         result = vtt_close_dev(vtt);    
566         
567 #ifdef USE_CONSOLE
568         if (result)
569         puts("[VTT:needle_up] Error: Failed closing device.");
570 #endif  
571         
572 }
573
574 /* Virtual_TurnTable::set_speed() : Sets the rotation speed of the
575    Virtual TurnTable. Rarely used as writing to speed directly is 
576    faster (and uglier). 
577 */
578
579 void vtt_set_speed(Virtual_TurnTable *vtt, f_prec targetspeed)
580 {
581 #ifdef FUSE_CONSOLE
582         if (verbose) printf("[VTT:set_speed] Speed setup: %f.\n", targetspeed);
583 #endif
584         vtt->speed=targetspeed;
585 }
586
587 /* Virtual_TurnTable::set_mode() : Just what it says ..*/
588
589 void vtt_set_mode(Virtual_TurnTable *vtt, int newmode)
590 {
591         vtt->mode=newmode;
592 }
593
594 /* Virtual_TurnTable::get_next_storage_block() : Returns a pointer to the next
595    block in recordbuffer.
596 */
597
598 int16_t * vtt_get_next_storage_block(Virtual_TurnTable *vtt)
599 {
600         if (vtt->block_ctr)
601         {
602                 vtt->block_ctr++;
603                 if (vtt->block_ctr > vtt->block_max) return(NULL);
604                 vtt->store_pos+=(size_t) vtt->samples_per_block;        
605                 return(vtt->store_pos);
606         }
607         else
608         {
609                 vtt->block_ctr++;
610                 return(vtt->store_pos);
611         }
612
613 }
614
615 void vtt_lowpass_setfreq (Virtual_TurnTable *vtt, f_prec freq_adj)
616 {
617         if (freq_adj > 0)
618         {
619                 vtt->lowpass_freq+=freq_adj;
620                 if (vtt->lowpass_freq >= 0.99) vtt->lowpass_freq=0.99;
621         }
622         else
623         {
624                 vtt->lowpass_freq+=freq_adj;
625                 if (vtt->lowpass_freq<0) vtt->lowpass_freq=0;
626         }
627         
628         vtt->lowpass_a=1.0-vtt->lowpass_freq;
629         vtt->lowpass_b=vtt->lowpass_q*(1.0+(1.0/vtt->lowpass_a));
630 }
631
632 void vtt_lowpass_conf (Virtual_TurnTable *vtt, f_prec freq, f_prec q)
633 {
634 //      printf("lowpass confed: f %f, %f q\n", freq, q);
635         vtt->lowpass_freq=freq;
636         vtt->lowpass_q=q;
637         
638         vtt->lowpass_a=1.0-freq;
639         vtt->lowpass_b=q*(1.0+(1.0/vtt->lowpass_a));
640         
641         vtt->lowpass_gainadj=1.0-q*GAIN_ADJUSTMENT_VALUE;       
642 }
643
644 void vtt_lowpass_block (Virtual_TurnTable *vtt, int16_t *buffer)
645 {
646         int sample;
647         f_prec f=vtt->lowpass_freq;
648         f_prec adj=vtt->lowpass_gainadj;
649         f_prec in;
650         f_prec buf0=vtt->lowpass_buf0;
651         f_prec buf1=vtt->lowpass_buf1;
652         f_prec a=vtt->lowpass_a;
653         f_prec b=vtt->lowpass_b;        
654         
655         for (sample=0; sample < vtt->samples_per_block; sample++, buffer++)
656         {
657                 in=*buffer*adj; 
658                 buf0 = a * buf0 + f * (in + b * (buf0 - buf1));
659                 buf1 = a * buf1 + f * buf0;
660                 *buffer=buf1;
661         }
662         vtt->lowpass_buf0=buf0;
663         vtt->lowpass_buf1=buf1;
664 }
665
666 /* Virtual_TurnTable::() : This triggers all required actions depending
667    on current mode.
668 */
669
670 int vtt_block_action(Virtual_TurnTable *vtt)
671 {
672         int16_t *ptr;
673
674         switch(vtt->mode)
675         {
676                 case MODE_SCRATCH:
677                         vtt_render_block(vtt, vtt->samplebuffer);
678                         /*if (globals.lowpass_enable)
679                         {
680                                 vtt_lowpass_block(vtt, vtt->samplebuffer);
681                         }*/
682                         if (globals.do_mix) vtt_add_mix(vtt, vtt->samplebuffer);
683                         vtt_play_block(vtt, vtt->samplebuffer);
684                         return(0);
685
686                 case MODE_RECORD_SCRATCH:
687                         ptr=vtt_get_next_storage_block(vtt);
688                         if (ptr)
689                         {
690                                 vtt_render_block(vtt, ptr);
691                                 /*if (globals.lowpass_enable)
692                                 {
693                                         vtt_lowpass_block(vtt, ptr);
694                                 }*/
695                                 
696                                 if (globals.do_mix) 
697                                 {
698                                         memcpy(vtt->samplebuffer, ptr, vtt->deviceblocksize);
699                                         vtt_add_mix(vtt, vtt->samplebuffer);
700                                         vtt_play_block(vtt, vtt->samplebuffer);
701                                 }
702                                 else
703                                 {
704                                         vtt_play_block(vtt, ptr);
705                                 }
706                                 return(0);
707                         }
708                         else
709                         {
710                                 return(1);
711                         }
712                 
713                 case MODE_PLAYBACK_RECORDED:
714                         if (vtt->block_ctr>vtt->last_block_recorded) return (1);
715                         ptr=vtt_get_next_storage_block(vtt);
716                         
717                         if (ptr)
718                         {
719                                 vtt->realpos = ptr-globals.rec_buffer;
720                         
721                                 if (globals.do_mix)
722                                 {
723                                         memcpy(vtt->samplebuffer, ptr, vtt->deviceblocksize);
724                                         vtt_add_mix(vtt,vtt->samplebuffer);
725                                         vtt_play_block(vtt, vtt->samplebuffer);
726                                 }
727                                 else
728                                 {
729                                         vtt_play_block(vtt,ptr);
730                                 }
731                                 return(0);
732                         }
733                         else
734                         {
735                                 return(1);
736                         }
737         }
738         return(1);
739 }
740
741 /* Virtual_TurnTable::add_mix() : This mixes the loop file date to the
742    given buffer (size = deviceblocksize)
743 */
744
745 void vtt_add_mix(Virtual_TurnTable *vtt, int16_t * buffer)
746 {
747         int sample;
748         int16_t *scratch_pos;
749         
750         f_prec f_val_s, f_val_l;        
751         
752         for (sample=0, scratch_pos=buffer; sample < vtt->samples_per_block; sample ++, scratch_pos++)
753         {
754                 f_val_l=(f_prec) *vtt->mix_pos;
755                 f_val_l*=vtt->vol_loop;
756                 f_val_s=(f_prec) *scratch_pos;
757                 f_val_s*=vtt->vol_scratch;
758                 *scratch_pos=(int16_t) (f_val_s + f_val_l);
759
760                 vtt->mix_pos++;
761                 if (vtt->mix_pos>=vtt->mix_max) vtt->mix_pos=globals.loop_data;         
762         }
763 }
764
765 /* Virtual_TurnTable::toggle_mix() : Dis- or enable mixing of loop data.*/
766 /*
767 void vtt_toggle_mix(Virtual_TurnTable *vtt)
768 {
769         if (globals.loop_data) vtt->do_mix=!vtt->do_mix;
770         else
771         {
772 #ifdef USE_CONSOLE
773                 puts("[VTT:toggle_mix] Error: Can't enable mixing: no loop loaded.");
774 #endif          
775                 vtt->do_mix=0;
776         }
777 }
778 */
779 /* Virtual_TurnTable::store_rec_pos() : Stores current recording position
780    for later playback or saving.
781 */
782
783 void vtt_store_rec_pos(Virtual_TurnTable *vtt)
784 {
785         if (vtt->block_ctr > vtt->block_max) vtt->last_block_recorded=vtt->block_max;
786         else vtt->last_block_recorded=vtt->block_ctr;
787         
788         globals.rec_len=vtt->last_block_recorded*vtt->samples_per_block;
789 }
790
791 /* Virtual_TurnTable::() : See above and guess ;) */
792
793 void vtt_reset_rec_pos(Virtual_TurnTable *vtt)
794 {
795         vtt->last_block_recorded=0;
796         globals.rec_len=0;
797 }
798
799 /* Virtual_TurnTable::save() : Saves a recorded scratch. If the mix == 1
800    then with loop data mixed else unmixed raw scratch.
801 */
802
803 int vtt_save(Virtual_TurnTable *vtt, char* filename, int mix)
804 {
805         wav_sig out_wav;
806         int16_t *ptr;
807         
808         out_wav.srate=44100;
809         out_wav.chans=1;
810         out_wav.depth=16;
811         out_wav.bps=88200;
812         out_wav.blkalign=2;
813         out_wav.len=vtt->last_block_recorded*vtt->deviceblocksize;
814         out_wav.sofar=out_wav.len;
815         
816 //      sprintf(out_wav.name, "%s%02i.wav", file_name, file_ctr);       
817         strcpy(out_wav.name, filename);
818         
819         if (!open_wav_rec(&out_wav))
820         {
821                 return(1);
822         }
823         
824         vtt->block_ctr=0;
825         vtt->store_pos=globals.rec_buffer;
826         vtt->mix_pos=globals.loop_data;
827         
828 #ifndef BIG_ENDIAN_MACHINE
829         if (mix)
830 #endif  
831         vtt->samplebuffer=(int16_t *) malloc(vtt->deviceblocksize);
832         
833         while (vtt->block_ctr<vtt->last_block_recorded)
834         {
835                 ptr=vtt_get_next_storage_block(vtt);
836                 if (mix)
837                 {
838                         memcpy(vtt->samplebuffer, ptr, vtt->deviceblocksize);
839                         vtt_add_mix(vtt, vtt->samplebuffer);
840 #ifdef BIG_ENDIAN_MACHINE
841                         swapbuffer(vtt->samplebuffer, vtt->samples_per_block);
842 #endif                  
843                         fwrite(vtt->samplebuffer, vtt->deviceblocksize, 1, out_wav.handle); 
844                 }
845                 else
846                 {
847 #ifdef BIG_ENDIAN_MACHINE
848                         memcpy(vtt->samplebuffer, ptr, vtt->deviceblocksize);
849                         swapbuffer(vtt->samplebuffer, vtt->samples_per_block);
850                         fwrite(vtt->samplebuffer, vtt->deviceblocksize, 1, out_wav.handle);                     
851 #else
852                         fwrite(ptr, vtt->deviceblocksize, 1, out_wav.handle);
853
854 #endif
855                 }
856                 wav_progress_update(((gfloat) vtt->block_ctr)/((gfloat) vtt->last_block_recorded));
857         }
858
859 #ifndef BIG_ENDIAN_MACHINE      
860         if (mix)
861 #endif  
862                 free(vtt->samplebuffer);
863         
864         wav_progress_update(0);
865         
866         wav_close(out_wav.handle);
867         return(0);
868 }