This is warp.c in view mode; [Download] [Up]
/* warp.c - dynamic rate resampling program */ /* * Implement dynamic sampling-rate changes; uses a second file to * indicate where periods should fall. This program may be used to add * or remove vibrato and micro pitch variations from a sound sample. */ #import "filterkit.h" #import "resample.h" #import <libc.h> #import <math.h> #define MAXNWING 8192 #define MAXFACTOR 4 #define IBUFFSIZE 1024 /* Input buffer size */ #define OBUFFSIZE (IBUFFSIZE*MAXFACTOR+2) /* Calc'd out buffer size */ static void fail(char *s) { printf("warp: %s\n\n", s); /* Display error message */ exit(1); /* Exit, indicating error */ } static void fails(char *s, char *s2) { printf("warp: "); /* Display error message */ printf(s, s2); printf("\n\n"); exit(1); /* Exit, indicating error */ } /* Global file pointers: */ FILE *fin, *fout; static void openData(int argc, char *argv[]) { if (argc != 3) fail("format is 'warp <file-in> <file-out>'"); if (NULL == (fin = fopen(*++argv,"r"))) fails("could not open <file-in> file '%s'",*argv); if (NULL == (fout = fopen(*++argv,"w"))) fails("could not open <file-out> file '%s'",*argv); } static void closeData(void) { (void) fclose(fin); (void) fclose(fout); } static int readData(HWORD Data[], int DataArraySize, int Xoff) /* return: 0 - notDone */ /* >0 - index of last sample */ { int Nsamps, Scan, val; HWORD *DataStart; DataStart = Data; Nsamps = DataArraySize - Xoff; /* Calculate number of samples to get */ Data += Xoff; /* Start at designated sample number */ for (; Nsamps>0; Nsamps--) { Scan = fscanf(fin, "%d", &val); /* Read in Nsamps samples */ if (Scan==EOF || Scan==0) /* unless read error or EOF */ break; /* in which case we exit and */ *Data++ = val; } if (Nsamps > 0) { val = Data - DataStart; /* (Calc return value) */ while (--Nsamps >= 0) /* fill unread spaces with 0's */ *Data++ = 0; /* and return FALSE */ return(val); } return(0); } static void writeData(int Nout, HWORD Data[]) { while (--Nout >= 0) /* Write Nout samples to ascii file */ fprintf(fout, "%d\n", *Data++); } void check(void) { /* Check for illegal constants */ if (Np >= 16) fail("Error: Np>=16"); if (Nb+Nhg+NLpScl >= 32) fail("Error: Nb+Nhg+NLpScl>=32"); if (Nh+Nb > 32) fail("Error: Nh+Nb>32"); } /* Globals for warping frequency */ double a,b,c,d,e,f,Total; int Acc; void initWarp(void) { Total = GetDouble("\n# of input samples",12000.0,""); printf("Warping function: Fout/Fin = w(n)\n"); printf(" w(n) = off + [amp * sin(ph1+frq1*n/N) * sin(ph2+frq2*n/N)]\n"); printf(" where: off,amp,ph1 - parameters\n"); printf(" frq1,ph2,frq2 - more parameters\n"); printf(" n - current input sample number\n"); printf(" N - total number of input samples\n"); a = GetDouble("off",1.5,""); b = GetDouble("amp",-0.5,""); c = D2R * GetDouble("ph1 (degrees)",-90.0,""); d = GetDouble("frq1",1.0,""); e = D2R * GetDouble("ph2 (degrees)",90.0,""); f = GetDouble("frq2",0.0,""); } double warpFunction(UWORD Time) { double fTime,t; /* Calc absolute position in input file: */ fTime = (double)Time / (double)(1<<Np) + (double)Acc; /* Calc fraction of file processed: */ t = fTime/Total; /* Return warp factor: */ return (1.0 / (a + b*sin(c+PI2*d*t)*sin(e+PI2*f*t))); } /* Sampling rate conversion subroutine */ static int SrcUD(HWORD X[], HWORD Y[], UWORD *Time, UHWORD Nx, UHWORD Nwing, UHWORD LpScl, HWORD Imp[], HWORD ImpD[], BOOL Interp) { HWORD *Xp, *Ystart; WORD v; UHWORD NewScl; /* Unity gain scale factor */ double dh; /* Step through filter impulse response */ double dt; /* Step through input signal */ UWORD endTime; /* When Time reaches EndTime, return to user */ UWORD dhb, dtb; /* Fixed-point versions of Dh,Dt */ double Factor; /* Current resampling factor */ Ystart = Y; endTime = *Time + (1<<Np)*(WORD)Nx; while (*Time < endTime) { Factor = warpFunction(*Time); /* Get new conversion Factor */ NewScl = LpScl * Factor; /* Calc new normalizing scalar */ dt = 1.0 / Factor; /* New output sampling period */ dtb = dt*(1<<Np) + 0.5; /* Fixed-point representation */ dh = MIN(Npc, Factor * Npc); /* New filter sampling period */ dhb = dh*(1<<Na) + 0.5; /* Fixed-point representation */ Xp = &X[*Time>>Np]; /* Ptr to current input sample */ v = FilterUD(Imp, ImpD, Nwing, Interp, Xp, (HWORD)(*Time&Pmask), -1, dhb); /* Perform left-wing inner product */ v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1, (HWORD)((-*Time)&Pmask), 1, dhb); /* Perform right-wing inner product */ v >>= Nhg; /* Make guard bits */ v *= NewScl; /* Normalize for unity filter gain */ *Y++ = v>>NLpScl; /* Deposit output */ *Time += dtb; /* Move to next sample by time inc */ } return (Y - Ystart); /* Return the # of output samples */ } static int localResample(HWORD Imp[], HWORD ImpD[], UHWORD LpScl, UHWORD Nmult, UHWORD Nwing, BOOL InterpFilt) { UWORD Time; /* Current time/pos in input sample */ UHWORD Xp, Xread, Ncreep, Xoff; HWORD X[IBUFFSIZE], Y[OBUFFSIZE]; /* I/O buffers */ UHWORD Nout, Nx; int i, Ycount, last; /* Calc reach of LP filter wing & give some creeping room */ Xoff = ((Nmult+1)/2.0) * MAX(1.0,1.0*MAXFACTOR) + 10; if (IBUFFSIZE < 2*Xoff) /* Check input buffer size */ fail("IBUFFSIZE (or Factor) is too small"); Nx = IBUFFSIZE - 2*Xoff; /* # of samples to proccess each iteration */ last = FALSE; /* Have we read last input sample yet? */ Ycount = 0; /* Output sample # and length of out file */ Xp = Xoff; /* Current position in input buffer */ Xread = Xoff; /* Position in input array to read into */ Time = (Xoff<<Np); /* Current-time pointer for converter */ Acc = -Xoff; /* Acc + int(Time) = index into input file */ for (i=0; i<Xoff; X[i++]=0); /* Need Xoff zeros at begining of sample */ do { if (!last) /* If haven't read last sample yet */ { last = readData(X, IBUFFSIZE, (int)Xread); /* Fill input buffer */ if (last && (last+Xoff<Nx)) /* If last sample has been read... */ Nx = last + Xoff; /* ...calc last sample affected by filter */ } Ycount += Nout = SrcUD(X,Y,&Time,Nx,Nwing,LpScl,Imp,ImpD,InterpFilt); Time -= (Nx<<Np); /* Move converter Nx samples back in time */ Xp += Nx; /* Advance by number of samples processed */ Acc += Nx; /* We moved Nx samples in the input file */ Ncreep = (Time>>Np) - Xoff; /* Calc time accumulation in Time */ if (Ncreep) { Time -= (Ncreep<<Np); /* Remove time accumulation */ Xp += Ncreep; /* and add it to read pointer */ Acc += Ncreep; } for (i=0; i<IBUFFSIZE-Xp+Xoff; i++) /* Copy portion of input signal */ X[i] = X[i+Xp-Xoff]; /* that must be re-used */ if (last) /* If near end of sample... */ { last -= Xp; /* ...keep track were it ends */ if (!last) /* Lengthen input by 1 sample */ last++; /* if needed to keep flag TRUE */ } Xread = i; /* Pos in input buff to read new data into */ Xp = Xoff; if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */ fail("Output array overflow"); writeData((int)Nout, Y); /* Write data in output buff to file */ } while (last >= 0); /* Continue until done processing samples */ return(Ycount); /* Return # of samples in output file */ } static HWORD Imp[MAXNWING]; /* Filter coefficients */ static HWORD ImpD[MAXNWING]; /* ImpD[n] = Imp[n+1]-Imp[n] */ void main(int argc, char *argv[]) { BOOL InterpFilt; /* TRUE means interpolate filter coeffs */ UHWORD LpScl, Nmult, Nwing; int outCount; Nmult = 13; InterpFilt = TRUE; check(); /* Check constants for validity */ openData(argc, argv); /* Interp arguments and open i&o files */ initWarp(); /* Set up the warp function's parameters */ if (readFilter(NULL, (HWORD **)&Imp, (HWORD **)&ImpD, &LpScl, &Nmult, &Nwing)) fail("could not open Filter file, or syntax error in filter file"); printf("\nConverting . . . "); outCount = localResample(Imp, ImpD, LpScl, Nmult, Nwing, InterpFilt); closeData(); printf("Done: %d output samples.\n\n", outCount); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.