/*************process replacing************/ t_int *phasevoc_tilde_perform (t_int *w) { t_phasevoc_tilde *x = (t_phasevoc_tilde *)(w[1]); t_sample *in = (t_sample *)(w[2]); t_sample *out1 = (t_sample *)(w[3]); int n = (int)(w[4]); t_float n2 = (t_float)n; x->n = n; int i, j; t_float psfact = phasevoc_tilde_cents(x); t_float tsfact = x->timestretch; t_float buffpos; long maskFFT=x->fftSize-1; //unless samphold or pause is on, always fill the circBuff if(x->pause!=1) { for(i=0; i<n; i++) { x->circBuff[x->circBuffIndex++] = in[i]; while(x->circBuffIndex > (x->circBuffLength-1))x->circBuffIndex-=(x->circBuffLength); while(x->circBuffIndex < 0 )x->circBuffIndex += x->circBuffLength; } x->delayCount+=n; } if(x->delayCount>x->fftSize) { if(!x->sampHoldBuffLength) { //init the indeces for this read-out fromt the circ buff x->circBuffWindowBackIndex = x->circBuffWindowStart; x->circBuffWindowFrontIndex = x->circBuffWindowBackIndex + (x->hopSize*psfact); } else { //init the indeces for this read-out fromt the sampholdbuff x->sampHoldBuffWindowBackIndex = x->sampHoldBuffWindowStart; x->sampHoldBuffWindowFrontIndex = x->sampHoldBuffWindowBackIndex + (x->hopSize*psfact); } //check for dsp_tick if(x->dsp_tick == (x->buffer_limit*x->overlap)) x->dsp_tick = 0; if((x->dsp_tick%x->buffer_limit)==0) { //buffer in the samples if no sampbuff if(!x->sampHoldBuffLength) { for(i=0; i<x->fftSize; i++) { x->inFrontBuff[i] = phasevoc_tilde_interpolate(x->circBuff, x->circBuffLength, x->circBuffWindowFrontIndex); x->inBackBuff[i] = phasevoc_tilde_interpolate(x->circBuff, x->circBuffLength, x->circBuffWindowBackIndex); //increment the indices by the pitchshifting factor x->circBuffWindowFrontIndex+=psfact; x->circBuffWindowBackIndex+=psfact; //wrap 'em while(x->circBuffWindowFrontIndex>(x->circBuffLength-1)) x->circBuffWindowFrontIndex-=(x->circBuffLength); while(x->circBuffWindowFrontIndex<0) x->circBuffWindowFrontIndex+=x->circBuffLength; while(x->circBuffWindowBackIndex>(x->circBuffLength-1))x->circBuffWindowBackIndex-=(x->circBuffLength); while(x->circBuffWindowBackIndex<0)x->circBuffWindowBackIndex+=x->circBuffLength; } } //buffer in the samples if sampbuff else { for(i=0; i<x->fftSize; i++) { x->inFrontBuff[i] = phasevoc_tilde_interpolate(x->sampHoldBuff, x->sampHoldBuffLength, x->sampHoldBuffWindowFrontIndex); x->inBackBuff[i] = phasevoc_tilde_interpolate(x->sampHoldBuff, x->sampHoldBuffLength, x->sampHoldBuffWindowBackIndex); //increment the indices by the pitchshifting factor x->sampHoldBuffWindowFrontIndex+=psfact; x->sampHoldBuffWindowBackIndex+=psfact; //wrap 'em while(x->sampHoldBuffWindowFrontIndex>(x->sampHoldBuffLength-1)) x->sampHoldBuffWindowFrontIndex-=(x->sampHoldBuffLength); while(x->sampHoldBuffWindowFrontIndex<0) x->sampHoldBuffWindowFrontIndex+=x->sampHoldBuffLength; while(x->sampHoldBuffWindowBackIndex>(x->sampHoldBuffLength-1))x->sampHoldBuffWindowBackIndex-=(x->sampHoldBuffLength); while(x->sampHoldBuffWindowBackIndex<0)x->sampHoldBuffWindowBackIndex+=x->sampHoldBuffLength; } } //window the signal for(i=0; i<x->fftSize; i++) { x->inFrontBuff[i] *= x->analWindow[i]; x->inBackBuff[i] *= x->analWindow[i]; } //go to frequency domain mayer_realfft(x->fftSize, x->inFrontBuff); mayer_realfft(x->fftSize, x->inBackBuff); //unpack the bizzarely packed mayer ffts for(i=0; i<=x->fftHalfSize; i++)// halfSizeFFT = nyquist { x->frontReal[i] = x->inFrontBuff[i]; x->backReal[i] = x->inBackBuff[i]; } x->frontImag[0] = x->backImag[0]= 0; // 0 DC for(i=(x->fftSize-1), j=1; i>x->fftHalfSize; i--, j++) { x->frontImag[j] = x->inFrontBuff[i]; x->backImag[j] = x->inBackBuff[i]; } x->frontImag[x->fftHalfSize]=x->backImag[x->fftHalfSize]=0; //halfSizeFFT empty for(i = 0; i <= x->fftHalfSize; i++) { //first normalize over magnitude so we get phase only x->rsqrt[i] = q8_rsqrt((x->prevReal[i] * x->prevReal[i]) + (x->prevImag[i] * x->prevImag[i]) + .000000000000000000001f); x->prevReal[i] *= x->rsqrt[i]; x->prevImag[i] *= x->rsqrt[i]; x->conjReal[i] = (x->prevReal[i] * x->backReal[i]) + (x->prevImag[i] * x->backImag[i]) + .0000000000000001; x->conjImag[i] = (x->prevImag[i] * x->backReal[i]) - (x->prevReal[i] * x->backImag[i]); x->rsqrt[i] = q8_rsqrt((x->conjReal[i] * x->conjReal[i]) + (x->conjImag[i] * x->conjImag[i])); x->conjReal[i] *= x->rsqrt[i]; x->conjImag[i] *= x->rsqrt[i]; //then add the front window (complex multiply) this time keeping magnitudes, and store the info for the next time around x->outReal[i] = (x->conjReal[i] * x->frontReal[i]) - (x->conjImag[i] * x->frontImag[i]); x->outImag[i] = (x->conjReal[i] * x->frontImag[i]) + (x->conjImag[i] * x->frontReal[i]); x->prevImag[i] = x->outImag[i]; x->prevReal[i] = x->outReal[i]; } //phase has been propogated, repack for ifft for(i=0; i<=x->fftHalfSize; i++) // +1 to include Nyquist x->outSpectra[i] = x->outReal[i]; for(j = x->fftHalfSize -1, i = x->fftHalfSize + 1; i < x->fftSize; j--, i++) x->outSpectra[i] = x->outImag[j]; //back to time domain mayer_realifft(x->fftSize, x->outSpectra); //william brent's overlap/add function: //window the synthesis for(i=0; i<x->fftSize; i++) x->outSpectra[i] *= x->synthWindow[i];//synthWindow is 2/3/fftSize*analWindow // first shift output in nonoverlapped buffer for(i=0; i<((x->overlap-1)*x->fftSize); i++) x->nonoverlappedOutBuff[i] = x->nonoverlappedOutBuff[x->fftSize+i]; // then, write a new window in for(i=0; i<x->fftSize; i++) x->nonoverlappedOutBuff[((x->overlap-1)*x->fftSize)+i] = x->outSpectra[i]; // init this chunk of the final output so it can be summed in the for() below for(i=0; i<(x->hopSize); i++) x->outBuff[i] = 0.0; // do the overlap/add: add the last hopsize of the first for(i=0; i<x->overlap; i++) for(j=0; j<(x->hopSize); j++) x->outBuff[j] += x->nonoverlappedOutBuff[(i*x->fftSize)+((x->overlap-i-1)*x->hopSize)+j/*overlap_chunk*/]; x->fft_tick=0; } //output for(i=0; i<n; i++, out1++) *out1 = x->outBuff[(x->fft_tick*n)+i]; if(!x->sampHoldBuffLength) buffpos = 1.0-(x->circBuffIndex - x->circBuffWindowStart) / x->circBuffLength; else buffpos = 1.0-(x->sampHoldBuffIndex - x->sampHoldBuffWindowStart) / x->sampHoldBuffLength; while(buffpos>=1.0)buffpos -= 1.0; while(buffpos<=0.0)buffpos += 1.0; outlet_float(x->buffPos, buffpos); x->fft_tick++; x->dsp_tick++; //increment the read start point and wrap it if(!x->sampHoldBuffLength) { x->circBuffWindowStart+=n*tsfact; while(x->circBuffWindowStart > (x->circBuffLength-1))x->circBuffWindowStart-=x->circBuffLength; while(x->circBuffWindowStart<0)x->circBuffWindowStart+=x->circBuffLength; } else { x->sampHoldBuffWindowStart+=n*tsfact; while(x->sampHoldBuffWindowStart > (x->sampHoldBuffLength-1))x->sampHoldBuffWindowStart-=x->sampHoldBuffLength; while(x->sampHoldBuffWindowStart<0)x->sampHoldBuffWindowStart+=x->sampHoldBuffLength; } return(w+5); } else { *out1++ = 0.0; return(w+5); } }
float qrsqrt(float f) {return (q8_rsqrt(f)); }