示例#1
0
/*
 * copy a chunk containing only frequencies between flo and fhi into stream.
 */
void BandPassFilterFFT::band_pass(uint8_t *stream, double flo, double fhi)
{
	double band_data[2*samples];
	band_window(band_data, ffind(fhi)+1, ffind(flo));
	//writef(band_data, "test.dat");
	fft_inverse(band_data, stream);
}
示例#2
0
/*
 * graphical equaliser using the function eq to boost/cut the stream.
 */
void BandPassFilterFFT::EQ(uint8_t *stream, double(*eq)(double, void*), void *args)
{
	double band_data[2*samples];

	/*
	 * EQ the data
	 */
	for(uint32_t i=0; i<=freqs; i++) // Go over each frequency.
	{
		double Eq = eq(f[i], args);
		REAL(band_data,POSITIVE(i,samples)) = Eq * REAL(fcache,POSITIVE(i,samples));
		IMAG(band_data,POSITIVE(i,samples)) = Eq * IMAG(fcache,POSITIVE(i,samples));
		REAL(band_data,NEGATIVE(i,samples)) = Eq * REAL(fcache,NEGATIVE(i,samples));
		IMAG(band_data,NEGATIVE(i,samples)) = Eq * IMAG(fcache,NEGATIVE(i,samples));
	}

	fft_inverse(band_data, stream);
}
示例#3
0
void AutoTalent::init(unsigned long sr)
{
  
  unsigned long ti;
  
  fs = sr;
  aref = 440;
  
  if (fs >=88200) {
    cbsize = 4096;
  }
  else {
    cbsize = 2048;
  }
  corrsize = cbsize / 2 + 1;
  
  pmax = 1/(float)70;  // max and min periods (ms)
  pmin = 1/(float)700; // eventually may want to bring these out as sliders
  
  pperiod = pmax;
  
  nmax = (unsigned long)(fs * pmax);
  if (nmax > corrsize) {
    nmax = corrsize;
  }
  nmin = (unsigned long)(fs * pmin);
  
  cbi = (float*) calloc(cbsize, sizeof(float));
  cbo = (float*) calloc(cbsize, sizeof(float));
  cbonorm = (float*) calloc(cbsize, sizeof(float));
  
  cbiwr = 0;
  cbord = 0;
  
  // Standard raised cosine window, max height at N/2
  hannwindow = (float*) calloc(cbsize, sizeof(float));
  for (ti=0; ti<cbsize; ti++) {
    hannwindow[ti] = -0.5*cos(2*PI*ti/(cbsize - 1)) + 0.5;
  }
  
  // Generate a window with a single raised cosine from N/4 to 3N/4
  cbwindow = (float*) calloc(cbsize, sizeof(float));
  for (ti=0; ti<(cbsize / 2); ti++) {
    cbwindow[ti+cbsize/4] = -0.5*cos(4*PI*ti/(cbsize - 1)) + 0.5;
  }
  
  noverlap = 4;
  
  fmembvars = fft_con(cbsize);
  
  ffttime = (float*) calloc(cbsize, sizeof(float));
  fftfreqre = (float*) calloc(corrsize, sizeof(float));
  fftfreqim = (float*) calloc(corrsize, sizeof(float));
  
  
  // ---- Calculate autocorrelation of window ----
  acwinv = (float*) calloc(cbsize, sizeof(float));
  for (ti=0; ti<cbsize; ti++) {
    ffttime[ti] = cbwindow[ti];
  }
  fft_forward(fmembvars, cbwindow, fftfreqre, fftfreqim);
  for (ti=0; ti<corrsize; ti++) {
    fftfreqre[ti] = (fftfreqre[ti])*(fftfreqre[ti]) + (fftfreqim[ti])*(fftfreqim[ti]);
    fftfreqim[ti] = 0;
  }
  fft_inverse(fmembvars, fftfreqre, fftfreqim, ffttime);
  for (ti=1; ti<cbsize; ti++) {
    acwinv[ti] = ffttime[ti]/ffttime[0];
    if (acwinv[ti] > 0.000001) {
      acwinv[ti] = (float)1/acwinv[ti];
    }
    else {
      acwinv[ti] = 0;
    }
  }
  acwinv[0] = 1;
  // ---- END Calculate autocorrelation of window ----
  
  lrshift = 0;
  ptarget = 0;
  sptarget = 0;
  wasvoiced = 0;
  persistamt = 0;
  
  glidepersist = 100; // 100 ms glide persist
  
  vthresh = 0.8;  //  The voiced confidence (unbiased peak) threshold level
  
  // Pitch shifter initialization
  phprdd = 0.01; // Default period
  phprd = phprdd;
  phinc = (float)1/(phprd * fs);
  phincfact = 1;
  phasein = 0;
  phaseout = 0;
  frag = (float*) calloc(cbsize, sizeof(float));
  fragsize = 0;
}
示例#4
0
/**
 This is the main loop where we'll process our samples
 */
