2018-01-29 15:14:50 +00:00
|
|
|
// fft.cpp
|
|
|
|
//
|
|
|
|
// Author: J.A. de Jong -ASCEE
|
|
|
|
//
|
|
|
|
// Description:
|
|
|
|
//
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#define TRACERPLUS (-5)
|
2018-02-06 11:01:27 +00:00
|
|
|
#include "ascee_tracer.h"
|
2018-01-29 15:14:50 +00:00
|
|
|
#include "fft.h"
|
|
|
|
#include "types.h"
|
|
|
|
#include "fftpack.h"
|
|
|
|
|
|
|
|
typedef struct Fft_s {
|
|
|
|
us nfft;
|
2018-02-09 10:56:49 +00:00
|
|
|
vd fft_work;
|
2018-02-12 18:32:23 +00:00
|
|
|
vd fft_result; /**< Temporary storage for the FFT
|
|
|
|
* result */
|
2018-01-29 15:14:50 +00:00
|
|
|
} Fft;
|
|
|
|
|
2018-02-10 20:14:17 +00:00
|
|
|
Fft* Fft_alloc(const us nfft) {
|
2018-01-29 15:14:50 +00:00
|
|
|
fsTRACE(15);
|
|
|
|
|
|
|
|
Fft* fft = a_malloc(sizeof(Fft));
|
|
|
|
if(fft==NULL) {
|
|
|
|
WARN("Fft allocation failed");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
fft->nfft = nfft;
|
|
|
|
|
2018-02-09 10:56:49 +00:00
|
|
|
/* Initialize foreign fft lib */
|
|
|
|
fft->fft_work = vd_alloc(2*nfft+15);
|
2018-02-12 18:32:23 +00:00
|
|
|
fft->fft_result = vd_alloc(nfft);
|
|
|
|
|
2018-02-12 19:44:07 +00:00
|
|
|
npy_rffti(nfft,getvdval(&fft->fft_work,0));
|
2018-02-09 10:56:49 +00:00
|
|
|
check_overflow_vx(fft->fft_work);
|
2018-01-29 15:14:50 +00:00
|
|
|
|
2018-02-09 10:56:49 +00:00
|
|
|
/* print_vd(&fft->fft_work); */
|
|
|
|
|
2018-01-29 15:14:50 +00:00
|
|
|
feTRACE(15);
|
|
|
|
return fft;
|
|
|
|
}
|
|
|
|
void Fft_free(Fft* fft) {
|
|
|
|
fsTRACE(15);
|
2018-02-09 10:56:49 +00:00
|
|
|
dbgassert(fft,NULLPTRDEREF);
|
|
|
|
vd_free(&fft->fft_work);
|
2018-02-12 18:32:23 +00:00
|
|
|
vd_free(&fft->fft_result);
|
2018-01-29 15:14:50 +00:00
|
|
|
a_free(fft);
|
|
|
|
feTRACE(15);
|
|
|
|
}
|
|
|
|
us Fft_nfft(const Fft* fft) {return fft->nfft;}
|
2018-02-10 20:14:17 +00:00
|
|
|
void Fft_fft_single(const Fft* fft,const vd* timedata,vc* result) {
|
2018-02-09 10:56:49 +00:00
|
|
|
|
2018-02-10 20:14:17 +00:00
|
|
|
fsTRACE(15);
|
2018-02-09 10:56:49 +00:00
|
|
|
dbgassert(fft && timedata && result,NULLPTRDEREF);
|
|
|
|
|
|
|
|
const us nfft = fft->nfft;
|
2018-02-10 20:14:17 +00:00
|
|
|
dbgassert(timedata->size == nfft,
|
|
|
|
"Invalid size for time data rows."
|
|
|
|
" Should be equal to nfft");
|
2018-01-29 15:14:50 +00:00
|
|
|
|
2018-02-10 20:14:17 +00:00
|
|
|
dbgassert(result->size == (nfft/2+1),"Invalid number of rows in"
|
|
|
|
" result array");
|
2018-02-09 10:56:49 +00:00
|
|
|
|
2018-02-12 18:32:23 +00:00
|
|
|
/* Obtain fft_result */
|
|
|
|
vd fft_result = fft->fft_result;
|
2018-02-09 10:56:49 +00:00
|
|
|
|
2018-02-12 18:32:23 +00:00
|
|
|
/* Copy timedata, as it will be overwritten in the fft pass. */
|
2018-02-10 20:14:17 +00:00
|
|
|
vd_copy(&fft_result,timedata);
|
2018-02-09 10:56:49 +00:00
|
|
|
|
2018-02-10 20:14:17 +00:00
|
|
|
/* Perform fft */
|
2018-02-12 19:44:07 +00:00
|
|
|
npy_rfftf(nfft,getvdval(&fft_result,0),
|
|
|
|
getvdval(&fft->fft_work,0));
|
2018-02-09 10:56:49 +00:00
|
|
|
|
2018-02-10 20:14:17 +00:00
|
|
|
/* Fftpack stores the data a bit strange, the resulting array
|
|
|
|
* has the DC value at 0,the first cosine at 1, the first sine
|
|
|
|
* at 2 etc. This needs to be shifted properly in the
|
|
|
|
* resulting matrix, as for the complex data, the imaginary
|
|
|
|
* part of the DC component equals zero. */
|
2018-02-09 10:56:49 +00:00
|
|
|
|
2018-02-10 20:14:17 +00:00
|
|
|
*getvcval(result,0) = *getvdval(&fft_result,0);
|
2018-02-09 10:56:49 +00:00
|
|
|
|
2018-02-10 20:14:17 +00:00
|
|
|
memcpy((void*) getvcval(result,1),
|
|
|
|
(void*) getvdval(&fft_result,1),
|
|
|
|
(nfft-1)*sizeof(d));
|
2018-02-09 10:56:49 +00:00
|
|
|
|
2018-02-10 20:14:17 +00:00
|
|
|
/* Set imaginary part of Nyquist frequency to zero */
|
|
|
|
((d*) getvcval(result,nfft/2))[1] = 0;
|
2018-01-29 15:14:50 +00:00
|
|
|
|
2018-02-10 20:14:17 +00:00
|
|
|
check_overflow_vx(fft_result);
|
|
|
|
check_overflow_vx(fft->fft_work);
|
|
|
|
feTRACE(15);
|
|
|
|
|
|
|
|
}
|
|
|
|
void Fft_fft(const Fft* fft,const dmat* timedata,cmat* result) {
|
|
|
|
fsTRACE(15);
|
|
|
|
|
|
|
|
dbgassert(fft && timedata && result,NULLPTRDEREF);
|
|
|
|
|
|
|
|
const us nchannels = timedata->n_cols;
|
|
|
|
dbgassert(timedata->n_cols == result->n_cols,
|
|
|
|
"Number of columns in timedata and result"
|
|
|
|
" should be equal.");
|
|
|
|
|
|
|
|
for(us col=0;col<nchannels;col++) {
|
|
|
|
|
|
|
|
vd timedata_col = dmat_column((dmat*) timedata,col);
|
|
|
|
vc result_col = cmat_column(result,col);
|
|
|
|
|
|
|
|
Fft_fft_single(fft,&timedata_col,&result_col);
|
|
|
|
|
|
|
|
vd_free(&timedata_col);
|
|
|
|
vc_free(&result_col);
|
|
|
|
}
|
|
|
|
check_overflow_xmat(*timedata);
|
|
|
|
check_overflow_xmat(*result);
|
|
|
|
|
2018-01-29 15:14:50 +00:00
|
|
|
feTRACE(15);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|