void PartitionedIR_freqDomain::setNewIRF(const IRF* irf, unsigned int blockSize) { //Delete if created before if(real_.data_) { delete [] real_; delete [] imaginary_; } //. //Setting numOfChannels_ = irf->numOfChannels_; partSize_ = 2 * blockSize; numOfPartsPerChannel_ = ceil((float_type)irf->N_ / (float_type)blockSize); channelLength_ = numOfPartsPerChannel_ * partSize_; unsigned int dataLength = numOfChannels_ * channelLength_; real_ = new float_type [dataLength]; imaginary_ = new float_type [dataLength]; //. //FFT Plan fftwf_iodim dim = {(int) (partSize_),1,1}; fftwf_iodim dim2= {(int) (numOfPartsPerChannel_ * numOfChannels_), (int) (partSize_), (int) (partSize_) }; //--- fftwf_plan fftPlan = fftwf_plan_guru_split_dft(1, &dim, 1, &dim2, real_.data_, imaginary_.data_, real_.data_, imaginary_.data_, FFTW_ESTIMATE); //. //Init Real and Imaginary part (each filter part has half samples from ir and half 0) //Real for(unsigned int channNum = 0; channNum < numOfChannels_; ++channNum) { unsigned int partNum; //parts 0,1... numOfPartsPerChannel_-2 for(partNum = 0; partNum < numOfPartsPerChannel_ - 1; ++partNum) { memcpy (real_[channNum] + partNum*/*PART_SIZE*/partSize_, irf->h_[channNum] + partNum*/*BLOCK_SIZE*/blockSize, sizeof(float_type) * blockSize ); std::fill_n (real_[channNum] + partNum*partSize_ + blockSize, blockSize, 0); } //. //part numOfPartsPerChannel_-1 (last) unsigned int numOfSamplesFromIrInLastPart = (irf->N_%blockSize); memcpy (real_[channNum] + partNum*partSize_, irf->h_[channNum] + partNum*blockSize, sizeof(float_type) * numOfSamplesFromIrInLastPart ); std::fill_n (real_[channNum] + partNum*partSize_ + numOfSamplesFromIrInLastPart, partSize_ - numOfSamplesFromIrInLastPart, 0); //. } //. //Imaginary for(unsigned int sampleNum = 0; sampleNum < dataLength; ++sampleNum) imaginary_.data_[sampleNum] = 0; //. //. fftwf_execute(fftPlan); fftwf_destroy_plan(fftPlan); }
// Calling convention: // comp_filterbank(f,g,a); void mexFunction( int UNUSED(nlhs), mxArray *plhs[], int UNUSED(nrhs), const mxArray *prhs[] ) { static int atExitRegistered = 0; if(!atExitRegistered) { atExitRegistered = 1; mexAtExit(filterbankAtExit); } const mxArray* mxf = prhs[0]; const mxArray* mxg = prhs[1]; const mxArray* mxa = prhs[2]; // input data length const mwSize L = mxGetM(mxf); const mwSize W = mxGetN(mxf); // filter number const mwSize M = mxGetNumberOfElements(mxg); // a col count mwSize acols = mxGetN(mxa); // pointer to a double *a = (double*) mxGetData(mxa); if (acols > 1) { int isOnes = 1; for (mwIndex m = 0; m < M; m++) { isOnes = isOnes && a[M + m] == 1; } if (isOnes) { acols = 1; } } // Cell output plhs[0] = mxCreateCellMatrix(M, 1); // Stuff for sorting the filters mwSize tdCount = 0; mwSize fftCount = 0; mwSize fftblCount = 0; mwIndex tdArgsIdx[M]; mwIndex fftArgsIdx[M]; mwIndex fftblArgsIdx[M]; // WALK the filters to determine what has to be done for (mwIndex m = 0; m < M; m++) { mxArray * gEl = mxGetCell(mxg, m); if (mxGetField(gEl, 0, "h") != NULL) { tdArgsIdx[tdCount++] = m; continue; } if (mxGetField(gEl, 0, "H") != NULL) { if (acols == 1 && L == mxGetNumberOfElements(mxGetField(gEl, 0, "H"))) { fftArgsIdx[fftCount++] = m; continue; } else { fftblArgsIdx[fftblCount++] = m; continue; } } } if (tdCount > 0) { /* Here, we have to reformat the inputs and pick up results to comply with: c=comp_filterbank_td(f,g,a,offset,ext); BEWARE OF THE AUTOMATIC DEALLOCATION!! by the Matlab engine. Arrays can be very easily freed twice causing segfaults. This happends particulary when using mxCreateCell* which stores pointers to other mxArray structs. Setting all such pointers to NULL after they are used seems to solve it. */ mxArray* plhs_td[1]; mxArray* prhs_td[5]; prhs_td[0] = (mxArray*) mxf; prhs_td[1] = mxCreateCellMatrix(tdCount, 1); prhs_td[2] = mxCreateDoubleMatrix(tdCount, 1, mxREAL); double* aPtr = mxGetData(prhs_td[2]); prhs_td[3] = mxCreateDoubleMatrix(tdCount, 1, mxREAL); double* offsetPtr = mxGetData(prhs_td[3]); prhs_td[4] = mxCreateString("per"); for (mwIndex m = 0; m < tdCount; m++) { mxArray * gEl = mxGetCell(mxg, tdArgsIdx[m]); mxSetCell(prhs_td[1], m, mxGetField(gEl, 0, "h")); // This has overhead //mxSetCell((mxArray*)prhs_td[1],m,mxDuplicateArray(mxGetField(gEl,0,"h"))); aPtr[m] = a[tdArgsIdx[m]]; offsetPtr[m] = mxGetScalar(mxGetField(gEl, 0, "offset")); } // Finally call it! // comp_filterbank_td(1,plhs_td,5, prhs_td); // This has overhead: mexCallMATLAB(1, plhs_td, 5, prhs_td, "comp_filterbank_td"); // Copy pointers to a proper index in the output + unset all duplicate cell elements for (mwIndex m = 0; m < tdCount; m++) { mxSetCell(plhs[0], tdArgsIdx[m], mxGetCell(plhs_td[0], m)); mxSetCell(plhs_td[0], m, NULL); mxSetCell(prhs_td[1], m, NULL); } mxDestroyArray(plhs_td[0]); mxDestroyArray(prhs_td[1]); mxDestroyArray(prhs_td[2]); mxDestroyArray(prhs_td[3]); mxDestroyArray(prhs_td[4]); } if (fftCount > 0 || fftblCount > 0) { // Need to do FFT of mxf mwIndex ndim = 2; const mwSize dims[] = {L, W}; if (mxF == NULL || mxGetM(mxF) != L || mxGetN(mxF) != W || mxGetClassID(mxF) != mxGetClassID(mxf)) { if (mxF != NULL) { mxDestroyArray(mxF); mxF = NULL; // printf("Should be called just once\n"); } if (mxIsDouble(mxf)) { mxF = mxCreateNumericArray(ndim, dims, mxDOUBLE_CLASS, mxCOMPLEX); fftw_iodim fftw_dims[1]; fftw_iodim howmanydims[1]; fftw_dims[0].n = L; fftw_dims[0].is = 1; fftw_dims[0].os = 1; howmanydims[0].n = W; howmanydims[0].is = L; howmanydims[0].os = L; if (p_double == NULL) p_double = (fftw_plan*) malloc(sizeof(fftw_plan)); else fftw_destroy_plan(*p_double); // FFTW_MEASURE sometimes hangs here *p_double = fftw_plan_guru_split_dft( 1, fftw_dims, 1, howmanydims, mxGetData(mxF), mxGetImagData(mxF), mxGetData(mxF), mxGetImagData(mxF), FFTW_ESTIMATE); } else if (mxIsSingle(mxf)) { mxF = mxCreateNumericArray(ndim, dims, mxSINGLE_CLASS, mxCOMPLEX); // mexPrintf("M= %i, N= %i\n",mxGetM(mxF),mxGetN(mxF)); fftwf_iodim fftw_dims[1]; fftwf_iodim howmanydims[1]; fftw_dims[0].n = L; fftw_dims[0].is = 1; fftw_dims[0].os = 1; howmanydims[0].n = W; howmanydims[0].is = L; howmanydims[0].os = L; if (p_float == NULL) p_float = (fftwf_plan*) malloc(sizeof(fftwf_plan)); else fftwf_destroy_plan(*p_float); *p_float = fftwf_plan_guru_split_dft( 1, fftw_dims, 1, howmanydims, mxGetData(mxF), mxGetImagData(mxF), mxGetData(mxF), mxGetImagData(mxF), FFTW_ESTIMATE); } } if (mxIsDouble(mxf)) { memcpy(mxGetPr(mxF), mxGetPr(mxf), L * W * sizeof(double)); memset(mxGetPi(mxF), 0, L * W * sizeof(double)); if (mxIsComplex(mxf)) memcpy(mxGetPi(mxF), mxGetPi(mxf), L * W * sizeof(double)); fftw_execute(*p_double); } else if (mxIsSingle(mxf)) { memcpy(mxGetPr(mxF), mxGetPr(mxf), L * W * sizeof(float)); memset(mxGetPi(mxF), 0, L * W * sizeof(float)); if (mxIsComplex(mxf)) memcpy(mxGetPi(mxF), mxGetPi(mxf), L * W * sizeof(float)); fftwf_execute(*p_float); } } if (fftCount > 0) { mxArray* plhs_fft[1]; mxArray* prhs_fft[3]; prhs_fft[0] = mxF; prhs_fft[1] = mxCreateCellMatrix(fftCount, 1); prhs_fft[2] = mxCreateDoubleMatrix(fftCount, 1, mxREAL); double* aPtr = mxGetData(prhs_fft[2]); for (mwIndex m = 0; m < fftCount; m++) { mxArray * gEl = mxGetCell(mxg, fftArgsIdx[m]); mxSetCell(prhs_fft[1], m, mxGetField(gEl, 0, "H")); // This has overhead //mxSetCell((mxArray*)prhs_td[1],m,mxDuplicateArray(mxGetField(gEl,0,"h"))); aPtr[m] = a[fftArgsIdx[m]]; } //comp_filterbank_fft(1,plhs_fft,3, prhs_fft); mexCallMATLAB(1, plhs_fft, 3, prhs_fft, "comp_filterbank_fft"); for (mwIndex m = 0; m < fftCount; m++) { mxSetCell(plhs[0], fftArgsIdx[m], mxGetCell(plhs_fft[0], m)); mxSetCell(plhs_fft[0], m, NULL); mxSetCell(prhs_fft[1], m, NULL); } mxDestroyArray(plhs_fft[0]); mxDestroyArray(prhs_fft[1]); mxDestroyArray(prhs_fft[2]); } if (fftblCount > 0) { mxArray* plhs_fftbl[1]; mxArray* prhs_fftbl[5]; prhs_fftbl[0] = mxF; prhs_fftbl[1] = mxCreateCellMatrix(fftblCount, 1); prhs_fftbl[2] = mxCreateDoubleMatrix(fftblCount, 1, mxREAL); prhs_fftbl[3] = mxCreateDoubleMatrix(fftblCount, 2, mxREAL); prhs_fftbl[4] = mxCreateDoubleMatrix(fftblCount, 1, mxREAL); double* foffPtr = mxGetData(prhs_fftbl[2]); double* aPtr = mxGetData(prhs_fftbl[3]); double* realonlyPtr = mxGetData(prhs_fftbl[4]); // Set all realonly flags to zero memset(realonlyPtr, 0, fftblCount * sizeof * realonlyPtr); for (mwIndex m = 0; m < fftblCount; m++) { mxArray * gEl = mxGetCell(mxg, fftblArgsIdx[m]); mxSetCell(prhs_fftbl[1], m, mxGetField(gEl, 0, "H")); foffPtr[m] = mxGetScalar(mxGetField(gEl, 0, "foff")); aPtr[m] = a[fftblArgsIdx[m]]; if (acols > 1) aPtr[m + fftblCount] = a[fftblArgsIdx[m] + M]; else aPtr[m + fftblCount] = 1; // Only if realonly is specified mxArray* mxrealonly; if ((mxrealonly = mxGetField(gEl, 0, "realonly"))) realonlyPtr[m] = mxGetScalar(mxrealonly); } // comp_filterbank_fftbl(1,plhs_fftbl,5, prhs_fftbl); mexCallMATLAB(1, plhs_fftbl, 5, prhs_fftbl, "comp_filterbank_fftbl"); for (mwIndex m = 0; m < fftblCount; m++) { mxSetCell(plhs[0], fftblArgsIdx[m], mxGetCell(plhs_fftbl[0], m)); mxSetCell(plhs_fftbl[0], m, NULL); mxSetCell(prhs_fftbl[1], m, NULL); } mxDestroyArray(plhs_fftbl[0]); mxDestroyArray(prhs_fftbl[1]); mxDestroyArray(prhs_fftbl[2]); mxDestroyArray(prhs_fftbl[3]); mxDestroyArray(prhs_fftbl[4]); } if (mxF != NULL) mexMakeArrayPersistent(mxF); if (L * W > MAXARRAYLEN && mxF != NULL) { //printf("Damn. Should not get here\n"); mxDestroyArray(mxF); mxF = NULL; } }
/* arr_plans_init(): initialize the global fftw plan array for use on * {one,two,three}-dimensional hypercomplex arrays. * * arguments: * @n1: first-dimension size of the arrays. * @n2: second-dimension size of the arrays, or zero. * @n3: third-dimension size of the arrays, or zero. */ int arr_plans_init (int n1, int n2, int n3) { /* declare variables required at any dimensionality: * @dims: transform size and stride data structure. * @vdims: vector size and stride data structure. * @ax, @bx: pointers to raw coefficient data in @a and @b. */ fftwf_iodim dims[3], vdims[6]; hx0 *ax, *bx; /* construct plans based on dimensionality. */ if (n1 > 1 && n2 > 1 && n3 > 1) { /* allocate two temporary arrays. */ arr3 *a = arr_alloc3(n1, n2, n3); arr3 *b = arr_alloc3(n1, n2, n3); if (!a || !b) return 0; /* set up the array data pointers. */ ax = (hx0*) a->x; bx = (hx0*) b->x; /* initialize the first-dimension transform size. */ dims[0].n = n1; dims[0].is = dims[0].os = 8; /* initialize the second-dimension transform size. */ dims[1].n = n2; dims[1].is = dims[1].os = 8 * n1; /* initialize the third-dimension transform size. */ dims[2].n = n3; dims[2].is = dims[2].os = 8 * n1 * n2; /* initialize the first-dimension vector size. */ vdims[0].n = n2; vdims[1].n = n3; vdims[0].is = vdims[0].os = 8 * n1; vdims[1].is = vdims[1].os = 8 * n1 * n2; /* initialize the first-dimension vector size. */ vdims[2].n = n1; vdims[3].n = n3; vdims[2].is = vdims[2].os = 8; vdims[3].is = vdims[3].os = 8 * n1 * n2; /* initialize the third-dimension vector size. */ vdims[4].n = n1; vdims[5].n = n2; vdims[4].is = vdims[4].os = 8; vdims[5].is = vdims[5].os = 8 * n1; /* allocate the plan array. */ planc = 24; planv = (fftwf_plan*) malloc(sizeof(fftwf_plan) * planc); if (!planv) return 0; /* construct a plan for dim=1 (a,b) fft. */ planv[0] = fftwf_plan_guru_split_dft( 1, dims, 2, vdims, ax + 0, ax + 1, bx + 0, bx + 1, FFTW_MEASURE); /* construct a plan for dim=1 (c,d) fft. */ planv[1] = fftwf_plan_guru_split_dft( 1, dims, 2, vdims, ax + 2, ax + 3, bx + 2, bx + 3, FFTW_MEASURE); /* construct a plan for dim=1 (e,f) fft. */ planv[2] = fftwf_plan_guru_split_dft( 1, dims, 2, vdims, ax + 4, ax + 5, bx + 4, bx + 5, FFTW_MEASURE); /* construct a plan for dim=1 (g,h) fft. */ planv[3] = fftwf_plan_guru_split_dft( 1, dims, 2, vdims, ax + 6, ax + 7, bx + 6, bx + 7, FFTW_MEASURE); /* construct a plan for dim=2 (a,c) fft. */ planv[4] = fftwf_plan_guru_split_dft( 1, dims + 1, 2, vdims + 2, bx + 0, bx + 2, bx + 0, bx + 2, FFTW_MEASURE); /* construct a plan for dim=2 (b,d) fft. */ planv[5] = fftwf_plan_guru_split_dft( 1, dims + 1, 2, vdims + 2, bx + 1, bx + 3, bx + 1, bx + 3, FFTW_MEASURE); /* construct a plan for dim=2 (e,g) fft. */ planv[6] = fftwf_plan_guru_split_dft( 1, dims + 1, 2, vdims + 2, bx + 4, bx + 6, bx + 4, bx + 6, FFTW_MEASURE); /* construct a plan for dim=2 (f,h) fft. */ planv[7] = fftwf_plan_guru_split_dft( 1, dims + 1, 2, vdims + 2, bx + 5, bx + 7, bx + 5, bx + 7, FFTW_MEASURE); /* construct a plan for dim=3 (a,e) fft. */ planv[8] = fftwf_plan_guru_split_dft( 1, dims + 2, 2, vdims + 4, bx + 0, bx + 4, bx + 0, bx + 4, FFTW_MEASURE); /* construct a plan for dim=3 (b,f) fft. */ planv[9] = fftwf_plan_guru_split_dft( 1, dims + 2, 2, vdims + 4, bx + 1, bx + 5, bx + 1, bx + 5, FFTW_MEASURE); /* construct a plan for dim=3 (c,g) fft. */ planv[10] = fftwf_plan_guru_split_dft( 1, dims + 2, 2, vdims + 4, bx + 2, bx + 6, bx + 2, bx + 6, FFTW_MEASURE); /* construct a plan for dim=3 (d,h) fft. */ planv[11] = fftwf_plan_guru_split_dft( 1, dims + 2, 2, vdims + 4, bx + 3, bx + 7, bx + 3, bx + 7, FFTW_MEASURE); /* construct a plan for dim=1 (a,b) ifft. */ planv[12] = fftwf_plan_guru_split_dft( 1, dims, 2, vdims, ax + 1, ax + 0, bx + 1, bx + 0, FFTW_MEASURE); /* construct a plan for dim=1 (c,d) ifft. */ planv[13] = fftwf_plan_guru_split_dft( 1, dims, 2, vdims, ax + 3, ax + 2, bx + 3, bx + 2, FFTW_MEASURE); /* construct a plan for dim=1 (e,f) ifft. */ planv[14] = fftwf_plan_guru_split_dft( 1, dims, 2, vdims, ax + 5, ax + 4, bx + 5, bx + 4, FFTW_MEASURE); /* construct a plan for dim=1 (g,h) ifft. */ planv[15] = fftwf_plan_guru_split_dft( 1, dims, 2, vdims, ax + 7, ax + 6, bx + 7, bx + 6, FFTW_MEASURE); /* construct a plan for dim=2 (a,c) ifft. */ planv[16] = fftwf_plan_guru_split_dft( 1, dims + 1, 2, vdims + 2, bx + 2, bx + 0, bx + 2, bx + 0, FFTW_MEASURE); /* construct a plan for dim=2 (b,d) ifft. */ planv[17] = fftwf_plan_guru_split_dft( 1, dims + 1, 2, vdims + 2, bx + 3, bx + 1, bx + 3, bx + 1, FFTW_MEASURE); /* construct a plan for dim=2 (e,g) ifft. */ planv[18] = fftwf_plan_guru_split_dft( 1, dims + 1, 2, vdims + 2, bx + 6, bx + 4, bx + 6, bx + 4, FFTW_MEASURE); /* construct a plan for dim=2 (f,h) ifft. */ planv[19] = fftwf_plan_guru_split_dft( 1, dims + 1, 2, vdims + 2, bx + 7, bx + 5, bx + 7, bx + 5, FFTW_MEASURE); /* construct a plan for dim=3 (a,e) ifft. */ planv[20] = fftwf_plan_guru_split_dft( 1, dims + 2, 2, vdims + 4, bx + 4, bx + 0, bx + 4, bx + 0, FFTW_MEASURE); /* construct a plan for dim=3 (b,f) ifft. */ planv[21] = fftwf_plan_guru_split_dft( 1, dims + 2, 2, vdims + 4, bx + 5, bx + 1, bx + 5, bx + 1, FFTW_MEASURE); /* construct a plan for dim=3 (c,g) ifft. */ planv[22] = fftwf_plan_guru_split_dft( 1, dims + 2, 2, vdims + 4, bx + 6, bx + 2, bx + 6, bx + 2, FFTW_MEASURE); /* construct a plan for dim=3 (d,h) ifft. */ planv[23] = fftwf_plan_guru_split_dft( 1, dims + 2, 2, vdims + 4, bx + 7, bx + 3, bx + 7, bx + 3, FFTW_MEASURE); /* check that the plans were successfully created. */ if (!planv[0] || !planv[1] || !planv[2] || !planv[3] || !planv[4] || !planv[5] || !planv[6] || !planv[7] || !planv[8] || !planv[9] || !planv[10] || !planv[11] || !planv[12] || !planv[13] || !planv[14] || !planv[15] || !planv[16] || !planv[17] || !planv[18] || !planv[19] || !planv[20] || !planv[21] || !planv[22] || !planv[23]) return 0; /* free the temporary arrays. */ arr_free3(a); arr_free3(b); } else if (n1 > 1 && n2 > 1) { /* allocate two temporary arrays. */ arr2 *a = arr_alloc2(n1, n2, n3); arr2 *b = arr_alloc2(n1, n2, n3); if (!a || !b) return 0; /* set up the array data pointers. */ ax = (hx0*) a->x; bx = (hx0*) b->x; /* initialize the first-dimension transform size. */ dims[0].n = n1; dims[0].is = dims[0].os = 4; /* initialize the second-dimension transform size. */ dims[1].n = n2; dims[1].is = dims[1].os = 4 * n1; /* initialize the first-dimension vector size. */ vdims[0].n = n2; vdims[0].is = vdims[0].os = 4 * n1; /* initialize the second-dimension vector size. */ vdims[1].n = n1; vdims[1].is = vdims[1].os = 4; /* allocate the plan array. */ planc = 8; planv = (fftwf_plan*) malloc(sizeof(fftwf_plan) * planc); if (!planv) return 0; /* construct a plan for dim=1 (a,b) fft. */ planv[0] = fftwf_plan_guru_split_dft( 1, dims, 1, vdims, ax + 0, ax + 1, bx + 0, bx + 1, FFTW_MEASURE); /* construct a plan for dim=1 (c,d) fft. */ planv[1] = fftwf_plan_guru_split_dft( 1, dims, 1, vdims, ax + 2, ax + 3, bx + 2, bx + 3, FFTW_MEASURE); /* construct a plan for dim=2 (a,c) fft. */ planv[2] = fftwf_plan_guru_split_dft( 1, dims + 1, 1, vdims + 1, bx + 0, bx + 2, bx + 0, bx + 2, FFTW_MEASURE); /* construct a plan for dim=2 (b,d) fft. */ planv[3] = fftwf_plan_guru_split_dft( 1, dims + 1, 1, vdims + 1, bx + 1, bx + 3, bx + 1, bx + 3, FFTW_MEASURE); /* construct a plan for dim=1 (a,b) ifft. */ planv[4] = fftwf_plan_guru_split_dft( 1, dims, 1, vdims, ax + 1, ax + 0, bx + 1, bx + 0, FFTW_MEASURE); /* construct a plan for dim=1 (c,d) ifft. */ planv[5] = fftwf_plan_guru_split_dft( 1, dims, 1, vdims, ax + 3, ax + 2, bx + 3, bx + 2, FFTW_MEASURE); /* construct a plan for dim=2 (a,c) ifft. */ planv[6] = fftwf_plan_guru_split_dft( 1, dims + 1, 1, vdims + 1, bx + 2, bx + 0, bx + 2, bx + 0, FFTW_MEASURE); /* construct a plan for dim=2 (b,d) ifft. */ planv[7] = fftwf_plan_guru_split_dft( 1, dims + 1, 1, vdims + 1, bx + 3, bx + 1, bx + 3, bx + 1, FFTW_MEASURE); /* check that the plans were successfully created. */ if (!planv[0] || !planv[1] || !planv[2] || !planv[3] || !planv[4] || !planv[5] || !planv[6] || !planv[7]) return 0; /* free the temporary arrays. */ arr_free2(a); arr_free2(b); } else if (n1 > 1) { /* allocate two temporary arrays. */ arr1 *a = arr_alloc1(n1, n2, n3); arr1 *b = arr_alloc1(n1, n2, n3); if (!a || !b) return 0; /* set up the array data pointers. */ ax = (hx0*) a->x; bx = (hx0*) b->x; /* initialize the transform size. */ dims[0].n = n1; dims[0].is = dims[0].os = 2; /* allocate the plan array. */ planc = 2; planv = (fftwf_plan*) malloc(sizeof(fftwf_plan) * planc); if (!planv) return 0; /* construct a plan for dim=1 (a,b) fft. */ planv[0] = fftwf_plan_guru_split_dft( 1, dims, 0, NULL, ax + 0, ax + 1, bx + 0, bx + 1, FFTW_MEASURE); /* construct a plan for dim=1 (a,b) ifft. */ planv[1] = fftwf_plan_guru_split_dft( 1, dims, 0, NULL, ax + 1, ax + 0, bx + 1, bx + 0, FFTW_MEASURE); /* check that the plans were successfully created. */ if (!planv[0] || !planv[1]) return 0; /* free the temporary arrays. */ arr_free1(a); arr_free1(b); } else { /* invalid dimensionality. */ return 0; } /* return success. */ return 1; }
void FFT::apply(Image im, bool transformX, bool transformY, bool transformT, bool inverse) { assert(im.channels % 2 == 0, "-fft requires an image with an even number of channels\n"); if (im.width == 1) { transformX = false; } if (im.height == 1) { transformY = false; } if (im.frames == 1) { transformT = false; } // rank 0 if (!transformX && !transformY && !transformT) { return; } vector<fftwf_iodim> loop_dims; vector<fftwf_iodim> fft_dims; // X { fftwf_iodim d = {im.width, 1, 1}; if (transformX) fft_dims.push_back(d); else loop_dims.push_back(d); } // Y { fftwf_iodim d = {im.height, im.ystride, im.ystride}; if (transformY) fft_dims.push_back(d); else loop_dims.push_back(d); } // T { fftwf_iodim d = {im.frames, im.tstride, im.tstride}; if (transformT) fft_dims.push_back(d); else loop_dims.push_back(d); } // C { fftwf_iodim d = {im.channels/2, im.cstride*2, im.cstride*2}; loop_dims.push_back(d); } // An inverse fft can be done by swapping real and imaginary parts int real_c = inverse ? 1 : 0; int imag_c = inverse ? 0 : 1; fftwf_plan plan = fftwf_plan_guru_split_dft((int)fft_dims.size(), &fft_dims[0], (int)loop_dims.size(), &loop_dims[0], &(im(0, 0, 0, real_c)), &(im(0, 0, 0, imag_c)), &(im(0, 0, 0, real_c)), &(im(0, 0, 0, imag_c)), FFTW_ESTIMATE); fftwf_execute(plan); fftwf_destroy_plan(plan); if (inverse) { float m = 1.0; if (transformX) m *= im.width; if (transformY) m *= im.height; if (transformT) m *= im.frames; im /= m; } }