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;
   }

}
Esempio n. 3
0
/* 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;
}
Esempio n. 4
0
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;
    }
}