static void FFT(unsigned NumSamples, int InverseTransform, const float *RealIn, float *ImagIn, float *RealOut, float *ImagOut) { unsigned i; double * work = malloc(2 * NumSamples * sizeof(*work)); for (i = 0; i < 2 * NumSamples; i += 2) { work[i] = RealIn[i >> 1]; work[i + 1] = ImagIn? ImagIn[i >> 1] : 0; } lsx_safe_cdft(2 * (int)NumSamples, InverseTransform? -1 : 1, work); if (InverseTransform) for (i = 0; i < 2 * NumSamples; i += 2) { RealOut[i >> 1] = work[i] / NumSamples; ImagOut[i >> 1] = work[i + 1] / NumSamples; } else for (i = 0; i < 2 * NumSamples; i += 2) {
static int flow(sox_effect_t * effp, const sox_sample_t * ibuf, sox_sample_t * obuf, size_t * isamp, size_t * osamp) { priv_t *p = (priv_t *) effp->priv; size_t i, len = *isamp = *osamp = min(*isamp, *osamp); double magn, phase, tmp, window, real, imag; double freqPerBin, expct; long k, qpd, index, inFifoLatency, stepSize, fftFrameSize2; float pitchShift = p->shift; /* set up some handy variables */ fftFrameSize2 = p->fftFrameSize / 2; stepSize = p->fftFrameSize / p->ovsamp; freqPerBin = effp->in_signal.rate / p->fftFrameSize; expct = 2. * M_PI * (double) stepSize / (double) p->fftFrameSize; inFifoLatency = p->fftFrameSize - stepSize; if (!p->gRover) p->gRover = inFifoLatency; /* main processing loop */ for (i = 0; i < len; i++) { SOX_SAMPLE_LOCALS; ++p->in_pos; /* As long as we have not yet collected enough data just read in */ p->gInFIFO[p->gRover] = SOX_SAMPLE_TO_FLOAT_32BIT(ibuf[i], effp->clips); obuf[i] = SOX_FLOAT_32BIT_TO_SAMPLE( p->gOutFIFO[p->gRover - inFifoLatency], effp->clips); p->gRover++; /* now we have enough data for processing */ if (p->gRover >= p->fftFrameSize) { if (p->bends_pos != p->nbends && p->in_pos >= p->bends[p->bends_pos].start + p->bends[p->bends_pos].duration) { pitchShift = p->shift *= pow(2., p->bends[p->bends_pos].cents / 1200); ++p->bends_pos; } if (p->bends_pos != p->nbends && p->in_pos >= p->bends[p->bends_pos].start) { double progress = (double)(p->in_pos - p->bends[p->bends_pos].start) / p->bends[p->bends_pos].duration; progress = 1 - cos(M_PI * progress); progress *= p->bends[p->bends_pos].cents * (.5 / 1200); pitchShift = p->shift * pow(2., progress); } p->gRover = inFifoLatency; /* do windowing and re,im interleave */ for (k = 0; k < p->fftFrameSize; k++) { window = -.5 * cos(2 * M_PI * k / (double) p->fftFrameSize) + .5; p->gFFTworksp[2 * k] = p->gInFIFO[k] * window; p->gFFTworksp[2 * k + 1] = 0.; } /* ***************** ANALYSIS ******************* */ lsx_safe_cdft(2 * p->fftFrameSize, 1, p->gFFTworksp); /* this is the analysis step */ for (k = 0; k <= fftFrameSize2; k++) { /* de-interlace FFT buffer */ real = p->gFFTworksp[2 * k]; imag = - p->gFFTworksp[2 * k + 1]; /* compute magnitude and phase */ magn = 2. * sqrt(real * real + imag * imag); phase = atan2(imag, real); /* compute phase difference */ tmp = phase - p->gLastPhase[k]; p->gLastPhase[k] = phase; tmp -= (double) k *expct; /* subtract expected phase difference */ /* map delta phase into +/- Pi interval */ qpd = tmp / M_PI; if (qpd >= 0) qpd += qpd & 1; else qpd -= qpd & 1; tmp -= M_PI * (double) qpd; /* get deviation from bin frequency from the +/- Pi interval */ tmp = p->ovsamp * tmp / (2. * M_PI); /* compute the k-th partials' true frequency */ tmp = (double) k *freqPerBin + tmp * freqPerBin; /* store magnitude and true frequency in analysis arrays */ p->gAnaMagn[k] = magn; p->gAnaFreq[k] = tmp; } /* this does the actual pitch shifting */ memset(p->gSynMagn, 0, p->fftFrameSize * sizeof(float)); memset(p->gSynFreq, 0, p->fftFrameSize * sizeof(float)); for (k = 0; k <= fftFrameSize2; k++) { index = k * pitchShift; if (index <= fftFrameSize2) { p->gSynMagn[index] += p->gAnaMagn[k]; p->gSynFreq[index] = p->gAnaFreq[k] * pitchShift; } } for (k = 0; k <= fftFrameSize2; k++) { /* SYNTHESIS */ /* get magnitude and true frequency from synthesis arrays */ magn = p->gSynMagn[k], tmp = p->gSynFreq[k]; tmp -= (double) k *freqPerBin; /* subtract bin mid frequency */ tmp /= freqPerBin; /* get bin deviation from freq deviation */ tmp = 2. * M_PI * tmp / p->ovsamp; /* take p->ovsamp into account */ tmp += (double) k *expct; /* add the overlap phase advance back in */ p->gSumPhase[k] += tmp; /* accumulate delta phase to get bin phase */ phase = p->gSumPhase[k]; /* get real and imag part and re-interleave */ p->gFFTworksp[2 * k] = magn * cos(phase); p->gFFTworksp[2 * k + 1] = - magn * sin(phase); } for (k = p->fftFrameSize + 2; k < 2 * p->fftFrameSize; k++) p->gFFTworksp[k] = 0.; /* zero negative frequencies */ lsx_safe_cdft(2 * p->fftFrameSize, -1, p->gFFTworksp); /* do windowing and add to output accumulator */ for (k = 0; k < p->fftFrameSize; k++) { window = -.5 * cos(2. * M_PI * (double) k / (double) p->fftFrameSize) + .5; p->gOutputAccum[k] += 2. * window * p->gFFTworksp[2 * k] / (fftFrameSize2 * p->ovsamp); } for (k = 0; k < stepSize; k++) p->gOutFIFO[k] = p->gOutputAccum[k]; memmove(p->gOutputAccum, /* shift accumulator */ p->gOutputAccum + stepSize, p->fftFrameSize * sizeof(float)); for (k = 0; k < inFifoLatency; k++) /* move input FIFO */ p->gInFIFO[k] = p->gInFIFO[k + stepSize]; } } return SOX_SUCCESS; }