void AutoTalent::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
  // Mutex is already locked for us.
  
  double* in1 = inputs[0];
  double* out1 = outputs[0];
  double* out2 = outputs[1];
  // copy struct variables to local
  /*
   float fMix = fMix;
   float fShift = fShift;
   float fTune = fTune;
   float fA = fA;
   float fBb = fBb;
   float fB = fB;
   float fC = fC;
   float fDb = fDb;
   float fD = fD;
   float fEb = fEb;
   float fE = fE;
   float fF = fF;
   float fGb = fGb;
   float fG = fG;
   float fAb = fAb;
   float fGlide = fGlide;
   float fAmount = fAmount;
   */
  float fPersist = glidepersist;
  
  aref = (float)440*pow(2,fTune/12);
		
  unsigned long N = cbsize;
  unsigned long Nf = corrsize;
  //unsigned long fs = fs;
  /*
   float pmax = pmax;
   float pmin = pmin;
   unsigned long nmax = nmax;
   unsigned long nmin = nmin;
   
   float pperiod = pperiod;
   float pitch = pitch;
   float conf = conf;
   float aref = aref;
   */
  //
  
  long int ti;
  long int ti2;
  long int ti3;
  float tf;
  float tf2;
  float tf3;
  
  
  //double samplesPerBeat = GetSamplesPerBeat();
  //double samplePos = (double) GetSamplePos();
  
  for (int s = 0; s < nFrames; ++s, ++in1, ++out1, ++out2)
  {
    
    // load data into circular buffer
    tf = (float) *in1;
    cbi[cbiwr] = tf;
    cbiwr++;
    if (cbiwr >= N) {
      cbiwr = 0;
    }
    
    
    // ********************
    // * Low-rate section *
    // ********************
    
    // Every N/noverlap samples, run pitch estimation / correction code
    if ((cbiwr)%(N/noverlap) == 0) {
      
      
      // ---- Obtain autocovariance ----
      
      // Window and fill FFT buffer
      ti2 = (long) cbiwr;
      for (ti=0; ti<(long)N; ti++) {
        ffttime[ti] = (float)(cbi[(ti2-ti)%N]*cbwindow[ti]);
      }
      
      // Calculate FFT
      fft_forward(fmembvars, ffttime, fftfreqre, fftfreqim);
      
      // Remove DC
      fftfreqre[0] = 0;
      fftfreqim[0] = 0;
      
      // Take magnitude squared
      for (ti=1; ti< (long) Nf; ti++) {
        fftfreqre[ti] = (fftfreqre[ti])*(fftfreqre[ti]) + (fftfreqim[ti])*(fftfreqim[ti]);
        fftfreqim[ti] = 0;
      }
      
      // Calculate IFFT
      fft_inverse(fmembvars, fftfreqre, fftfreqim, ffttime);
      
      // Normalize
      for (ti=1; ti<(long)N; ti++) {
        ffttime[ti] = ffttime[ti] / ffttime[0];
      }
      ffttime[0] = 1;
      
      //  ---- END Obtain autocovariance ----
      
      
      //  ---- Calculate pitch and confidence ----
      
      // Calculate pitch period
      //   Pitch period is determined by the location of the max (biased)
      //     peak within a given range
      //   Confidence is determined by the corresponding unbiased height
      tf2 = 0;
      pperiod = pmin;
      for (ti=nmin; ti<(long)nmax; ti++) {
        ti2 = ti-1;
        ti3 = ti+1;
        if (ti2<0) {
          ti2 = 0;
        }
        if (ti3>(long)Nf) {
          ti3 = Nf;
        }
        tf = ffttime[ti];
        
        if (tf>ffttime[ti2] && tf>=ffttime[ti3] && tf>tf2) {
          tf2 = tf;
          conf = tf*acwinv[ti];
          pperiod = (float)ti/fs;
        }
      }
      
      // Convert to semitones
      pitch = (float) -12*log10((float)aref*pperiod)*L2SC;
      pitch = pitch;
      pperiod = pperiod;
      conf = conf;
      
      //  ---- END Calculate pitch and confidence ----
      
      
      //  ---- Determine pitch target ----
      
      // If voiced
      if (conf>=vthresh) {
        // TODO: Scale sliders
        // Determine pitch target
        tf = -1;
        tf2 = 0;
        tf3 = 0;
        for (ti=0; ti<12; ti++) {
          switch (ti) {
            case 0:
              tf2 = fNotes[9];
              break;
            case 1:
              tf2 = fNotes[10];
              break;
            case 2:
              tf2 = fNotes[11];
              break;
            case 3:
              tf2 = fNotes[0];
              break;
            case 4:
              tf2 = fNotes[1];
              break;
            case 5:
              tf2 = fNotes[2];
              break;
            case 6:
              tf2 = fNotes[3];
              break;
            case 7:
              tf2 = fNotes[4];
              break;
            case 8:
              tf2 = fNotes[5];
              break;
            case 9:
              tf2 = fNotes[6];
              break;
            case 10:
              tf2 = fNotes[7];
              break;
            case 11:
              tf2 = fNotes[8];
              break;
          }
          /* 	  if (ti==ptarget) { */
          /* 	    tf2 = tf2 + 0.01; // add a little hysteresis */
          /* 	  } */
          tf2 = tf2 - (float)fabs( (pitch-(float)ti)/6 - 2*floorf(((pitch-(float)ti)/12 + 0.5)) ); // like a likelihood function
          if (tf2>=tf) {                                                                           // that we're maximizing
            tf3 = (float)ti;                                                                       // to find the target pitch
            tf = tf2;
          }
        }
        ptarget = tf3;
        
        // Glide persist
        if (wasvoiced == 0) {
          wasvoiced = 1;
          tf = persistamt;
          sptarget = (1-tf)*ptarget + tf*sptarget;
          persistamt = 1;
        }
        
        // Glide on circular scale
        tf3 = (float)ptarget - sptarget;
        tf3 = tf3 - (float)12*floorf(tf3/12 + 0.5);
        if (fGlide>0) {
          tf2 = (float)1-pow((float)1/24, (float)N * 1000/ (noverlap*fs*fGlide));
        }
        else {
          tf2 = 1;
        }
        sptarget = sptarget + tf3*tf2;
      }
      // If not voiced
      else {
        wasvoiced = 0;
        
        // Keep track of persist amount
        if (fPersist>0) {
          tf = pow((float)1/2, (float)N * 1000/ (noverlap*fs*fPersist));
        }
        else {
          tf = 0;
        }
        persistamt = persistamt * tf; // Persist amount decays exponentially
      }
      // END If voiced
      
      //  ---- END Determine pitch target ----
      
      
      // ---- Determine correction to feed to the pitch shifter ----
      tf = sptarget - pitch; // Correction amount
      tf = tf - (float)12*floorf(tf/12 + 0.5); // Never do more than +- 6 semitones of correction
      if (conf<vthresh) {
        tf = 0;
      }
      lrshift = fShift + fAmount*tf;  // Add in pitch shift slider
      
      
      // ---- Compute variables for pitch shifter that depend on pitch ---
      phincfact = (float)pow(2, lrshift/12);
      if (conf>=vthresh) {  // Keep old period when unvoiced
        phinc = (float)1/(pperiod*fs);
        phprd = pperiod*2;
      }
    }
    // ************************
    // * END Low-Rate Section *
    // ************************
    
    
    // *****************
    // * Pitch Shifter *
    // *****************
    
    // TODO: Pre-filter with some kind of filter (maybe cheby2 or just svf)
    // TODO: Use cubic spline interpolation
    
    // IMPROVE QUALITY OF PITCH SHIFTER!
    // what is the glitch at "lAaAack"? probably pitch shifter
    
    //   Better snippet management
    //   Pre-filter
    //   Cubic spline interp
    // Pitch shifter (overlap-add, pitch synchronous)
    //   Note: pitch estimate is naturally N/2 samples old
    phasein = phasein + phinc;
    phaseout = phaseout + phinc*phincfact;
    
    //   If it happens that there are no snippets placed at the output, grab a new snippet!
    /*     if (cbonorm[((long int)cbord + (long int)(N/2*(1 - (float)1 / phincfact)))%N] < 0.2) { */
    /*       fprintf(stderr, "help!"); */
    /*       phasein = 1; */
    /*       phaseout = 1; */
    /*     } */
    
    //   When input phase resets, take a snippet from N/2 samples in the past
    if (phasein >= 1) {
      phasein = phasein - 1;
      ti2 = cbiwr - (long int)N/2;
      for (ti=-((long int)N)/2; ti<(long int)N/2; ti++) {
        frag[ti%N] = cbi[(ti + ti2)%N];
      }
    }
    
    //   When output phase resets, put a snippet N/2 samples in the future
    if (phaseout >= 1) {
      fragsize = fragsize*2;
      if (fragsize >= N) {
        fragsize = N;
      }
      phaseout = phaseout - 1;
      ti2 = cbord + N/2;
      ti3 = (long int)(((float)fragsize) / phincfact);
      for (ti=-ti3/2; ti<(ti3/2); ti++) {
        tf = hannwindow[(long int)N/2 + ti*(long int)N/ti3];
        cbo[(ti + ti2)%N] = cbo[(ti + ti2)%N] + frag[((int)(phincfact*ti))%N]*tf;
        cbonorm[(ti + ti2)%N] = cbonorm[(ti + ti2)%N] + tf;
      }
      fragsize = 0;
    }
    fragsize++;
    
    //   Get output signal from buffer
    tf = cbonorm[cbord];
    //   Normalize
    if (tf>0.5) {
      tf = (float)1/tf;
    }
    else {
      tf = 1;
    }
    tf = tf*cbo[cbord]; // read buffer
    tf = cbo[cbord];
    cbo[cbord] = 0; // erase for next cycle
    cbonorm[cbord] = 0;
    cbord++; // increment read pointer
    if (cbord >= N) {
      cbord = 0;
    }
    
    // *********************
    // * END Pitch Shifter *
    // *********************
    
    
    // Write audio to output of plugin
    // Mix (blend between original (delayed) =0 and shifted/corrected =1)
    *out1 = *out2 = (double) fMix*tf + (1-fMix)*cbi[(cbiwr - N + 1)%N];
  }
  
}
示例#5
0
文件: autotune~.c 项目: Angeldude/pd
//*************************//
// Perform Routine PD//
//*************************//
t_int *autotune_perform(t_int *w)
{
	t_autotune *x = (t_autotune *)(w[1]); // object is first arg 
	t_float *in = (t_float *)(w[2]);
	t_float *out = (t_float *)(w[3]);
	unsigned long SampleCount = (unsigned long)(w[4]);
	
	// copy struct variables to local
	
	/*float fA = x->fA;
	float fBb = x->fBb;
	float fB = x->fB;
	float fC = x->fC;
	float fDb = x->fDb;
	float fD = x->fD;
	float fEb = x->fEb;
	float fE = x->fE;
	float fF = x->fF;
	float fGb = x->fGb;
	float fG = x->fG;
	float fAb = x->fAb;*/
	//float fGlide = x->fGlide;
	//float fPersist = x->glidepersist;
	
	int iNotes[12];
	int iPitch2Note[12];
	int iNote2Pitch[12];
	int numNotes;

	float fAmount = x->fAmount;
	float fSmooth = x->fSmooth * 0.8;
	float fTune = x->fTune;
	iNotes[0] = (int) x->fA;
	iNotes[1] = (int) x->fBb;
	iNotes[2] = (int) x->fB;
	iNotes[3] = (int) x->fC;
	iNotes[4] = (int) x->fDb;
	iNotes[5] = (int) x->fD;
	iNotes[6] = (int) x->fEb;
	iNotes[7] = (int) x->fE;
	iNotes[8] = (int) x->fF;
	iNotes[9] = (int) x->fGb;
	iNotes[10] = (int) x->fG;
	iNotes[11] = (int) x->fAb;
	float fFixed = x->fFixed;
	float fPull = x->fPull;
	float fShift = x->fShift;
	int iScwarp = x->fScwarp;
	float fLfoamp = x->fLfoamp;
	float fLforate = x->fLforate;
	float fLfoshape = x->fLfoshape;
	float fLfosymm = x->fLfosymm;
	int iLfoquant = x->fLfoquant;
	int iFcorr = x->fFcorr;
	float fFwarp = x->fFwarp;
	float fMix = x->fMix;
	
	//x->aref = (float)440*pow(2,fTune/12);
	
	unsigned long int lSampleIndex;
	
	unsigned long N = x->cbsize;
	unsigned long Nf = x->corrsize;
	unsigned long fs = x->fs;

	float pmax = x->pmax;
	float pmin = x->pmin;
	unsigned long nmax = x->nmax;
	unsigned long nmin = x->nmin;
	
	//float pperiod = x->pperiod;
	//float pitch = x->pitch;
	
		//
	
	volatile long int ti;
	volatile long int ti2;
	volatile long int ti3;
	volatile long int ti4;
	volatile float tf;
	volatile float tf2;
	volatile float tf3;

	// Variables for cubic spline interpolator
	volatile float indd;
	volatile int ind0;
	volatile int ind1;
	volatile int ind2;
	volatile int ind3;
	volatile float vald;
	volatile float val0;
	volatile float val1;
	volatile float val2;
	volatile float val3;

	volatile int lowersnap;
	volatile int uppersnap;
	volatile float lfoval;

	volatile float pperiod;
	volatile float inpitch;
	volatile float conf;
	volatile float outpitch;
	volatile float aref;
	volatile float fa;
	volatile float fb;
	volatile float fc;
	volatile float fk;
	volatile float flamb;
	volatile float frlamb;
	volatile float falph;
	volatile float foma;
	volatile float f1resp;
	volatile float f0resp;
	volatile float flpa;
	volatile int ford;

	// Some logic for the semitone->scale and scale->semitone conversion
	// If no notes are selected as being in the scale, instead snap to all notes
	ti2 = 0;
	for (ti=0; ti<12; ti++) {
		if (iNotes[ti]>=0) {
			iPitch2Note[ti] = ti2;
			iNote2Pitch[ti2] = ti;
			ti2 = ti2 + 1;
		}
		else {
			iPitch2Note[ti] = -1;
		}
	}
	numNotes = ti2;
	while (ti2<12) {
		iNote2Pitch[ti2] = -1;
		ti2 = ti2 + 1;
	}
	if (numNotes==0) {
		for (ti=0; ti<12; ti++) {
			iNotes[ti] = 1;
			iPitch2Note[ti] = ti;
			iNote2Pitch[ti] = ti;
		}
		numNotes = 12;
	}
	iScwarp = (iScwarp + numNotes*5)%numNotes;

	ford = x->ford;
	falph = x->falph;
	foma = (float)1 - falph;
	flpa = x->flpa;
	flamb = x->flamb;
	tf = pow((float)2,fFwarp/2)*(1+flamb)/(1-flamb);
	frlamb = (tf - 1)/(tf + 1);

	x->aref = (float)fTune;

	N = x->cbsize;
	Nf = x->corrsize;
	fs = x->fs;

	pmax = x->pmax;
	pmin = x->pmin;
	nmax = x->nmax;
	nmin = x->nmin;

	aref = x->aref;
	pperiod = x->pmax;
	inpitch = x->inpitch;
	conf = x->conf;
	outpitch = x->outpitch;

	
	//******************//
	//  MAIN DSP LOOP   //
	//******************//
	for (lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++)  
	{
		
		// load data into circular buffer
		tf = (float) *(in++);
		ti4 = x->cbiwr;
		//fprintf(stderr,"ti4=%d N=%d\n", ti4, N);
		x->cbi[ti4] = tf;
		/*x->cbiwr++;
		if (x->cbiwr >= N) {
			x->cbiwr = 0;
		}*/
		
		if (iFcorr>=1) {
			// Somewhat experimental formant corrector
			//  formants are removed using an adaptive pre-filter and
			//  re-introduced after pitch manipulation using post-filter
			// tf is signal input
			fa = tf - x->fhp; // highpass pre-emphasis filter
			x->fhp = tf;
			fb = fa;
			for (ti=0; ti<(long)ford; ti++) {
				x->fsig[ti] = fa*fa*foma + x->fsig[ti]*falph;
				fc = (fb-x->fc[ti])*flamb + x->fb[ti];
				x->fc[ti] = fc;
				x->fb[ti] = fb;
				fk = fa*fc*foma + x->fk[ti]*falph;
				x->fk[ti] = fk;
				tf = fk/(x->fsig[ti] + 0.000001);
				tf = tf*foma + x->fsmooth[ti]*falph;
				x->fsmooth[ti] = tf;
				x->fbuff[ti][ti4] = tf;
				fb = fc - tf*fa;
				fa = fa - tf*fc;
			}
			x->cbf[ti4] = fa;
			// Now hopefully the formants are reduced
			// More formant correction code at the end of the DSP loop
		}
		else {
			x->cbf[ti4] = tf;
		}

		//fprintf(stderr,"x->cbf[ti4]=%f\n", x->cbf[ti4]);

	    // Input write pointer logic
	    x->cbiwr++;
	    if (x->cbiwr >= N) {
	      x->cbiwr = 0;
	    }

		
		// ********************//
		// * Low-rate section *//
		// ********************//

		//fprintf(stderr,"overlap=%d outpitch=%f inpitch=%f\n", (x->cbiwr)%(N/x->noverlap), outpitch, inpitch);
		//fprintf(stderr,"outpitch=%f inpitch=%f\n", outpitch, inpitch);
		
		// Every N/noverlap samples, run pitch estimation / correction code
		if ((x->cbiwr)%(N/x->noverlap) == 0) {
			
			//fprintf(stderr,"ti4=%d N=%d\n", ti4, N);
			// ---- Obtain autocovariance ---- //
			
			// Window and fill FFT buffer
			ti2 = (long) x->cbiwr;
			for (ti=0; ti<(long)N; ti++) {
				x->ffttime[ti] = (float)(x->cbi[(ti2-ti)%N]*x->cbwindow[ti]);
			}
			
			// Calculate FFT
			fft_forward(x->fx, x->ffttime, x->fftfreqre, x->fftfreqim);
			
			// Remove DC
			x->fftfreqre[0] = 0;
			x->fftfreqim[0] = 0;
			
			// Take magnitude squared
			for (ti=1; ti< (long) Nf; ti++) {
				x->fftfreqre[ti] = (x->fftfreqre[ti])*(x->fftfreqre[ti]) + (x->fftfreqim[ti])*(x->fftfreqim[ti]);
				x->fftfreqim[ti] = 0;
			}
			
			// Calculate IFFT
			fft_inverse(x->fx, x->fftfreqre, x->fftfreqim, x->ffttime);
			
			// Normalize
			for (ti=1; ti<(long)N; ti++) {
				x->ffttime[ti] = x->ffttime[ti] / x->ffttime[0];
			}
			x->ffttime[0] = 1;
			
			//  ---- END Obtain autocovariance ----
			
			
			//  ---- Calculate pitch and confidence ----
			
			// Calculate pitch period
			//   Pitch period is determined by the location of the max (biased)
			//   peak within a given range
			//   Confidence is determined by the corresponding unbiased height
			tf2 = 0;
			pperiod = pmin;
			for (ti=nmin; ti<(long)nmax; ti++) {
				ti2 = ti-1;
				ti3 = ti+1;
				if (ti2<0) {
					ti2 = 0;
				}
				if (ti3>(long)Nf) {
					ti3 = Nf;
				}
				tf = x->ffttime[ti];
				
				if (tf>x->ffttime[ti2] && tf>=x->ffttime[ti3] && tf>tf2) {
					tf2 = tf;
					ti4 = ti;
					//conf = tf*x->acwinv[ti];
					//pperiod = (float)ti/fs;
				}
			}
			if (tf2>0) {
				conf = tf2*x->acwinv[ti4];
				if (ti4>0 && ti4<(long)Nf) {
					// Find the center of mass in the vicinity of the detected peak
					tf = x->ffttime[ti4-1]*(ti4-1);
					tf = tf + x->ffttime[ti4]*(ti4);
					tf = tf + x->ffttime[ti4+1]*(ti4+1);
					tf = tf/(x->ffttime[ti4-1] + x->ffttime[ti4] + x->ffttime[ti4+1]);
					pperiod = tf/fs;
				}
				else {
					pperiod = (float)ti4/fs;
				}
			}
			
			// Convert to semitones
			tf = (float) -12*log10((float)aref*pperiod)*L2SC;
			//fprintf(stderr,"tf=%f aref=%f pperiod=%f\n", tf, aref, pperiod);
			//post("pperiod=%f conf=%f\n", pperiod, conf);
			float pp_test = x->pperiod/(x->pperiod - pperiod);
			if (pp_test < 0.5 || pp_test > 2)
				pp_test = 1;
			else
				pp_test = 0;
			if (conf>=x->vthresh && tf == tf) { // second check is for NANs
				inpitch = tf;
				x->inpitch = tf; // update pitch only if voiced
				x->pperiod = pperiod;
			}
			x->conf = conf;

			x->fPitch = inpitch;
			x->fConf = conf;

			//x->pitch = pitch;
			//x->pperiod = pperiod;
			//x->conf = conf;
			
			//  ---- END Calculate pitch and confidence ----
			
			
			/*
			//  ---- Determine pitch target ----
			
			// If voiced
			if (conf>=x->vthresh) {
				// TODO: Scale sliders
				// Determine pitch target
				tf = -1;
				tf2 = 0;
				tf3 = 0;
				for (ti=0; ti<12; ti++) {
					switch (ti) {
						case 0:
							tf2 = fA;
							break;
						case 1:
							tf2 = fBb;
							break;
						case 2:
							tf2 = fB;
							break;
						case 3:
							tf2 = fC;
							break;
						case 4:
							tf2 = fDb;
							break;
						case 5:
							tf2 = fD;
							break;
						case 6:
							tf2 = fEb;
							break;
						case 7:
							tf2 = fE;
							break;
						case 8:
							tf2 = fF;
							break;
						case 9:
							tf2 = fGb;
							break;
						case 10:
							tf2 = fG;
							break;
						case 11:
							tf2 = fAb;
							break;
					}
					// 	  if (ti==x->ptarget) {
					// 	    tf2 = tf2 + 0.01; // add a little hysteresis
					// 	  }
					tf2 = tf2 - (float)fabs( (pitch-(float)ti)/6 - 2*floorf(((pitch-(float)ti)/12 + 0.5)) ); // like a likelihood function
					if (tf2>=tf) {                                                                           // that we're maximizing
						tf3 = (float)ti;                                                                       // to find the target pitch
						tf = tf2;
					}
				}
				x->ptarget = tf3;
				
				// Glide persist
				if (x->wasvoiced == 0) {
					x->wasvoiced = 1;
					tf = x->persistamt;
					x->sptarget = (1-tf)*x->ptarget + tf*x->sptarget;
					x->persistamt = 1;
				}
				
				// Glide on circular scale
				tf3 = (float)x->ptarget - x->sptarget;
				tf3 = tf3 - (float)12*floorf(tf3/12 + 0.5);
				if (fGlide>0) {
					tf2 = (float)1-pow((float)1/24, (float)N * 1000/ (x->noverlap*fs*fGlide));
				}
				else {
					tf2 = 1;
				}
				x->sptarget = x->sptarget + tf3*tf2;
			}
			// If not voiced
			else {
				x->wasvoiced = 0;
				
				// Keep track of persist amount
				if (fPersist>0) {
					tf = pow((float)1/2, (float)N * 1000/ (x->noverlap*fs*fPersist));
				}
				else {
					tf = 0;
				}
				x->persistamt = x->persistamt * tf; // Persist amount decays exponentially
			}
			// END If voiced
			
			//  ---- END Determine pitch target ----
			
			
			// ---- Determine correction to feed to the pitch shifter ----
			tf = x->sptarget - pitch; // Correction amount
			tf = tf - (float)12*floorf(tf/12 + 0.5); // Never do more than +- 6 semitones of correction
			if (conf<x->vthresh) {
				tf = 0;
			}
			x->lrshift = fShift + fAmount*tf;  // Add in pitch shift slider
			
			
			// ---- Compute variables for pitch shifter that depend on pitch ---
			x->phincfact = (float)pow(2, x->lrshift/12);
			if (conf>=x->vthresh) {  // Keep old period when unvoiced
				x->inphinc = (float)1/(pperiod*fs);
				x->phprd = pperiod*2;
			}
		}
		// ************************
		// * END Low-Rate Section *
		// ************************
		*/
			//fprintf(stderr,"%f %f %f %f", inpitch, outpitch, pperiod, ti4);

			//  ---- Modify pitch in all kinds of ways! ----

			outpitch = inpitch;

			//fprintf(stderr,"outpitch=%f\n", outpitch);

			// Pull to fixed pitch

			// when fPull is 1 (legacy behavior which picks absolute pitch in respect to A intonation)
			if (fPull <= 1)
			{
				outpitch = (1-fPull)*outpitch + fPull*fFixed;
			}
			else
			{
				// Special pull case when fPull is 2
				/*if (fFixed < 0)
					while (fFixed < 0)
						fFixed += 12;
				else if (fFixed > 12)
					while (fFixed > 12)
						fFixed -= 12;*/

				float inpitch_norm = inpitch;
				if (inpitch_norm < 6)
					while (inpitch_norm < 6)
						inpitch_norm += 12;
				else if (inpitch_norm > 6)
					while (inpitch_norm > 6)
						inpitch_norm -= 12;
				/*float a = fFixed - inpitch_norm;
				float b = fFixed - 12 - inpitch_norm;
				float c = fFixed + 12 - inpitch_norm;
				float result = a;
				if (abs(b) < abs(result)) result = b;
				if (abs(c) < abs(result)) result = c;
				outpitch = inpitch + result;*/
				float a = inpitch - inpitch_norm;
				float b = inpitch - 12 - inpitch_norm;
				float c = inpitch + 12 - inpitch_norm;
				//post("a=%f b=%f c=%f in_norm=%f\n", a, b, c, inpitch_norm);
				float result = a;
				if (abs(b) < abs(result)) result = b;
				if (abs(c) < abs(result)) result = c;
				outpitch = result + fFixed;
				//fprintf(stderr,"outpitch=%f inpitch=%f in_norm=%f\n", outpitch, inpitch, inpitch_norm);

			}

			// -- Convert from semitones to scale notes --
			ti = (int)(outpitch/12 + 32) - 32; // octave
			tf = outpitch - ti*12; // semitone in octave
			ti2 = (int)tf;
			ti3 = ti2 + 1;
			// a little bit of pitch correction logic, since it's a convenient place for it
			if (iNotes[ti2%12]<0 || iNotes[ti3%12]<0) { // if between 2 notes that are more than a semitone apart
				lowersnap = 1;
				uppersnap = 1;
			}
			else {
				lowersnap = 0;
				uppersnap = 0;
				if (iNotes[ti2%12]==1) { // if specified by user
					lowersnap = 1;
				}
				if (iNotes[ti3%12]==1) { // if specified by user
					uppersnap = 1;
				}
			}
			// (back to the semitone->scale conversion)
			// finding next lower pitch in scale
			while (iNotes[(ti2+12)%12]<0) {
				ti2 = ti2 - 1;
			}
			// finding next higher pitch in scale
			while (iNotes[ti3%12]<0) {
				ti3 = ti3 + 1;
			}
			tf = (tf-ti2)/(ti3-ti2) + iPitch2Note[(ti2+12)%12];
			if (ti2<0) {
				tf = tf - numNotes;
			}
			outpitch = tf + numNotes*ti;
			// -- Done converting to scale notes --

			// The actual pitch correction
			ti = (int)(outpitch+128) - 128;
			tf = outpitch - ti - 0.5;
			ti2 = ti3-ti2;
			if (ti2>2) { // if more than 2 semitones apart, put a 2-semitone-like transition halfway between
				tf2 = (float)ti2/2;
			}
			else {
				tf2 = (float)1;
			}
			if (fSmooth<0.001) {
				tf2 = tf*tf2/0.001;
			}
			else {
				tf2 = tf*tf2/fSmooth;
			}
			if (tf2<-0.5) tf2 = -0.5;
			if (tf2>0.5) tf2 = 0.5;
			tf2 = 0.5*sin(PI*tf2) + 0.5; // jumping between notes using horizontally-scaled sine segment
			tf2 = tf2 + ti;
			if ( (tf<0.5 && lowersnap) || (tf>=0.5 && uppersnap) ) {
				outpitch = fAmount*tf2 + ((float)1-fAmount)*outpitch;
			}

			// Add in pitch shift
			outpitch = outpitch + fShift;

			// LFO logic
			tf = fLforate*N/(x->noverlap*fs);
			if (tf>1) tf=1;
			x->lfophase = x->lfophase + tf;
			if (x->lfophase>1) x->lfophase = x->lfophase-1;
			lfoval = x->lfophase;
			tf = (fLfosymm + 1)/2;
			if (tf<=0 || tf>=1) {
				if (tf<=0) lfoval = 1-lfoval;
			}
			else {
				if (lfoval<=tf) {
					lfoval = lfoval/tf;
				}
				else {
					lfoval = 1 - (lfoval-tf)/(1-tf);
				}
			}
			if (fLfoshape>=0) {
				// linear combination of cos and line
				lfoval = (0.5 - 0.5*cos(lfoval*PI))*fLfoshape + lfoval*(1-fLfoshape);
				lfoval = fLfoamp*(lfoval*2 - 1);
			}
			else {
				// smoosh the sine horizontally until it's squarish
				tf = 1 + fLfoshape;
				if (tf<0.001) {
					lfoval = (lfoval - 0.5)*2/0.001;
				}
				else {
					lfoval = (lfoval - 0.5)*2/tf;
				}
				if (lfoval>1) lfoval = 1;
				if (lfoval<-1) lfoval = -1;
				lfoval = fLfoamp*sin(lfoval*PI*0.5);
			}
			// add in quantized LFO
			if (iLfoquant>=1) {
				outpitch = outpitch + (int)(numNotes*lfoval + numNotes + 0.5) - numNotes;
			}


			// Convert back from scale notes to semitones
			outpitch = outpitch + iScwarp; // output scale rotate implemented here
			ti = (int)(outpitch/numNotes + 32) - 32;
			tf = outpitch - ti*numNotes;
			ti2 = (int)tf;
			ti3 = ti2 + 1;
			outpitch = iNote2Pitch[ti3%numNotes] - iNote2Pitch[ti2];
			if (ti3>=numNotes) {
				outpitch = outpitch + 12;
			}
			outpitch = outpitch*(tf - ti2) + iNote2Pitch[ti2];
			outpitch = outpitch + 12*ti;
			outpitch = outpitch - (iNote2Pitch[iScwarp] - iNote2Pitch[0]); //more scale rotation here

			// add in unquantized LFO
			if (iLfoquant<=0) {
				outpitch = outpitch + lfoval*2;
			}

			if (outpitch<-36) outpitch = -48;
			if (outpitch>24) outpitch = 24;

			x->outpitch = outpitch;

			//  ---- END Modify pitch in all kinds of ways! ----

			// Compute variables for pitch shifter that depend on pitch
			x->inphinc = aref*pow(2,inpitch/12)/fs;
			x->outphinc = aref*pow(2,outpitch/12)/fs;
			x->phincfact = x->outphinc/x->inphinc;
		}
		// ************************
		// * END Low-Rate Section *
		// ************************
		
		
		// *****************
		// * Pitch Shifter *
		// *****************
		
	    // Pitch shifter (kind of like a pitch-synchronous version of Fairbanks' technique)
	    //   Note: pitch estimate is naturally N/2 samples old
		x->phasein = x->phasein + x->inphinc;
		x->phaseout = x->phaseout + x->inphinc*x->phincfact;
		
		//   If it happens that there are no snippets placed at the output, grab a new snippet!
		/*     if (x->cbonorm[((long int)x->cbord + (long int)(N/2*(1 - (float)1 / x->phincfact)))%N] < 0.2) { */
		/*       post( "help!"); */
		/*       x->phasein = 1; */
		/*       x->phaseout = 1; */
		/*     } */
		
		//   When input phase resets, take a snippet from N/2 samples in the past
		if (x->phasein >= 1) {
			x->phasein = x->phasein - 1;
			ti2 = x->cbiwr - (long int)N/2;
			for (ti=-((long int)N)/2; ti<(long int)N/2; ti++) {
				x->frag[ti%N] = x->cbi[(ti + ti2)%N];
			}
		}
		
		//   When output phase resets, put a snippet N/2 samples in the future
		if (x->phaseout >= 1) {
			x->fragsize = x->fragsize*2;
			if (x->fragsize >= N) {
				x->fragsize = N;
			}
			x->phaseout = x->phaseout - 1;
			ti2 = x->cbord + N/2;
			ti3 = (long int)(((float)x->fragsize) / x->phincfact);
			if (ti3>=(long int)N/2) {
				ti3 = N/2 - 1;
			}
			for (ti=-ti3/2; ti<(ti3/2); ti++) {
				tf = x->hannwindow[(long int)N/2 + ti*(long int)N/ti3];
				// 3rd degree polynomial interpolator - based on eqns from Hal Chamberlin's book
				indd = x->phincfact*ti;
				ind1 = (int)indd;
				ind2 = ind1+1;
				ind3 = ind1+2;
				ind0 = ind1-1;
				val0 = x->frag[(ind0+N)%N];
				val1 = x->frag[(ind1+N)%N];
				val2 = x->frag[(ind2+N)%N];
				val3 = x->frag[(ind3+N)%N];
				vald = 0;
				vald = vald - (float)0.166666666667 * val0 * (indd - ind1) * (indd - ind2) * (indd - ind3);
				vald = vald + (float)0.5 * val1 * (indd - ind0) * (indd - ind2) * (indd - ind3);
				vald = vald - (float)0.5 * val2 * (indd - ind0) * (indd - ind1) * (indd - ind3);
				vald = vald + (float)0.166666666667 * val3 * (indd - ind0) * (indd - ind1) * (indd - ind2);
				x->cbo[(ti + ti2 + N)%N] = x->cbo[(ti + ti2 + N)%N] + vald*tf;
			}
			x->fragsize = 0;
		}
		x->fragsize++;

		//   Get output signal from buffer
		tf = x->cbo[x->cbord];
		/*//   Normalize
		if (tf>0.5) {
			tf = (float)1/tf;
		}
		else {
			tf = 1;
		}*/
		//tf = tf*x->cbo[x->cbord]; // read buffer
		tf = x->cbo[x->cbord];
		x->cbo[x->cbord] = 0; // erase for next cycle
		//x->cbonorm[x->cbord] = 0;
		x->cbord++; // increment read pointer
		if (x->cbord >= N) {
			x->cbord = 0;
		}
		
		// *********************
		// * END Pitch Shifter *
		// *********************
		
		ti4 = (x->cbiwr + 2)%N;
		if (iFcorr>=1) {
			// The second part of the formant corrector
			// This is a post-filter that re-applies the formants, designed
			//   to result in the exact original signal when no pitch
			//   manipulation is performed.
			// tf is signal input
			// gotta run it 3 times because of a pesky delay free loop
			//  first time: compute 0-response
			tf2 = tf;
			fa = 0;
			fb = fa;
			for (ti=0; ti<ford; ti++) {
				fc = (fb-x->frc[ti])*frlamb + x->frb[ti];
				tf = x->fbuff[ti][ti4];
				fb = fc - tf*fa;
				x->ftvec[ti] = tf*fc;
				fa = fa - x->ftvec[ti];
			}
			tf = -fa;
			for (ti=ford-1; ti>=0; ti--) {
				tf = tf + x->ftvec[ti];
			}
			f0resp = tf;
			//  second time: compute 1-response
			fa = 1;
			fb = fa;
			for (ti=0; ti<ford; ti++) {
				fc = (fb-x->frc[ti])*frlamb + x->frb[ti];
				tf = x->fbuff[ti][ti4];
				fb = fc - tf*fa;
				x->ftvec[ti] = tf*fc;
				fa = fa - x->ftvec[ti];
			}
			tf = -fa;
			for (ti=ford-1; ti>=0; ti--) {
				tf = tf + x->ftvec[ti];
			}
			f1resp = tf;
			//  now solve equations for output, based on 0-response and 1-response
			tf = (float)2*tf2;
			tf2 = tf;
			tf = ((float)1 - f1resp + f0resp);
			if (tf!=0) {
				tf2 = (tf2 + f0resp) / tf;
			}
			else {
				tf2 = 0;
			}
			//  third time: update delay registers
			fa = tf2;
			fb = fa;
			for (ti=0; ti<ford; ti++) {
				fc = (fb-x->frc[ti])*frlamb + x->frb[ti];
				x->frc[ti] = fc;
				x->frb[ti] = fb;
				tf = x->fbuff[ti][ti4];
				fb = fc - tf*fa;
				fa = fa - tf*fc;
			}
			tf = tf2;
			tf = tf + flpa*x->flp;  // lowpass post-emphasis filter
			x->flp = tf;
			// Bring up the gain slowly when formant correction goes from disabled
			// to enabled, while things stabilize.
			if (x->fmute>0.5) {
				tf = tf*(x->fmute - 0.5)*2;
			}
			else {
				tf = 0;
			}
			tf2 = x->fmutealph;
			x->fmute = (1-tf2) + tf2*x->fmute;
			// now tf is signal output
			// ...and we're done messing with formants
		}
		else {
			x->fmute = 0;
		}
		
		// Write audio to output of plugin
		// Mix (blend between original (delayed) =0 and shifted/corrected =1)
		*(out++) = fMix*tf + (1-fMix)*x->cbi[ti4];
		//*(pfOutput++) = (float) fMix*tf + (1-fMix)*x->cbi[(x->cbiwr - N + 1)%N];
		
	}

    return (w + 5); // always add one more than the 2nd argument in dsp_add()
}
示例#6
0
文件: autotune~.c 项目: Angeldude/pd
void autotune_init(t_autotune *x,unsigned long sr)
{
	unsigned long ti;

	x->fs = sr;
	x->aref = 440;
	x->fTune = x->aref;
	
	if (x->cbsize == 0)
	{
		if (x->fs >=88200) {
			x->cbsize = 4096;
		}
		else {
			x->cbsize = 2048;
		}
	}
	x->corrsize = x->cbsize / 2 + 1;
	
	x->pmax = 1/(float)70;  // max and min periods (ms)
	x->pmin = 1/(float)2400; // eventually may want to bring these out as sliders
	
	x->pperiod = x->pmax;
	
	x->nmax = (unsigned long)(x->fs * x->pmax);
	if (x->nmax > x->corrsize) {
		x->nmax = x->corrsize;
	}
	x->nmin = (unsigned long)(x->fs * x->pmin);
	
	x->cbi = (float*) calloc(x->cbsize, sizeof(float));
	x->cbf = (float*) calloc(x->cbsize, sizeof(float));
	x->cbo = (float*) calloc(x->cbsize, sizeof(float));
	//x->cbonorm = (float*) calloc(x->cbsize, sizeof(float));
	
	x->cbiwr = 0;
	x->cbord = 0;

	x->lfophase = 0;

	// Initialize formant corrector
	x->ford = 7; // should be sufficient to capture formants
	x->falph = pow(0.001, (float) 80 / (x->fs));
	x->flamb = -(0.8517*sqrt(atan(0.06583*x->fs))-0.1916); // or about -0.88 @ 44.1kHz
	x->fk = calloc(x->ford, sizeof(float));
	x->fb = calloc(x->ford, sizeof(float));
	x->fc = calloc(x->ford, sizeof(float));
	x->frb = calloc(x->ford, sizeof(float));
	x->frc = calloc(x->ford, sizeof(float));
	x->fsig = calloc(x->ford, sizeof(float));
	x->fsmooth = calloc(x->ford, sizeof(float));
	x->fhp = 0;
	x->flp = 0;
	x->flpa = pow(0.001, (float) 10 / (x->fs));
	x->fbuff = (float**) malloc((x->ford)*sizeof(float*));
	for (ti=0; ti<x->ford; ti++) {
		x->fbuff[ti] = calloc(x->cbsize, sizeof(float));
	}
	x->ftvec = calloc(x->ford, sizeof(float));
	x->fmute = 1;
	x->fmutealph = pow(0.001, (float)1 / (x->fs));
	
	// Standard raised cosine window, max height at N/2
	x->hannwindow = (float*) calloc(x->cbsize, sizeof(float));
	for (ti=0; ti<x->cbsize; ti++) {
		x->hannwindow[ti] = -0.5*cos(2*PI*ti/(x->cbsize - 1)) + 0.5;
	}
	
	// Generate a window with a single raised cosine from N/4 to 3N/4
	x->cbwindow = (float*) calloc(x->cbsize, sizeof(float));
	for (ti=0; ti<(x->cbsize / 2); ti++) {
		x->cbwindow[ti+x->cbsize/4] = -0.5*cos(4*PI*ti/(x->cbsize - 1)) + 0.5;
	}
	
	if (x->noverlap == 0)
		x->noverlap = 4;

	//fprintf(stderr,"%d %d\n", x->cbsize, x->noverlap);
	
	x->fx = fft_con(x->cbsize);
	
	x->ffttime = (float*) calloc(x->cbsize, sizeof(float));
	x->fftfreqre = (float*) calloc(x->corrsize, sizeof(float));
	x->fftfreqim = (float*) calloc(x->corrsize, sizeof(float));
	
	
	// ---- Calculate autocorrelation of window ----
	x->acwinv = (float*) calloc(x->cbsize, sizeof(float));
	for (ti=0; ti<x->cbsize; ti++) {
		x->ffttime[ti] = x->cbwindow[ti];
	}
	fft_forward(x->fx, x->cbwindow, x->fftfreqre, x->fftfreqim);
	for (ti=0; ti<x->corrsize; ti++) {
		x->fftfreqre[ti] = (x->fftfreqre[ti])*(x->fftfreqre[ti]) + (x->fftfreqim[ti])*(x->fftfreqim[ti]);
		x->fftfreqim[ti] = 0;
	}
	fft_inverse(x->fx, x->fftfreqre, x->fftfreqim, x->ffttime);
	for (ti=1; ti<x->cbsize; ti++) {
		x->acwinv[ti] = x->ffttime[ti]/x->ffttime[0];
		if (x->acwinv[ti] > 0.000001) {
			x->acwinv[ti] = (float)1/x->acwinv[ti];
		}
		else {
			x->acwinv[ti] = 0;
		}
	}
	x->acwinv[0] = 1;
	// ---- END Calculate autocorrelation of window ----	
	
	x->lrshift = 0;
	x->ptarget = 0;
	x->sptarget = 0;
	//x->sptarget = 0;
	//x->wasvoiced = 0;
	//x->persistamt = 0;
	
	//x->glidepersist = 100; // 100 ms glide persist
	
	x->vthresh = 0.7;  //  The voiced confidence (unbiased peak) threshold level
	
	// Pitch shifter initialization
	x->phprdd = 0.01; // Default period
	//x->phprd = x->phprdd;
	x->inphinc = (float)1/(x->phprdd * x->fs);
	x->phincfact = 1;
	x->phasein = 0;
	x->phaseout = 0;
	x->frag = (float*) calloc(x->cbsize, sizeof(float));
	x->fragsize = 0;
}
示例#7
0
// Called every time we get a new chunk of audio
void runAutotalent(Autotalent * Instance, unsigned long SampleCount) {
  
  // some kind of buffer, need to find out the type, looks like floats
  float* pfInput;
  float* pfOutput;

  float fAmount;
  float fSmooth;
  int iNotes[12];
  int iPitch2Note[12];
  int iNote2Pitch[12];
  int numNotes;
  float fTune;
  float fFixed;
  float fPull;
  float fShift;
  int iScwarp;
  float fLfoamp;
  float fLforate;
  float fLfoshape;
  float fLfosymm;
  int iLfoquant;
  int iFcorr;
  float fFwarp;
  float fMix;
  Autotalent* psAutotalent;
  unsigned long lSampleIndex;

  long int N;
  long int Nf;
  long int fs;
  float pmin;
  float pmax;
  unsigned long nmin;
  unsigned long nmax;

  long int ti;
  long int ti2;
  long int ti3;
  long int ti4;
  float tf;
  float tf2;

  // Variables for cubic spline interpolator
  float indd;
  int ind0;
  int ind1;
  int ind2;
  int ind3;
  float vald;
  float val0;
  float val1;
  float val2;
  float val3;

  int lowersnap;
  int uppersnap;
  float lfoval;

  float pperiod;
  float inpitch;
  float conf;
  float outpitch;
  float aref;
  float fa;
  float fb;
  float fc;
  float fk;
  float flamb;
  float frlamb;
  float falph;
  float foma;
  float f1resp;
  float f0resp;
  float flpa;
  int ford;
  psAutotalent = (Autotalent *)Instance;

  pfInput = psAutotalent->m_pfInputBuffer1;
  pfOutput = psAutotalent->m_pfOutputBuffer1;
  fAmount = (float) *(psAutotalent->m_pfAmount);
  fSmooth = (float) *(psAutotalent->m_pfSmooth) * 0.8; // Scales max to a more reasonable value
  fTune = (float) *(psAutotalent->m_pfTune);
  iNotes[0] = psAutotalent->m_pfKey[AT_A];
  iNotes[1] = psAutotalent->m_pfKey[AT_Bb];
  iNotes[2] = psAutotalent->m_pfKey[AT_B];
  iNotes[3] = psAutotalent->m_pfKey[AT_C];
  iNotes[4] = psAutotalent->m_pfKey[AT_Db];
  iNotes[5] = psAutotalent->m_pfKey[AT_D];
  iNotes[6] = psAutotalent->m_pfKey[AT_Eb];
  iNotes[7] = psAutotalent->m_pfKey[AT_E];
  iNotes[8] = psAutotalent->m_pfKey[AT_F];
  iNotes[9] = psAutotalent->m_pfKey[AT_Gb];
  iNotes[10] = psAutotalent->m_pfKey[AT_G];
  iNotes[11] = psAutotalent->m_pfKey[AT_Ab];
  fFixed = (float) *(psAutotalent->m_pfFixed);
  fPull = (float) *(psAutotalent->m_pfPull);
  fShift = (float) *(psAutotalent->m_pfShift);
  iScwarp = (int) *(psAutotalent->m_pfScwarp);
  fLfoamp = (float) *(psAutotalent->m_pfLfoamp);
  fLforate = (float) *(psAutotalent->m_pfLforate);
  fLfoshape = (float) *(psAutotalent->m_pfLfoshape);
  fLfosymm = (float) *(psAutotalent->m_pfLfosymm);
  iLfoquant = (int) *(psAutotalent->m_pfLfoquant);
  iFcorr = (int) *(psAutotalent->m_pfFcorr);
  fFwarp = (float) *(psAutotalent->m_pfFwarp);
  fMix = (float) *(psAutotalent->m_pfMix);

  // Some logic for the semitone->scale and scale->semitone conversion
  // If no notes are selected as being in the scale, instead snap to all notes
  ti2 = 0;
  for (ti=0; ti<12; ti++) {
    if (iNotes[ti]>=0) {
      iPitch2Note[ti] = ti2;
      iNote2Pitch[ti2] = ti;
      ti2 = ti2 + 1;
    }
    else {
      iPitch2Note[ti] = -1;
    }
  }
  numNotes = ti2;
  while (ti2<12) {
    iNote2Pitch[ti2] = -1;
    ti2 = ti2 + 1;
  }
  if (numNotes==0) {
    for (ti=0; ti<12; ti++) {
      iNotes[ti] = 1;
      iPitch2Note[ti] = ti;
      iNote2Pitch[ti] = ti;
    }
    numNotes = 12;
  }
  iScwarp = (iScwarp + numNotes*5)%numNotes;

  ford = psAutotalent->ford;
  falph = psAutotalent->falph;
  foma = (float)1 - falph;
  flpa = psAutotalent->flpa;
  flamb = psAutotalent->flamb;
  tf = pow((float)2,fFwarp/2)*(1+flamb)/(1-flamb);
  frlamb = (tf - 1)/(tf + 1);

  psAutotalent->aref = (float)fTune;

  N = psAutotalent->cbsize;
  Nf = psAutotalent->corrsize;
  fs = psAutotalent->fs;

  pmax = psAutotalent->pmax;
  pmin = psAutotalent->pmin;
  nmax = psAutotalent->nmax;
  nmin = psAutotalent->nmin;

  aref = psAutotalent->aref;
  pperiod = psAutotalent->pmax;
  inpitch = psAutotalent->inpitch;
  conf = psAutotalent->conf;
  outpitch = psAutotalent->outpitch;

  /*******************
   *  MAIN DSP LOOP  *
   *******************/
  for (lSampleIndex = 0; lSampleIndex < SampleCount; lSampleIndex++)  {
    
    // load data into circular buffer
    tf = (float) *(pfInput++);
    ti4 = psAutotalent->cbiwr;
    psAutotalent->cbi[ti4] = tf;

    if (iFcorr>=1) {
      // Somewhat experimental formant corrector
      //  formants are removed using an adaptive pre-filter and
      //  re-introduced after pitch manipulation using post-filter
      // tf is signal input
      fa = tf - psAutotalent->fhp; // highpass pre-emphasis filter
      psAutotalent->fhp = tf;
      fb = fa;
      for (ti=0; ti<ford; ti++) {
	    psAutotalent->fsig[ti] = fa*fa*foma + psAutotalent->fsig[ti]*falph;
	    fc = (fb-psAutotalent->fc[ti])*flamb + psAutotalent->fb[ti];
	    psAutotalent->fc[ti] = fc;
	    psAutotalent->fb[ti] = fb;
	    fk = fa*fc*foma + psAutotalent->fk[ti]*falph;
	    psAutotalent->fk[ti] = fk;
	    tf = fk/(psAutotalent->fsig[ti] + 0.000001);
	    tf = tf*foma + psAutotalent->fsmooth[ti]*falph;
	    psAutotalent->fsmooth[ti] = tf;
	    psAutotalent->fbuff[ti][ti4] = tf;
	    fb = fc - tf*fa;
	    fa = fa - tf*fc;
      }
      psAutotalent->cbf[ti4] = fa;
      // Now hopefully the formants are reduced
      // More formant correction code at the end of the DSP loop
    }
    else {
      psAutotalent->cbf[ti4] = tf;
    }


    // Input write pointer logic
    psAutotalent->cbiwr++;
    if (psAutotalent->cbiwr >= N) {
      psAutotalent->cbiwr = 0;
    }

    // ********************
    // * Low-rate section *
    // ********************

    // Every N/noverlap samples, run pitch estimation / manipulation code
    if ((psAutotalent->cbiwr)%(N/psAutotalent->noverlap) == 0) {

      // ---- Obtain autocovariance ----

      // Window and fill FFT buffer
      ti2 = psAutotalent->cbiwr;
      for (ti=0; ti<N; ti++) {
	    psAutotalent->ffttime[ti] = (float)(psAutotalent->cbi[(ti2-ti+N)%N]*psAutotalent->cbwindow[ti]);
      }

      // Calculate FFT
      fft_forward(psAutotalent->fmembvars, psAutotalent->ffttime, psAutotalent->fftfreqre, psAutotalent->fftfreqim);

      // Remove DC
      psAutotalent->fftfreqre[0] = 0;
      psAutotalent->fftfreqim[0] = 0;

      // Take magnitude squared
      for (ti=1; ti<Nf; ti++) {
	    psAutotalent->fftfreqre[ti] = (psAutotalent->fftfreqre[ti])*(psAutotalent->fftfreqre[ti]) + (psAutotalent->fftfreqim[ti])*(psAutotalent->fftfreqim[ti]);
	    psAutotalent->fftfreqim[ti] = 0;
      }

      // Calculate IFFT
      fft_inverse(psAutotalent->fmembvars, psAutotalent->fftfreqre, psAutotalent->fftfreqim, psAutotalent->ffttime);

      // Normalize
      tf = (float)1/psAutotalent->ffttime[0];
      for (ti=1; ti<N; ti++) {
	    psAutotalent->ffttime[ti] = psAutotalent->ffttime[ti] * tf;
      }
      psAutotalent->ffttime[0] = 1;

      //  ---- END Obtain autocovariance ----

      //  ---- Calculate pitch and confidence ----

      // Calculate pitch period
      //   Pitch period is determined by the location of the max (biased)
      //     peak within a given range
      //   Confidence is determined by the corresponding unbiased height
      tf2 = 0;
      pperiod = pmin;
      for (ti=nmin; ti<nmax; ti++) {
	    ti2 = ti-1;
	    ti3 = ti+1;
	    if (ti2<0) {
	      ti2 = 0;
	    }
	    if (ti3>Nf) {
	      ti3 = Nf;
	    }
	    tf = psAutotalent->ffttime[ti];

	    if (tf>psAutotalent->ffttime[ti2] && tf>=psAutotalent->ffttime[ti3] && tf>tf2) {
	      tf2 = tf;
	      ti4 = ti;
	    }
      }
      if (tf2>0) {
	    conf = tf2*psAutotalent->acwinv[ti4];
	    if (ti4>0 && ti4<Nf) {
	      // Find the center of mass in the vicinity of the detected peak
	      tf = psAutotalent->ffttime[ti4-1]*(ti4-1);
	      tf = tf + psAutotalent->ffttime[ti4]*(ti4);
	      tf = tf + psAutotalent->ffttime[ti4+1]*(ti4+1);
	      tf = tf/(psAutotalent->ffttime[ti4-1] + psAutotalent->ffttime[ti4] + psAutotalent->ffttime[ti4+1]);
	      pperiod = tf/fs;
	    }
	    else {
	      pperiod = (float)ti4/fs;
	    }
      }

      // Convert to semitones
      tf = (float) -12*log10((float)aref*pperiod)*L2SC;
      if (conf>=psAutotalent->vthresh) {
	    inpitch = tf;
	    psAutotalent->inpitch = tf; // update pitch only if voiced
      }
      psAutotalent->conf = conf;

      *(psAutotalent->m_pfPitch) = inpitch;
      *(psAutotalent->m_pfConf) = conf;

      //  ---- END Calculate pitch and confidence ----

      //  ---- Modify pitch in all kinds of ways! ----

      outpitch = inpitch;

      // Pull to fixed pitch
      outpitch = (1-fPull)*outpitch + fPull*fFixed;

      // -- Convert from semitones to scale notes --
      ti = (int)(outpitch/12 + 32) - 32; // octave
      tf = outpitch - ti*12; // semitone in octave
      ti2 = (int)tf;
      ti3 = ti2 + 1;
      // a little bit of pitch correction logic, since it's a convenient place for it
      if (iNotes[ti2%12]<0 || iNotes[ti3%12]<0) { // if between 2 notes that are more than a semitone apart
	    lowersnap = 1;
	    uppersnap = 1;
      }
      else {
	    lowersnap = 0;
	    uppersnap = 0;
	    if (iNotes[ti2%12]==1) { // if specified by user
	      lowersnap = 1;
	    }
	    if (iNotes[ti3%12]==1) { // if specified by user
	      uppersnap = 1;
	    }
      }
      // (back to the semitone->scale conversion)
      // finding next lower pitch in scale
      while (iNotes[(ti2+12)%12]<0) {
      	ti2 = ti2 - 1;
      }
      // finding next higher pitch in scale
      while (iNotes[ti3%12]<0) {
      	ti3 = ti3 + 1;
      }
      tf = (tf-ti2)/(ti3-ti2) + iPitch2Note[(ti2+12)%12];
      if (ti2<0) {
      	tf = tf - numNotes;
      }
      outpitch = tf + numNotes*ti;

      // -- Done converting to scale notes --

      // The actual pitch correction
      ti = (int)(outpitch+128) - 128;
      tf = outpitch - ti - 0.5;
      ti2 = ti3-ti2;
      if (ti2>2) { // if more than 2 semitones apart, put a 2-semitone-like transition halfway between
	    tf2 = (float)ti2/2;
      }
      else {
	    tf2 = (float)1;
      }
      if (fSmooth<0.001) {
	    tf2 = tf*tf2/0.001;
      }
      else {
	    tf2 = tf*tf2/fSmooth;
      }
      if (tf2<-0.5) tf2 = -0.5;
      if (tf2>0.5) tf2 = 0.5;
      tf2 = 0.5*sin(PI*tf2) + 0.5; // jumping between notes using horizontally-scaled sine segment
      tf2 = tf2 + ti;
      if ( (tf<0.5 && lowersnap) || (tf>=0.5 && uppersnap) ) {
	    outpitch = fAmount*tf2 + ((float)1-fAmount)*outpitch;
      }

      // Add in pitch shift
      outpitch = outpitch + fShift;

      // LFO logic
      tf = fLforate*N/(psAutotalent->noverlap*fs);
      if (tf>1) tf=1;
      psAutotalent->lfophase = psAutotalent->lfophase + tf;
      if (psAutotalent->lfophase>1) psAutotalent->lfophase = psAutotalent->lfophase-1;
      lfoval = psAutotalent->lfophase;
      tf = (fLfosymm + 1)/2;
      if (tf<=0 || tf>=1) {
	    if (tf<=0) {
	      lfoval = 1-lfoval;
	    }
      }
      else {
	    if (lfoval<=tf) {
	      lfoval = lfoval/tf;
	    }
	    else {
	      lfoval = 1 - (lfoval-tf)/(1-tf);
	    }
      }
      if (fLfoshape>=0) {
	    // linear combination of cos and line
	    lfoval = (0.5 - 0.5*cos(lfoval*PI))*fLfoshape + lfoval*(1-fLfoshape);
	    lfoval = fLfoamp*(lfoval*2 - 1);
      }
      else {
	    // smoosh the sine horizontally until it's squarish
	    tf = 1 + fLfoshape;
	    if (tf<0.001) {
	      lfoval = (lfoval - 0.5)*2/0.001;
	    }
	    else {
	      lfoval = (lfoval - 0.5)*2/tf;
	    }
	    if (lfoval>1) lfoval = 1;
	    if (lfoval<-1) lfoval = -1;
	    lfoval = fLfoamp*sin(lfoval*PI*0.5);
      }
      // add in quantized LFO
      if (iLfoquant>=1) {
	    outpitch = outpitch + (int)(numNotes*lfoval + numNotes + 0.5) - numNotes;
      }

      // Convert back from scale notes to semitones
      outpitch = outpitch + iScwarp; // output scale rotate implemented here
      ti = (int)(outpitch/numNotes + 32) - 32;
      tf = outpitch - ti*numNotes;
      ti2 = (int)tf;
      ti3 = ti2 + 1;
      outpitch = iNote2Pitch[ti3%numNotes] - iNote2Pitch[ti2];
      if (ti3>=numNotes) {
	    outpitch = outpitch + 12;
      }
      outpitch = outpitch*(tf - ti2) + iNote2Pitch[ti2];
      outpitch = outpitch + 12*ti;
      outpitch = outpitch - (iNote2Pitch[iScwarp] - iNote2Pitch[0]); //more scale rotation here

      // add in unquantized LFO
      if (iLfoquant<=0) {
	    outpitch = outpitch + lfoval*2;
      }

      if (outpitch<-36) outpitch = -48;
      if (outpitch>24) outpitch = 24;

      psAutotalent->outpitch = outpitch;

      //  ---- END Modify pitch in all kinds of ways! ----

      // Compute variables for pitch shifter that depend on pitch
      psAutotalent->inphinc = aref*pow(2,inpitch/12)/fs;
      psAutotalent->outphinc = aref*pow(2,outpitch/12)/fs;
      psAutotalent->phincfact = psAutotalent->outphinc/psAutotalent->inphinc;
    }
    // ************************
    // * END Low-Rate Section *
    // ************************

    // *****************
    // * Pitch Shifter *
    // *****************

    // Pitch shifter (kind of like a pitch-synchronous version of Fairbanks' technique)
    //   Note: pitch estimate is naturally N/2 samples old
    psAutotalent->phasein = psAutotalent->phasein + psAutotalent->inphinc;
    psAutotalent->phaseout = psAutotalent->phaseout + psAutotalent->outphinc;

    //   When input phase resets, take a snippet from N/2 samples in the past
    if (psAutotalent->phasein >= 1) {
      psAutotalent->phasein = psAutotalent->phasein - 1;
      ti2 = psAutotalent->cbiwr - N/2;
      for (ti=-N/2; ti<N/2; ti++) {
	    psAutotalent->frag[(ti+N)%N] = psAutotalent->cbf[(ti + ti2 + N)%N];
      }
    }

    //   When output phase resets, put a snippet N/2 samples in the future
    if (psAutotalent->phaseout >= 1) {
      psAutotalent->fragsize = psAutotalent->fragsize*2;
      if (psAutotalent->fragsize > N) {
	    psAutotalent->fragsize = N;
      }
      psAutotalent->phaseout = psAutotalent->phaseout - 1;
      ti2 = psAutotalent->cbord + N/2;
      ti3 = (long int)(((float)psAutotalent->fragsize) / psAutotalent->phincfact);
      if (ti3>=N/2) {
	    ti3 = N/2 - 1;
      }
      for (ti=-ti3/2; ti<(ti3/2); ti++) {
	    tf = psAutotalent->hannwindow[(long int)N/2 + ti*(long int)N/ti3];
	    // 3rd degree polynomial interpolator - based on eqns from Hal Chamberlin's book
	    indd = psAutotalent->phincfact*ti;
	    ind1 = (int)indd;
		ind2 = ind1+1;
		ind3 = ind1+2;
		ind0 = ind1-1;
		val0 = psAutotalent->frag[(ind0+N)%N];
		val1 = psAutotalent->frag[(ind1+N)%N];
		val2 = psAutotalent->frag[(ind2+N)%N];
		val3 = psAutotalent->frag[(ind3+N)%N];
		vald = 0;
		vald = vald - (float)0.166666666667 * val0 * (indd - ind1) * (indd - ind2) * (indd - ind3);
		vald = vald + (float)0.5 * val1 * (indd - ind0) * (indd - ind2) * (indd - ind3);
		vald = vald - (float)0.5 * val2 * (indd - ind0) * (indd - ind1) * (indd - ind3);
		vald = vald + (float)0.166666666667 * val3 * (indd - ind0) * (indd - ind1) * (indd - ind2);
		psAutotalent->cbo[(ti + ti2 + N)%N] = psAutotalent->cbo[(ti + ti2 + N)%N] + vald*tf;
      }
      psAutotalent->fragsize = 0;
    }
    psAutotalent->fragsize++;

    //   Get output signal from buffer
    tf = psAutotalent->cbo[psAutotalent->cbord]; // read buffer

    psAutotalent->cbo[psAutotalent->cbord] = 0; // erase for next cycle
    psAutotalent->cbord++; // increment read pointer
    if (psAutotalent->cbord >= N) {
      psAutotalent->cbord = 0;
    }

    // *********************
    // * END Pitch Shifter *
    // *********************

    ti4 = (psAutotalent->cbiwr + 2)%N;
    if (iFcorr>=1) {
      // The second part of the formant corrector
      // This is a post-filter that re-applies the formants, designed
      //   to result in the exact original signal when no pitch
      //   manipulation is performed.
      // tf is signal input
      // gotta run it 3 times because of a pesky delay free loop
      //  first time: compute 0-response
      tf2 = tf;
      fa = 0;
      fb = fa;
      for (ti=0; ti<ford; ti++) {
	    fc = (fb-psAutotalent->frc[ti])*frlamb + psAutotalent->frb[ti];
		tf = psAutotalent->fbuff[ti][ti4];
		fb = fc - tf*fa;
		psAutotalent->ftvec[ti] = tf*fc;
		fa = fa - psAutotalent->ftvec[ti];
      }
      tf = -fa;
      for (ti=ford-1; ti>=0; ti--) {
	    tf = tf + psAutotalent->ftvec[ti];
      }
      f0resp = tf;
      //  second time: compute 1-response
      fa = 1;
      fb = fa;
      for (ti=0; ti<ford; ti++) {
	    fc = (fb-psAutotalent->frc[ti])*frlamb + psAutotalent->frb[ti];
		tf = psAutotalent->fbuff[ti][ti4];
		fb = fc - tf*fa;
		psAutotalent->ftvec[ti] = tf*fc;
		fa = fa - psAutotalent->ftvec[ti];
      }
      tf = -fa;
      for (ti=ford-1; ti>=0; ti--) {
	    tf = tf + psAutotalent->ftvec[ti];
      }
      f1resp = tf;
      //  now solve equations for output, based on 0-response and 1-response
      tf = (float)2*tf2;
      tf2 = tf;
      tf = ((float)1 - f1resp + f0resp);
      if (tf!=0) {
	    tf2 = (tf2 + f0resp) / tf;
      }
      else {
	    tf2 = 0;
      }
      //  third time: update delay registers
      fa = tf2;
      fb = fa;
      for (ti=0; ti<ford; ti++) {
	    fc = (fb-psAutotalent->frc[ti])*frlamb + psAutotalent->frb[ti];
		psAutotalent->frc[ti] = fc;
		psAutotalent->frb[ti] = fb;
		tf = psAutotalent->fbuff[ti][ti4];
		fb = fc - tf*fa;
		fa = fa - tf*fc;
      }
      tf = tf2;
      tf = tf + flpa*psAutotalent->flp;  // lowpass post-emphasis filter
      psAutotalent->flp = tf;
      // Bring up the gain slowly when formant correction goes from disabled
      // to enabled, while things stabilize.
      if (psAutotalent->fmute>0.5) {
	    tf = tf*(psAutotalent->fmute - 0.5)*2;
      }
      else {
	    tf = 0;
      }
      tf2 = psAutotalent->fmutealph;
      psAutotalent->fmute = (1-tf2) + tf2*psAutotalent->fmute;
      // now tf is signal output
      // ...and we're done messing with formants
    }
    else {
      psAutotalent->fmute = 0;
    }

    // Write audio to output of plugin
    // Mix (blend between original (delayed) =0 and processed =1)
    *(pfOutput++) =  fMix*tf + (1-fMix)*psAutotalent->cbi[ti4];
  }

  // Tell the host the algorithm latency
  *(psAutotalent->m_pfLatency) = (N-1);
}
示例#8
0
Autotalent * instantiateAutotalent(unsigned long SampleRate) {

  unsigned long ti;

  Autotalent* membvars = malloc(sizeof(Autotalent));

  membvars->aref = 440;
  
  membvars->fs = SampleRate;

  if (SampleRate>=88200) {
    membvars->cbsize = 4096;
  }
  else {
    membvars->cbsize = 2048;
  }
  membvars->corrsize = membvars->cbsize / 2 + 1;

  membvars->pmax = 1/(float)70;  // max and min periods (ms)
  membvars->pmin = 1/(float)700; // eventually may want to bring these out as sliders

  membvars->nmax = (unsigned long)(SampleRate * membvars->pmax);
  if (membvars->nmax > membvars->corrsize) {
    membvars->nmax = membvars->corrsize;
  }
  membvars->nmin = (unsigned long)(SampleRate * membvars->pmin);

  membvars->cbi = calloc(membvars->cbsize, sizeof(float));
  membvars->cbf = calloc(membvars->cbsize, sizeof(float));
  membvars->cbo = calloc(membvars->cbsize, sizeof(float));

  membvars->cbiwr = 0;
  membvars->cbord = 0;

  membvars->lfophase = 0;

  // Initialize formant corrector
  membvars->ford = 7; // should be sufficient to capture formants
  membvars->falph = pow(0.001, (float) 80 / (SampleRate));
  membvars->flamb = -(0.8517*sqrt(atan(0.06583*SampleRate))-0.1916); // or about -0.88 @ 44.1kHz
  membvars->fk = calloc(membvars->ford, sizeof(float));
  membvars->fb = calloc(membvars->ford, sizeof(float));
  membvars->fc = calloc(membvars->ford, sizeof(float));
  membvars->frb = calloc(membvars->ford, sizeof(float));
  membvars->frc = calloc(membvars->ford, sizeof(float));
  membvars->fsig = calloc(membvars->ford, sizeof(float));
  membvars->fsmooth = calloc(membvars->ford, sizeof(float));
  membvars->fhp = 0;
  membvars->flp = 0;
  membvars->flpa = pow(0.001, (float) 10 / (SampleRate));
  membvars->fbuff = (float**) malloc((membvars->ford)*sizeof(float*));
  for (ti=0; ti<membvars->ford; ti++) {
    membvars->fbuff[ti] = calloc(membvars->cbsize, sizeof(float));
  }
  membvars->ftvec = calloc(membvars->ford, sizeof(float));
  membvars->fmute = 1;
  membvars->fmutealph = pow(0.001, (float)1 / (SampleRate));

  // Standard raised cosine window, max height at N/2
  membvars->hannwindow = calloc(membvars->cbsize, sizeof(float));
  for (ti=0; ti<membvars->cbsize; ti++) {
    membvars->hannwindow[ti] = -0.5*cos(2*PI*ti/membvars->cbsize) + 0.5;
  }

  // Generate a window with a single raised cosine from N/4 to 3N/4
  membvars->cbwindow = calloc(membvars->cbsize, sizeof(float));
  for (ti=0; ti<(membvars->cbsize / 2); ti++) {
    membvars->cbwindow[ti+membvars->cbsize/4] = -0.5*cos(4*PI*ti/(membvars->cbsize - 1)) + 0.5;
  }

  membvars->noverlap = 4;

  membvars->fmembvars = fft_con(membvars->cbsize);

  membvars->ffttime = calloc(membvars->cbsize, sizeof(float));
  membvars->fftfreqre = calloc(membvars->corrsize, sizeof(float));
  membvars->fftfreqim = calloc(membvars->corrsize, sizeof(float));


  // ---- Calculate autocorrelation of window ----
  membvars->acwinv = calloc(membvars->cbsize, sizeof(float));
  for (ti=0; ti<membvars->cbsize; ti++) {
    membvars->ffttime[ti] = membvars->cbwindow[ti];
  }
  fft_forward(membvars->fmembvars, membvars->cbwindow, membvars->fftfreqre, membvars->fftfreqim);
  for (ti=0; ti<membvars->corrsize; ti++) {
    membvars->fftfreqre[ti] = (membvars->fftfreqre[ti])*(membvars->fftfreqre[ti]) + (membvars->fftfreqim[ti])*(membvars->fftfreqim[ti]);
    membvars->fftfreqim[ti] = 0;
  }
  fft_inverse(membvars->fmembvars, membvars->fftfreqre, membvars->fftfreqim, membvars->ffttime);
  for (ti=1; ti<membvars->cbsize; ti++) {
    membvars->acwinv[ti] = membvars->ffttime[ti]/membvars->ffttime[0];
    if (membvars->acwinv[ti] > 0.000001) {
      membvars->acwinv[ti] = (float)1/membvars->acwinv[ti];
    }
    else {
      membvars->acwinv[ti] = 0;
    }
  }
  membvars->acwinv[0] = 1;
  // ---- END Calculate autocorrelation of window ----
  

  membvars->lrshift = 0;
  membvars->ptarget = 0;
  membvars->sptarget = 0;

  membvars->vthresh = 0.7;  //  The voiced confidence (unbiased peak) threshold level

  // Pitch shifter initialization
  membvars->phprdd = 0.01; // Default period
  membvars->inphinc = (float)1/(membvars->phprdd * SampleRate);
  membvars->phincfact = 1;
  membvars->phasein = 0;
  membvars->phaseout = 0;
  membvars->frag = calloc(membvars->cbsize, sizeof(float));
  membvars->fragsize = 0;
  
  return membvars;
}