/* * 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 #include #ifdef unix #define round(x) lround((x)) #else #define round(x) cdp_round((x)) #endif #define CALCLIM (0.02) #define MININC (0.002) /* rwd - black hole avoidance */ static int create_vtrans_buffers(dataptr dz); static int create_strans_buffers(dataptr dz); static int read_wrapped_samps_mono(dataptr dz); static int read_wrapped_samps_stereo(dataptr dz); static int strans_process(dataptr dz); static int vtrans_process(dataptr dz); static int do_acceleration(dataptr dz); static int do_vibrato(dataptr dz); static int vtrans_vtrans(dataptr dz); static int read_samps_for_vtrans(dataptr dz); static int write_samps_with_intime_display(float *buffer,int samps_to_write,dataptr dz); static int convert_brkpnts(dataptr dz); static int timevents(int *obufcnt,int intime0,int intime1,double insize0,double insize1,dataptr dz); static double cntevents(int dur,double s0,double s1); static int samesize(int *obufcnt,int intime0,double insize0,double insize1,int duration,dataptr dz); static int integral_times(int *obufcnt,int intime0,int isize,int number,dataptr dz); static int putintval(int *obufcnt,int i,dataptr dz); static int unvarying_times(int *obufcnt,int intime0,double size,int number,dataptr dz); static int getetime(int *obufcnt,int t0,int t1,double s0,double s1,int number,dataptr dz); static double refinesize(double hibound,double lobound,double fnumber,int duration,double error,double insize0); static int putval(int *obufcnt,double pos,dataptr dz); static int sizeq(double f1,double f2); static int change_frame(dataptr dz); static int inv_cntevents(int dur,double s0,double s1); static int force_value_at_end_time(int paramno,dataptr dz); static void splice_end(int obufcnt,dataptr dz); static double interp_read_sintable(double *sintab,double sfindex); /************************* VTRANS_PREPROCESS *****************************/ int vtrans_preprocess(dataptr dz) { double acceltime, tabratio, *p, *pend; int n; switch(dz->mode) { case(MOD_TRANSPOS): case(MOD_TRANSPOS_SEMIT): case(MOD_TRANSPOS_INFO): case(MOD_TRANSPOS_SEMIT_INFO): dz->iparam[UNITSIZE] = dz->insams[0]/dz->infile->channels; dz->param[VTRANS_SR] = (double)dz->infile->srate; dz->iparam[TOTAL_UNITS_READ] = 0; break; case(MOD_ACCEL): acceltime = dz->param[ACCEL_GOALTIME] - dz->param[ACCEL_STARTTIME]; if(acceltime < MINTIME_ACCEL) { sprintf(errstr,"time for acceleration (%lf) must be greater than %.3fsecs\n",acceltime,MINTIME_ACCEL); return(DATA_ERROR); } dz->param[ACCEL_ACCEL] = pow(dz->param[ACCEL_ACCEL],(1.0/(acceltime *(double)dz->infile->srate))); dz->iparam[ACCEL_STARTTIME] = /* convert to time-in-samples */ round(dz->param[ACCEL_STARTTIME] * (double)dz->infile->srate) * dz->infile->channels; break; case(MOD_VIBRATO): tabratio = (double)VIB_TABSIZE/(double)dz->infile->srate; /* converts frq to sintable step */ if(dz->brksize[VIB_FRQ]) { p = dz->brk[VIB_FRQ] + 1; pend = dz->brk[VIB_FRQ] + (dz->brksize[VIB_FRQ] * 2); while(p < pend) { *p *= tabratio; p += 2; } } else dz->param[VIB_FRQ] *= tabratio; if(dz->brksize[VIB_DEPTH]) { /* converts semitones to 8vas */ p = dz->brk[VIB_DEPTH] + 1; pend = dz->brk[VIB_DEPTH] + (dz->brksize[VIB_DEPTH] * 2); while(p < pend) { *p *= OCTAVES_PER_SEMITONE; p += 2; } } else dz->param[VIB_DEPTH] *= OCTAVES_PER_SEMITONE; if((dz->parray[VIB_SINTAB] = (double *)malloc((VIB_TABSIZE + 1) * sizeof(double)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY for vibrato sintable.\n"); return(MEMORY_ERROR); } tabratio = TWOPI/(double)VIB_TABSIZE; /* converts table-step to fraction of 2PI */ for(n=0;nparray[VIB_SINTAB][n] = sin((double)n * tabratio); dz->parray[VIB_SINTAB][n] = 0.0; break; } return(FINISHED); } /************************* CREATE_MODSPEED_BUFFERS *****************************/ int create_modspeed_buffers(dataptr dz) { switch(dz->mode) { case(MOD_TRANSPOS): case(MOD_TRANSPOS_SEMIT): case(MOD_TRANSPOS_INFO): case(MOD_TRANSPOS_SEMIT_INFO): if(dz->brksize[VTRANS_TRANS]==0) return create_strans_buffers(dz); return create_vtrans_buffers(dz); case(MOD_ACCEL): case(MOD_VIBRATO): return create_strans_buffers(dz); default: sprintf(errstr,"Buffers not established for this MOD_SPEED mode.\n"); break; } return(PROGRAM_ERROR); } /************************* CREATE_STRANS_BUFFERS *****************************/ //TW replaced by global //#define FSECSIZE (256) int create_strans_buffers(dataptr dz) { size_t bigbufsize; int framesize; int guardspace = dz->infile->channels * sizeof(float); /* WRAPPED POINT(S) */ bigbufsize = (size_t)Malloc(-1); /* RWD belt'n'braces */ if(dz->infile->channels>STEREO) { sprintf(errstr, "File has too many channels.\n"); return(DATA_ERROR); } if(dz->infile->channels==STEREO) { //TW Safety first: stick to existing secsize-convention for now //6 takes into account STEREO channel-count; no need to realign. //Will do it completely differently when go to 4+ channels framesize = F_SECSIZE * sizeof(float) * 6; if((bigbufsize = (bigbufsize/framesize) * framesize)<=0) bigbufsize = framesize; dz->buflen = (int)(bigbufsize / 3 / sizeof(float)); bigbufsize = dz->buflen * 3 * sizeof(float); dz->iparam[VTRANS_HBUFSIZE] = dz->buflen/2; if((dz->bigbuf = (float *)Malloc(bigbufsize + guardspace)) == 0) { sprintf(errstr,"INSUFFICIENT MEMORY FOR SND BUFFERS.\n"); return(MEMORY_ERROR); } memset((char *)dz->bigbuf,0,bigbufsize + guardspace); /*dz->bigbufsize = dz->bigbufsize/3;*/ dz->sampbuf[TRUE_LBUF] = dz->bigbuf; dz->sampbuf[L_GRDPNT] = dz->sampbuf[TRUE_LBUF]; /* GUARD POINT */ dz->sampbuf[LBUF] = dz->bigbuf + 1; dz->sampbuf[TRUE_RBUF] = dz->sampbuf[LBUF] + dz->iparam[VTRANS_HBUFSIZE]; dz->sampbuf[R_GRDPNT] = dz->sampbuf[TRUE_RBUF]; dz->sampbuf[RBUF] = dz->sampbuf[R_GRDPNT] + 1; dz->sampbuf[INBUF] = dz->sampbuf[RBUF] + dz->iparam[VTRANS_HBUFSIZE]; dz->sampbuf[OUTBUF] = dz->sampbuf[INBUF] + dz->buflen; dz->sampbuf[OBUFEND] = dz->sampbuf[OUTBUF] + dz->buflen; } else { //TW Safety first: stick to existing secsize-convention for now framesize = F_SECSIZE * sizeof(float) * 2; bigbufsize = (bigbufsize/framesize) * framesize; dz->buflen = bigbufsize/2/sizeof(float); /* RWD probably unnecessary, but may be when we move to nChannels */ bigbufsize = dz->buflen * 2 * sizeof(float); if((dz->bigbuf = (float *)malloc(bigbufsize + guardspace)) == 0) { sprintf(errstr, "Can't allocate memory for sound.\n"); return(MEMORY_ERROR); } memset((char *)dz->bigbuf,0,bigbufsize + guardspace); /*dz->bigbufsize /= 2;*/ dz->sampbuf[TRUE_LBUF] = dz->bigbuf; dz->sampbuf[L_GRDPNT] = dz->sampbuf[TRUE_LBUF]; dz->sampbuf[INBUF] = dz->bigbuf + 1; dz->sampbuf[OUTBUF] = dz->sampbuf[INBUF] + dz->buflen; dz->sampbuf[OBUFEND] = dz->sampbuf[OUTBUF] + dz->buflen; } return(FINISHED); } /*************************** CREATE_VTRANS_BUFFERS **************************/ int create_vtrans_buffers(dataptr dz) { size_t bigbufsize; //TW: SAFETY FIRST for now int fsecbytesize = F_SECSIZE * sizeof(float); bigbufsize = (size_t)Malloc(-1); bigbufsize /= dz->bufcnt; //TW: SAFETY FIRST for now bigbufsize = (bigbufsize/fsecbytesize) * fsecbytesize; dz->buflen = bigbufsize/sizeof(float); dz->iparam[UNIT_BUFLEN] = dz->buflen/dz->infile->channels; bigbufsize = dz->buflen * sizeof(float); if((dz->bigbuf = (float *)malloc((bigbufsize * dz->bufcnt) + fsecbytesize)) == NULL) { sprintf(errstr, "Can't allocate memory for sound.\n"); return(MEMORY_ERROR); } dz->sampbuf[INBUF] = dz->bigbuf; dz->sampbuf[OUTBUF] = dz->sampbuf[INBUF] + dz->buflen + F_SECSIZE; return(FINISHED); } /************************* PROCESS_VARISPEED ******************************/ int process_varispeed(dataptr dz) { switch(dz->mode) { case(MOD_ACCEL): return do_acceleration(dz); case(MOD_VIBRATO): return do_vibrato(dz); case(MOD_TRANSPOS): case(MOD_TRANSPOS_SEMIT): case(MOD_TRANSPOS_INFO): case(MOD_TRANSPOS_SEMIT_INFO): if(dz->brksize[VTRANS_TRANS]==0) return strans_process(dz); return vtrans_process(dz); } /* RWD 9:2001 need retval*/ return PROGRAM_ERROR; } /************************* STRANS_PROCESS ******************************/ int strans_process(dataptr dz) { int exit_status; int place; double flplace = 1.0, fracsamp, step; //HEREH double interp; float *obufptr = dz->sampbuf[OUTBUF]; float *obuf = dz->sampbuf[OUTBUF]; float *obufend = dz->sampbuf[OBUFEND]; float *true_lbuf = dz->sampbuf[TRUE_LBUF]; float *true_rbuf; double place_inc = dz->param[VTRANS_TRANS]; switch(dz->mode) { case(MOD_TRANSPOS_INFO): sprintf(errstr,"Output duration = %lf secs\n",dz->duration/dz->param[VTRANS_TRANS]); if(!sloom) { fprintf(stdout,"INFO: END\n"); fflush(stdout); } return(FINISHED); case(MOD_TRANSPOS_SEMIT_INFO): place_inc = pow(2.0,(place_inc * OCTAVES_PER_SEMITONE)); sprintf(errstr,"Output duration = %lf secs\n",dz->duration/place_inc); if(!sloom) { fprintf(stdout,"INFO: END\n"); fflush(stdout); } return(FINISHED); case(MOD_TRANSPOS_SEMIT): place_inc = pow(2.0,(place_inc * OCTAVES_PER_SEMITONE)); break; } switch(dz->infile->channels) { case(MONO): if((exit_status = read_wrapped_samps_mono(dz))<0) return(exit_status); while(dz->ssampsread > 0) { while(flplace < (double)dz->ssampsread) { place = (int)flplace; fracsamp = flplace - (double)place; step = true_lbuf[place+1] - true_lbuf[place]; // interp = round(fracsamp * step); interp = fracsamp * step; *obufptr = (float)(true_lbuf[place] + interp); if(++obufptr >= obufend) { if((exit_status = write_samps(obuf,dz->buflen,dz))<0) return(exit_status); obufptr = obuf; } flplace += place_inc; } if((exit_status = read_wrapped_samps_mono(dz))<0) return(exit_status); flplace -= (double)dz->buflen; } break; case(STEREO): true_rbuf = dz->sampbuf[TRUE_RBUF]; if((exit_status = read_wrapped_samps_stereo(dz))<0) return(exit_status); while(dz->ssampsread > 0) { /* 2 */ while(flplace < (double)dz->ssampsread) { place = (int)flplace; fracsamp = flplace - (double)place; step = true_lbuf[place+1] - true_lbuf[place]; // interp = round(fracsamp * step); interp = fracsamp * step; *obufptr++ = (float)(true_lbuf[place] + interp); step = true_rbuf[place+1] - true_rbuf[place]; // interp = round(fracsamp * step); interp = fracsamp * step; *obufptr++ = (float)(true_rbuf[place] + interp); if(obufptr >= obufend) { if((exit_status = write_samps(obuf,dz->buflen,dz))<0) return(exit_status); obufptr = obuf; } flplace += place_inc; } if((exit_status = read_wrapped_samps_stereo(dz))<0) return(exit_status); flplace -= (double)dz->iparam[VTRANS_HBUFSIZE]; } break; } if(obufptr!=obuf) /* 12 */ return write_samps(obuf,obufptr - obuf,dz); return(FINISHED); } /************************** READ_WRAPPED_SAMPS_MONO *****************************/ int read_wrapped_samps_mono(dataptr dz) { *(dz->sampbuf[L_GRDPNT]) = *(dz->sampbuf[INBUF] + dz->buflen - 1); return read_samps(dz->sampbuf[INBUF], dz); } /************************* READ_WRAPPED_SAMPS_STEREO *****************************/ int read_wrapped_samps_stereo(dataptr dz) { int exit_status; int n, m; float *lbuf = dz->sampbuf[LBUF]; float *rbuf = dz->sampbuf[RBUF]; float *l_grdpnt = dz->sampbuf[L_GRDPNT]; float *r_grdpnt = dz->sampbuf[R_GRDPNT]; *l_grdpnt = *(lbuf + dz->iparam[VTRANS_HBUFSIZE] - 1); *r_grdpnt = *(rbuf + dz->iparam[VTRANS_HBUFSIZE] - 1); if((exit_status = read_samps(dz->sampbuf[INBUF],dz))<0) return(exit_status); for(n = 0, m = 0; n < dz->ssampsread; m++, n+=2) { lbuf[m] = dz->sampbuf[INBUF][n]; rbuf[m] = dz->sampbuf[INBUF][n+1]; } dz->ssampsread /= 2; /* stereo */ return(FINISHED); } /****************************** VTRANS_PROCESS *************************/ int vtrans_process(dataptr dz) { int exit_status; if((exit_status = convert_brkpnts(dz))<0) return(exit_status); if((exit_status = change_frame(dz))<0) return(exit_status); if(dz->mode==MOD_TRANSPOS_INFO || dz->mode==MOD_TRANSPOS_SEMIT_INFO) return(FINISHED); if((exit_status = create_vtrans_buffers(dz))<0) return(exit_status); return vtrans_vtrans(dz); } /****************************** VTRANS_VTRANS *************************/ int vtrans_vtrans(dataptr dz) { int exit_status; int n, m; double *dbrk = dz->brk[VTRANS_TRANS]; int obufcnt = 0; display_virtual_time(0L,dz); if((exit_status = read_samps_for_vtrans(dz))<0) return(exit_status); for(n=1,m=2;nbrksize[VTRANS_TRANS];n++,m+=2) { if((exit_status = timevents(&obufcnt,(int)round(dbrk[m-2]),(int)round(dbrk[m]),dbrk[m-1],dbrk[m+1],dz))!=CONTINUE) break; } if(exit_status < 0) return(exit_status); splice_end(obufcnt,dz); return write_samps_with_intime_display(dz->sampbuf[OUTBUF],obufcnt ,dz); return FINISHED; } /*************************** READ_SAMPS_FOR_VTRANS **************************/ int read_samps_for_vtrans(dataptr dz) { //TW MUST READ EXTRA SECTOR to get wrap-around value float *buffer = dz->sampbuf[INBUF]; int samps_read, samps_to_read = dz->buflen + F_SECSIZE; dz->iparam[UNITS_RD_PRE_THISBUF] = dz->iparam[TOTAL_UNITS_READ]; if((samps_read = fgetfbufEx(buffer, samps_to_read,dz->ifd[0],0)) < 0) { sprintf(errstr, "Can't read from input soundfile.\n"); return(SYSTEM_ERROR); } dz->samps_left -= samps_read; if(samps_read == samps_to_read) { if((sndseekEx(dz->ifd[0],-(int)F_SECSIZE,1))<0) { /* WE'VE READ EXTRA SECTOR,for wrap-around */ sprintf(errstr,"sndseekEx() failed.\n"); return(SYSTEM_ERROR); } samps_read -= F_SECSIZE; //TW: correcting an omission in original dz->samps_left += F_SECSIZE; } dz->total_samps_read += samps_read; dz->iparam[UNITS_READ] = samps_read/dz->infile->channels; dz->iparam[TOTAL_UNITS_READ] += dz->iparam[UNITS_READ]; return(FINISHED); } /*************************** WRITE_SAMPS_WITH_INTIME_DISPLAY ***********************/ int write_samps_with_intime_display(float *buf,int samps_to_write,dataptr dz) { int exit_status; int samps_written; // if((samps_written = fputfbufEx(buf,samps_to_write,dz->ofd))<0) { if(samps_to_write > 0) { if((exit_status = write_samps_no_report(buf,samps_to_write,&samps_written,dz))<0) { sprintf(errstr, "Can't write to output soundfile.\n"); return(SYSTEM_ERROR); } display_virtual_time(dz->total_samps_read,dz); } return(FINISHED); } /************************ CONVERT_BRKPNTS ************************/ int convert_brkpnts(dataptr dz) { int exit_status; double *p, *pend; if((exit_status= force_value_at_zero_time(VTRANS_TRANS,dz))<0) return(exit_status); if((exit_status= force_value_at_end_time(VTRANS_TRANS,dz))<0) return(exit_status); p = dz->brk[VTRANS_TRANS]; pend = p + (dz->brksize[VTRANS_TRANS] * 2); while(p < pend) { *p = (double)round((*p) * dz->param[VTRANS_SR]); /* convert to (mono) sample frame */ p += 2; } if(dz->mode==MOD_TRANSPOS_SEMIT || dz->mode==MOD_TRANSPOS_SEMIT_INFO) { p = dz->brk[VTRANS_TRANS] + 1; while(p < pend) { *p = pow(2.0,(*p) * OCTAVES_PER_SEMITONE); /* convert to ratios */ p += 2; } } return(FINISHED); } /************************** TIMEVENTS *******************************/ /* * Generates event positions from startsize and end size * * Let start-time be T0 and end time be T1 * Let start size be S0 and end size be S1 * * number of event is given by :- * * N = (T1-T0) log S1 * ------- e__ * (S1-S0) S0 * * In general this will be non-integral, and we should * round N to an integer, and recalculate S1 by successive * approximation. * * Then positions of events are given by * * for X = 0 to N (S1-S0) * ----- X * T = (S1T0 - S0T1) S0(T1 - T0) (T1-T0) * s ----------- + ---------- e * (S1 - S0) (S1 - S0) * * If difference in eventsizes input to the main program is very small * * This function calculates the number of events within the time-interval, * and generates the times of these events. */ int timevents(int *obufcnt,int intime0,int intime1,double insize0,double insize1,dataptr dz) { int exit_status; int number; double fnum, fnumber, error, pos; double lobound, hibound; int duration; if(flteq(insize0,0.0) || flteq(insize1,0.0)) { sprintf(errstr,"Event size of zero encountered in pair %lf %lf at time %lf\n", insize0,insize1,(double)intime0/dz->param[VTRANS_SR]); return(DATA_ERROR); } duration = intime1-intime0; if(duration<=0) { sprintf(errstr,"Inconsistent input times [ %lf : %lf ] to timevents()\n", (double)intime0/dz->param[VTRANS_SR],(double)intime1/dz->param[VTRANS_SR]); return(DATA_ERROR); } if(sizeq(insize1,insize0)) /* 1 */ return(samesize(obufcnt,intime0,insize0,insize1,duration,dz)); fnum =cntevents(duration,insize0,insize1); /* 2 */ number = round(fnum); if(number<2) { /* 3 */ pos = (double)(intime0 - dz->iparam[UNITS_RD_PRE_THISBUF]); if(pos >= (double)dz->iparam[UNITS_READ]) { if(dz->samps_left <= 0) return(FINISHED); if((exit_status = read_samps_for_vtrans(dz))<0) return(exit_status); pos -= (double)dz->iparam[UNIT_BUFLEN]; } if((exit_status = putval(obufcnt,pos,dz))<0) return(exit_status); } else { fnumber = (double)number; /* 4 */ error = fabs(fnum - fnumber); /* HIBOUND is a SMALLER value of SIZE to give BIGGER value of NUM-OF-SEGS */ /* LOBOUND is a LARGER value of SIZE to give SMALLER value of NUM-OF-SEGS */ lobound = max(insize1,insize0); /* 5 */ hibound = min(insize1,insize0); if(error > FLTERR) /* 6 */ insize1 = refinesize(hibound,lobound,fnumber,duration,error,insize0); else insize1 = (hibound+lobound)/2; return(getetime(obufcnt,intime0,intime1,insize0,insize1,number,dz)); } /* 7 */ return(CONTINUE); } /*************************** CNTEVENTS *****************************/ double cntevents(int dur,double s0,double s1) { double f1 = (double)dur,f2; if(sizeq(s1,s0)) return((f1*2.0)/(s1+s0)); f2 = s1-s0; f1 /= f2; f2 = s1/s0; f2 = log(f2); f1 *= f2; return(fabs(f1)); } /******************************* SAMESIZE(): ******************************* * * get event positions, if eventsize approx same throughout segment. * *(1) Get average size, find number of events and round to nearest int. *(2) If too many or zero events, do exception. *(3) Recalculate size, and thence event times. */ int samesize(int *obufcnt,int intime0,double insize0,double insize1,int duration,dataptr dz) { int exit_status; int number, isize; double size, pos; /* 1 */ size = (insize0+insize1)/2; number = round((double)duration/size); if(number==0) { /* 2 */ pos = (double)(intime0 - dz->iparam[UNITS_RD_PRE_THISBUF]); if(pos >= (double)dz->iparam[UNITS_READ]) { if(dz->samps_left <= 0) return(FINISHED); if((exit_status = read_samps_for_vtrans(dz))<0) return(exit_status); pos -= (double)dz->iparam[UNIT_BUFLEN]; } if((exit_status = putval(obufcnt,pos,dz))<0) return(exit_status); return(CONTINUE); } size = (double)duration/(double)number; if(flteq((double)(isize = (int)round(size)),size)) return integral_times(obufcnt,intime0,isize,number,dz); return unvarying_times(obufcnt,intime0,size,number,dz); } /************************ INTEGRAL_TIMES *************************** * * GENERATE vals for equally spaced events, spaced by whole nos. of samps. */ int integral_times(int *obufcnt,int intime0,int isize,int number,dataptr dz) { int exit_status; int k, pos = intime0 - dz->iparam[UNITS_RD_PRE_THISBUF]; for(k=0;k= dz->iparam[UNITS_READ]) { if(dz->samps_left <= 0) return(FINISHED); if((exit_status = read_samps_for_vtrans(dz))<0) return(exit_status); pos -= dz->iparam[UNIT_BUFLEN]; } if((exit_status = putintval(obufcnt,pos,dz))<0) return(exit_status); pos += isize; } return(CONTINUE); } /****************************** PUTINTVAL ******************************/ int putintval(int *obufcnt,int i,dataptr dz) { int exit_status; int n; float *buffer = dz->sampbuf[INBUF]; float *obuf = dz->sampbuf[OUTBUF]; i *= dz->infile->channels; for(n=0;ninfile->channels;n++) { obuf[(*obufcnt)++] = buffer[i]; if(*obufcnt >= dz->buflen) { if((exit_status = write_samps_with_intime_display(obuf,dz->buflen,dz))<0) return(exit_status); *obufcnt = 0; } i++; } return(FINISHED); } /************************ UNVARYING_TIMES *************************** * * GENERATE vals for equally spaced events. */ int unvarying_times(int *obufcnt,int intime0,double size,int number,dataptr dz) { int exit_status; int k; double pos = (double)(intime0 - dz->iparam[UNITS_RD_PRE_THISBUF]); /******* k = 0 *********/ for(k=0;k= (double)dz->iparam[UNITS_READ]) { if(dz->samps_left <= 0) return(FINISHED); if((exit_status = read_samps_for_vtrans(dz))<0) return(exit_status); pos -= (double)dz->iparam[UNIT_BUFLEN]; } if((exit_status = putval(obufcnt,pos,dz))<0) return(exit_status); pos += size; } return(CONTINUE); } /******************************* GETETIME(): ******************************** * * Calculate time-positions of events that vary in size between s0 and s1. * NB We need to invert the time order, if s1 < s0. */ int getetime(int *obufcnt,int t0,int t1,double s0,double s1,int number,dataptr dz) { int exit_status; int n; double sdiff = s1-s0, tdiff = (double)(t1-t0), d1, d2, d3, pos; /***** TW n=0 NOT 1 ********/ // for(n=1;niparam[UNITS_RD_PRE_THISBUF]; if(pos >= (double)dz->iparam[UNITS_READ]) { if(dz->samps_left <= 0) return(FINISHED); if((exit_status = read_samps_for_vtrans(dz))<0) return(exit_status); pos -= (double)dz->iparam[UNIT_BUFLEN]; } if((exit_status = putval(obufcnt,pos,dz))<0) return(exit_status); } return(CONTINUE); } /***************************** REFINESIZE(): ****************************** * * refine size of final event to reduce error within bounds. */ double refinesize(double hibound,double lobound,double fnumber,int duration,double error,double insize0) { double size, fnum, lasterror; double flterr_squared = FLTERR * FLTERR; do { lasterror = error; size = (hibound+lobound)/2.0; fnum = cntevents(duration,insize0,size); error = fabs(fnumber-fnum); if(error>FLTERR) { if(fnum FLTERR); return(size); } /****************************** PUTVAL ******************************/ int putval(int *obufcnt,double pos,dataptr dz) { int exit_status; int i = (int)pos; /* TRUNCATE */ double frac = pos - (double)i, diff; float val1, val2; float *buffer = dz->sampbuf[INBUF]; float *obuf = dz->sampbuf[OUTBUF]; int chans = dz->infile->channels; int n; i *= chans; for(n=0;n= dz->buflen) { if((exit_status = write_samps_with_intime_display(obuf,dz->buflen,dz))<0) return(exit_status); *obufcnt = 0; } i++; } return(CONTINUE); } /**************************** SIZEQ *******************************/ int sizeq(double f1,double f2) { double upperbnd, lowerbnd; upperbnd = f2 + CALCLIM; lowerbnd = f2 - CALCLIM; if((f1>upperbnd) || (f1brk[VTRANS_TRANS]; double lasttime, lastval, thistime, thisval, intime, outtime; if((newtime = (int *)malloc(dz->brksize[VTRANS_TRANS] * 2 * sizeof(double)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY to create transformed brktable.\n"); return(MEMORY_ERROR); } newtime[0] = 0; lasttime = dbrk[0]; lastval = dbrk[1]; switch(dz->mode) { case(MOD_TRANSPOS_INFO): case(MOD_TRANSPOS_SEMIT_INFO): for(n=1,m=2;nbrksize[VTRANS_TRANS];n++,m+=2) { thistime = dbrk[m]; thisval = dbrk[m+1]; if(dz->vflag[VTRANS_OUTTIMES]) newtime[n] = newtime[n-1] + inv_cntevents((int)round(thistime - lasttime),lastval,thisval); else newtime[n] = newtime[n-1] + round(cntevents((int)round(thistime - lasttime),lastval,thisval)); lasttime = thistime; lastval = thisval; } print_outmessage_flush("TIME GIVEN\tOCCURS AT OUTTIME\n"); for(n=0,m=0;nbrksize[VTRANS_TRANS];n++,m+=2) { intime = dbrk[m]/dz->param[VTRANS_SR]; outtime = (double)newtime[n]/dz->param[VTRANS_SR]; sprintf(errstr,"%lf\t%lf\n",intime,outtime); print_outmessage_flush(errstr); } if(!sloom) { fprintf(stdout,"INFO: END\n"); fflush(stdout); } break; case(MOD_TRANSPOS): case(MOD_TRANSPOS_SEMIT): if(dz->vflag[VTRANS_OUTTIMES]) { /* convert to intimes */ for(n=1,m=2;nbrksize[VTRANS_TRANS];n++,m+=2) { thistime = dbrk[m]; thisval = dbrk[m+1]; newtime[n] = newtime[n-1] + inv_cntevents((int)round(thistime - lasttime),lastval,thisval); lasttime = thistime; lastval = thisval; } for(n=1,m=2;nbrksize[VTRANS_TRANS];n++,m+=2) dbrk[m] = (double)newtime[n]; } break; } free(newtime); return(FINISHED); } /*************************** INV_CNTEVENTS ***************************** * * no. of event in input (N) corresponding to output (T1-T0) given by :- * * N = (T1-T0) log S1 * ------- e__ * (S1-S0) S0 * * Hence, * no. of event in output (T1-T0) corresponding to input (N) given by :- * * (S1-S0)N = (T1-T0) * -------- * log S1 * e__ * S0 * * Except where S1==S0, when (T1-T0) = S * N */ int inv_cntevents(int dur,double s0,double s1) { double ftime; int time; if(sizeq(s1,s0)) ftime = (double)dur * s0; else ftime = ((double)dur * (s1-s0))/log(s1/s0); time = round(ftime); if(time==0) time = 1; return(time); } /*************************** FORCE_VALUE_AT_END_TIME *****************************/ int force_value_at_end_time(int paramno,dataptr dz) { double duration = (double)dz->iparam[UNITSIZE]/dz->param[VTRANS_SR]; double *p = dz->brk[paramno] + ((dz->brksize[paramno]-1) * 2); double timegap, newgap, step, newstep, timeratio; if(dz->brksize[paramno] < 2) { sprintf(errstr,"Brktable too small (< 2 pairs).\n"); return(DATA_ERROR); } if(flteq(*p,duration)) { *p = duration; return(FINISHED); } else if(*p < duration) { dz->brksize[paramno]++; if((dz->brk[paramno] = realloc((char *)dz->brk[paramno],dz->brksize[paramno] * 2 * sizeof(double)))==NULL) { sprintf(errstr,"INSUFFICIENT MEMORY TO GROW BRKTABLE.\n"); return(MEMORY_ERROR); } p = dz->brk[paramno] + ((dz->brksize[paramno]-1) * 2); *p = duration; *(p+1) = *(p-1); return(FINISHED); } else { /* *p > duration) */ while(p > dz->brk[paramno]) { p -= 2; if(flteq(*p,duration)) { *p = duration; dz->brksize[paramno] = (p - dz->brk[paramno] + 2)/2; return(FINISHED); } else if(*p < duration) { timegap = *(p+2) - *p; newgap = duration - *p; timeratio = newgap/timegap; switch(dz->mode) { case(MOD_TRANSPOS_SEMIT): case(MOD_TRANSPOS_SEMIT_INFO): step = *(p+3) - *(p+1); newstep = step * timeratio; *(p+3) = *(p+1) + newstep; break; case(MOD_TRANSPOS): case(MOD_TRANSPOS_INFO): step = LOG2(*(p+3)) - LOG2(*(p+1)); newstep = pow(2.0,step * timeratio); *(p+3) = *(p+1) * newstep; break; } *(p+2) = duration; dz->brksize[paramno] = (p - dz->brk[paramno] + 4)/2; return(FINISHED); } } } sprintf(errstr,"Failed to place brkpnt at snd endtime.\n"); return(PROGRAM_ERROR); } /*************************** SPLICE_END *****************************/ void splice_end(int obufcnt,dataptr dz) /* A kludge to avoid clicks at end */ { #define VTRANS_SPLICELEN (5.0) float *buf = dz->sampbuf[OUTBUF]; int chans = dz->infile->channels; int splicelen = round(VTRANS_SPLICELEN * MS_TO_SECS * dz->infile->srate) * dz->infile->channels; int n, m, k = min(obufcnt,splicelen); int startsamp = obufcnt - k; double inv_k; k /= chans; inv_k = 1.0/(double)k; for(n = k-1;n >= 0;n--) { for(m=0;msampbuf[INBUF]; float *obuf = dz->sampbuf[OUTBUF]; float *true_lbuf = dz->sampbuf[TRUE_LBUF]; float *true_rbuf = dz->sampbuf[TRUE_RBUF]; float *obufend = dz->sampbuf[OBUFEND]; float *obufptr = obuf; double place_inc = 1.0; int startsamp = dz->iparam[ACCEL_STARTTIME]; int previous_total_ssampsread = 0; double accel = dz->param[ACCEL_ACCEL]; dz->total_samps_read = 0; display_virtual_time(0L,dz); if(dz->infile->channels==STEREO) { while(dz->total_samps_read<=startsamp) { previous_total_ssampsread = dz->total_samps_read; if((exit_status = read_wrapped_samps_stereo(dz))<0) return(exit_status); if(dz->total_samps_read <= startsamp) if((exit_status = write_samps_with_intime_display(ibuf,dz->ssampsread * STEREO,dz))<0) return(exit_status); } startsamp -= previous_total_ssampsread; if(startsamp > 0) memcpy((char *)obuf,(char *)ibuf,startsamp * sizeof(float)); obufptr += startsamp; startsamp /= 2; /* STEREO divided into two buffers */ place = startsamp + 1; flplace = place; while(dz->ssampsread > place) { while(place < dz->ssampsread) { fracsamp = flplace - (double)place; step = true_lbuf[place+1] - true_lbuf[place]; // interp = round(fracsamp * step); interp = fracsamp * step; *obufptr++ = (float)(true_lbuf[place] + interp); step = true_rbuf[place+1] - true_rbuf[place]; // interp = round(fracsamp * step); interp = fracsamp * step; *obufptr++ = (float)(true_rbuf[place] + interp); if(obufptr >= obufend) { if((exit_status = write_samps_with_intime_display(obuf,dz->buflen,dz))<0) return(exit_status); obufptr = obuf; } flplace += place_inc; place_inc *= accel; if(place_inc <= MININC) { fprintf(stdout, "INFO: Acceleration reached black hole! - finishing\n"); fflush(stdout); OK = 0; break; } place = (int)flplace; } if(!OK) { break; } if(dz->samps_left > 0) { flplace -= (double)dz->ssampsread; place -= dz->ssampsread; if((exit_status = read_wrapped_samps_stereo(dz))<0) return(exit_status); if(dz->ssampsread<=0) break; } else break; } } else { while(dz->total_samps_read<=startsamp) { previous_total_ssampsread = dz->total_samps_read; if((exit_status = read_wrapped_samps_mono(dz))<0) return(exit_status); if(dz->total_samps_read <= startsamp) { if((exit_status = write_samps_with_intime_display(ibuf,dz->ssampsread,dz))<0) return(exit_status); } } startsamp -= previous_total_ssampsread; if(startsamp > 0) memcpy((char *)obuf,(char *)ibuf,startsamp * sizeof(float)); obufptr += startsamp; place = startsamp + 1; flplace = place; while(dz->ssampsread > place) { while(place < dz->ssampsread) { fracsamp = flplace - (double)place; step = true_lbuf[place+1] - true_lbuf[place]; // interp = round(fracsamp * step); interp = fracsamp * step; *obufptr++ = (float)(true_lbuf[place] + interp); if(obufptr >= obufend) { if((exit_status = write_samps_with_intime_display(obuf,dz->buflen,dz))<0) return(exit_status); obufptr = obuf; } flplace += place_inc; place_inc *= accel; if(place_inc <= MININC) { fprintf(stdout, "INFO: Acceleration reached black hole! - finishing\n\n"); fflush(stdout); OK = 0; break; } place = (int)flplace; } if(!OK) { break; } if(dz->samps_left > 0) { flplace -= (double)dz->ssampsread; place -= dz->ssampsread; if((exit_status = read_wrapped_samps_mono(dz))<0) return(exit_status); if(dz->ssampsread<=0) break; } else break; } } splice_end(obufptr - obuf,dz); return write_samps_with_intime_display(obuf,obufptr - obuf ,dz); } /******************************* DO_VIBRATO ********************************/ int do_vibrato(dataptr dz) { int exit_status; float *ibuf = dz->sampbuf[INBUF]; float *obuf = dz->sampbuf[OUTBUF]; float *obufend = dz->sampbuf[OBUFEND]; float *true_lbuf = dz->sampbuf[TRUE_LBUF]; float *true_rbuf = NULL; double *sintab = dz->parray[VIB_SINTAB]; int chans = dz->infile->channels; double sr = (double)dz->infile->srate; double tabsize = (double)VIB_TABSIZE; double bloksize = (double)VIB_BLOKSIZE; double inv_bloksize = 1.0/bloksize; double thistime = 0.0; double time_incr = bloksize/sr; /* timestep between param reads */ int effective_buflen = dz->buflen/chans; int place = 0; /* integer position in sndfile */ double flplace = 0.0; /* float position in sndfile */ double incr; /* incr of position in sndfile */ double sfindex = 0.0; /* float position in sintable */ double sinval; /* current sintable value */ double current_depth, lastdepth, depth_incr; double current_frq, lastfrq, frq_incr; double fracsamp; /* fraction of samptime to interp*/ double step; /* step between snd samples */ // int interp; /* part of sampstep to use */ double interp; /* part of sampstep to use */ int blokcnt = 0; /* distance through blokd params */ float *obufptr = obuf; if(dz->brksize[VIB_FRQ]) { if((exit_status = read_value_from_brktable(thistime,VIB_FRQ,dz))<0) return(exit_status); } else frq_incr = 0.0; if(dz->brksize[VIB_DEPTH]) { if((exit_status = read_value_from_brktable(thistime,VIB_DEPTH,dz))<0) return(exit_status); } else depth_incr = 0.0; current_frq = lastfrq = dz->param[VIB_FRQ]; current_depth = lastdepth = dz->param[VIB_DEPTH]; thistime += time_incr; /* now time is 1 bloklength ahead */ switch(chans) { case(MONO): if((exit_status = read_wrapped_samps_mono(dz))<0) return(exit_status); obuf[0] = ibuf[0]; obufptr++; break; case(STEREO): true_rbuf = dz->sampbuf[TRUE_RBUF]; if((exit_status = read_wrapped_samps_stereo(dz))<0) return(exit_status); obuf[0] = ibuf[0]; obufptr++; obuf[1] = ibuf[1]; obufptr++; break; } if((exit_status = read_values_from_all_existing_brktables(thistime,dz))<0) return(exit_status); /* read value 1 bloklength ahead */ frq_incr = (dz->param[VIB_FRQ] - lastfrq) * inv_bloksize; depth_incr = (dz->param[VIB_DEPTH] - lastdepth) * inv_bloksize; lastfrq = dz->param[VIB_FRQ]; lastdepth = dz->param[VIB_DEPTH]; blokcnt = VIB_BLOKSIZE - 1; /* -1 as we've read 1 (stereo) sample already. */ thistime += time_incr; /* Now time is 2 bloklengths ahead */ /* but we won't read till another 1 blok has passed. */ for(;;) { if(--blokcnt <= 0) { /* look at params only every BLOKCNT (stereo)samples */ if((exit_status = read_values_from_all_existing_brktables(thistime,dz))<0) return(exit_status); /* & read vals 1 bloklen ahead,to calc par incr */ frq_incr = (dz->param[VIB_FRQ] - lastfrq) * inv_bloksize; depth_incr = (dz->param[VIB_DEPTH] - lastdepth) * inv_bloksize; lastfrq = dz->param[VIB_FRQ]; lastdepth = dz->param[VIB_DEPTH]; blokcnt = VIB_BLOKSIZE; thistime += time_incr; } current_depth += depth_incr; /* increment params sample by (stereo) sample */ current_frq += frq_incr; if((sfindex += current_frq) >= tabsize) sfindex -= tabsize; /* advance in sintable,wrapping around if ness */ sinval = interp_read_sintable(sintab,sfindex); /* read sintab by interpolation */ incr = pow(2.0,sinval * current_depth); /* convert speed & depth from 8vas to ratio */ if((flplace += incr) >= (double)dz->ssampsread) { /* advance through src sound */ if(dz->samps_left <=0) /* if at end of src, finish */ break; /* else if at end of buffer, get more sound in */ switch(chans) { case(MONO): if((exit_status = read_wrapped_samps_mono(dz))<0) return(exit_status); break; case(STEREO): if((exit_status = read_wrapped_samps_stereo(dz))<0) return(exit_status); break; } flplace -= effective_buflen; } place = (int)flplace; /* TRUNCATE */ /* read sndfile by interpolation */ fracsamp = flplace - (double)place; step = true_lbuf[place+1] - true_lbuf[place]; // interp = round(fracsamp * step); interp = fracsamp * step; *obufptr++ = (float)(true_lbuf[place] + interp); if(chans==STEREO) { step = true_rbuf[place+1] - true_rbuf[place]; // interp = round(fracsamp * step); interp = fracsamp * step; *obufptr++ = (float)(true_rbuf[place] + interp); } if(obufptr >= obufend) { /* if at end of outbuf, write a buffer */ if((exit_status = write_samps_with_intime_display(obuf,dz->buflen,dz))<0) return(exit_status); obufptr = obuf; } } if(obufptr < obufend) /* if samples remain in outbuf, write them */ return write_samps_with_intime_display(obuf,obufptr - obuf,dz); return(FINISHED); } /******************************* INTERP_READ_SINTABLE ********************************/ double interp_read_sintable(double *sintab,double sfindex) { int sindex0 = (int)sfindex; /* TRUNCATE */ int sindex1 = sindex0 + 1; double frac = sfindex - (double)sindex0; double val0 = sintab[sindex0]; double val1 = sintab[sindex1]; double valdiff = val1 - val0; double valfrac = valdiff * frac; return(val0 + valfrac); }