2 terminatorX - realtime audio scratching software
3 Copyright (C) 1999 Alexander König
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 Description: This implements the new virtual turntable class. It replaces
22 the old turntable.c from terminatorX 3.2 and earlier. The lowpass
23 filter is based on some sample code by Paul Kellett
24 <paul.kellett@maxim.abel.co.uk>
28 #include "tX_global.h"
32 #include "tX_wavfunc.h"
41 extern void build_vtt_gui(vtt_class *);
42 extern void gui_set_name(vtt_class *vtt, char *newname);
43 extern void gui_set_filename(vtt_class *vtt, char *newname);
44 extern void delete_gui(vtt_class *vtt);
45 extern void gui_update_display(vtt_class *vtt);
46 extern void gui_clear_master_button(vtt_class *vtt);
47 extern void cleanup_vtt(vtt_class *vtt);
49 int vtt_class::vtt_amount=0;
50 list <vtt_class *> vtt_class::main_list;
51 list <vtt_class *> vtt_class::render_list;
52 int16_t* vtt_class::mix_out_buffer=NULL;
53 f_prec * vtt_class::mix_buffer=NULL;
54 int vtt_class::samples_in_mix_buffer=0;
55 pthread_mutex_t vtt_class::render_lock=PTHREAD_MUTEX_INITIALIZER;
56 pthread_mutex_t vtt_class::main_lock=PTHREAD_MUTEX_INITIALIZER;
57 f_prec vtt_class::master_volume=1.0;
58 f_prec vtt_class::res_master_volume=1.0;
59 //f_prec vtt_class::saturate_fac=((f_prec) SAMPLE_MAX-SAMPLE_BORDER)*1.0/FLT_MAX;
60 f_prec vtt_class::saturate_fac=0.1;
61 int vtt_class::do_saturate=0;
62 vtt_class * vtt_class::sync_master=NULL;
63 int vtt_class::master_triggered=0;
64 int vtt_class::master_triggered_at=0;
65 vtt_class * vtt_class::focused_vtt=NULL;
66 f_prec vtt_class::mix_max=0;
67 f_prec vtt_class::vol_channel_adjust=1.0;
69 #define GAIN_AUTO_ADJUST 0.8
71 vtt_class :: vtt_class (int do_create_gui)
74 sprintf (name, "Turntable %i", vtt_amount);
75 strcpy(filename, "NONE");
91 x_control=CONTROL_SCRATCH;
92 y_control=CONTROL_CUTOFF;
98 lp_setup(lp_gain, lp_reso, lp_freq);
106 // pthread_mutex_lock(&main_lock);
107 main_list.push_back(this);
108 // pthread_mutex_unlock(&main_lock);
116 set_master_volume(globals.volume);
117 set_output_buffer_size(samples_in_mix_buffer);
120 vtt_class :: ~vtt_class()
123 // pthread_mutex_lock(&main_lock);
124 main_list.remove(this);
125 // pthread_mutex_unlock(&main_lock);
126 if (buffer) free(buffer);
127 if (output_buffer) free(output_buffer);
133 void vtt_class :: set_name(char *newname)
135 strcpy(name, newname);
136 gui_set_name(this, name);
139 void vtt_class :: set_file_data(char *newfilename, int16_t *newbuffer, int samples)
141 if (is_playing) stop();
143 if (buffer) free(buffer);
145 samples_in_buffer=samples;
148 strcpy(filename, newfilename);
151 gui_set_filename(this, newfilename);
152 gui_update_display(this);
154 ec_set_length(ec_length);
157 int vtt_class :: set_output_buffer_size(int newsize)
159 if (output_buffer) free(output_buffer);
160 output_buffer = (float *) malloc (sizeof(float)*newsize);
161 end_of_outputbuffer = output_buffer + newsize; //size_t(sizeof(float)*(newsize));
163 samples_in_outputbuffer=newsize;
164 inv_samples_in_outputbuffer=1.0/samples_in_outputbuffer;
166 if (output_buffer) return(0);
170 void vtt_class :: set_volume(f_prec newvol)
173 res_volume=rel_volume*res_master_volume;
176 void vtt_class :: recalc_volume()
178 res_volume=rel_volume*res_master_volume;
181 void vtt_class :: set_pitch(f_prec newpitch)
184 // res_pitch=fabs(globals.pitch)*rel_pitch;
185 res_pitch=globals.pitch*rel_pitch;
187 ec_set_length(ec_length);
190 void vtt_class :: recalc_pitch()
192 // res_pitch=fabs(globals.pitch)*rel_pitch;
193 res_pitch=globals.pitch*rel_pitch;
195 ec_set_length(ec_length);
198 void vtt_class :: set_autotrigger(int newstate)
200 autotrigger=newstate;
203 void vtt_class :: set_loop(int newstate)
208 void vtt_class :: set_controls (int x, int y)
214 void vtt_class :: set_mute(int newstate)
219 void vtt_class :: lp_set_enable (int newstate)
224 void vtt_class :: lp_set_gain (f_prec gain)
227 lp_resgain=lp_gain*lp_autogain;
230 void vtt_class :: lp_set_reso(f_prec reso)
234 lp_b=reso*(1.0+(1.0/lp_a));
235 lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
236 lp_resgain=lp_gain*lp_autogain;
239 void vtt_class :: lp_set_freq(f_prec freq)
244 lp_b=lp_reso*(1.0+(1.0/lp_a));
247 void vtt_class :: lp_setup(f_prec gain, f_prec reso, f_prec freq)
253 lp_b=reso*(1.0+(1.0/lp_a));
255 lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
256 lp_resgain=lp_gain*lp_autogain;
259 void vtt_class :: ec_set_enable(int newstate)
264 void vtt_class :: ec_set_length(f_prec length)
271 ec_res_length=length*samples_in_buffer;
275 ec_res_length=length*samples_in_buffer/res_pitch;
278 if (ec_res_length<0) ec_res_length*=-1;
279 // printf("le: %f\n", ec_res_length);
281 if (ec_res_length>=EC_MAX_BUFFER) ec_res_length=EC_MAX_BUFFER;
283 delay=(int )floor(ec_res_length);
285 ec_delay=&ec_buffer[delay];
288 void vtt_class :: ec_set_feedback(f_prec feedback)
290 ec_feedback=feedback;
293 void vtt_class :: ec_clear_buffer()
297 for (i=0; i<EC_MAX_BUFFER; i++)
304 void vtt_class :: render()
311 if (sense_cycles==0) speed=0;
315 if (lp_enable) render_lp();
316 if (ec_enable) render_ec();
319 f_prec speed_step_last=0;
322 void vtt_class :: render_scratch()
333 // unsigned int pos_a_i;
346 // if (speed != speed_last) printf("%s: from %f to %f.\n", name, speed, speed_last);
348 if (speed != speed_target)
351 speed_step=speed_target-speed_real;
355 if (speed_target != speed_real)
357 speed_real+=speed_step;
358 if ((speed_step<0) && (speed_real<speed_target)) speed_real=speed_target;
360 if ((speed_step>0) && (speed_real>speed_target)) speed_real=speed_target;
364 /* if (speed_real != speed_step_last)
366 printf("last: %f now: %f \n", speed_step_last, speed_real);
367 speed_step_last=speed_real;
370 speed_step_last=pos_f;
374 if ((speed_last==0) && (speed_real !=0))
382 if ((speed_last!=0) && (speed_real==0))
389 if (mute != mute_old)
393 fade_out=1; fade_in=0;
398 fade_in=1; fade_out=0;
408 for (sample =0,out=output_buffer, fade_vol=0.0; sample < samples_in_outputbuffer;sample++, out++, fade_vol+=inv_samples_in_outputbuffer)
410 if ((speed_real!=0) || (fade_out))
424 master_triggered_at=sample;
444 master_triggered_at=sample;
454 pos_a_f=floor(pos_f);
455 pos_i=(unsigned int) pos_a_f;
457 amount_b=pos_f-pos_a_f;
458 amount_a=1.0-amount_b;
467 sample_a=(f_prec) *ptr;
469 if (pos_i == samples_in_buffer)
476 sample_b=(f_prec) *ptr;
479 sample_res=(sample_a*amount_a)+(sample_b*amount_b);
483 sample_res*=fade_vol;
488 sample_res*=1.0-fade_vol;
499 speed_last = speed_real;
503 The following lowpass filter is based on some sample code by
504 Paul Kellett <paul.kellett@maxim.abel.co.uk>
507 void vtt_class :: render_lp()
509 #ifdef NOT_NOT_NOT_USE_3DNOW
515 mmx_gain.s[0]=lp_resgain;
516 mmx_gain.s[1]=lp_resgain;
518 for (sample = (mmx_t *) output_buffer, sample<(mmx_t*) end_of_outputbuffer; sample++)
520 movq_m2r(*sample, mm0);
521 movq_m2r(mmx_gain, mm1);
526 lp_buf0 = lp_a * lp_buf0 + lp_freq * (in + lp_b * (lp_buf0 - lp_buf1));
527 lp_buf1 = lp_a * lp_buf1 + lp_freq * lp_buf0;
534 for (sample = output_buffer; sample<end_of_outputbuffer; sample++)
536 lp_buf0 = lp_a * lp_buf0 + lp_freq * ((*sample)*lp_resgain + lp_b * (lp_buf0 - lp_buf1));
537 lp_buf1 = lp_a * lp_buf1 + lp_freq * lp_buf0;
544 void vtt_class :: render_ec()
550 feed.s[0]=ec_feedback;
551 feed.s[1]=ec_feedback;
555 for (sample = (mmx_t*) output_buffer; sample<(mmx_t*) end_of_outputbuffer; sample++, ec_ptr+=2)
558 if (ec_ptr>ec_delay) ec_ptr=ec_buffer;
560 movq_m2r(*sample, mm1);
561 movq_m2r(*ec_ptr, mm2);
566 movq_r2m(mm2, *sample);
567 movq_r2m(mm2, *ec_ptr);
577 for (i=0, sample = output_buffer; i<samples_in_outputbuffer; i++, sample++, ec_ptr++)
579 if (ec_ptr>ec_delay) ec_ptr=ec_buffer;
581 temp= *sample + (*ec_ptr) *ec_feedback;
588 int vtt_class :: set_mix_buffer_size(int no_samples)
590 list <vtt_class *> :: iterator vtt;
593 if (mix_buffer) free(mix_buffer);
594 mix_buffer=(float *) malloc (sizeof(float)*no_samples);
595 if (mix_out_buffer) free(mix_out_buffer);
596 mix_out_buffer=(int16_t *) malloc (sizeof(int16_t)*no_samples);
597 samples_in_mix_buffer=no_samples;
599 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
601 res|=(*vtt)->set_output_buffer_size(no_samples);
604 if ((!mix_buffer) || (!mix_out_buffer) || res) return(1);
608 int16_t * vtt_class :: render_all_turntables()
610 list <vtt_class *> :: iterator vtt, next;
618 pthread_mutex_lock(&render_lock);
620 switch (render_list.size())
622 case 0: for (sample=0; sample<samples_in_mix_buffer; sample++)
624 mix_out_buffer[sample]=0;
627 /* case 1: vtt=render_list.begin();
631 for (sample=0; sample<samples_in_mix_buffer; sample++)
633 temp=((*vtt)->output_buffer[sample]*(*vtt)->res_volume);
634 if (temp>SAMPLE_BORDER)
641 if (temp<-SAMPLE_BORDER)
647 mix_out_buffer[sample]=(int16_t) temp;
650 for (sample=0; sample<samples_in_mix_buffer; sample++)
652 mix_out_buffer[sample]=(int16_t) ((*vtt)->output_buffer[sample]*(*vtt)->res_volume);
656 vtt=render_list.begin();
659 max=(*vtt)->max_value;
662 for (sample=0; sample<samples_in_mix_buffer; sample++)
664 temp=(*vtt)->output_buffer[sample];
665 mix_buffer[sample]=temp*(*vtt)->res_volume;
667 if (temp>max) max=temp;
668 else if (temp<min) min=temp;
672 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
675 for (sample=0; sample<samples_in_mix_buffer; sample++)
677 mix_buffer[sample]=(*vtt)->output_buffer[sample]*(*vtt)->res_volume;
680 if (master_triggered)
682 pthread_mutex_unlock(&render_lock);
683 // pthread_mutex_lock(&main_lock);
684 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
686 if ((*vtt)->is_sync_client)
688 if ((*vtt)->sync_countdown)
690 (*vtt)->sync_countdown--;
694 (*vtt)->sync_countdown=(*vtt)->sync_cycles;
699 // pthread_mutex_unlock(&main_lock);
700 pthread_mutex_lock(&render_lock);
702 vtt=render_list.begin();
703 for (vtt++; vtt!=render_list.end(); vtt++)
707 max=(*vtt)->max_value;
710 for (sample=0; sample<samples_in_mix_buffer; sample++)
712 temp=(*vtt)->output_buffer[sample];
713 mix_buffer[sample]+=temp*(*vtt)->res_volume;
715 if (temp>max) max=temp;
716 else if (temp<min) min=temp;
720 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
722 for (sample=0; sample<samples_in_mix_buffer; sample++)
724 mix_buffer[sample]+=(*vtt)->output_buffer[sample]*(*vtt)->res_volume;
730 for (sample=0; sample<samples_in_mix_buffer; sample++)
732 temp=(int16_t)mix_buffer[sample];
733 if (temp>SAMPLE_BORDER)
735 printf("sat: %f -> ", temp);
736 temp=SAMPLE_BORDER+(saturate_fac*(temp-SAMPLE_BORDER));
737 printf("%hi\n", int16_t(temp));
741 if (temp<-SAMPLE_BORDER)
743 printf("sat: %f -> ", temp);
744 temp=-SAMPLE_BORDER+(saturate_fac*(temp+ SAMPLE_BORDER));
747 mix_out_buffer[sample]=(int16_t) temp;
753 for (sample=0; sample<samples_in_mix_buffer; sample++)
755 temp=mix_buffer[sample];
756 mix_out_buffer[sample]=(int16_t) temp;
758 if (temp>max) max=temp;
759 else if (temp<min) min=temp;
762 if (min>max) mix_max=min; else mix_max=max;
764 for (sample=0; sample<samples_in_mix_buffer; sample++)
766 mix_out_buffer[sample]=(int16_t)mix_buffer[sample];
774 vtt=render_list.begin();
775 while (vtt!=render_list.end())
780 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
783 pthread_mutex_unlock(&render_lock);
785 return(mix_out_buffer);
788 int vtt_class :: trigger()
790 if (!buffer) return (1);
792 if (!is_playing) pthread_mutex_lock(&render_lock);
794 if (res_pitch>=0) pos_f=0;
798 speed_real=res_pitch;
799 speed_target=res_pitch;
811 master_triggered_at=0;
820 render_list.push_front(this);
824 render_list.push_back(this);
826 pthread_mutex_unlock(&render_lock);
831 int vtt_class :: stop_nolock()
833 // pthread_mutex_lock(&render_lock);
837 pthread_mutex_unlock(&render_lock);
840 render_list.remove(this);
844 // pthread_mutex_unlock(&render_lock);
855 int vtt_class :: stop()
859 pthread_mutex_lock(&render_lock);
863 pthread_mutex_unlock(&render_lock);
868 void vtt_class :: set_sync_master(int master)
872 if (sync_master) sync_master->set_sync_master(0);
878 if (sync_master==this) sync_master=0;
880 gui_clear_master_button(this);
884 void vtt_class :: set_sync_client(int slave, int cycles)
886 is_sync_client=slave;
888 // sync_countdown=cycles;
892 void vtt_class :: set_master_volume(f_prec new_volume)
894 list <vtt_class *> :: iterator vtt;
896 master_volume=new_volume;
897 globals.volume=new_volume;
899 if (main_list.size()>0)
901 // res_master_volume=master_volume/((f_prec) main_list.size());
902 vol_channel_adjust=sqrt((f_prec) main_list.size());
903 res_master_volume=master_volume/vol_channel_adjust;
907 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
909 (*vtt)->recalc_volume();
913 void vtt_class :: set_master_pitch(f_prec new_pitch)
915 list <vtt_class *> :: iterator vtt;
917 globals.pitch=new_pitch;
918 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
920 (*vtt)->recalc_pitch();
924 int vtt_class :: enable_saturate (int newstate)
926 do_saturate=newstate;
929 void vtt_class :: focus_no(int no)
931 list <vtt_class *> :: iterator vtt;
934 for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++)
943 void vtt_class :: focus_next()
945 list <vtt_class *> :: iterator vtt;
949 if (main_list.size())
951 focused_vtt=(*main_list.begin());
956 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++)
958 if ((*vtt)==focused_vtt)
961 if (vtt==main_list.end())
963 focused_vtt=(*main_list.begin());
974 focused_vtt=(*main_list.begin());
977 void vtt_class :: set_scratch(int newstate)
983 sense_cycles=globals.sense_cycles;
994 void vtt_class :: handle_input(int control, f_prec value)
1000 case CONTROL_SCRATCH:
1001 if (do_scratch) speed=value*globals.mouse_speed;
1002 sense_cycles=globals.sense_cycles;
1005 case CONTROL_VOLUME:
1006 temp=rel_volume+MAGIC*value*globals.mouse_speed;
1007 if (temp>1.0) temp=1.0;
1008 else if (temp<0) temp=0;
1012 case CONTROL_CUTOFF:
1013 temp=lp_freq+MAGIC*value*globals.mouse_speed;
1014 if (temp>0.99) temp=0.99;
1015 else if (temp<0) temp=0;
1019 case CONTROL_FEEDBACK:
1020 temp=ec_feedback+MAGIC*value*globals.mouse_speed;
1021 if (temp>1.0) temp=1.0;
1022 else if (temp<0) temp=0;
1023 ec_set_feedback(temp);
1028 void vtt_class :: unfocus()
1033 void vtt_class :: xy_input(f_prec x_value, f_prec y_value)
1035 handle_input(x_control, x_value);
1036 handle_input(y_control, y_value);
1040 #define store(data); if (fwrite((void *) &data, sizeof(data), 1, output)!=1) res+=1;
1042 int vtt_class :: save(FILE * output)
1048 store(is_sync_master);
1049 store(is_sync_client);
1073 #define atload(data); if (fread((void *) &data, sizeof(data), 1, input)!=1) res+=1;
1075 int vtt_class :: load(FILE * input)
1081 atload(is_sync_master);
1082 atload(is_sync_client);
1083 atload(sync_cycles);
1089 atload(autotrigger);
1100 lp_setup(lp_gain, lp_reso, lp_freq);
1104 ec_set_length(ec_length);
1105 atload(ec_feedback);
1106 ec_set_feedback(ec_feedback);
1111 int vtt_class :: save_all(FILE* output)
1114 list <vtt_class *> :: iterator vtt;
1117 store(master_volume);
1118 store(globals.pitch);
1121 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1123 res+=(*vtt)->save(output);
1129 int vtt_class :: load_all(FILE* input)
1131 int res=0, restmp=0;
1132 list <vtt_class *> :: iterator vtt;
1133 unsigned int i, max, size;
1137 while (main_list.size())
1139 delete((*main_list.begin()));
1143 atload(master_volume);
1144 set_master_volume(master_volume);
1145 globals.volume=master_volume;
1146 atload(globals.pitch);
1147 set_master_pitch(globals.pitch);
1149 for (i=0; i<max; i++)
1151 newvtt=new vtt_class(0);
1152 res+=newvtt->load(input);
1153 if (strlen(newvtt->filename))
1155 restmp=load_wav(newvtt->filename, &newbuffer, &size);
1156 if (!restmp) newvtt->set_file_data(newvtt->filename, newbuffer, size/sizeof(int16_t));
1164 int add_vtt(GtkWidget *daddy)
1167 hmmpg = new vtt_class(1);
1168 gtk_box_pack_start(GTK_BOX(daddy), hmmpg->gui.frame, TRUE, TRUE, 0);
1169 gtk_widget_show(hmmpg->gui.frame);