/* * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd * http://www.trevorwishart.co.uk * http://www.composersdesktop.com * This file is part of the CDP System. The CDP System is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The CDP System is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the CDP System; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* floatsam version*/ #include #include #include #include #include #include #include #include #include #include #include #include #if defined unix || defined __GNUC__ #define round lround #endif //TW COMMENT : phase as used here, with vals >1 or <-1 (meaning above zero or below zero) in intrinsically 'int' // phase is also not 'float' elsewhere, // To avoid the construction "switch((int)phase)", I've made phase 'int' everywhere, casting in situ where ness. //static int distort_func(float *b,int tthis,int i,float phase,int lastzero,float cyclemax,dataptr dz); static int distort_func(float *b,int tthis,int i,int phase,int lastzero,float cyclemax,dataptr dz); //static int distort_func_crosbuf(int tthis,int i,float phase,int lastzero,float cyclemax,int oldbufcnt,dataptr dz); static int distort_func_crosbuf(int tthis,int i,int phase,int lastzero,float cyclemax,int oldbufcnt,dataptr dz); static int sinusoid(int tthis,int lastzero,float cyclemax,int endcycle,dataptr dz); static int end_sinusoid(int tthis,int lastzero,float cyclemax,int newbufcnt,int oldbufcnt,dataptr dz); static int genpulse(int step,float maxamp,float *bufptr,float *bufend); static int triangle(float *b,int lastzero,float cyclemax,int endcycle); static int end_triangle(int tthis,int lastzero,float cyclemax,int newbufcnt,int oldbufcnt,dataptr dz); //static int exaggerate(int lastzero,int thiszero,float phase,float *b,double powfac); static int exaggerate(int lastzero,int thiszero,int phase,float *b,double powfac); static int do_exagg (double lastmax,int lastpos,double thismax,int thispos,double powfac,float *b); //static int do_exagg2(float phase,int lastpos,int thispos,double powfac,float *b); static int do_exagg2(int phase,int lastpos,int thispos,double powfac,float *b); //static int end_exagg(int tthis,int lastzero,int newbufcnt,int oldbufcnt,double powfac,float phase,dataptr dz); static int end_exagg(int tthis,int lastzero,int newbufcnt,int oldbufcnt,double powfac,int phase,dataptr dz); static int get_powfac(int lastzero,int thiszero,dataptr dz); /************************* DO_DISTORT *********************************** * * Works on SINGLE HALF wavecycles. * * This looks for single half-wavecycles, and does not change there * number (or their phase) in the output. It therefore resets the * input & output phase on each entry. */ int do_distort(int tthis,int is_last,int *lastzero,float *cyclemax,dataptr dz) { int exit_status; register int i = *lastzero; int oldbufcnt, lastmarker; int phase = 1; float *b = dz->sampbuf[tthis]; int samples = dz->buflen; if(is_last) samples = dz->ssampsread; //TW CHANGED while(smpflteq(b[i],0.0) && i 0) { if(b[i]>*cyclemax) *cyclemax=b[i]; i++; } else { if((exit_status = distort_func(b,tthis,i,phase,*lastzero,*cyclemax,dz))<0) return(exit_status); i = lastmarker = reset(i,samples,b,lastzero,cyclemax); if(b[i]<0) phase=-1; } break; case(-1): if(b[i] < 0) { if(b[i]<*cyclemax) *cyclemax=b[i]; i++; } else { if((exit_status = distort_func(b,tthis,i,phase,*lastzero,*cyclemax,dz))<0) return(exit_status); i = lastmarker = reset(i,samples,b,lastzero,cyclemax); if(b[i]>0) phase=1; } break; } } if(!is_last) { oldbufcnt = dz->buflen - *lastzero; b = dz->sampbuf[!tthis]; samples = dz->ssampsread; i = 0; switch(phase) { case(1): while(i < samples) { if(b[i]>0) { if(b[i]>*cyclemax) *cyclemax = b[i]; i++; } else break; } break; case(-1): while(i < samples) { if(b[i]<0) { if(b[i]<*cyclemax) *cyclemax = b[i]; i++; } else break; } break; } if((exit_status = distort_func_crosbuf(tthis,i,phase,*lastzero,*cyclemax,oldbufcnt,dz))<0) return(exit_status); i = lastmarker = reset(i,samples,dz->sampbuf[!tthis],lastzero,cyclemax); } return(FINISHED); } /*************************** DISTORT_FUNC ******************************/ int distort_func(float *b,int tthis,int i,int phase,int lastzero,float cyclemax,dataptr dz) { int exit_status; register int j; int halfcycle, step; float clipmax; switch(dz->mode) { case(DISTORT_SQUARE_FIXED): clipmax = FCLIPMAX * (float)phase; for(j=lastzero;j 3) { if((exit_status = triangle(b,lastzero,clipmax,i))<0) return(exit_status); } break; case(DISTORT_TRIANGLE): if(i - lastzero > 3) { if((exit_status = triangle(b,lastzero,cyclemax,i))<0) return(exit_status); } break; case(DISTORT_INVERT_HALFCYCLE): for(j=lastzero;jiparam[DISTORT_PULSE],halfcycle); if((exit_status = genpulse(step,cyclemax,b+lastzero,b+i))<0) return(exit_status); break; case(DISTORT_SINE): if(i - lastzero > 5) { if((exit_status = sinusoid(tthis,lastzero,cyclemax,i,dz))<0) return(exit_status); } break; case(DISTORT_EXAGG): if(dz->brksize[DISTORT_POWFAC] && (exit_status = get_powfac(lastzero,i,dz))<0) return(exit_status); if((exit_status = exaggerate(lastzero,i,phase,dz->sampbuf[tthis],dz->param[DISTORT_POWFAC]))<0) return(exit_status); break; default: sprintf(errstr,"Unknown case in distort_func()\n"); return(PROGRAM_ERROR); } return(FINISHED); } /************************ DISTORT_FUNC_CROSBUF **********************/ int distort_func_crosbuf(int tthis,int i,int phase,int lastzero,float cyclemax,int oldbufcnt,dataptr dz) { int exit_status; register int j; int end_bit, halfcycle, step; float *buf = dz->sampbuf[tthis]; /*int*/float clipmax; switch(dz->mode) { case(DISTORT_SQUARE_FIXED): clipmax = (float)(FCLIPMAX * (float)phase); for(j=lastzero;jbuflen; j++) buf[j] = clipmax; buf = dz->sampbuf[!tthis]; for(j=0;jbuflen; j++) buf[j] = cyclemax; buf = dz->sampbuf[!tthis]; for(j=0;j 3) { if((exit_status = end_triangle(tthis,lastzero,clipmax,i,oldbufcnt,dz))<0) return(exit_status); } break; case(DISTORT_TRIANGLE): if(oldbufcnt + i > 3) { if((exit_status = end_triangle(tthis,lastzero,cyclemax,i,oldbufcnt,dz))<0) return(exit_status); } break; case(DISTORT_INVERT_HALFCYCLE): for(j=lastzero;jbuflen; j++) buf[j] = cyclemax - buf[j]; buf = dz->sampbuf[!tthis]; for(j=0;jbuflen - lastzero; halfcycle = i + end_bit; step = min((int)dz->iparam[DISTORT_PULSE],halfcycle); if(step > end_bit) { if((exit_status = genpulse(end_bit,cyclemax,buf+lastzero,buf+dz->buflen))<0) return(exit_status); buf = dz->sampbuf[!tthis]; if((exit_status = genpulse(step - end_bit,cyclemax,buf,buf+i))<0) return(exit_status); } else { if((exit_status = genpulse(end_bit,cyclemax,buf + lastzero,buf + dz->buflen))<0) return(exit_status); buf = dz->sampbuf[!tthis]; if((exit_status = genpulse(0,cyclemax,buf,buf+i))<0) return(exit_status); } break; case(DISTORT_SINE): if(oldbufcnt + i > 5) { if((exit_status = end_sinusoid(tthis,lastzero,cyclemax,i,oldbufcnt,dz))<0) return(exit_status); } break; case(DISTORT_EXAGG): if(dz->brksize[DISTORT_POWFAC] && (exit_status = get_powfac(lastzero,dz->buflen+i,dz))<0) return(exit_status); if((exit_status = end_exagg(tthis,lastzero,i,oldbufcnt,dz->param[DISTORT_POWFAC],phase,dz))<0) return(exit_status); break; default: sprintf(errstr,"Unknown case in distort_func_crosbuf()\n"); return(PROGRAM_ERROR); } return(FINISHED); } /***************************** SINUSOID ****************************** * * Create sinusoidal half-wave, over half-cycle. */ int sinusoid(int tthis,int lastzero,float cyclemax,int endcycle,dataptr dz) { float *bb = dz->sampbuf[tthis]; int i, j, start = lastzero; /* 1 */ int half_cyclecnt = endcycle - lastzero; /* 2 */ double index_factor = (double)SINETABLEN/(double)half_cyclecnt; for(j=start, i=0; jparray[DISTORT_SIN][round(i * index_factor)] * cyclemax); return(FINISHED); } /*********************** END_SINUSOID ***************************/ int end_sinusoid(int tthis,int lastzero,float cyclemax,int newbufcnt,int oldbufcnt,dataptr dz) { float *bb = dz->sampbuf[tthis]; int i, j, start = lastzero; int half_cyclecnt = oldbufcnt + newbufcnt; double index_factor = (double)SINETABLEN/(double)half_cyclecnt; for(j=start, i=0; jbuflen; j++,i++) bb[j] = /*round*/(float)(dz->parray[DISTORT_SIN][round(i * index_factor)] * cyclemax); bb = dz->sampbuf[!tthis]; for(j=0; jparray[DISTORT_SIN][round(i * index_factor)] * cyclemax); return(FINISHED); } /***************************** GENPULSE ****************************/ int genpulse(int step,float maxamp,float *bufptr,float *bufend) { int n, m, z, sum = 0; float ampval = maxamp; while(sum < step) { n = round(drand48() * MAXWIDTH); /* TRUNCATE */ n++; sum += n; z = min(n,step-sum); for(m=0;msampbuf[tthis]; b[lastzero] = 0.0; /* 1c */ step = (double)cyclemax/(double)(halfcnt); if(middle < dz->buflen) { /* 2 */ for(j=start; jbuflen; j++) { realval -= step; /* 6 */ b[j] = (float)realval; } b = dz->sampbuf[!tthis]; /* 7 */ for(j=0; jbuflen; j++) { realval += step; /* 10 */ b[j] = (float)realval; } middle -= dz->buflen; /* 11 */ b = dz->sampbuf[!tthis]; /* 12 */ for(j=0; j= b[n-1]) n++; lastmax = (double)b[n-1]; lastpos = n-1; if(powfac < 0.0) exit_status = do_exagg2(phase,lastzero+1,lastpos,powfac,b); else exit_status = do_exagg2(phase,lastzero,lastpos,powfac,b); if(exit_status < 0) return(exit_status); while(n < thiszero) { while(b[n] < b[n-1]) { if(++n >= thiszero) { OK = 0; break; } } if(OK) { //thismin = (double)b[n-1]; //minpos = n-1; while(b[n] >= b[n-1]) n++; thismax = (double)b[n-1]; thispos = n-1; if((exit_status = do_exagg(lastmax,lastpos,thismax,thispos,powfac,b))<0) return(exit_status); lastmax = thismax; lastpos = thispos; } else break; } if(powfac < 0.0) exit_status = do_exagg2(phase,lastpos+1,n-1,powfac,b); else exit_status = do_exagg2(phase,lastpos,n-1,powfac,b); if(exit_status < 0) return(exit_status); break; case(-1): while(b[n] <= b[n-1]) n++; lastmax = (double)b[n-1]; lastpos = n-1; if(powfac < 0.0) exit_status = do_exagg2(phase,lastzero+1,lastpos,powfac,b); else exit_status = do_exagg2(phase,lastzero,lastpos,powfac,b); if(exit_status < 0) return(exit_status); while(n < thiszero) { while(b[n] > b[n-1]) { if(++n >= thiszero) { OK = 0; break; } } if(OK) { //thismin = (double)b[n-1]; //minpos = n-1; while(b[n] <= b[n-1]) n++; thismax = (double)b[n-1]; thispos = n-1; if((exit_status = do_exagg(lastmax,lastpos,thismax,thispos,powfac,b))<0) return(exit_status); lastmax = thismax; lastpos = thispos; } else break; } if(powfac < 0.0) exit_status = do_exagg2(phase,lastpos+1,n-1,powfac,b); else exit_status = do_exagg2(phase,lastpos,n-1,powfac,b); if(exit_status < 0) return(exit_status); break; } return(FINISHED); } /****************************** DO_EXAGG ******************************/ int do_exagg (double lastmax,int lastpos,double thismax,int thispos,double powfac,float *b) { double maxdif = thismax - lastmax; double posdif = thispos - lastpos; double local_max, rati_o; int n, m; for(n = lastpos+1, m = 1; nsampbuf[tthis] + lastzero; float *bnew = dz->sampbuf[!tthis]; float *btemp = dz->sampbuf[2]; memmove((char *)btemp,(char *)bold,oldbufcnt * sizeof(float)); btemp += oldbufcnt; memmove((char *)btemp,(char *)bnew,newbufcnt * sizeof(float)); exaggerate(0,oldbufcnt+newbufcnt,phase,dz->sampbuf[2],powfac); btemp = dz->sampbuf[2]; /* copy the transformed material back to where it came from */ memmove((char *)bold,(char *)btemp,oldbufcnt * sizeof(float)); btemp += oldbufcnt; memmove((char *)bnew,(char *)btemp,newbufcnt * sizeof(float)); return(FINISHED); } /************************ GET_POWFAC *******************************/ int get_powfac(int lastzero,int thiszero,dataptr dz) { double thistime; thistime = (double)(dz->total_samps_read - dz->ssampsread - dz->buflen); /* START OF BUF IN USE */ thistime += ((double)(thiszero + lastzero)/2.0); /* MEAN OFFSET OF CYCLE IN CURRENT BUF */ thistime /= (double)dz->infile->srate; return read_value_from_brktable(thistime,DISTORT_POWFAC,dz); } //TW UPDATE : NEW FUNCTION /************************ DISTORT_OVERLOAD *******************************/ // NOV 2002: NEED TO FIX buffers to float, MAXSAMP to F_MAXSAP, (short) to THINGY!! int distort_overload(dataptr dz) { int exit_status, n; // short *buf; float *buf; double *tab = NULL; double maxgate, mingate, inc_ratio, time = 0.0, timestep = 0.01, tabposd = 0.0, normaliser, k; int stepper, tabpos = 0, in_maxgate = 0, in_mingate = 0; buf = dz->sampbuf[0]; if(dz->mode==OVER_SINE) tab = dz->parray[0]; maxgate = dz->param[DISTORTER_MULT]; mingate = -maxgate; inc_ratio = (double)DISTORTER_TABLEN/(double)dz->infile->srate; stepper = (int)round((double)dz->infile->srate * timestep); normaliser = ((double)F_MAXSAMP/(maxgate + 1.0)) /* TEST * 0.9 */; // while(dz->bytes_left > 0) { while(dz->samps_left > 0) { // if((exit_status = read_bytes((char *)dz->bigbuf,dz))<0) if((exit_status = read_samps(dz->bigbuf,dz))<0) return(exit_status); switch(dz->mode) { case(OVER_NOISE): for(n=0;nssampsread;n++) { if(!(n%stepper)) { if((exit_status = read_values_from_all_existing_brktables(time,dz))<0) return(exit_status); time += timestep; } if((double)buf[n] >= maxgate) { k = 1.0 - (drand48() * dz->param[DISTORTER_DEPTH]); // buf[n] = (short)round(k * maxgate); buf[n] = (float)(k * maxgate); } else if((double)buf[n] <= mingate) { k = 1.0 - (drand48() * dz->param[DISTORTER_DEPTH]); // buf[n] = (short)round(k * mingate); buf[n] = (float)(k * mingate); } // buf[n] = (short)round(buf[n] * normaliser); buf[n] = (float)(buf[n] * normaliser); } break; case(OVER_SINE): for(n=0;nssampsread;n++) { if(!(n%stepper)) { if((exit_status = read_values_from_all_existing_brktables(time,dz))<0) return(exit_status); time += timestep; } if((double)buf[n] >= maxgate) { if(!in_maxgate) { tabpos = 0; tabposd = 0.0; in_mingate = 0; in_maxgate = 1; } k = 1.0 + (tab[tabpos] * dz->param[DISTORTER_DEPTH]); // buf[n] = (short)round(k * maxgate); buf[n] = (float)(k * maxgate); } else if((double)buf[n] <= mingate) { if(!in_mingate) { tabpos = 0; tabposd = 0.0; in_maxgate = 0; in_mingate = 1; } k = 1.0 + (tab[tabpos] * dz->param[DISTORTER_DEPTH]); // buf[n] = (short)round(k * mingate); buf[n] = (float)(k * mingate); } else { in_maxgate = 0; in_mingate = 0; } // buf[n] = (short)round(buf[n] * normaliser); buf[n] = (float)(buf[n] * normaliser); tabposd = fmod(tabposd + (dz->param[DISTORTER_FRQ] * inc_ratio),(double)DISTORTER_TABLEN); tabpos = round(tabposd) % DISTORTER_TABLEN; } break; } if(dz->ssampsread > 0) { if((exit_status = write_samps(dz->bigbuf,dz->ssampsread,dz))<0) return(exit_status); } } return(FINISHED); }