/**************************************************************************** | Digital Audio Processor | ======================= | | Filename : DPResample.cc | | Object : None | | Description : DPResample functions (for resampling using phase vocoder) | | (c) Richard Kent 1996 and (c) Richard Moore | | $Id: DPResample.cc,v 1.1 2003/09/10 00:06:25 rk Exp $ | ****************************************************************************/ static char DPResample_cc [] = "$Id: DPResample.cc,v 1.1 2003/09/10 00:06:25 rk Exp $"; #include "DPResample.h" #define FORWARD 1 #define INVERSE 0 #define RESAMPCHECK 10 // #define USEREGISTERS // #define SNEAKYCHECK #define FREEALL \ convert (0,0,0,0,0,0,1); \ oscbank (0,0,0,0,0,0,0,0,1); \ unconvert (0,0,0,0,0,0,1); \ delete [] Wanal; \ delete [] Wsyn; \ delete [] input; \ delete [] buffer; \ delete [] channel; \ delete [] output double PII; double TWOPI; int framesToWrite; int framesWritten; #define ALLOCATEDOUBLE(name,size) \ name = new double [(size)]; \ for (i=0; i<(size); i++) name [i] = 0.0 int resample ( DPSample *sample, DPSample *newSample, int chan, int R, int N, int Nw, int D, int I, double P, double synt) { int i; int N2; int Nw2; int in; int on; int eof = 0; int obank = 0; double *Wanal = 0; double *Wsyn = 0; double *input = 0; double *buffer = 0; double *channel = 0; double *output = 0; #ifndef NOFORMS double percentComp; char tempString [20]; #endif #ifdef SNEAKYCHECK XEvent newEvent; #endif int checkReset = RESAMPCHECK; int check = 1; framesToWrite = newSample->getRangeEnd () - newSample->getRangeStart (); framesWritten = 0; PII = 4.0 * atan (1.0); TWOPI = 8.0 * atan (1.0); if (P < 0.999999999 || P > 1.000000001) obank = 1; N2 = N >> 1; Nw2 = Nw >> 1; ALLOCATEDOUBLE (Wanal,Nw); ALLOCATEDOUBLE (Wsyn,Nw); ALLOCATEDOUBLE (input,Nw); ALLOCATEDOUBLE (buffer,N); ALLOCATEDOUBLE (channel,N+2); ALLOCATEDOUBLE (output,Nw); if (!Wanal || !Wsyn || !input || !buffer || !channel || !output) { delete [] Wanal; delete [] Wsyn; delete [] input; delete [] buffer; delete [] channel; delete [] output; return 0; } shiftin (sample,chan,0,0,0,1); shiftout (newSample,chan,0,0,0,0,1); convert (0,0,0,0,0,1,0); oscbank (0,0,0,0,0,0,0,1,0); unconvert (0,0,0,0,0,1,0); makewindows (Wanal,Wsyn,Nw,N,I); in = -Nw; on = (in * I) / D; while (!eof) { in += D; on += I; eof = shiftin (sample,chan,input,Nw,D,0); fold (input,Wanal,Nw,buffer,N,in); rfft (buffer,N2,FORWARD); if (!convert (buffer,channel,N2,D,R,0,0)) { FREEALL; return 0; } if (obank) { if (!oscbank (channel,N2,R,I,output,P,synt,0,0)) { FREEALL; return 0; } shiftout (newSample,chan,output,Nw,I,(in+Nw2+D),0); } else { if (!unconvert (channel,buffer,N2,I,R,0,0)) { FREEALL; return 0; } rfft (buffer,N2,INVERSE); overlapadd (buffer,N,Wsyn,output,Nw,on); shiftout (newSample,chan,output,Nw,I,on,0); } if (!--check) { check = checkReset; #ifndef NOFORMS percentComp = 100.0 * framesWritten / framesToWrite; fl_set_slider_value (stretchForm->percentCompSlider,percentComp); sprintf (tempString,"%.0f",percentComp); fl_set_object_label (stretchForm->percentComp,tempString); #ifdef SNEAKYCHECK if (XCheckWindowEvent (fl_display, stretchForm->stretchForm->window,~(int)0,&newEvent)) { XPutBackEvent (fl_display,&newEvent); fl_check_forms (); } #else fl_check_forms (); #endif // SNEAKYCHECK if (stretchCancel) { FREEALL; return 0; } #endif // NOFORMS } } FREEALL; return 1; } void makewindows ( double A [], double S [], int Nw, int N, int I) { int i; double sum; for (i=0; i N) { double x; x = - (Nw - 1) / 2.0; for (i=0; i N ? 1.0 / afac : afac; A [i] *= afac; S [i] *= sfac; } if (Nw <= N) { for (sum=i=0; igetRangeStart (); endFrame = sample->getRangeEnd (); return 0; } if (valid < 0) valid = N; for (i=0; i= endFrame) { valid = i; break; } else A [i] = sample->getFrameDb (frame++,channel); } } if (valid < N) { for (i=valid; i PII) { phasediff -= TWOPI; } while (phasediff < -PII) { phasediff += TWOPI; } } C [freq] = phasediff * factor + i * fundamental; } return 1; } int oscbank ( double C [], int N, int R, int I, double O [], double P, double synt, int initialise, int remove) { static int NP; static int L; static int first; static double Iinv; static double *lastamp; static double *lastfreq; static double *index; static double *table; static double Pinc; int i; int amp; int freq; int n; int chan; if (initialise) { NP = 0; L = 8192; first = 1; Iinv = 0.0; lastamp = 0; lastfreq = 0; index = 0; table = 0; Pinc = 0.0; return 1; } if (remove) { delete [] lastamp; delete [] lastfreq; delete [] index; delete [] table; lastamp = 0; lastfreq = 0; index = 0; table = 0; return 1; } if (first) { first = 0; ALLOCATEDOUBLE (lastamp,N+1); ALLOCATEDOUBLE (lastfreq,N+1); ALLOCATEDOUBLE (index,N+1); ALLOCATEDOUBLE (table,L); if (!lastamp || !lastfreq || !index || !table) { delete [] lastamp; delete [] lastfreq; delete [] index; delete [] table; lastamp = 0; lastfreq = 0; index = 0; table = 0; return 0; } for (n=0; n 1.0) NP = (int) (N / P); else NP = N; Iinv = 1.0 / I; Pinc = P * L / R; } for (chan=0; chan= L) { address -= L; } while (address < 0) { address += L; } a += ainc; f += finc; } } lastamp [chan] = C [amp]; lastfreq [chan] = C [freq]; index [chan] = address; } return 1; } int unconvert ( double C [], double S [], int N2, int I, int R, int initialise, int remove) { static int first; static double *lastphase; static double fundamental; static double factor; double mag; double phase; int i; int real; int imag; int amp; int freq; if (initialise) { first = 1; lastphase = 0; fundamental = 0.0; factor = 0.0; return 1; } if (remove) { delete [] lastphase; lastphase = 0; return 1; } if (first) { first = 0; ALLOCATEDOUBLE (lastphase,N2+1); fundamental = (double) R / (N2 << 1); factor = TWOPI * I / R; if (!lastphase) return 0; } for (i=0; i<=N2; i++) { imag = freq = (real = amp = i << 1) + 1; if (i == N2) real = 1; mag = C [amp]; lastphase [i] += C [freq] - i * fundamental; phase = lastphase [i] * factor; S [real] = mag * cos (phase); if (i != N2) { S [imag] = -mag * sin (phase); } } return 1; } void overlapadd ( double I [], int N, double W [], double O [], int Nw, int n) { int i; while (n < 0) { n += N; } n %= N; for (i=0; igetRangeStart (); endFrame = newSample->getRangeEnd (); return; } if (n >= 0) { for (i=0; isetFrameDb (frame++,channel,A [i]); framesWritten++; } } } for (i=0; i>1; i++) { i1 = i << 1; i2 = i1 + 1; i3 = N2p1 - i2; i4 = i3 + 1; if (i == 0) { h1r = c1 * (x [i1] + xr); h1i = c1 * (x [i2] - xi); h2r = -c2 * (x [i2] + xi); h2i = c2 * (x [i1] - xr); x [i1] = h1r + wr * h2r - wi * h2i; x [i2] = h1i + wr * h2i + wi * h2r; xr = h1r - wr * h2r + wi * h2i; xi = -h1i + wr * h2i + wi * h2r; } else { h1r = c1 * (x [i1] + x [i3]); h1i = c1 * (x [i2] - x [i4]); h2r = -c2 * (x [i2] + x [i4]); h2i = c2 * (x [i1] - x [i3]); x [i1] = h1r + wr * h2r - wi * h2i; x [i2] = h1i + wr * h2i + wi * h2r; x [i3] = h1r - wr * h2r + wi * h2i; x [i4] = -h1i + wr * h2i + wi * h2r; } wr = (temp = wr) * wpr - wi * wpi + wr; wi = wi * wpr + temp * wpi + wi; } if (forward) x [1] = xr; else cfft (x,N,forward); } void cfft ( double x [], int NC, int forward ) { double wr; double wi; double wpr; double wpi; double theta; double scale; double temp; int mmax; int ND; int m; int i; int j; int delta; ND = NC << 1; bitreverse (x,ND); delta = 0; for (mmax=2; mmaxi) { rtemp = x [j]; itemp = x [j+1]; x [j] = x [i]; x [j+1] = x [i+1]; x [i] = rtemp; x [i+1] = itemp; } for (m=N>>1; m>=2 && j>=m; m>>=1) { j -= m; } } } /***************************************************************************/