/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /* synth - the synthesizer treatment for YOUR wavefiles! */ /* term project for Computational Physics */ /* spring 1997 */ /* by Richard Metzler */ /*_________________________________________________________________*/ /*-----------------------------------------------------------------*/ /* include-files */ /*-----------------------------------------------------------------*/ #include #include #include #include "Xgraphics.h" #include "/usr2/people/metzler/synth/AFsp-V2R2/include/libtsp.h" /*-----------------------------------------------------------------*/ /* declarations */ /*-----------------------------------------------------------------*/ /* GUI windows and worlds */ Window mainwindow, freqwindow, ampwindow,filtwindow; World mainworld, mainwrite; World fvalues, feg, avalues, aeg, ivalues, ieg; XEvent mainmenu; /* functions for envelopes etc. */ float env(float lvl0, float lvl1,float lvl2, float lvl3, float lvl4, float time1, float time2, float time3, float time4, float time); float lfo(int form, float offset,float pos,float amp, float freq, float time); /* subroutines for editing parameters */ void mainrenew(); void freqpage(); void frenew(char menu, float ftmpfloat); void freqwrite(); void amppage(); void arenew(char amenu, float atmpfloat); void awrite(); void filtpage(); void irenew(char menu, float tmpfloat); void iwrite(); void drawenv(World w, float lvl0, float lvl1, float lvl2, float lvl3, float lvl4, float tm1, float tm2, float tm3, float tm4); /* subroutines for calculating modified wave file */ void recalculate(); float timestretch(float time, float pos); float lint(float y[], float x); float resfct(float f,float f0, float resonance); /* functions from fftpack */ void srffti_(int *n, float wsave[]); void srfftf_(int *n, float r[], float wsave[]); void srfftb_(int *n, float r[], float wsave[]); /* some flags */ int done = 0; int stop = 0; /* names for input and output files */ char infile[60] = "in.wav"; char tempfile[30] = "tmp.wav"; char tem2file[30] = "tm2.wav"; char outfile[60]= "out.wav"; AFILE *inptr; AFILE *tmpptr; AFILE *outptr; /* counters for old and new sample */ long int channels; long int length1,length2; /* sample rate */ float samplerate; /* parameters */ float flvl0 = 0.5, flvl1=0.5,flvl2=0.5,flvl3=0.5,flvl4=0.5; float ftime1=0.25,ftime2=0.5,ftime3=0.75,ftime4=1.0; float flforate=0.3,flfooffset=0.2,flfoamp= 0.00; int flfoform= 1; float alvl0=0,alvl1=1.0, alvl2=0.8, alvl3=0.7,alvl4=0.0; float atime1=0.05,atime2=0.15,atime3=.75,atime4=1.0; float alforate= 0.3,alfooffset=0.2, alfoamp = 0.0; int alfoform=1; float ilvl0=0,ilvl1=1,ilvl2=0.8,ilvl3=0.7,ilvl4=0.0; float itime1=0.1, itime2=0.25, itime3=0.75, itime4=1.0; float resonance=0; /*-----------------------------------------------------------------*/ /* main menu */ /*-----------------------------------------------------------------*/ void main(int argc, char* argv[3]) { int j; char wstring[40]; InitX(); mainwindow = CreateWindow(500,265,"Synth - Main Menu"); freqwindow = CreateWindow(600, 530, "Frequency menu"); ampwindow = CreateWindow(600, 530, "Amplitude menu"); filtwindow = CreateWindow(600, 465, "Filter menu"); if(argc>1) {strcpy(infile, argv[1]);} if(argc>2) {strcpy(outfile,argv[2]);} if(argc>3) {fprintf(stderr, "Usage: synth [] []\n"); fprintf(stderr, "Additional arguments ignored\n");} /* show parameters of input file */ inptr= AFopenRead(infile, &length1, &channels, &samplerate, NULL); AFclose(inptr); mainwrite= CreateWorld(mainwindow, 0, 0, 300, 260, 0.0,0.0,300.0,260.0,0,0); mainrenew(); ShowWindow(mainwindow); while(done == 0) { if (GetEvent(&mainmenu,1)){ switch(mainmenu.type) { case Expose: mainrenew(); break; case KeyPress: switch(ExtractChar(mainmenu)){ case 'r': recalculate(); mainrenew(); break; case 'f': freqpage(); mainrenew(); break; case 'a': amppage(); mainrenew(); break; case 'i': filtpage(); mainrenew(); break; case 'x': done = 1; break; } /*switch*/ } /*switch */ } /*if*/ } /*while*/ ExitX(); } /* end of main*/ /*----- ---------------------------------------*/ /* mainrenew writes stuff to the main menu when necessary */ /*----- ---------------------------------------*/ void mainrenew() { char wstring[60]; sprintf(wstring,"Input file: %s",infile); WDrawString(mainwrite,50, 33, wstring, 1); sprintf(wstring,"Length: %i samples",length1); WDrawString(mainwrite,50, 66, wstring,1); sprintf(wstring,"Sample rate: %6.2f Hz", samplerate); WDrawString(mainwrite,50, 100,wstring,1); sprintf(wstring,"Channels: %i",channels); WDrawString(mainwrite,50, 133,wstring,1); sprintf(wstring,"Output file: %s",outfile); WDrawString(mainwrite,50, 166,wstring,1); InitButtons(mainwindow, "b,recalculate,r,b,frequency page,f,b,amplitude page,\ a,b,filter page,i,b,exit,x",200); return; } /*----------------------------------------------------------------*/ /* subroutines for calculating new wave file */ /*----------------------------------------------------------------*/ /*------ ---------------*/ /* recalculate basically does all the work... */ /*------ ---------------*/ void recalculate() { float pos,time; int i,j,l,m,n; int nsamp; int blocksize; float x, xtemp[9]; int xnr, xcount=0; float y[2050], y2a[2050]; float sampbuff[4100],fftbuff[4100],backbuff[4100]; float wtemp[8300]; float yout[8200]; float sampout[16400]; float cutoff; char wstring[40]; /*---- -----------*/ /* 1st task: frequency */ /*---- -----------*/ /* important: always proclaim that you ARE working ;-) */ WDrawString(mainwrite,50, 250,"Working... ",1); inptr= AFopenRead(infile, &length1, &channels, &samplerate, NULL); tmpptr = AFopenWrite(tempfile, 261, channels, samplerate, NULL); for(j=0;j2047) { return (2047-x)*y[2046]+ (x-2046)*y[2047];} else {return (xround+1.0-x)*y[xint] + (x - xround)*y[xint+1];} } /*---------------------------------------------------------------*/ /* resonance function */ float resfct(float f,float f0, float resonance) { float r; float eps = 1e-8; float damp = 0.95; /* prevents resonance catastrophe */ r = 2*f0*f0*(1 - damp*resonance); return (f0*f0 +eps)/(sqrt(pow((f*f -f0*f0),2)+ r*f*f)+eps); /* eps prevents numerical divergence */ } /*---------------------------------------------------------------*/ /* envelope generator */ float env(float lvl0, float lvl1,float lvl2, float lvl3, float lvl4, float time1, float time2, float time3, float time4, float time) { if(time <= time1) {if (time1==0.0) return lvl1; else return lvl0 + (time/time1)*(lvl1-lvl0);} else if(time <=time2) return lvl1 - (lvl1-lvl2)*(time - time1)/(time2 - time1); else if(time <=time3) return lvl2 - (lvl2-lvl3)*(time - time2)/(time3 - time2); else if(time <= time4) return lvl3 - (lvl3-lvl4)*(time - time3)/(time4 - time3); else return lvl4; } /*---------------------------------------------------------------*/ /* low frequency oscillator */ float lfo(int form, float offset,float pos, float amp, float freq, float time) { float pi = 3.1415927; float modulo = (freq*time) -(float)((int)(freq*time)); float stor; if(form == 1){ stor=amp*sin(2*pi*freq*time);} else if(form ==2){ if(modulo<=0.5) stor = -amp; else stor= amp;} else if(form ==3) { stor= 2*amp*(modulo-0.5);} else if(form ==4){ if(modulo<0.5) stor = amp*(1 + 4*modulo); else stor = amp*(3 - 4*modulo); } if((pos+0.1)1.0) tempfloat = 1.0; frenew(fmenu, tempfloat); /* assign tempfloat to corresponding parameter */ break; case 'x': leave =1; HideWindow(freqwindow); break; }; /*switch */ }/*switch*/ }/*if*/ }/*while */ } /*-------------------------------------------------------------------*/ /* frenew updates values of parameters, calls freqwrite */ void frenew(char menu, float tmpfloat) { switch(menu){ case 'a': flvl1 = tmpfloat;break; case 'b': flvl2 = tmpfloat;break; case 'c': flvl3 = tmpfloat;break; case 'd': flvl4 = tmpfloat;break; case 'e': ftime1 = tmpfloat; if (ftime1> ftime2) ftime1= ftime2; break; case 'f': ftime2 = tmpfloat; if(ftime2ftime3) ftime2=ftime3; break; case 'g': ftime3 = tmpfloat; if(ftime3ftime4) ftime3=ftime4; break; case 'h': ftime4 = tmpfloat; if(ftime41.0) tempfloat = 1.0; arenew(amenu, tempfloat); /* assign tempfloat to corresponding parameter */ break; case 'x': leave =1; HideWindow(ampwindow); break; }; /*switch */ }/*switch*/ }/*if*/ }/*while */ } /*-------------------------------------------------------------------*/ /* arenew updates values of parameters, calls awrite to print */ /* them and draw envelope */ void arenew(char menu, float tmpfloat) { switch(menu){ case 'a': alvl1 = tmpfloat;break; case 'b': alvl2 = tmpfloat;break; case 'c': alvl3 = tmpfloat;break; case 'd': alvl4 = tmpfloat;break; case 'e': atime1 = tmpfloat; if (atime1>atime2) atime1= atime2; break; case 'f': atime2 = tmpfloat; if(atime2atime3) atime2=atime3; break; case 'g': atime3 = tmpfloat; if(atime3atime4) atime3=atime4; break; case 'h': atime4 = tmpfloat; if(atime41.0) tempfloat = 1.0; irenew(imenu, tempfloat); /* assign tempfloat to corresponding parameter */ break; case 'x': leave =1; HideWindow(filtwindow); break; }; /*switch */ }/*switch*/ }/*if*/ }/*while */ } /*-------------------------------------------------------------------*/ /* irenew updates values of parameters, calls iwrite() */ void irenew(char menu, float tmpfloat) { switch(menu){ case 'a': ilvl1 = tmpfloat;break; case 'b': ilvl2 = tmpfloat;break; case 'c': ilvl3 = tmpfloat;break; case 'd': ilvl4 = tmpfloat;break; case 'e': itime1 = tmpfloat; if (itime1>itime2) itime1= itime2; break; case 'f': itime2 = tmpfloat; if(itime2itime3) itime2=itime3; break; case 'g': itime3 = tmpfloat; if(itime3itime4) itime3=itime4; break; case 'h': itime4 = tmpfloat; if(itime4