/** * Run the actual transform based on the parameters set up in the * constructor. */ void Tracter::Fourier::Transform() { assert(mFourierData); FourierData& m = *mFourierData; switch (m.Type) { case DCT2: { /* Duplicate */ float* idata = (float*)m.IData; for (int i=0; i<m.Order; i++) { /* [1 2 3] -> [1 2 3 3 2 1] */ idata[i+m.Order] = idata[m.Order-1-i]; } /* Transform and rotate */ kiss_fftr((kiss_fftr_cfg)m.Config, (const float*)m.IData, m.TmpData); float* odata = (float*)m.OData; for (int i=0; i<m.Order; i++) { float theta = 2.0f*M_PI*(-0.5f)*i/(2.0f*m.Order); odata[i] = ( m.TmpData[i].r * cos(theta) - m.TmpData[i].i * sin(theta) ); } break; } case REAL_TO_COMPLEX: kiss_fftr( (kiss_fftr_cfg)m.Config, (const float*)m.IData, (kiss_fft_cpx*)m.OData ); break; case COMPLEX_TO_REAL: kiss_fftri( (kiss_fftr_cfg)m.Config, (const kiss_fft_cpx*)m.IData, (float*)m.OData ); break; case COMPLEX_TO_COMPLEX: kiss_fft( (kiss_fft_cfg)m.Config, (const kiss_fft_cpx*)m.IData, (kiss_fft_cpx*)m.OData ); break; default: assert(0); } }
void fft_do(const fft_cfg cfg, const COMP *in, COMP *out) { #ifdef KISS_FFT kiss_fft(cfg, in, out); #elif defined(LIBAVCODEC_FFT) memcpy(out, in, cfg->size); av_fft_permute(cfg->context, (FFTComplex *)out); av_fft_calc(cfg->context, (FFTComplex *)out); #else #error FFT engine was not defined #endif }
void ffti( FFT_Tables *fft_tables, double *xr, double *xi, int logm ) { int nfft = 0; kiss_fft_cpx fin[1 << MAXLOGM]; kiss_fft_cpx fout[1 << MAXLOGM]; if ( logm > MAXLOGM ) { fprintf(stderr, "fft size too big\n"); exit(1); } nfft = logm_to_nfft[logm]; if ( fft_tables->cfg[logm][1] == NULL ) { if ( nfft ) { fft_tables->cfg[logm][1] = kiss_fft_alloc( nfft, 1, NULL, NULL ); } else { fprintf(stderr, "bad logm = %d\n", logm); exit( 1 ); } } if ( fft_tables->cfg[logm][1] ) { unsigned int i; double fac = 1.0 / (double)nfft; for ( i = 0; i < nfft; i++ ) { fin[i].r = xr[i]; fin[i].i = xi[i]; } kiss_fft( (kiss_fft_cfg)fft_tables->cfg[logm][1], fin, fout ); for ( i = 0; i < nfft; i++ ) { xr[i] = fout[i].r * fac; xi[i] = fout[i].i * fac; } } else { fprintf( stderr, "bad config for logm = %d\n", logm); exit( 1 ); } }
void fft_filt_c::work_complex() { for (uint32_t i=0;i<fft_len;i++) { input_buf_c[i].i = (i<l) ? fft_len * (*in)[2*i] : 0; input_buf_c[i].r = (i<l) ? fft_len * (*in)[2*i+1] : 0; }; kiss_fft(fft_fcfg_c, input_buf_c, fdom_buf); // now we convolve with the filter. // the filter buffer is a fraction of i16's, the fdom buffer is i32's if (1) { for (uint32_t i=0;i<fft_len;i++) { int64_t i_i = fdom_buf[i].i; int64_t i_r = fdom_buf[i].r; int64_t f_i = filt_buf[i].i; int64_t f_r = filt_buf[i].r; int64_t p_r = (i_r * f_r - i_i * f_i); int64_t p_i = (i_r * f_i + i_i * f_r); fdom_conv_buf[i].i = p_i >> 15; fdom_conv_buf[i].r = p_r >> 15; } } kiss_fft(fft_icfg_c,fdom_conv_buf,output_buf_c); uint32_t extra = fft_len - l; for (uint32_t i=0; i<l; i++) { float vi = output_buf_c[i].i; float vr = output_buf_c[i].r; vi += (i<extra) ? last_output_buf_c[i].i : 0; vr += (i<extra) ? last_output_buf_c[i].r : 0; (*out)[2*i] = vi; (*out)[2*i+1] = vr; } for (uint32_t i=0;i<extra;i++) { last_output_buf_c[i] = output_buf_c[i+l]; } };
void lpf_peak_pick(float *foff, float *max, COMP pilot_baseband[], COMP pilot_lpf[], kiss_fft_cfg fft_pilot_cfg, COMP S[], int nin) { int i,j,k; int mpilot; COMP s[MPILOTFFT]; float mag, imax; int ix; float r; /* LPF cutoff 200Hz, so we can handle max +/- 200 Hz freq offset */ for(i=0; i<NPILOTLPF-nin; i++) pilot_lpf[i] = pilot_lpf[nin+i]; for(i=NPILOTLPF-nin, j=0; i<NPILOTLPF; i++,j++) { pilot_lpf[i].real = 0.0; pilot_lpf[i].imag = 0.0; for(k=0; k<NPILOTCOEFF; k++) pilot_lpf[i] = cadd(pilot_lpf[i], fcmult(pilot_coeff[k], pilot_baseband[j+k])); } /* decimate to improve DFT resolution, window and DFT */ mpilot = FS/(2*200); /* calc decimation rate given new sample rate is twice LPF freq */ for(i=0; i<MPILOTFFT; i++) { s[i].real = 0.0; s[i].imag = 0.0; } for(i=0,j=0; i<NPILOTLPF; i+=mpilot,j++) { s[j] = fcmult(hanning[i], pilot_lpf[i]); } kiss_fft(fft_pilot_cfg, (kiss_fft_cpx *)s, (kiss_fft_cpx *)S); /* peak pick and convert to Hz */ imax = 0.0; ix = 0; for(i=0; i<MPILOTFFT; i++) { mag = S[i].real*S[i].real + S[i].imag*S[i].imag; if (mag > imax) { imax = mag; ix = i; } } r = 2.0*200.0/MPILOTFFT; /* maps FFT bin to frequency in Hz */ if (ix >= MPILOTFFT/2) *foff = (ix - MPILOTFFT)*r; else *foff = (ix)*r; *max = imax; }
void *ConstQ::sparseKernelThread(void *arg) { ConstQ *This = (ConstQ*) arg; unsigned int _fftLength = This->fftLength; int _constQBins = This->constQBins; int _Q = This->Q; double _minFreq = This->minFreq; double _maxFreq = This->maxFreq; int _fs = This->fs; float _thresh = This->thresh; int _bpo = This->bpo; kiss_fft_cpx tempKernel[_fftLength]; memset(tempKernel, 0, _fftLength * sizeof(kiss_fft_cpx)); kiss_fft_cpx specKernel[_fftLength]; for (int k=_constQBins; k > 0; k--){ This->progress = 1.0/_constQBins *(_constQBins - k); double centerFreq = (_minFreq * pow(2,(float(k-1)/_bpo))); int length = ceil(_Q * _fs / centerFreq); for(int n=0; n<length; n++){ kiss_fft_cpx cpx = This->e(2*pi*_Q*n/length); double hwin = This->hamming(n, length) / length; tempKernel[n].r = (kiss_fft_scalar) hwin * cpx.r; tempKernel[n].i = (kiss_fft_scalar) hwin * cpx.i; } kiss_fft(This->fft, tempKernel, specKernel); int upperBound = This->sparkernel[k-1].e; int lowerBound = This->sparkernel[k-1].s; // cut under the threshold, Conjugate and scaling for(int i=lowerBound; i<upperBound; i++){ if (This->mag(specKernel[i]) > _thresh){ This->sparkernel[k-1].cpx[i-lowerBound].r = specKernel[i].r / _fftLength; This->sparkernel[k-1].cpx[i-lowerBound].i = - specKernel[i].i / _fftLength; // Conjugate } else { This->sparkernel[k-1].cpx[i-lowerBound].r = 0; This->sparkernel[k-1].cpx[i-lowerBound].i = 0; } } } This->progress = 1.0; }
DP_FN_POSTAMBLE /* Some optimization work needs to be done. This function // can work directly from the input and output buffers for the // object, but there are two downsides. 1) we'd still need // another buffer to do smoothing and 2) the output order of the // fft is not convenient for visualization. It has 0 Hz at index 0 // rather than centered int the list. The (-1)^i flipping below // fixes that, but requires another buffer. */ DP_FN_PREAMBLE(cfft,work) { uint32_t i; if (s->need_buffers && !s->buffs_allocd) { dp_cfft_prerun(b); } if (s->need_buffers) { for (i=0;i<b->runlength;i++) { /* making sure to get r and i parts in the right sequence * and also applying -i^i transform to make result in order * linear from -sr/2 to sr/2. */ s->ibuff[i].r = b->in_v->v[2*i] * ((i%2) ? -1 : 1); s->ibuff[i].i = b->in_v->v[2*i+1] * ((i%2) ? -1 : 1); } } else { s->ibuff = (kiss_fft_cpx *)(void *)b->in_v->v; s->obuff = (kiss_fft_cpx *)(void *)b->out_v->v; } kiss_fft(s->cfg,s->ibuff, s->obuff); if (s->need_buffers) { for (i=0;i<b->runlength;i++) { int32_t av_r, av_i; av_r = (255 - s->averaging) * s->obuff[i].r + s->averaging * b->out_v->v[2*i]; av_i = (255 - s->averaging) * s->obuff[i].i + s->averaging * b->out_v->v[2*i+1]; b->out_v->v[2*i] = av_r >> 8; b->out_v->v[2*i+1] = av_i >> 8; /* printf("i,%d,fft,%d,%d,in,%d,%d\n",i,av_r>>8,av_i>>8,b->in_v->v[2*i],b->in_v->v[2*i+1]); */ } } /* printf("\n\n\n\n"); */ }
void test1d(int nfft,int isinverse) { size_t buflen = sizeof(kiss_fft_cpx)*nfft; kiss_fft_cpx * in = (kiss_fft_cpx*)malloc(buflen); kiss_fft_cpx * out= (kiss_fft_cpx*)malloc(buflen); kiss_fft_cfg cfg = kiss_fft_alloc(nfft,0,0); int k; for (k=0;k<nfft;++k) { in[k].r = (rand() % 32767) - 16384; in[k].i = (rand() % 32767) - 16384; } #ifdef DOUBLE_PRECISION for (k=0;k<nfft;++k) { in[k].r *= 32768; in[k].i *= 32768; } #endif if (isinverse) { for (k=0;k<nfft;++k) { in[k].r /= nfft; in[k].i /= nfft; } } /*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/ if (isinverse) kiss_ifft(cfg,in,out); else kiss_fft(cfg,in,out); /*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/ check(in,out,nfft,isinverse); free(in); free(out); free(cfg); }
static void fft_file(FILE * fin, FILE * fout, int nfft, int isinverse) { kiss_fft_cfg st; kiss_fft_cpx * buf; kiss_fft_cpx * bufout; buf = (kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx) * nfft); bufout = (kiss_fft_cpx*)malloc(sizeof(kiss_fft_cpx) * nfft); st = kiss_fft_alloc(nfft , isinverse , 0, 0); while (fread(buf , sizeof(kiss_fft_cpx) * nfft , 1, fin) > 0) { kiss_fft(st , buf , bufout); fwrite(bufout , sizeof(kiss_fft_cpx) , nfft , fout); } free(st); free(buf); free(bufout); }
FFT_RESULT PerformFFT(kiss_fft_cpx* in, kiss_fft_cpx* out, int samplesRead) { kiss_fft_cfg cfg; if (samplesRead > 0) { /* printf("Samples Read: %i \n", samplesRead); */ if ((cfg = kiss_fft_alloc(samplesRead, 0/*is_inverse_fft*/, NULL, NULL)) != NULL) { kiss_fft(cfg, in, out); free(cfg); } else { printf("Cannot set up kissFFT.\n"); exit(EXIT_FAILURE); } } FFT_RESULT result; result.bins = out; result.samples = samplesRead; return result; }
void CODEC2_WIN32SUPPORT fdmdv_get_rx_spectrum(struct FDMDV *f, float mag_spec_dB[], COMP rx_fdm[], int nin) { int i,j; COMP fft_in[2*FDMDV_NSPEC]; COMP fft_out[2*FDMDV_NSPEC]; float full_scale_dB; /* update buffer of input samples */ for(i=0; i<2*FDMDV_NSPEC-nin; i++) f->fft_buf[i] = f->fft_buf[i+nin]; for(j=0; j<nin; j++,i++) f->fft_buf[i] = rx_fdm[j].real; assert(i == 2*FDMDV_NSPEC); /* window and FFT */ for(i=0; i<2*FDMDV_NSPEC; i++) { fft_in[i].real = f->fft_buf[i] * (0.5 - 0.5*cos((float)i*2.0*PI/(2*FDMDV_NSPEC))); fft_in[i].imag = 0.0; } kiss_fft(f->fft_cfg, (kiss_fft_cpx *)fft_in, (kiss_fft_cpx *)fft_out); /* FFT scales up a signal of level 1 FDMDV_NSPEC */ full_scale_dB = 20*log10(FDMDV_NSPEC); /* scale and convert to dB */ for(i=0; i<FDMDV_NSPEC; i++) { mag_spec_dB[i] = 10.0*log10(fft_out[i].real*fft_out[i].real + fft_out[i].imag*fft_out[i].imag + 1E-12); mag_spec_dB[i] -= full_scale_dB; } }
void lpc_post_filter(kiss_fft_cfg fft_fwd_cfg, MODEL *model, COMP Pw[], float ak[], int order, int dump, float beta, float gamma, int bass_boost) { int i; COMP x[FFT_ENC]; /* input to FFTs */ COMP Aw[FFT_ENC]; /* LPC analysis filter spectrum */ COMP Ww[FFT_ENC]; /* weighting spectrum */ float Rw[FFT_ENC]; /* R = WA */ float e_before, e_after, gain; float Pfw[FFT_ENC]; /* Post filter mag spectrum */ float max_Rw, min_Rw; float coeff; TIMER_VAR(tstart, tfft1, taw, tfft2, tww, tr); TIMER_SAMPLE(tstart); /* Determine LPC inverse filter spectrum 1/A(exp(jw)) -----------*/ /* we actually want the synthesis filter A(exp(jw)) but the inverse (analysis) filter is easier to find as it's FIR, we just use the inverse of 1/A to get the synthesis filter A(exp(jw)) */ for(i=0; i<FFT_ENC; i++) { x[i].real = 0.0; x[i].imag = 0.0; } for(i=0; i<=order; i++) x[i].real = ak[i]; kiss_fft(fft_fwd_cfg, (kiss_fft_cpx *)x, (kiss_fft_cpx *)Aw); TIMER_SAMPLE_AND_LOG(tfft1, tstart, " fft1"); for(i=0; i<FFT_ENC/2; i++) { Aw[i].real = 1.0/(Aw[i].real*Aw[i].real + Aw[i].imag*Aw[i].imag); } TIMER_SAMPLE_AND_LOG(taw, tfft1, " Aw"); /* Determine weighting filter spectrum W(exp(jw)) ---------------*/ for(i=0; i<FFT_ENC; i++) { x[i].real = 0.0; x[i].imag = 0.0; } x[0].real = ak[0]; coeff = gamma; for(i=1; i<=order; i++) { x[i].real = ak[i] * coeff; coeff *= gamma; } kiss_fft(fft_fwd_cfg, (kiss_fft_cpx *)x, (kiss_fft_cpx *)Ww); TIMER_SAMPLE_AND_LOG(tfft2, taw, " fft2"); for(i=0; i<FFT_ENC/2; i++) { Ww[i].real = Ww[i].real*Ww[i].real + Ww[i].imag*Ww[i].imag; } TIMER_SAMPLE_AND_LOG(tww, tfft2, " Ww"); /* Determined combined filter R = WA ---------------------------*/ max_Rw = 0.0; min_Rw = 1E32; for(i=0; i<FFT_ENC/2; i++) { Rw[i] = sqrtf(Ww[i].real * Aw[i].real); if (Rw[i] > max_Rw) max_Rw = Rw[i]; if (Rw[i] < min_Rw) min_Rw = Rw[i]; } TIMER_SAMPLE_AND_LOG(tr, tww, " R"); #ifdef DUMP if (dump) dump_Rw(Rw); #endif /* create post filter mag spectrum and apply ------------------*/ /* measure energy before post filtering */ e_before = 1E-4; for(i=0; i<FFT_ENC/2; i++) e_before += Pw[i].real; /* apply post filter and measure energy */ #ifdef DUMP if (dump) dump_Pwb(Pw); #endif e_after = 1E-4; for(i=0; i<FFT_ENC/2; i++) { Pfw[i] = powf(Rw[i], beta); Pw[i].real *= Pfw[i] * Pfw[i]; e_after += Pw[i].real; } gain = e_before/e_after; /* apply gain factor to normalise energy */ for(i=0; i<FFT_ENC/2; i++) { Pw[i].real *= gain; } if (bass_boost) { /* add 3dB to first 1 kHz to account for LP effect of PF */ for(i=0; i<FFT_ENC/8; i++) { Pw[i].real *= 1.4*1.4; } } TIMER_SAMPLE_AND_LOG2(tr, " filt"); }
/*------------------------------------------------------------*/ void ompfft2(bool inv /* inverse/forward flag */, kiss_fft_cpx **pp /* [1...n2][1...n1] */, int ompith, fft2d fft) /*< Apply 2-D FFT >*/ { int i1,i2; if (inv) { /* IFT 1 */ for (i2=0; i2 < fft->n2; i2++) { #ifdef _OPENMP #pragma omp critical #endif kiss_fft(fft->invs1[ompith],pp[i2],pp[i2]); } /* IFT 2 */ for (i1=0; i1 < fft->n1; i1++) { #ifdef _OPENMP #pragma omp critical #endif kiss_fft_stride(fft->invs2[ompith],pp[0]+i1, fft->ctrace[ompith],fft->n1); for (i2=0; i2<fft->n2; i2++) { pp[i2][i1] = fft->ctrace[ompith][i2]; } } /* scaling */ for (i2=0; i2<fft->n2; i2++) { for (i1=0; i1<fft->n1; i1++) { pp[i2][i1] = sf_crmul(pp[i2][i1],fft->fftscale); } } } else { /* scaling */ for (i2=0; i2<fft->n2; i2++) { for (i1=0; i1<fft->n1; i1++) { pp[i2][i1] = sf_crmul(pp[i2][i1],fft->fftscale); } } /* FFT 2 */ for (i1=0; i1 < fft->n1; i1++) { #ifdef _OPENMP #pragma omp critical #endif kiss_fft_stride(fft->forw2[ompith],pp[0]+i1, fft->ctrace[ompith],fft->n1); for (i2=0; i2<fft->n2; i2++) { pp[i2][i1] = fft->ctrace[ompith][i2]; } } /* FFT 1 */ for (i2=0; i2 < fft->n2; i2++) { #ifdef _OPENMP #pragma omp critical #endif kiss_fft(fft->forw1[ompith],pp[i2],pp[i2]); } } }
void kfc_ifft(int nfft, const kiss_fft_cpx * fin,kiss_fft_cpx * fout) { kiss_fft( find_cached_fft(nfft,1),fin,fout ); }
KissFFTTest::KissFFTTest() { CtrlLayout(*this, "Window title"); #if _DIRECT_KISSFFT_MEANS kiss_fft_cpx sin[N]; kiss_fft_cpx sout[N]; for(int i=0; i<N; i++) { sin[i].r = (kiss_fft_scalar)0; sin[i].i = (kiss_fft_scalar)0; } sin[0].r = (kiss_fft_scalar)1; kiss_fft_cfg st = kiss_fft_alloc(N,0,0,0); kiss_fft(st,sin,sout); kiss_fft_free(st); print_buffs(sin, sout, N); RLOG(""); st = kiss_fft_alloc(N,1,0,0); kiss_fft(st,sout,sin); kiss_fft_free(st); //apply scale double sc = 1./N; for(int i = 0; i < N; i++) { sin[i].r *= sc, sin[i].i *= sc; } print_buffs(sout, sin, N); #else //USING UPP STRUCTURES #ifdef CD Vector<Complex> vt, vf; #else Vector<kiss_fft_cpx> vt, vf; #endif vt.SetCount(N); //in vf.SetCount(N); //out #ifdef CD vt[0] = Complex(1.); #else for(int i=0; i<N; i++) { vt[i].r = (kiss_fft_scalar)0, vt[i].i = (kiss_fft_scalar)0; } vt[0].r = (kiss_fft_scalar)1; #endif RLOG("fw fft"); { KissFFT fft(N); fft(vf, vt); } #ifdef CD DUMPC(vt); DUMPC(vf); #else print_buffs((const kiss_fft_cpx*)vt, (const kiss_fft_cpx*)vf, N); #endif RLOG("bw fft"); { KissFFT fft(N,true); fft(vt, vf); } double sc = 1./N; #ifdef CD for(int i = 0; i < vt.GetCount(); i++) vt[i] *= sc; DUMPC(vf); DUMPC(vt); #else for(int i = 0; i < vt.GetCount(); i++) { vt[i].r *= sc, vt[i].i *= sc; } print_buffs((const kiss_fft_cpx*)vf, (const kiss_fft_cpx*)vt, N); #endif #endif }
/* generic complex 1d-transform. */ int tcl_cfft_1d(ClientData nodata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *result, **tdata; const char *name; kiss_fft_cpx *input; kiss_fft_cpx *output; kiss_fft_cfg work; int dir, ndat, k; /* thread safety */ Tcl_MutexLock(&myFftMutex); /* set defaults: */ dir = FFT_FORWARD; ndat = -1; /* Parse arguments: * * usage: cfftf_1d <data> * or: cfftb_1d <data> * * cfftf_1d : is the 1d complex forward transform. * cfftb_1d : is the 1d complex backward transform. * <data> : list containing data to be transformed. this can either a real * or a list with two reals interpreted as complex. */ name = Tcl_GetString(objv[0]); if (strcmp(name,"cfftf_1d") == 0) { dir = FFT_FORWARD; } else if (strcmp(name,"cfftb_1d") == 0) { dir = FFT_BACKWARD; } else { Tcl_AppendResult(interp, name, ": unknown fft command.", NULL); Tcl_MutexUnlock(&myFftMutex); return TCL_ERROR; } if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "<data>"); Tcl_MutexUnlock(&myFftMutex); return TCL_ERROR; } /* get handle on data and check */ Tcl_IncrRefCount(objv[1]); if (Tcl_ListObjGetElements(interp, objv[1], &ndat, &tdata) != TCL_OK) { Tcl_DecrRefCount(objv[1]); Tcl_MutexUnlock(&myFftMutex); return TCL_ERROR; } if (ndat < 0) { /* this should not happen, but... */ Tcl_AppendResult(interp, name, ": illegal data array.", NULL); Tcl_DecrRefCount(objv[1]); Tcl_MutexUnlock(&myFftMutex); return TCL_ERROR; } if ((ndat == 0) || (ndat == 1)) { /* no effect for zero or one element */ Tcl_DecrRefCount(objv[1]); Tcl_SetObjResult(interp, objv[1]); Tcl_MutexUnlock(&myFftMutex); return TCL_OK; } check_thread_count(interp,"fftcmds"); /* get dynamic storage for passing data to the lowlevel code. */ input = (void *)Tcl_Alloc(ndat*sizeof(kiss_fft_cpx)); output = (void *)Tcl_Alloc(ndat*sizeof(kiss_fft_cpx)); work = kiss_fft_alloc(ndat, dir, NULL, NULL); /* parse/copy data list */ for (k=0; k<ndat; ++k) { if (read_list_cpx(interp, tdata[k], input + k) != TCL_OK) { Tcl_AppendResult(interp, name, ": illegal data array.", NULL); Tcl_DecrRefCount(objv[1]); Tcl_MutexUnlock(&myFftMutex); return TCL_ERROR; } } Tcl_DecrRefCount(objv[1]); /* finally run the transform */ kiss_fft(work, input, output); /* prepare results */ result = Tcl_NewListObj(0, NULL); for (k=0; k<ndat; ++k) { make_list_cpx(interp, result, output + k); } Tcl_SetObjResult(interp, result); /* free intermediate storage */ Tcl_Free((char *)input); Tcl_Free((char *)output); kiss_fft_free(work); kiss_fft_cleanup(); Tcl_MutexUnlock(&myFftMutex); return TCL_OK; }
void make_analysis_window(kiss_fft_cfg fft_fwd_cfg, float w[], COMP W[]) { float m; COMP wshift[FFT_ENC]; COMP temp; int i,j; /* Generate Hamming window centered on M-sample pitch analysis window 0 M/2 M-1 |-------------|-------------| |-------|-------| NW samples All our analysis/synthsis is centred on the M/2 sample. */ m = 0.0; for(i=0; i<M/2-NW/2; i++) w[i] = 0.0; for(i=M/2-NW/2,j=0; i<M/2+NW/2; i++,j++) { w[i] = 0.5 - 0.5*cos(TWO_PI*j/(NW-1)); m += w[i]*w[i]; } for(i=M/2+NW/2; i<M; i++) w[i] = 0.0; /* Normalise - makes freq domain amplitude estimation straight forward */ m = 1.0/sqrt(m*FFT_ENC); for(i=0; i<M; i++) { w[i] *= m; } /* Generate DFT of analysis window, used for later processing. Note we modulo FFT_ENC shift the time domain window w[], this makes the imaginary part of the DFT W[] equal to zero as the shifted w[] is even about the n=0 time axis if NW is odd. Having the imag part of the DFT W[] makes computation easier. 0 FFT_ENC-1 |-------------------------| ----\ /---- \ / \ / <- shifted version of window w[n] \ / \ / ------- |---------| |---------| NW/2 NW/2 */ for(i=0; i<FFT_ENC; i++) { wshift[i].real = 0.0; wshift[i].imag = 0.0; } for(i=0; i<NW/2; i++) wshift[i].real = w[i+M/2]; for(i=FFT_ENC-NW/2,j=M/2-NW/2; i<FFT_ENC; i++,j++) wshift[i].real = w[j]; kiss_fft(fft_fwd_cfg, (kiss_fft_cpx *)wshift, (kiss_fft_cpx *)W); /* Re-arrange W[] to be symmetrical about FFT_ENC/2. Makes later analysis convenient. Before: 0 FFT_ENC-1 |----------|---------| __ _ \ / \_______________/ After: 0 FFT_ENC-1 |----------|---------| ___ / \ ________/ \_______ */ for(i=0; i<FFT_ENC/2; i++) { temp.real = W[i].real; temp.imag = W[i].imag; W[i].real = W[i+FFT_ENC/2].real; W[i].imag = W[i+FFT_ENC/2].imag; W[i+FFT_ENC/2].real = temp.real; W[i+FFT_ENC/2].imag = temp.imag; } }
__declspec(dllexport) void KISS_FFT(kiss_fft_cfg cfg, const kiss_fft_cpx* fin, kiss_fft_cpx* fout) { kiss_fft(cfg, fin, fout); }
int main(int argc, char ** argv) { int k; int nfft[32]; int ndims = 1; int isinverse = 0; int numffts = 1000, i; kiss_fft_cpx * buf; kiss_fft_cpx * bufout; int real = 0; nfft[0] = 1024;// default while (1) { int c = getopt(argc, argv, "n:ix:r"); if (c == -1) break; switch (c) { case 'r': real = 1; break; case 'n': ndims = getdims(nfft, optarg); if (nfft[0] != kiss_fft_next_fast_size(nfft[0])) { int ng = kiss_fft_next_fast_size(nfft[0]); fprintf(stderr, "warning: %d might be a better choice for speed than %d\n", ng, nfft[0]); } break; case 'x': numffts = atoi(optarg); break; case 'i': isinverse = 1; break; } } int nbytes = sizeof(kiss_fft_cpx); for (k = 0; k < ndims; ++k) nbytes *= nfft[k]; #ifdef USE_SIMD numffts /= 4; fprintf(stderr, "since SIMD implementation does 4 ffts at a time, numffts is being reduced to %d\n", numffts); #endif buf = (kiss_fft_cpx*)KISS_FFT_MALLOC(nbytes); bufout = (kiss_fft_cpx*)KISS_FFT_MALLOC(nbytes); memset(buf, 0, nbytes); pstats_init(); if (ndims == 1) { if (real) { kiss_fftr_cfg st = kiss_fftr_alloc(nfft[0] , isinverse , 0, 0); if (isinverse) for (i = 0; i < numffts; ++i) kiss_fftri(st , (kiss_fft_cpx*)buf, (kiss_fft_scalar*)bufout); else for (i = 0; i < numffts; ++i) kiss_fftr(st , (kiss_fft_scalar*)buf, (kiss_fft_cpx*)bufout); free(st); } else { kiss_fft_cfg st = kiss_fft_alloc(nfft[0] , isinverse , 0, 0); for (i = 0; i < numffts; ++i) kiss_fft(st , buf, bufout); free(st); } } else { if (real) { kiss_fftndr_cfg st = kiss_fftndr_alloc(nfft, ndims , isinverse , 0, 0); if (isinverse) for (i = 0; i < numffts; ++i) kiss_fftndri(st , (kiss_fft_cpx*)buf, (kiss_fft_scalar*)bufout); else for (i = 0; i < numffts; ++i) kiss_fftndr(st , (kiss_fft_scalar*)buf, (kiss_fft_cpx*)bufout); free(st); } else { kiss_fftnd_cfg st = kiss_fftnd_alloc(nfft, ndims, isinverse , 0, 0); for (i = 0; i < numffts; ++i) kiss_fftnd(st , buf, bufout); free(st); } } free(buf); free(bufout); fprintf(stderr, "KISS\tnfft="); for (k = 0; k < ndims; ++k) fprintf(stderr, "%d,", nfft[k]); fprintf(stderr, "\tnumffts=%d\n" , numffts); pstats_report(); kiss_fft_cleanup(); return 0; }
void generateSyntheticData(int row, int hosts, double ** m, std::string prefix, std::string topofile, double demand_jump_factor, double demand_locality_factor, int merge_len) { char filedir[200]; sprintf(filedir,"%s%s", prefix.c_str(),"patterns"); printf("dir=%s!\n", filedir); FILE * fPattern = fopen(filedir,"r"); assert(fPattern != NULL && "Unable to open petterns file"); int nWeeks; int frlt=fscanf(fPattern, "%i", &nWeeks); assert(frlt >= 0); double ** totflow = new double *[nWeeks]; for (int curWeek = 0; curWeek < nWeeks;curWeek++) { totflow[curWeek] = new double[2016]; for (int i = 0; i < 2016; i++) frlt=fscanf(fPattern, "%lf", &totflow[curWeek][i]); } const int nfft = 2016; kiss_fft_cfg cfg = kiss_fft_alloc(nfft, false, 0, 0); kiss_fft_cfg cfg2 = kiss_fft_alloc(nfft,true, 0, 0); kiss_fft_cpx cx_in[nfft], cx_out[nfft]; for (int curWeek = 0; curWeek < nWeeks; curWeek++) { for (int i = 0; i < nfft; i++) { cx_in[i].r = totflow[curWeek][i]; cx_in[i].i = 0; } kiss_fft(cfg, cx_in, cx_out); for (int i = 0; i < nfft; i++) { cx_out[i].r /= nfft; cx_out[i].i /= nfft; } int position[nfft]; for (int i = 0; i < nfft; i++) position[i] = i; for (int i = 0; i < nfft - 1; i++) for (int j = i + 1; j < nfft; j++) { double n1 = cxnorm(cx_out[position[i]]); double n2 = cxnorm(cx_out[position[j]]); if (n1 < n2) { int tmp; tmp = position[i]; position[i] = position[j]; position[j] = tmp; } } for (int i = 6; i < nfft; i++) { double a = uniform_rand(0, 3); cx_out[position[i]].r *= a; cx_out[position[i]].i *= a; } kiss_fft(cfg2, cx_out, cx_in); for (int i = 0; i < nfft; i++) totflow[curWeek][i] = cx_in[i].r; } /* FILE * fFFTout = fopen("fftout", "w"); for (int curWeek = 0; curWeek < nWeeks; curWeek++) { for (int i = 0; i < 2016; i++) fprintf(fFFTout, "%.2lf ", totflow[curWeek][i]); fprintf(fFFTout, "\n"); } fclose(fFFTout); */ int nMean; char filedir2[200]; sprintf(filedir2,"%s%s", prefix.c_str(),"pareto"); printf("dir=%s!\n", filedir2); FILE * fpareto = fopen(filedir2, "r"); frlt=fscanf(fpareto, "%i", &nMean); double * saveMean = new double[nMean]; for (int i = 0; i < nMean; i++) frlt=fscanf(fpareto, "%lf", &saveMean[i]); //m[col][row]; double ** Tin = new double*[hosts]; double ** Tout = new double*[hosts]; for (int i = 0; i < hosts; i++) { Tin[i] = new double[row]; Tout[i] = new double[row]; generateW(Tin[i], saveMean[getRandNum(nMean)], row,demand_jump_factor); generateW(Tout[i], saveMean[getRandNum(nMean)], row,demand_jump_factor); } /* for (int i = 0; i < hosts; i++) { printf("No%i ----------%lf ", i, Tin[i][0]); for (int j = 0; j < 100;j++) printf("%.2lf -- ", Tin[i][j]); double avg = 0; for (int j = 0; j < row; j++) avg += Tin[i][j] / row; printf("avg == %.2lf\n\n", avg); } */ double tot_in, tot_out; for (int i = 0; i < row; i++) { tot_in = 0; tot_out = 0; for (int j = 0; j < hosts;j++) { tot_in += Tin[j][i]; tot_out += Tout[j][i]; } if (tot_in==0) tot_in=1; for (int j = 0; j < hosts; j++) { Tin[j][i] /= tot_in; Tout[j][i] /= tot_out; } } /* for (int i = 0; i < 5; i++) { printf("No%i ---------- \n\n\n", i); for (int j = 0; j < 100;j++) printf("%.6lf -- ", Tin[i][j]); }*/ double maxDist = 0; double ** graph=NULL; if (topofile.length() > 1) { FILE* topof=fopen(topofile.c_str(), "r"); assert(topof != NULL); int topo_n, topo_m; int tmp_rlt; tmp_rlt=fscanf(topof, "%i%i", &topo_n, &topo_m); if (tmp_rlt<0) printf("error! in fscanf\n"); graph = new double *[topo_n]; for (int i = 0; i < topo_n; i++) graph[i] = new double[topo_n]; for (int i = 0; i < topo_n; i++) for (int j = 0; j < topo_n; j++) if (i != j) graph[i][j] = 214748368; else graph[i][j] = 0; for (int i = 0; i < topo_m; i++) { int va, vb; double edge_len; double tmp_rlt=fscanf(topof, "%i%i%lf", &va, &vb, &edge_len); if (tmp_rlt<0) printf("error! in fscanf\n"); graph[va][vb] = edge_len; graph[vb][va] = edge_len; } for (int k = 0; k < topo_n; k++) for (int i = 0; i < topo_n; i++) if (k != i) for (int j = 0; j < topo_n; j++) if ((k != j) && (i != j)) if (graph[i][j]>graph[i][k] + graph[k][j]) graph[i][j] = graph[i][k] + graph[k][j]; for (int i = 0; i < topo_n; i++) for (int j = 0; j < topo_n; j++) if (maxDist<graph[i][j]) maxDist = graph[i][j]; fclose(topof); } int next=0; int pickedTotPattern=0; for (int i = 0; i < row; i++) { double s_merge=0; for (int j=0;j<merge_len;j++) { s_merge+= totflow[pickedTotPattern][next]; next++; if (next>=2016) { next=0; pickedTotPattern=0; } } s_merge/=merge_len; for (int j = 0; j < hosts; j++) for (int k = 0; k < hosts; k++){ if (maxDist == 0) m[j*hosts + k][i] = s_merge * Tin[j][i] * Tout[k][i]; else m[j*hosts + k][i] = s_merge * Tin[j][i] * Tout[k][i]* exp(-demand_locality_factor* graph[j][k]/maxDist/2); if (isnan(m[j*hosts+k][i])) printf("%lf %lf %lf", s_merge, Tin[j][i], Tout[k][i]); if (m[j*hosts+k][i]==0) m[j*hosts+k][i]=1000; } } fclose(fPattern); fclose(fpareto); for (int i = 0; i < nWeeks; i++) delete[] totflow[i]; delete[] totflow; delete[] saveMean; delete[] Tin; delete[] Tout; }
void freqfilt4pi_lop (bool adj, bool add, int nx, int ny, float* x, float* y) /*< linear filtering operator >*/ { int iw, ik; kiss_fft_cpx temp; int verb; // just outputting values to check when I get zeroes sf_adjnull(adj,add,nx,ny,x,y); for (ik=0; ik < m2; ik++) { for (iw=0; iw < m1; iw++) { trace[iw] = adj? y[ik*m1+iw]: x[ik*m1+iw]; /*if(trace[iw] == 0.0){ sf_warning("trace[%d] = %f",iw,trace[iw]); }*/ } for (iw=m1; iw < nfft; iw++) { trace[iw]=0.; } kiss_fftr (tfor,trace,ctrace); for (iw=0; iw < nw; iw++) { fft[ik][iw] = ik%2? sf_cneg(ctrace[iw]): ctrace[iw]; } } for (iw=0; iw < nw; iw++) { kiss_fft_stride(xfor,fft[0]+iw,ctrace2,nw); for (ik=0; ik < m2; ik++) { //double creal( double complex z ); //transform to kiss fft cpx //creal are double complex functions - what should we //do when double complex is not supported??? if (adj){ temp.r = creal(shape[iw][ik]); temp.i = (-1.0)*cimag(shape[iw][ik]); } else { temp.r = creal(shape[iw][ik]); temp.i = cimag(shape[iw][ik]); } ctrace2[ik] = sf_cmul(ctrace2[ik],temp); } kiss_fft(xinv,ctrace2,ctrace2); for (ik=0; ik < m2; ik++) { fft[ik][iw] = ik%2? sf_cneg(ctrace2[ik]): ctrace2[ik]; } } for (ik=0; ik < m2; ik++) { kiss_fftri (tinv,fft[ik],trace); for (iw=0; iw < m1; iw++) { if (adj) { x[ik*m1+iw] += trace[iw]; } else { y[ik*m1+iw] += trace[iw]; } } } }
/*------------------------------------------------------------*/ void ompfft3(bool inv /* inverse/forward flag */, kiss_fft_cpx ***pp /* [n1][n2][n3] */, int ompith, fft3d fft) /*< Apply 3-D FFT >*/ { int i1,i2,i3; if (inv) { /* IFT 1 */ for (i3=0; i3 < fft->n3; i3++) { for (i2=0; i2 < fft->n2; i2++) { #ifdef _OPENMP #pragma omp critical #endif kiss_fft(fft->invs1[ompith],pp[i3][i2],pp[i3][i2]); } } /* IFT 2 */ for (i3=0; i3 < fft->n3; i3++) { for (i1=0; i1 < fft->n1; i1++) { #ifdef _OPENMP #pragma omp critical #endif kiss_fft_stride(fft->invs2[ompith],pp[i3][0]+i1, fft->ctrace2[ompith],fft->n1); for (i2=0; i2<fft->n2; i2++) { pp[i3][i2][i1] = fft->ctrace2[ompith][i2]; } } } /* IFT 3 */ for (i2=0; i2 < fft->n2; i2++) { for (i1=0; i1 < fft->n1; i1++) { #ifdef _OPENMP #pragma omp critical #endif kiss_fft_stride(fft->invs3[ompith],pp[0][i2]+i1, fft->ctrace3[ompith],fft->n1); for (i3=0; i3 < fft->n3; i3++) { pp[i3][i2][i1] = fft->ctrace3[ompith][i3]; } } } /* scaling */ for (i3=0; i3 < fft->n3; i3++) { for (i2=0; i2 < fft->n2; i2++) { for (i1=0; i1 < fft->n1; i1++) { pp[i3][i2][i1] = sf_crmul(pp[i3][i2][i1],fft->fftscale); } } } } else { /* scaling */ for (i3=0; i3 < fft->n3; i3++) { for (i2=0; i2 < fft->n2; i2++) { for (i1=0; i1 < fft->n1; i1++) { pp[i3][i2][i1] = sf_crmul(pp[i3][i2][i1],fft->fftscale); } } } /* FFT 3 */ for (i2=0; i2 < fft->n2; i2++) { for (i1=0; i1 < fft->n1; i1++) { #ifdef _OPENMP #pragma omp critical #endif kiss_fft_stride(fft->forw3[ompith],pp[0][i2]+i1,fft->ctrace3[ompith],fft->n1); for (i3=0; i3 < fft->n3; i3++) { pp[i3][i2][i1] = fft->ctrace3[ompith][i3]; } } } /* FFT 2 */ for (i3=0; i3 < fft->n3; i3++) { for (i1=0; i1 < fft->n1; i1++) { #ifdef _OPENMP #pragma omp critical #endif kiss_fft_stride(fft->forw2[ompith],pp[i3][0]+i1, fft->ctrace2[ompith],fft->n1); for (i2=0; i2 < fft->n2; i2++) { pp[i3][i2][i1] = fft->ctrace2[ompith][i2]; } } } /* FFT 1 */ for (i3=0; i3 < fft->n3; i3++) { for (i2=0; i2 < fft->n2; i2++) { #ifdef _OPENMP #pragma omp critical #endif kiss_fft(fft->forw1[ompith],pp[i3][i2],pp[i3][i2]); } } } }
float nlp( void *nlp_state, float Sn[], /* input speech vector */ int n, /* frames shift (no. new samples in Sn[]) */ int pmin, /* minimum pitch value */ int pmax, /* maximum pitch value */ float *pitch, /* estimated pitch period in samples */ COMP Sw[], /* Freq domain version of Sn[] */ COMP W[], /* Freq domain window */ float *prev_Wo ) { NLP *nlp; float notch; /* current notch filter output */ COMP fw[PE_FFT_SIZE]; /* DFT of squared signal (input) */ COMP Fw[PE_FFT_SIZE]; /* DFT of squared signal (output) */ float gmax; int gmax_bin; int m, i,j; float best_f0; TIMER_VAR(start, tnotch, filter, peakpick, window, fft, magsq, shiftmem); assert(nlp_state != NULL); nlp = (NLP*)nlp_state; m = nlp->m; TIMER_SAMPLE(start); /* Square, notch filter at DC, and LP filter vector */ for(i=m-n; i<m; i++) /* square latest speech samples */ nlp->sq[i] = Sn[i]*Sn[i]; for(i=m-n; i<m; i++) { /* notch filter at DC */ notch = nlp->sq[i] - nlp->mem_x; notch += COEFF*nlp->mem_y; nlp->mem_x = nlp->sq[i]; nlp->mem_y = notch; nlp->sq[i] = notch + 1.0; /* With 0 input vectors to codec, kiss_fft() would take a long time to execute when running in real time. Problem was traced to kiss_fft function call in this function. Adding this small constant fixed problem. Not exactly sure why. */ } TIMER_SAMPLE_AND_LOG(tnotch, start, " square and notch"); for(i=m-n; i<m; i++) { /* FIR filter vector */ for(j=0; j<NLP_NTAP-1; j++) nlp->mem_fir[j] = nlp->mem_fir[j+1]; nlp->mem_fir[NLP_NTAP-1] = nlp->sq[i]; nlp->sq[i] = 0.0; for(j=0; j<NLP_NTAP; j++) nlp->sq[i] += nlp->mem_fir[j]*nlp_fir[j]; } TIMER_SAMPLE_AND_LOG(filter, tnotch, " filter"); /* Decimate and DFT */ for(i=0; i<PE_FFT_SIZE; i++) { fw[i].real = 0.0; fw[i].imag = 0.0; } for(i=0; i<m/DEC; i++) { fw[i].real = nlp->sq[i*DEC]*nlp->w[i]; } TIMER_SAMPLE_AND_LOG(window, filter, " window"); #ifdef DUMP dump_dec(Fw); #endif kiss_fft(nlp->fft_cfg, (kiss_fft_cpx *)fw, (kiss_fft_cpx *)Fw); TIMER_SAMPLE_AND_LOG(fft, window, " fft"); for(i=0; i<PE_FFT_SIZE; i++) Fw[i].real = Fw[i].real*Fw[i].real + Fw[i].imag*Fw[i].imag; TIMER_SAMPLE_AND_LOG(magsq, fft, " mag sq"); #ifdef DUMP dump_sq(nlp->sq); dump_Fw(Fw); #endif /* find global peak */ gmax = 0.0; gmax_bin = PE_FFT_SIZE*DEC/pmax; for(i=PE_FFT_SIZE*DEC/pmax; i<=PE_FFT_SIZE*DEC/pmin; i++) { if (Fw[i].real > gmax) { gmax = Fw[i].real; gmax_bin = i; } } TIMER_SAMPLE_AND_LOG(peakpick, magsq, " peak pick"); //#define POST_PROCESS_MBE #ifdef POST_PROCESS_MBE best_f0 = post_process_mbe(Fw, pmin, pmax, gmax, Sw, W, prev_Wo); #else best_f0 = post_process_sub_multiples(Fw, pmin, pmax, gmax, gmax_bin, prev_Wo); #endif TIMER_SAMPLE_AND_LOG(shiftmem, peakpick, " post process"); /* Shift samples in buffer to make room for new samples */ for(i=0; i<m-n; i++) nlp->sq[i] = nlp->sq[i+n]; /* return pitch and F0 estimate */ *pitch = (float)SAMPLE_RATE/best_f0; TIMER_SAMPLE_AND_LOG2(shiftmem, " shift mem"); TIMER_SAMPLE_AND_LOG2(start, " nlp int"); return(best_f0); }
int OfdmGenerator::process(Buffer* const dataIn, Buffer* dataOut) { PDEBUG("OfdmGenerator::process(dataIn: %p, dataOut: %p)\n", dataIn, dataOut); dataOut->setLength(myNbSymbols * mySpacing * sizeof(complexf)); FFT_TYPE* in = reinterpret_cast<FFT_TYPE*>(dataIn->getData()); FFT_TYPE* out = reinterpret_cast<FFT_TYPE*>(dataOut->getData()); size_t sizeIn = dataIn->getLength() / sizeof(complexf); size_t sizeOut = dataOut->getLength() / sizeof(complexf); if (sizeIn != myNbSymbols * myNbCarriers) { PDEBUG("Nb symbols: %zu\n", myNbSymbols); PDEBUG("Nb carriers: %zu\n", myNbCarriers); PDEBUG("Spacing: %zu\n", mySpacing); PDEBUG("\n%zu != %zu\n", sizeIn, myNbSymbols * myNbCarriers); throw std::runtime_error( "OfdmGenerator::process input size not valid!"); } if (sizeOut != myNbSymbols * mySpacing) { PDEBUG("Nb symbols: %zu\n", myNbSymbols); PDEBUG("Nb carriers: %zu\n", myNbCarriers); PDEBUG("Spacing: %zu\n", mySpacing); PDEBUG("\n%zu != %zu\n", sizeIn, myNbSymbols * mySpacing); throw std::runtime_error( "OfdmGenerator::process output size not valid!"); } #if USE_FFTW // No SIMD/no-SIMD distinction, it's too early to optimize anything for (size_t i = 0; i < myNbSymbols; ++i) { myFftIn[0][0] = 0; myFftIn[0][1] = 0; bzero(&myFftIn[myZeroDst], myZeroSize * sizeof(FFT_TYPE)); memcpy(&myFftIn[myPosDst], &in[myPosSrc], myPosSize * sizeof(FFT_TYPE)); memcpy(&myFftIn[myNegDst], &in[myNegSrc], myNegSize * sizeof(FFT_TYPE)); fftwf_execute(myFftPlan); memcpy(out, myFftOut, mySpacing * sizeof(FFT_TYPE)); in += myNbCarriers; out += mySpacing; } #else # ifdef USE_SIMD for (size_t i = 0, j = 0; i < sizeIn; ) { // Pack 4 fft operations typedef struct { float r[4]; float i[4]; } fft_data; assert(sizeof(FFT_TYPE) == sizeof(fft_data)); complexf *cplxIn = (complexf*)in; complexf *cplxOut = (complexf*)out; fft_data *dataBuffer = (fft_data*)myFftBuffer; FFT_REAL(myFftBuffer[0]) = _mm_setzero_ps(); FFT_IMAG(myFftBuffer[0]) = _mm_setzero_ps(); for (size_t k = 0; k < myZeroSize; ++k) { FFT_REAL(myFftBuffer[myZeroDst + k]) = _mm_setzero_ps(); FFT_IMAG(myFftBuffer[myZeroDst + k]) = _mm_setzero_ps(); } for (int k = 0; k < 4; ++k) { if (i < sizeIn) { for (size_t l = 0; l < myPosSize; ++l) { dataBuffer[myPosDst + l].r[k] = cplxIn[i + myPosSrc + l].real(); dataBuffer[myPosDst + l].i[k] = cplxIn[i + myPosSrc + l].imag(); } for (size_t l = 0; l < myNegSize; ++l) { dataBuffer[myNegDst + l].r[k] = cplxIn[i + myNegSrc + l].real(); dataBuffer[myNegDst + l].i[k] = cplxIn[i + myNegSrc + l].imag(); } i += myNbCarriers; } else { for (size_t l = 0; l < myNbCarriers; ++l) { dataBuffer[l].r[k] = 0.0f; dataBuffer[l].i[k] = 0.0f; } } } kiss_fft(myFftPlan, myFftBuffer, myFftBuffer); for (int k = 0; k < 4; ++k) { if (j < sizeOut) { for (size_t l = 0; l < mySpacing; ++l) { cplxOut[j + l] = complexf(dataBuffer[l].r[k], dataBuffer[l].i[k]); } j += mySpacing; } } } # else for (size_t i = 0; i < myNbSymbols; ++i) { FFT_REAL(myFftBuffer[0]) = 0; FFT_IMAG(myFftBuffer[0]) = 0; bzero(&myFftBuffer[myZeroDst], myZeroSize * sizeof(FFT_TYPE)); memcpy(&myFftBuffer[myPosDst], &in[myPosSrc], myPosSize * sizeof(FFT_TYPE)); memcpy(&myFftBuffer[myNegDst], &in[myNegSrc], myNegSize * sizeof(FFT_TYPE)); kiss_fft(myFftPlan, myFftBuffer, out); in += myNbCarriers; out += mySpacing; } # endif #endif return sizeOut; }
void fft_1d_only(FFT_DATA *data, int nsize, int flag, struct fft_plan_3d *plan) { int i,total,length,offset,num; FFT_SCALAR norm, *data_ptr; // system specific constants #ifdef FFT_SCSL int isys = 0; FFT_PREC scalef = 1.0; #endif #ifdef FFT_DEC char c = 'C'; char f = 'F'; char b = 'B'; int one = 1; #endif #ifdef FFT_T3E int isys = 0; double scalef = 1.0; #endif // total = size of data needed in each dim // length = length of 1d FFT in each dim // total/length = # of 1d FFTs in each dim // if total > nsize, limit # of 1d FFTs to available size of data int total1 = plan->total1; int length1 = plan->length1; int total2 = plan->total2; int length2 = plan->length2; int total3 = plan->total3; int length3 = plan->length3; // fftw3 and Dfti in MKL encode the number of transforms // into the plan, so we cannot operate on a smaller data set. #if defined(FFT_MKL) || defined(FFT_FFTW3) if ((total1 > nsize) || (total2 > nsize) || (total3 > nsize)) return; #endif if (total1 > nsize) total1 = (nsize/length1) * length1; if (total2 > nsize) total2 = (nsize/length2) * length2; if (total3 > nsize) total3 = (nsize/length3) * length3; // perform 1d FFTs in each of 3 dimensions // data is just an array of 0.0 #ifdef FFT_SGI for (offset = 0; offset < total1; offset += length1) FFT_1D(flag,length1,&data[offset],1,plan->coeff1); for (offset = 0; offset < total2; offset += length2) FFT_1D(flag,length2,&data[offset],1,plan->coeff2); for (offset = 0; offset < total3; offset += length3) FFT_1D(flag,length3,&data[offset],1,plan->coeff3); #elif defined(FFT_SCSL) for (offset = 0; offset < total1; offset += length1) FFT_1D(flag,length1,scalef,&data[offset],&data[offset],plan->coeff1, plan->work1,&isys); for (offset = 0; offset < total2; offset += length2) FFT_1D(flag,length2,scalef,&data[offset],&data[offset],plan->coeff2, plan->work2,&isys); for (offset = 0; offset < total3; offset += length3) FFT_1D(flag,length3,scalef,&data[offset],&data[offset],plan->coeff3, plan->work3,&isys); #elif defined(FFT_ACML) int info=0; num=total1/length1; FFT_1D(&flag,&num,&length1,data,plan->coeff1,&info); num=total2/length2; FFT_1D(&flag,&num,&length2,data,plan->coeff2,&info); num=total3/length3; FFT_1D(&flag,&num,&length3,data,plan->coeff3,&info); #elif defined(FFT_INTEL) for (offset = 0; offset < total1; offset += length1) FFT_1D(&data[offset],&length1,&flag,plan->coeff1); for (offset = 0; offset < total2; offset += length2) FFT_1D(&data[offset],&length2,&flag,plan->coeff2); for (offset = 0; offset < total3; offset += length3) FFT_1D(&data[offset],&length3,&flag,plan->coeff3); #elif defined(FFT_MKL) if (flag == -1) { DftiComputeForward(plan->handle_fast,data); DftiComputeForward(plan->handle_mid,data); DftiComputeForward(plan->handle_slow,data); } else { DftiComputeBackward(plan->handle_fast,data); DftiComputeBackward(plan->handle_mid,data); DftiComputeBackward(plan->handle_slow,data); } #elif defined(FFT_DEC) if (flag == -1) { for (offset = 0; offset < total1; offset += length1) FFT_1D(&c,&c,&f,&data[offset],&data[offset],&length1,&one); for (offset = 0; offset < total2; offset += length2) FFT_1D(&c,&c,&f,&data[offset],&data[offset],&length2,&one); for (offset = 0; offset < total3; offset += length3) FFT_1D(&c,&c,&f,&data[offset],&data[offset],&length3,&one); } else { for (offset = 0; offset < total1; offset += length1) FFT_1D(&c,&c,&b,&data[offset],&data[offset],&length1,&one); for (offset = 0; offset < total2; offset += length2) FFT_1D(&c,&c,&b,&data[offset],&data[offset],&length2,&one); for (offset = 0; offset < total3; offset += length3) FFT_1D(&c,&c,&b,&data[offset],&data[offset],&length3,&one); } #elif defined(FFT_T3E) for (offset = 0; offset < total1; offset += length1) FFT_1D(&flag,&length1,&scalef,&data[offset],&data[offset],plan->coeff1, plan->work1,&isys); for (offset = 0; offset < total2; offset += length2) FFT_1D(&flag,&length2,&scalef,&data[offset],&data[offset],plan->coeff2, plan->work2,&isys); for (offset = 0; offset < total3; offset += length3) FFT_1D(&flag,&length3,&scalef,&data[offset],&data[offset],plan->coeff3, plan->work3,&isys); #elif defined(FFT_FFTW2) if (flag == -1) { fftw(plan->plan_fast_forward,total1/length1,data,1,0,NULL,0,0); fftw(plan->plan_mid_forward,total2/length2,data,1,0,NULL,0,0); fftw(plan->plan_slow_forward,total3/length3,data,1,0,NULL,0,0); } else { fftw(plan->plan_fast_backward,total1/length1,data,1,0,NULL,0,0); fftw(plan->plan_mid_backward,total2/length2,data,1,0,NULL,0,0); fftw(plan->plan_slow_backward,total3/length3,data,1,0,NULL,0,0); } #elif defined(FFT_FFTW3) FFTW_API(plan) theplan; if (flag == -1) theplan=plan->plan_fast_forward; else theplan=plan->plan_fast_backward; FFTW_API(execute_dft)(theplan,data,data); if (flag == -1) theplan=plan->plan_mid_forward; else theplan=plan->plan_mid_backward; FFTW_API(execute_dft)(theplan,data,data); if (flag == -1) theplan=plan->plan_slow_forward; else theplan=plan->plan_slow_backward; FFTW_API(execute_dft)(theplan,data,data); #else if (flag == -1) { for (offset = 0; offset < total1; offset += length1) kiss_fft(plan->cfg_fast_forward,&data[offset],&data[offset]); for (offset = 0; offset < total2; offset += length2) kiss_fft(plan->cfg_mid_forward,&data[offset],&data[offset]); for (offset = 0; offset < total3; offset += length3) kiss_fft(plan->cfg_slow_forward,&data[offset],&data[offset]); } else { for (offset = 0; offset < total1; offset += length1) kiss_fft(plan->cfg_fast_backward,&data[offset],&data[offset]); for (offset = 0; offset < total2; offset += length2) kiss_fft(plan->cfg_mid_backward,&data[offset],&data[offset]); for (offset = 0; offset < total3; offset += length3) kiss_fft(plan->cfg_slow_backward,&data[offset],&data[offset]); } #endif // scaling if required // limit num to size of data #ifndef FFT_T3E if (flag == 1 && plan->scaled) { norm = plan->norm; num = MIN(plan->normnum,nsize); data_ptr = (FFT_SCALAR *)data; for (i = 0; i < num; i++) { #if defined(FFT_FFTW3) *(data_ptr++) *= norm; *(data_ptr++) *= norm; #elif defined(FFT_MKL) data[i] *= norm; #else data[i].re *= norm; data[i].im *= norm; #endif } } #endif #ifdef FFT_T3E if (flag == 1 && plan->scaled) { norm = plan->norm; num = MIN(plan->normnum,nsize); for (i = 0; i < num; i++) data[i] *= (norm,norm); } #endif }
int main(int argc, char *argv[]) { //************************************************************ // Initialisation //************************************************************ std::cout << "INIT" << std::endl; srand((int)time(NULL)); if (argc < 3) { std::cerr << "not enough parameters" << std::endl << "usage : ./NeuralNetwork sample_sound.wav sound_to_process.wav [output_sound.wav]" << std::endl; return EXIT_FAILURE; } // Charge les fichiers audio WAV _inputWav, _sampleWav; if (_inputWav.Read(argv[2]) || _sampleWav.Read(argv[1])) { std::cerr << "unable to read file" << std::endl; return EXIT_FAILURE; } if (_inputWav.getChannels() != 1 || _sampleWav.getChannels() != 1) { std::cerr << "stereo sounds are not supported" << std::endl; return EXIT_FAILURE; } if (_inputWav.getBit() != 16 || _sampleWav.getBit() != 16) { std::cerr << "sounds must be 16 bits" << std::endl; return EXIT_FAILURE; } if (_inputWav.getSampleCount() < BUFFER_SIZE || _sampleWav.getSampleCount() < BUFFER_SIZE) { std::cerr << "sounds are too smalls" << std::endl; return EXIT_FAILURE; } // init buffers std::vector<kiss_fft_cpx> _fftIn(BUFFER_SIZE); for (int i = 0; i < BUFFER_SIZE; i++) { _fftIn[i].r = ((short*) _sampleWav.getData())[i] / 32767.f; _fftIn[i].i = 0.f; } // lance FFT kiss_fft_cfg _fftCfg = kiss_fft_alloc(BUFFER_SIZE, 0, 0, 0); std::vector<kiss_fft_cpx> _fftOut(BUFFER_SIZE); kiss_fft(_fftCfg, _fftIn.data(), _fftOut.data()); normalizeFFT(_fftOut); // Reseaux de neruones std::vector<NeuralNetwork*> _pool (POOL_SIZE); for (unsigned int i = 0; i < _pool.size(); i++) { NeuralNetwork* _network = new NeuralNetwork(); _pool[i] = _network; } Generator _generator; std::vector<float> _generatorParam(GENERATOR_COUNT, 0.f); std::vector<kiss_fft_cpx> _outGenerator(BUFFER_SIZE); std::vector<kiss_fft_cpx> _fftGenerator(BUFFER_SIZE); //************************************************************ // Algorithme génétique pour trouver un bon réseau de neurone //************************************************************ for (int _generation = 0; _generation < GENERATION_COUNT; _generation++) { std::cout << "generation : " << _generation << std::endl; for (unsigned int i = 0; i < _pool.size(); i++) { // test avec le reseau de neurone _pool[i]->run(_fftOut, _generatorParam); // genere le son _generator.run(_generatorParam, _outGenerator, (float) _sampleWav.getSampleRate()); // FFT du signal généré kiss_fft(_fftCfg, _outGenerator.data(), _fftGenerator.data()); normalizeFFT(_fftGenerator); // calcul la distance entre les deux FFTs float _distance = 0.f; for (unsigned int j = 0; j < BUFFER_SIZE/2; j++) { _distance += fabs(_fftGenerator[j].r - _fftOut[j].r); } // plus le score est petit, mieux c'est _pool[i]->mScore = _distance; } // Trie la pool dans l'ordre croissant de score std::sort(_pool.begin(), _pool.end(), &NeuralNetwork::sortFct); std::cout << "best network : " << _pool[0]->mScore << std::endl; // croisement genetique entre les meilleurs réseaux de neurones int _selection = (int)_pool.size() / 3; for (int i = 0; i < _selection; i++) { NeuralNetwork* _nn = new NeuralNetwork(_pool[i], _pool[random(0, _selection)]); // detruit les reseaux les plus mauvais et les remplace par des enfants delete _pool[_pool.size() - 1 - i]; _pool[_pool.size() - 1 - i] = _nn; } } //************************************************************ // Ecriture du son final //************************************************************ // test avec le meilleur reseau de neurone std::sort(_pool.begin(), _pool.end(), &NeuralNetwork::sortFct); // genere le son std::vector<short> _outputData(_inputWav.getSampleCount()); std::vector<float> _previousGeneratorParam(GENERATOR_COUNT, 0.f); // le son est traité par morceau for (unsigned int i = 0; i < _inputWav.getSampleCount() - BUFFER_SIZE; i += BUFFER_SIZE) { for (unsigned int j = 0; j < BUFFER_SIZE; j++) { _fftIn[j].r = ((short*) _inputWav.getData())[i + j] / 32767.f; _fftIn[j].i = 0.f; } // fft kiss_fft(_fftCfg, _fftIn.data(), _fftOut.data()); normalizeFFT(_fftOut); // réseau de neurone _pool[0]->run(_fftOut, _generatorParam); // générateurs _generator.run(_previousGeneratorParam, _generatorParam, _outGenerator, (float) _inputWav.getSampleRate(), i); _previousGeneratorParam = _generatorParam; // convertit en entier 16 bits for (unsigned int j = 0; j < BUFFER_SIZE; j++) { _outputData[i + j] = (short) (32767.f * _outGenerator[j].r); } } // écrit le son en sortie _inputWav.setSampleCount(_outputData.size()); _inputWav.setData(_outputData.data(), _outputData.size() * sizeof(short)); std::string _outFile = "out.wav"; if (argc >= 4) { _outFile = argv[3]; } std::cout << "write " << _outFile << std::endl; _inputWav.Write(_outFile.c_str()); return EXIT_SUCCESS; }
void aks_to_M2( kiss_fft_cfg fft_fwd_cfg, float ak[], /* LPC's */ int order, MODEL *model, /* sinusoidal model parameters for this frame */ float E, /* energy term */ float *snr, /* signal to noise ratio for this frame in dB */ int dump, /* true to dump sample to dump file */ int sim_pf, /* true to simulate a post filter */ int pf, /* true to LPC post filter */ int bass_boost, /* enable LPC filter 0-1khz 3dB boost */ float beta, float gamma /* LPC post filter parameters */ ) { COMP pw[FFT_ENC]; /* input to FFT for power spectrum */ COMP Pw[FFT_ENC]; /* output power spectrum */ int i,m; /* loop variables */ int am,bm; /* limits of current band */ float r; /* no. rads/bin */ float Em; /* energy in band */ float Am; /* spectral amplitude sample */ float signal, noise; TIMER_VAR(tstart, tfft, tpw, tpf); TIMER_SAMPLE(tstart); r = TWO_PI/(FFT_ENC); /* Determine DFT of A(exp(jw)) --------------------------------------------*/ for(i=0; i<FFT_ENC; i++) { pw[i].real = 0.0; pw[i].imag = 0.0; } for(i=0; i<=order; i++) pw[i].real = ak[i]; kiss_fft(fft_fwd_cfg, (kiss_fft_cpx *)pw, (kiss_fft_cpx *)Pw); TIMER_SAMPLE_AND_LOG(tfft, tstart, " fft"); /* Determine power spectrum P(w) = E/(A(exp(jw))^2 ------------------------*/ for(i=0; i<FFT_ENC/2; i++) Pw[i].real = E/(Pw[i].real*Pw[i].real + Pw[i].imag*Pw[i].imag); TIMER_SAMPLE_AND_LOG(tpw, tfft, " Pw"); if (pf) lpc_post_filter(fft_fwd_cfg, model, Pw, ak, order, dump, beta, gamma, bass_boost); TIMER_SAMPLE_AND_LOG(tpf, tpw, " LPC post filter"); #ifdef DUMP if (dump) dump_Pw(Pw); #endif /* Determine magnitudes from P(w) ----------------------------------------*/ /* when used just by decoder {A} might be all zeroes so init signal and noise to prevent log(0) errors */ signal = 1E-30; noise = 1E-32; for(m=1; m<=model->L; m++) { am = (int)((m - 0.5)*model->Wo/r + 0.5); bm = (int)((m + 0.5)*model->Wo/r + 0.5); Em = 0.0; for(i=am; i<bm; i++) Em += Pw[i].real; Am = sqrtf(Em); signal += model->A[m]*model->A[m]; noise += (model->A[m] - Am)*(model->A[m] - Am); /* This code significantly improves perf of LPC model, in particular when combined with phase0. The LPC spectrum tends to track just under the peaks of the spectral envelope, and just above nulls. This algorithm does the reverse to compensate - raising the amplitudes of spectral peaks, while attenuating the null. This enhances the formants, and supresses the energy between formants. */ if (sim_pf) { if (Am > model->A[m]) Am *= 0.7; if (Am < model->A[m]) Am *= 1.4; } model->A[m] = Am; } *snr = 10.0*log10f(signal/noise); TIMER_SAMPLE_AND_LOG2(tpf, " rec"); }
void synthesise( kiss_fft_cfg fft_inv_cfg, float Sn_[], /* time domain synthesised signal */ MODEL *model, /* ptr to model parameters for this frame */ float Pn[], /* time domain Parzen window */ int shift /* flag used to handle transition frames */ ) { int i,l,j,b; /* loop variables */ COMP Sw_[FFT_DEC]; /* DFT of synthesised signal */ COMP sw_[FFT_DEC]; /* synthesised signal */ if (shift) { /* Update memories */ for(i=0; i<N-1; i++) { Sn_[i] = Sn_[i+N]; } Sn_[N-1] = 0.0; } for(i=0; i<FFT_DEC; i++) { Sw_[i].real = 0.0; Sw_[i].imag = 0.0; } /* Nov 2010 - found that synthesis using time domain cos() functions gives better results for synthesis frames greater than 10ms. Inverse FFT synthesis using a 512 pt FFT works well for 10ms window. I think (but am not sure) that the problem is related to the quantisation of the harmonic frequencies to the FFT bin size, e.g. there is a 8000/512 Hz step between FFT bins. For some reason this makes the speech from longer frame > 10ms sound poor. The effect can also be seen when synthesising test signals like single sine waves, some sort of amplitude modulation at the frame rate. Another possibility is using a larger FFT size (1024 or 2048). */ #define FFT_SYNTHESIS #ifdef FFT_SYNTHESIS /* Now set up frequency domain synthesised speech */ for(l=1; l<=model->L; l++) { //for(l=model->L/2; l<=model->L; l++) { //for(l=1; l<=model->L/4; l++) { b = floor(l*model->Wo*FFT_DEC/TWO_PI + 0.5); if (b > ((FFT_DEC/2)-1)) { b = (FFT_DEC/2)-1; } Sw_[b].real = model->A[l]*cos(model->phi[l]); Sw_[b].imag = model->A[l]*sin(model->phi[l]); Sw_[FFT_DEC-b].real = Sw_[b].real; Sw_[FFT_DEC-b].imag = -Sw_[b].imag; } /* Perform inverse DFT */ kiss_fft(fft_inv_cfg, (kiss_fft_cpx *)Sw_, (kiss_fft_cpx *)sw_); #else /* Direct time domain synthesis using the cos() function. Works well at 10ms and 20ms frames rates. Note synthesis window is still used to handle overlap-add between adjacent frames. This could be simplified as we don't need to synthesise where Pn[] is zero. */ for(l=1; l<=model->L; l++) { for(i=0,j=-N+1; i<N-1; i++,j++) { Sw_[FFT_DEC-N+1+i].real += 2.0*model->A[l]*cos(j*model->Wo*l + model->phi[l]); } for(i=N-1,j=0; i<2*N; i++,j++) Sw_[j].real += 2.0*model->A[l]*cos(j*model->Wo*l + model->phi[l]); } #endif /* Overlap add to previous samples */ for(i=0; i<N-1; i++) { Sn_[i] += sw_[FFT_DEC-N+1+i].real*Pn[i]; } if (shift) for(i=N-1,j=0; i<2*N; i++,j++) Sn_[i] = sw_[j].real*Pn[i]; else for(i=N-1,j=0; i<2*N; i++,j++) Sn_[i] += sw_[j].real*Pn[i]; }
int main(int argc, char *argv[]) { FILE *fout = NULL; /* output speech file */ FILE *fin; /* input speech file */ short buf[N]; /* input/output buffer */ float buf_float[N]; float Sn[M]; /* float input speech samples */ float Sn_pre[N]; /* pre-emphasised input speech samples */ COMP Sw[FFT_ENC]; /* DFT of Sn[] */ kiss_fft_cfg fft_fwd_cfg; kiss_fft_cfg fft_inv_cfg; float w[M]; /* time domain hamming window */ COMP W[FFT_ENC]; /* DFT of w[] */ MODEL model; float Pn[2*N]; /* trapezoidal synthesis window */ float Sn_[2*N]; /* synthesised speech */ int i,m; /* loop variable */ int frames; float prev_Wo, prev__Wo, prev_uq_Wo; float pitch; char out_file[MAX_STR]; char ampexp_arg[MAX_STR]; char phaseexp_arg[MAX_STR]; float snr; float sum_snr; int orderi; int lpc_model = 0, order = LPC_ORD; int lsp = 0, lspd = 0, lspvq = 0; int lspres = 0; int lspjvm = 0, lspjnd = 0, lspmel = 0; #ifdef __EXPERIMENTAL__ int lspanssi = 0, #endif int prede = 0; float pre_mem = 0.0, de_mem = 0.0; float ak[order]; COMP Sw_[FFT_ENC]; COMP Ew[FFT_ENC]; int phase0 = 0; float ex_phase[MAX_AMP+1]; int postfilt; int hand_voicing = 0, phaseexp = 0, ampexp = 0, hi = 0, simlpcpf = 0; int lpcpf = 0; FILE *fvoicing = 0; MODEL prev_model; int dec; int decimate = 1; float lsps[order]; float e, prev_e; int lsp_indexes[order]; float lsps_[order]; float Woe_[2]; float lsps_dec[4][LPC_ORD], e_dec[4], weight, weight_inc, ak_dec[4][LPC_ORD]; MODEL model_dec[4], prev_model_dec; float prev_lsps_dec[order], prev_e_dec; void *nlp_states; float hpf_states[2]; int scalar_quant_Wo_e = 0; int vector_quant_Wo_e = 0; int dump_pitch_e = 0; FILE *fjvm = NULL; #ifdef DUMP int dump; #endif struct PEXP *pexp = NULL; struct AEXP *aexp = NULL; float gain = 1.0; int bpf_en = 0; float bpf_buf[BPF_N+N]; char* opt_string = "ho:"; struct option long_options[] = { { "lpc", required_argument, &lpc_model, 1 }, { "lspjnd", no_argument, &lspjnd, 1 }, { "lspmel", no_argument, &lspmel, 1 }, { "lsp", no_argument, &lsp, 1 }, { "lspd", no_argument, &lspd, 1 }, { "lspvq", no_argument, &lspvq, 1 }, { "lspres", no_argument, &lspres, 1 }, { "lspjvm", no_argument, &lspjvm, 1 }, #ifdef __EXPERIMENTAL__ { "lspanssi", no_argument, &lspanssi, 1 }, #endif { "phase0", no_argument, &phase0, 1 }, { "phaseexp", required_argument, &phaseexp, 1 }, { "ampexp", required_argument, &exp, 1 }, { "postfilter", no_argument, &postfilt, 1 }, { "hand_voicing", required_argument, &hand_voicing, 1 }, { "dec", required_argument, &dec, 1 }, { "hi", no_argument, &hi, 1 }, { "simlpcpf", no_argument, &simlpcpf, 1 }, { "lpcpf", no_argument, &lpcpf, 1 }, { "prede", no_argument, &prede, 1 }, { "dump_pitch_e", required_argument, &dump_pitch_e, 1 }, { "sq_pitch_e", no_argument, &scalar_quant_Wo_e, 1 }, { "vq_pitch_e", no_argument, &vector_quant_Wo_e, 1 }, { "rate", required_argument, NULL, 0 }, { "gain", required_argument, NULL, 0 }, { "bpf", no_argument, &bpf_en, 1 }, #ifdef DUMP { "dump", required_argument, &dump, 1 }, #endif { "help", no_argument, NULL, 'h' }, { NULL, no_argument, NULL, 0 } }; int num_opts=sizeof(long_options)/sizeof(struct option); COMP Aw[FFT_ENC]; for(i=0; i<M; i++) { Sn[i] = 1.0; Sn_pre[i] = 1.0; } for(i=0; i<2*N; i++) Sn_[i] = 0; prev_uq_Wo = prev_Wo = prev__Wo = TWO_PI/P_MAX; prev_model.Wo = TWO_PI/P_MIN; prev_model.L = floor(PI/prev_model.Wo); for(i=1; i<=prev_model.L; i++) { prev_model.A[i] = 0.0; prev_model.phi[i] = 0.0; } for(i=1; i<=MAX_AMP; i++) { //ex_phase[i] = (PI/3)*(float)rand()/RAND_MAX; ex_phase[i] = 0.0; } e = prev_e = 1; hpf_states[0] = hpf_states[1] = 0.0; nlp_states = nlp_create(M); if (argc < 2) { print_help(long_options, num_opts, argv); } /*----------------------------------------------------------------*\ Interpret Command Line Arguments \*----------------------------------------------------------------*/ while(1) { int option_index = 0; int opt = getopt_long(argc, argv, opt_string, long_options, &option_index); if (opt == -1) break; switch (opt) { case 0: if(strcmp(long_options[option_index].name, "lpc") == 0) { orderi = atoi(optarg); if((orderi < 4) || (orderi > order)) { fprintf(stderr, "Error in LPC order (4 to %d): %s\n", order, optarg); exit(1); } order = orderi; #ifdef DUMP } else if(strcmp(long_options[option_index].name, "dump") == 0) { if (dump) dump_on(optarg); #endif } else if(strcmp(long_options[option_index].name, "lsp") == 0 || strcmp(long_options[option_index].name, "lspd") == 0 || strcmp(long_options[option_index].name, "lspvq") == 0) { assert(order == LPC_ORD); } else if(strcmp(long_options[option_index].name, "dec") == 0) { decimate = atoi(optarg); if ((decimate != 2) && (decimate != 4)) { fprintf(stderr, "Error in --dec, must be 2 or 4\n"); exit(1); } if (!phase0) { printf("needs --phase0 to resample phase when using --dec\n"); exit(1); } if (!lpc_model) { printf("needs --lpc [order] to resample amplitudes when using --dec\n"); exit(1); } } else if(strcmp(long_options[option_index].name, "hand_voicing") == 0) { if ((fvoicing = fopen(optarg,"rt")) == NULL) { fprintf(stderr, "Error opening voicing file: %s: %s.\n", optarg, strerror(errno)); exit(1); } } else if(strcmp(long_options[option_index].name, "dump_pitch_e") == 0) { if ((fjvm = fopen(optarg,"wt")) == NULL) { fprintf(stderr, "Error opening pitch & energy dump file: %s: %s.\n", optarg, strerror(errno)); exit(1); } } else if(strcmp(long_options[option_index].name, "phaseexp") == 0) { strcpy(phaseexp_arg, optarg); } else if(strcmp(long_options[option_index].name, "ampexp") == 0) { strcpy(ampexp_arg, optarg); } else if(strcmp(long_options[option_index].name, "gain") == 0) { gain = atof(optarg); } else if(strcmp(long_options[option_index].name, "rate") == 0) { if(strcmp(optarg,"3200") == 0) { lpc_model = 1; scalar_quant_Wo_e = 1; lspd = 1; phase0 = 1; postfilt = 1; decimate = 1; lpcpf = 1; } else if(strcmp(optarg,"2400") == 0) { lpc_model = 1; vector_quant_Wo_e = 1; lsp = 1; phase0 = 1; postfilt = 1; decimate = 2; lpcpf = 1; } else if(strcmp(optarg,"1400") == 0) { lpc_model = 1; vector_quant_Wo_e = 1; lsp = 1; phase0 = 1; postfilt = 1; decimate = 4; lpcpf = 1; } else if(strcmp(optarg,"1300") == 0) { lpc_model = 1; scalar_quant_Wo_e = 1; lsp = 1; phase0 = 1; postfilt = 1; decimate = 4; lpcpf = 1; } else if(strcmp(optarg,"1200") == 0) { lpc_model = 1; scalar_quant_Wo_e = 1; lspjvm = 1; phase0 = 1; postfilt = 1; decimate = 4; lpcpf = 1; } else { fprintf(stderr, "Error: invalid output rate (3200|2400|1400|1200) %s\n", optarg); exit(1); } } break; case 'h': print_help(long_options, num_opts, argv); break; case 'o': if (strcmp(optarg, "-") == 0) fout = stdout; else if ((fout = fopen(optarg,"wb")) == NULL) { fprintf(stderr, "Error opening output speech file: %s: %s.\n", optarg, strerror(errno)); exit(1); } strcpy(out_file,optarg); break; default: /* This will never be reached */ break; } } /* Input file */ if (strcmp(argv[optind], "-") == 0) fin = stdin; else if ((fin = fopen(argv[optind],"rb")) == NULL) { fprintf(stderr, "Error opening input speech file: %s: %s.\n", argv[optind], strerror(errno)); exit(1); } ex_phase[0] = 0; Woe_[0] = Woe_[1] = 1.0; /* printf("lspd: %d lspdt: %d lspdt_mode: %d phase0: %d postfilt: %d " "decimate: %d dt: %d\n",lspd,lspdt,lspdt_mode,phase0,postfilt, decimate,dt); */ /* Initialise ------------------------------------------------------------*/ fft_fwd_cfg = kiss_fft_alloc(FFT_ENC, 0, NULL, NULL); /* fwd FFT,used in several places */ fft_inv_cfg = kiss_fft_alloc(FFT_DEC, 1, NULL, NULL); /* inverse FFT, used just for synth */ make_analysis_window(fft_fwd_cfg, w, W); make_synthesis_window(Pn); quantise_init(); if (phaseexp) pexp = phase_experiment_create(); if (ampexp) aexp = amp_experiment_create(); if (bpf_en) { for(i=0; i<BPF_N; i++) bpf_buf[i] = 0.0; } for(i=0; i<LPC_ORD; i++) { prev_lsps_dec[i] = i*PI/(LPC_ORD+1); } prev_e_dec = 1; for(m=1; m<=MAX_AMP; m++) prev_model_dec.A[m] = 0.0; prev_model_dec.Wo = TWO_PI/P_MAX; prev_model_dec.L = PI/prev_model_dec.Wo; prev_model_dec.voiced = 0; /*----------------------------------------------------------------* \ Main Loop \*----------------------------------------------------------------*/ frames = 0; sum_snr = 0; while(fread(buf,sizeof(short),N,fin)) { frames++; for(i=0; i<N; i++) buf_float[i] = buf[i]; /* optionally filter input speech */ if (prede) { pre_emp(Sn_pre, buf_float, &pre_mem, N); for(i=0; i<N; i++) buf_float[i] = Sn_pre[i]; } if (bpf_en) { for(i=0; i<BPF_N; i++) bpf_buf[i] = bpf_buf[N+i]; for(i=0; i<N; i++) bpf_buf[BPF_N+i] = buf_float[i]; inverse_filter(&bpf_buf[BPF_N], bpf, N, buf_float, BPF_N); } /* shift buffer of input samples, and insert new samples */ for(i=0; i<M-N; i++) { Sn[i] = Sn[i+N]; } for(i=0; i<N; i++) Sn[i+M-N] = buf_float[i]; /*------------------------------------------------------------*\ Estimate Sinusoidal Model Parameters \*------------------------------------------------------------*/ nlp(nlp_states,Sn,N,P_MIN,P_MAX,&pitch,Sw,W,&prev_uq_Wo); model.Wo = TWO_PI/pitch; dft_speech(fft_fwd_cfg, Sw, Sn, w); two_stage_pitch_refinement(&model, Sw); estimate_amplitudes(&model, Sw, W, 1); #ifdef DUMP dump_Sn(Sn); dump_Sw(Sw); dump_model(&model); #endif if (ampexp) amp_experiment(aexp, &model, ampexp_arg); if (phaseexp) { #ifdef DUMP dump_phase(&model.phi[0], model.L); #endif phase_experiment(pexp, &model, phaseexp_arg); #ifdef DUMP dump_phase_(&model.phi[0], model.L); #endif } if (hi) { int m; for(m=1; m<model.L/2; m++) model.A[m] = 0.0; for(m=3*model.L/4; m<=model.L; m++) model.A[m] = 0.0; } /*------------------------------------------------------------*\ Zero-phase modelling \*------------------------------------------------------------*/ if (phase0) { float Wn[M]; /* windowed speech samples */ float Rk[order+1]; /* autocorrelation coeffs */ COMP a[FFT_ENC]; #ifdef DUMP dump_phase(&model.phi[0], model.L); #endif /* find aks here, these are overwritten if LPC modelling is enabled */ for(i=0; i<M; i++) Wn[i] = Sn[i]*w[i]; autocorrelate(Wn,Rk,M,order); levinson_durbin(Rk,ak,order); /* determine voicing */ snr = est_voicing_mbe(&model, Sw, W, Sw_, Ew); if (dump_pitch_e) fprintf(fjvm, "%f %f %d ", model.Wo, snr, model.voiced); //printf("snr %3.2f v: %d Wo: %f prev_Wo: %f\n", snr, model.voiced, // model.Wo, prev_uq_Wo); #ifdef DUMP dump_Sw_(Sw_); dump_Ew(Ew); dump_snr(snr); #endif /* just to make sure we are not cheating - kill all phases */ for(i=0; i<=MAX_AMP; i++) model.phi[i] = 0; /* Determine DFT of A(exp(jw)), which is needed for phase0 model when LPC is not used, e.g. indecimate=1 (10ms) frames with no LPC */ for(i=0; i<FFT_ENC; i++) { a[i].real = 0.0; a[i].imag = 0.0; } for(i=0; i<=order; i++) a[i].real = ak[i]; kiss_fft(fft_fwd_cfg, (kiss_fft_cpx *)a, (kiss_fft_cpx *)Aw); if (hand_voicing) { fscanf(fvoicing,"%d\n",&model.voiced); } } /*------------------------------------------------------------*\ LPC model amplitudes and LSP quantisation \*------------------------------------------------------------*/ if (lpc_model) { e = speech_to_uq_lsps(lsps, ak, Sn, w, order); for(i=0; i<LPC_ORD; i++) lsps_[i] = lsps[i]; #ifdef DUMP dump_ak(ak, order); dump_E(e); #endif /* tracking down -ve energy values with BW expansion */ /* if (e < 0.0) { int i; FILE*f=fopen("x.txt","wt"); for(i=0; i<M; i++) fprintf(f,"%f\n", Sn[i]); fclose(f); printf("e = %f frames = %d\n", e, frames); for(i=0; i<order; i++) printf("%f ", ak[i]); exit(0); } */ if (dump_pitch_e) fprintf(fjvm, "%f\n", e); #ifdef DUMP dump_lsp(lsps); #endif /* various LSP quantisation schemes */ if (lsp) { encode_lsps_scalar(lsp_indexes, lsps, LPC_ORD); decode_lsps_scalar(lsps_, lsp_indexes, LPC_ORD); bw_expand_lsps(lsps_, LPC_ORD, 50.0, 100.0); lsp_to_lpc(lsps_, ak, LPC_ORD); } if (lspd) { encode_lspds_scalar(lsp_indexes, lsps, LPC_ORD); decode_lspds_scalar(lsps_, lsp_indexes, LPC_ORD); lsp_to_lpc(lsps_, ak, LPC_ORD); } #ifdef __EXPERIMENTAL__ if (lspvq) { lspvq_quantise(lsps, lsps_, LPC_ORD); bw_expand_lsps(lsps_, LPC_ORD, 50.0, 100.0); lsp_to_lpc(lsps_, ak, LPC_ORD); } #endif if (lspjvm) { /* Jean-Marc's multi-stage, split VQ */ lspjvm_quantise(lsps, lsps_, LPC_ORD); { float lsps_bw[LPC_ORD]; memcpy(lsps_bw, lsps_, sizeof(float)*LPC_ORD); bw_expand_lsps(lsps_bw, LPC_ORD, 50.0, 100.0); lsp_to_lpc(lsps_bw, ak, LPC_ORD); } } #ifdef __EXPERIMENTAL__ if (lspanssi) { /* multi-stage VQ from Anssi Ramo OH3GDD */ lspanssi_quantise(lsps, lsps_, LPC_ORD, 5); bw_expand_lsps(lsps_, LPC_ORD, 50.0, 100.0); lsp_to_lpc(lsps_, ak, LPC_ORD); } #endif /* experimenting with non-linear LSP spacing to see if it's just noticable */ if (lspjnd) { for(i=0; i<LPC_ORD; i++) lsps_[i] = lsps[i]; locate_lsps_jnd_steps(lsps_, LPC_ORD); lsp_to_lpc(lsps_, ak, LPC_ORD); } /* Another experiment with non-linear LSP spacing, this time using a scaled version of mel frequency axis warping. The scaling is such that the integer output can be directly sent over the channel. */ if (lspmel) { float f, f_; float mel[LPC_ORD]; int mel_indexes[LPC_ORD]; for(i=0; i<order; i++) { f = (4000.0/PI)*lsps[i]; mel[i] = floor(2595.0*log10(1.0 + f/700.0) + 0.5); } for(i=1; i<order; i++) { if (mel[i] == mel[i-1]) mel[i]++; } encode_mels_scalar(mel_indexes, mel, 6); decode_mels_scalar(mel, mel_indexes, 6); #ifdef DUMP dump_mel(mel, order); #endif for(i=0; i<LPC_ORD; i++) { f_ = 700.0*( pow(10.0, (float)mel[i]/2595.0) - 1.0); lsps_[i] = f_*(PI/4000.0); } lsp_to_lpc(lsps_, ak, order); } if (scalar_quant_Wo_e) { e = decode_energy(encode_energy(e, E_BITS), E_BITS); model.Wo = decode_Wo(encode_Wo(model.Wo, WO_BITS), WO_BITS); model.L = PI/model.Wo; /* if we quantise Wo re-compute L */ } if (vector_quant_Wo_e) { /* JVM's experimental joint Wo & LPC energy quantiser */ quantise_WoE(&model, &e, Woe_); } } /*------------------------------------------------------------*\ Synthesise and optional decimation to 20 or 40ms frame rate \*------------------------------------------------------------*/ /* if decimate == 2, we interpolate frame n from frame n-1 and n+1 if decimate == 4, we interpolate frames n, n+1, n+2, from frames n-1 and n+3 This is meant to give identical results to the implementations of various modes in codec2.c */ /* delay line to keep frame by frame voicing decisions */ for(i=0; i<decimate-1; i++) model_dec[i] = model_dec[i+1]; model_dec[decimate-1] = model; if ((frames % decimate) == 0) { for(i=0; i<order; i++) lsps_dec[decimate-1][i] = lsps_[i]; e_dec[decimate-1] = e; model_dec[decimate-1] = model; /* interpolate the model parameters */ weight_inc = 1.0/decimate; for(i=0, weight=weight_inc; i<decimate-1; i++, weight += weight_inc) { //model_dec[i].voiced = model_dec[decimate-1].voiced; interpolate_lsp_ver2(&lsps_dec[i][0], prev_lsps_dec, &lsps_dec[decimate-1][0], weight, order); interp_Wo2(&model_dec[i], &prev_model_dec, &model_dec[decimate-1], weight); e_dec[i] = interp_energy2(prev_e_dec, e_dec[decimate-1],weight); } /* then recover spectral amplitudes and synthesise */ for(i=0; i<decimate; i++) { if (lpc_model) { lsp_to_lpc(&lsps_dec[i][0], &ak_dec[i][0], order); aks_to_M2(fft_fwd_cfg, &ak_dec[i][0], order, &model_dec[i], e_dec[i], &snr, 0, simlpcpf, lpcpf, 1, LPCPF_BETA, LPCPF_GAMMA, Aw); apply_lpc_correction(&model_dec[i]); #ifdef DUMP dump_lsp_(&lsps_dec[i][0]); dump_ak_(&ak_dec[i][0], order); sum_snr += snr; dump_quantised_model(&model_dec[i]); #endif } if (phase0) phase_synth_zero_order(fft_fwd_cfg, &model_dec[i], ex_phase, Aw); synth_one_frame(fft_inv_cfg, buf, &model_dec[i], Sn_, Pn, prede, &de_mem, gain); if (fout != NULL) fwrite(buf,sizeof(short),N,fout); } /* for(i=0; i<decimate; i++) { printf("%d Wo: %f L: %d v: %d\n", frames, model_dec[i].Wo, model_dec[i].L, model_dec[i].voiced); } if (frames == 4*50) exit(0); */ /* update memories for next frame ----------------------------*/ prev_model_dec = model_dec[decimate-1]; prev_e_dec = e_dec[decimate-1]; for(i=0; i<LPC_ORD; i++) prev_lsps_dec[i] = lsps_dec[decimate-1][i]; } } /*----------------------------------------------------------------*\ End Main Loop \*----------------------------------------------------------------*/ fclose(fin); if (fout != NULL) fclose(fout); if (lpc_model) printf("SNR av = %5.2f dB\n", sum_snr/frames); if (phaseexp) phase_experiment_destroy(pexp); if (ampexp) amp_experiment_destroy(aexp); #ifdef DUMP if (dump) dump_off(); #endif if (hand_voicing) fclose(fvoicing); nlp_destroy(nlp_states); return 0; }
void fft_3d(FFT_DATA *in, FFT_DATA *out, int flag, struct fft_plan_3d *plan) { int i,total,length,offset,num; FFT_SCALAR norm, *out_ptr; FFT_DATA *data,*copy; // system specific constants #if defined(FFT_SCSL) int isys = 0; FFT_PREC scalef = 1.0; #elif defined(FFT_DEC) char c = 'C'; char f = 'F'; char b = 'B'; int one = 1; #elif defined(FFT_T3E) int isys = 0; double scalef = 1.0; #elif defined(FFT_ACML) int info; #elif defined(FFT_FFTW3) FFTW_API(plan) theplan; #else // nothing to do for other FFTs. #endif // pre-remap to prepare for 1st FFTs if needed // copy = loc for remap result if (plan->pre_plan) { if (plan->pre_target == 0) copy = out; else copy = plan->copy; remap_3d((FFT_SCALAR *) in, (FFT_SCALAR *) copy, (FFT_SCALAR *) plan->scratch, plan->pre_plan); data = copy; } else data = in; // 1d FFTs along fast axis total = plan->total1; length = plan->length1; #if defined(FFT_SGI) for (offset = 0; offset < total; offset += length) FFT_1D(flag,length,&data[offset],1,plan->coeff1); #elif defined(FFT_SCSL) for (offset = 0; offset < total; offset += length) FFT_1D(flag,length,scalef,&data[offset],&data[offset],plan->coeff1, plan->work1,&isys); #elif defined(FFT_ACML) num=total/length; FFT_1D(&flag,&num,&length,data,plan->coeff1,&info); #elif defined(FFT_INTEL) for (offset = 0; offset < total; offset += length) FFT_1D(&data[offset],&length,&flag,plan->coeff1); #elif defined(FFT_MKL) if (flag == -1) DftiComputeForward(plan->handle_fast,data); else DftiComputeBackward(plan->handle_fast,data); #elif defined(FFT_DEC) if (flag == -1) for (offset = 0; offset < total; offset += length) FFT_1D(&c,&c,&f,&data[offset],&data[offset],&length,&one); else for (offset = 0; offset < total; offset += length) FFT_1D(&c,&c,&b,&data[offset],&data[offset],&length,&one); #elif defined(FFT_T3E) for (offset = 0; offset < total; offset += length) FFT_1D(&flag,&length,&scalef,&data[offset],&data[offset],plan->coeff1, plan->work1,&isys); #elif defined(FFT_FFTW2) if (flag == -1) fftw(plan->plan_fast_forward,total/length,data,1,length,NULL,0,0); else fftw(plan->plan_fast_backward,total/length,data,1,length,NULL,0,0); #elif defined(FFT_FFTW3) if (flag == -1) theplan=plan->plan_fast_forward; else theplan=plan->plan_fast_backward; FFTW_API(execute_dft)(theplan,data,data); #else if (flag == -1) for (offset = 0; offset < total; offset += length) kiss_fft(plan->cfg_fast_forward,&data[offset],&data[offset]); else for (offset = 0; offset < total; offset += length) kiss_fft(plan->cfg_fast_backward,&data[offset],&data[offset]); #endif // 1st mid-remap to prepare for 2nd FFTs // copy = loc for remap result if (plan->mid1_target == 0) copy = out; else copy = plan->copy; remap_3d((FFT_SCALAR *) data, (FFT_SCALAR *) copy, (FFT_SCALAR *) plan->scratch, plan->mid1_plan); data = copy; // 1d FFTs along mid axis total = plan->total2; length = plan->length2; #if defined(FFT_SGI) for (offset = 0; offset < total; offset += length) FFT_1D(flag,length,&data[offset],1,plan->coeff2); #elif defined(FFT_SCSL) for (offset = 0; offset < total; offset += length) FFT_1D(flag,length,scalef,&data[offset],&data[offset],plan->coeff2, plan->work2,&isys); #elif defined(FFT_ACML) num=total/length; FFT_1D(&flag,&num,&length,data,plan->coeff2,&info); #elif defined(FFT_INTEL) for (offset = 0; offset < total; offset += length) FFT_1D(&data[offset],&length,&flag,plan->coeff2); #elif defined(FFT_MKL) if (flag == -1) DftiComputeForward(plan->handle_mid,data); else DftiComputeBackward(plan->handle_mid,data); #elif defined(FFT_DEC) if (flag == -1) for (offset = 0; offset < total; offset += length) FFT_1D(&c,&c,&f,&data[offset],&data[offset],&length,&one); else for (offset = 0; offset < total; offset += length) FFT_1D(&c,&c,&b,&data[offset],&data[offset],&length,&one); #elif defined(FFT_T3E) for (offset = 0; offset < total; offset += length) FFT_1D(&flag,&length,&scalef,&data[offset],&data[offset],plan->coeff2, plan->work2,&isys); #elif defined(FFT_FFTW2) if (flag == -1) fftw(plan->plan_mid_forward,total/length,data,1,length,NULL,0,0); else fftw(plan->plan_mid_backward,total/length,data,1,length,NULL,0,0); #elif defined(FFT_FFTW3) if (flag == -1) theplan=plan->plan_mid_forward; else theplan=plan->plan_mid_backward; FFTW_API(execute_dft)(theplan,data,data); #else if (flag == -1) for (offset = 0; offset < total; offset += length) kiss_fft(plan->cfg_mid_forward,&data[offset],&data[offset]); else for (offset = 0; offset < total; offset += length) kiss_fft(plan->cfg_mid_backward,&data[offset],&data[offset]); #endif // 2nd mid-remap to prepare for 3rd FFTs // copy = loc for remap result if (plan->mid2_target == 0) copy = out; else copy = plan->copy; remap_3d((FFT_SCALAR *) data, (FFT_SCALAR *) copy, (FFT_SCALAR *) plan->scratch, plan->mid2_plan); data = copy; // 1d FFTs along slow axis total = plan->total3; length = plan->length3; #if defined(FFT_SGI) for (offset = 0; offset < total; offset += length) FFT_1D(flag,length,&data[offset],1,plan->coeff3); #elif defined(FFT_SCSL) for (offset = 0; offset < total; offset += length) FFT_1D(flag,length,scalef,&data[offset],&data[offset],plan->coeff3, plan->work3,&isys); #elif defined(FFT_ACML) num=total/length; FFT_1D(&flag,&num,&length,data,plan->coeff3,&info); #elif defined(FFT_INTEL) for (offset = 0; offset < total; offset += length) FFT_1D(&data[offset],&length,&flag,plan->coeff3); #elif defined(FFT_MKL) if (flag == -1) DftiComputeForward(plan->handle_slow,data); else DftiComputeBackward(plan->handle_slow,data); #elif defined(FFT_DEC) if (flag == -1) for (offset = 0; offset < total; offset += length) FFT_1D(&c,&c,&f,&data[offset],&data[offset],&length,&one); else for (offset = 0; offset < total; offset += length) FFT_1D(&c,&c,&b,&data[offset],&data[offset],&length,&one); #elif defined(FFT_T3E) for (offset = 0; offset < total; offset += length) FFT_1D(&flag,&length,&scalef,&data[offset],&data[offset],plan->coeff3, plan->work3,&isys); #elif defined(FFT_FFTW2) if (flag == -1) fftw(plan->plan_slow_forward,total/length,data,1,length,NULL,0,0); else fftw(plan->plan_slow_backward,total/length,data,1,length,NULL,0,0); #elif defined(FFT_FFTW3) if (flag == -1) theplan=plan->plan_slow_forward; else theplan=plan->plan_slow_backward; FFTW_API(execute_dft)(theplan,data,data); #else if (flag == -1) for (offset = 0; offset < total; offset += length) kiss_fft(plan->cfg_slow_forward,&data[offset],&data[offset]); else for (offset = 0; offset < total; offset += length) kiss_fft(plan->cfg_slow_backward,&data[offset],&data[offset]); #endif // post-remap to put data in output format if needed // destination is always out if (plan->post_plan) remap_3d((FFT_SCALAR *) data, (FFT_SCALAR *) out, (FFT_SCALAR *) plan->scratch, plan->post_plan); // scaling if required #if !defined(FFT_T3E) && !defined(FFT_ACML) if (flag == 1 && plan->scaled) { norm = plan->norm; num = plan->normnum; out_ptr = (FFT_SCALAR *)out; for (i = 0; i < num; i++) { #if defined(FFT_FFTW3) *(out_ptr++) *= norm; *(out_ptr++) *= norm; #elif defined(FFT_MKL) out[i] *= norm; #else out[i].re *= norm; out[i].im *= norm; #endif } } #endif #ifdef FFT_T3E if (flag == 1 && plan->scaled) { norm = plan->norm; num = plan->normnum; for (i = 0; i < num; i++) out[i] *= (norm,norm); } #endif #ifdef FFT_ACML norm = plan->norm; num = plan->normnum; for (i = 0; i < num; i++) { out[i].re *= norm; out[i].im *= norm; } #endif }