OfdmGenerator::~OfdmGenerator() { PDEBUG("OfdmGenerator::~OfdmGenerator() @ %p\n", this); #if USE_FFTW if (myFftIn) { fftwf_free(myFftIn); } if (myFftOut) { fftwf_free(myFftOut); } if (myFftPlan) { fftwf_destroy_plan(myFftPlan); } #else if (myFftPlan != NULL) { kiss_fft_free(myFftPlan); } if (myFftBuffer != NULL) { free(myFftBuffer); } kiss_fft_cleanup(); #endif }
void Close() { mal_device_stop( &captureDevice ); mal_device_uninit( &captureDevice ); mal_context_uninit( &context ); kiss_fft_free( fftcfg ); }
/* * * User-callable function to allocate all necessary storage space for the fft. * * The return value is a contiguous block of memory, allocated with malloc. As such, * It can be freed with free(), rather than a kiss_fft-specific function. * */ kiss_fft_state *kiss_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base) { kiss_fft_state *st=NULL; size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/ if ( lenmem==NULL ) { st = ( kiss_fft_state*)KISS_FFT_MALLOC( memneeded ); }else{ if (mem != NULL && *lenmem >= memneeded) st = (kiss_fft_state*)mem; *lenmem = memneeded; } if (st) { celt_int16 *bitrev; kiss_twiddle_cpx *twiddles; st->nfft=nfft; #ifndef FIXED_POINT st->scale = 1./nfft; #endif if (base != NULL) { st->twiddles = base->twiddles; st->shift = 0; while (nfft<<st->shift != base->nfft && st->shift < 32) st->shift++; /* FIXME: Report error and do proper cleanup */ if (st->shift>=32) return NULL; } else { st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft); compute_twiddles(twiddles, nfft); st->shift = -1; } if (!kf_factor(nfft,st->factors)) { kiss_fft_free(st); return NULL; } /* bitrev */ st->bitrev = bitrev = (celt_int16*)KISS_FFT_MALLOC(sizeof(celt_int16)*nfft); compute_bitrev_table(0, bitrev, 1,1, st->factors,st); } return st; }
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 }
/* real-to-complex transform in 1 dimension */ int tcl_rfft_1d(ClientData nodata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *result, **tdata; const char *name; kiss_fft_scalar *timed; kiss_fft_cpx *freqd; kiss_fftr_cfg work; int dir, ndat, k; /* thread safety */ Tcl_MutexLock(&myFftMutex); /* set defaults: */ dir = FFT_FORWARD; ndat = -1; /* Parse arguments: * * usage: r2cfft_1d <data> * or: c2rfft_1d <data> * * r2cfftf_1d : is the 1d real-to-complex forward transform. * c2rfftb_1d : is the 1d complex-to-real 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,"r2cfft_1d") == 0) { dir = FFT_FORWARD; } else if (strcmp(name,"c2rfft_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 */ 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; } /* no effect for zero or one element */ if ((ndat == 0) || (ndat == 1)) { Tcl_DecrRefCount(objv[1]); Tcl_SetObjResult(interp, objv[1]); Tcl_MutexUnlock(&myFftMutex); return TCL_OK; } /* we need an even number of data points for the forward transform */ if (ndat & 1) { if (dir == FFT_FORWARD) { Tcl_AppendResult(interp, name, " needs an even number of data points.", NULL); Tcl_DecrRefCount(objv[1]); Tcl_MutexUnlock(&myFftMutex); return TCL_ERROR; } } check_thread_count(interp,"fftcmds"); /* size of data arrays for backward transform */ if (dir == FFT_BACKWARD) ndat = (ndat-1)*2; /* get dynamic storage for passing data to the lowlevel code. */ timed = (void *)Tcl_Alloc(ndat*sizeof(kiss_fft_scalar)); freqd = (void *)Tcl_Alloc((ndat/2+1)*sizeof(kiss_fft_cpx)); work = kiss_fftr_alloc(ndat, dir, NULL, NULL); /* parse/copy data list */ if (dir == FFT_FORWARD) { for (k=0; k<ndat; ++k) { if (Tcl_GetDoubleFromObj(interp, tdata[k], timed + k) != TCL_OK) { Tcl_AppendResult(interp, name, ": illegal data array.", NULL); Tcl_DecrRefCount(objv[1]); Tcl_MutexUnlock(&myFftMutex); return TCL_ERROR; } } } else { for (k=0; k<(ndat/2)+1; ++k) { if (read_list_cpx(interp, tdata[k], freqd + 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 */ if (dir == FFT_FORWARD) { kiss_fftr(work, timed, freqd); } else { kiss_fftri(work, freqd, timed); } /* prepare results */ result = Tcl_NewListObj(0, NULL); if (dir == FFT_FORWARD) { for (k=0; k<(ndat/2)+1; ++k) { make_list_cpx(interp, result, freqd + k); } } else { for (k=0; k<ndat; ++k) { Tcl_ListObjAppendElement(interp, result, Tcl_NewDoubleObj(timed[k])); } } Tcl_SetObjResult(interp, result); /* free intermediate storage */ Tcl_Free((char *)timed); Tcl_Free((char *)freqd); kiss_fft_free(work); kiss_fft_cleanup(); Tcl_MutexUnlock(&myFftMutex); return TCL_OK; }
/* generic complex <N>d-transform. */ int tcl_cfft_nd(ClientData nodata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Tcl_Obj *result, **tdata[FFT_MAX_DIM]; const char *name; kiss_fft_cpx *input; kiss_fft_cpx *output; kiss_fftnd_cfg work; int dir, ndim, alldim, ndat[FFT_MAX_DIM]; int i; Tcl_MutexLock(&myFftMutex); /* set defaults: */ dir = FFT_FORWARD; ndim = -1; /* Parse arguments: * * usage: cfftf_nd <data> * or: cfftb_nd <data> * * cfftf_nd : is the Nd complex forward transform. * cfftb_nd : is the Nd 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_2d") == 0) { dir = FFT_FORWARD; ndim = 2; } else if (strcmp(name,"cfftb_2d") == 0) { dir = FFT_BACKWARD; ndim = 2; } else if (strcmp(name,"cfftf_3d") == 0) { dir = FFT_FORWARD; ndim = 3; } else if (strcmp(name,"cfftb_3d") == 0) { dir = FFT_BACKWARD; ndim = 3; } else if (strcmp(name,"cfftf_4d") == 0) { dir = FFT_FORWARD; ndim = 4; } else if (strcmp(name,"cfftb_4d") == 0) { dir = FFT_BACKWARD; ndim = 4; } 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; } /* mark data as busy and check */ Tcl_IncrRefCount(objv[1]); if (Tcl_ListObjGetElements(interp, objv[1], &(ndat[0]), &(tdata[0])) != TCL_OK) { Tcl_DecrRefCount(objv[1]); Tcl_MutexUnlock(&myFftMutex); return TCL_ERROR; } if ((ndat[0] < 0) || (ndim > FFT_MAX_DIM)) { /* this should not happen, but... */ Tcl_AppendResult(interp, name, ": illegal or unsupported data array.", NULL); Tcl_DecrRefCount(objv[1]); Tcl_MutexUnlock(&myFftMutex); return TCL_ERROR; } if (ndat[0] == 0) { /* no effect for empty array */ Tcl_DecrRefCount(objv[1]); Tcl_SetObjResult(interp, objv[1]); Tcl_MutexUnlock(&myFftMutex); return TCL_OK; } check_thread_count(interp,"fftcmds"); /* determine size of each dimension for storage size and parsing/checking. */ alldim=ndat[0]; for (i=1; i<ndim; ++i) { if (Tcl_ListObjGetElements(interp, tdata[i-1][0], &(ndat[i]), &(tdata[i])) != TCL_OK) { Tcl_DecrRefCount(objv[1]); Tcl_MutexUnlock(&myFftMutex); return TCL_ERROR; } alldim *= ndat[i]; } input = (void *)Tcl_Alloc(alldim*sizeof(kiss_fft_cpx)); output = (void *)Tcl_Alloc(alldim*sizeof(kiss_fft_cpx)); work = kiss_fftnd_alloc(ndat, ndim, dir, NULL, NULL); /* parse/copy data list through recursive function and release original data. */ alldim=0; for (i=0; i<ndat[0]; ++i) { if (read_list_list(interp, tdata[0][i], 1, ndim, ndat, input, &alldim) != 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_fftnd(work, input, output); /* build result list(s) recursively */ result = Tcl_NewListObj(0, NULL); alldim = 0; for (i=0; i<ndat[0]; ++i) { make_list_list(interp, result, 1, ndim, ndat, output, &alldim); } 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; }
/* 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; }