Blame gst-libs/gst/fft/kiss_fft_s16.c

Packit 0652a1
/*
Packit 0652a1
Copyright (c) 2003-2004, Mark Borgerding
Packit 0652a1
Packit 0652a1
All rights reserved.
Packit 0652a1
Packit 0652a1
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Packit 0652a1
Packit 0652a1
    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Packit 0652a1
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Packit 0652a1
    * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
Packit 0652a1
Packit 0652a1
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 0652a1
*/
Packit 0652a1
#ifdef HAVE_CONFIG_H
Packit 0652a1
#include "config.h"
Packit 0652a1
#endif
Packit 0652a1
Packit 0652a1
#include "_kiss_fft_guts_s16.h"
Packit 0652a1
/* The guts header contains all the multiplication and addition macros that are defined for
Packit 0652a1
 fixed or floating point complex numbers.  It also delares the kf_ internal functions.
Packit 0652a1
 */
Packit 0652a1
Packit 0652a1
static kiss_fft_s16_cpx *scratchbuf = NULL;
Packit 0652a1
static size_t nscratchbuf = 0;
Packit 0652a1
static kiss_fft_s16_cpx *tmpbuf = NULL;
Packit 0652a1
static size_t ntmpbuf = 0;
Packit 0652a1
Packit 0652a1
#define CHECKBUF(buf,nbuf,n) \
Packit 0652a1
    do { \
Packit 0652a1
        if ( nbuf < (size_t)(n) ) {\
Packit 0652a1
            free(buf); \
Packit 0652a1
            buf = (kiss_fft_s16_cpx*)KISS_FFT_S16_MALLOC(sizeof(kiss_fft_s16_cpx)*(n)); \
Packit 0652a1
            nbuf = (size_t)(n); \
Packit 0652a1
        } \
Packit 0652a1
   }while(0)
Packit 0652a1
Packit 0652a1
Packit 0652a1
static void
Packit 0652a1
kf_bfly2 (kiss_fft_s16_cpx * Fout,
Packit 0652a1
    const size_t fstride, const kiss_fft_s16_cfg st, int m)
Packit 0652a1
{
Packit 0652a1
  kiss_fft_s16_cpx *Fout2;
Packit 0652a1
  kiss_fft_s16_cpx *tw1 = st->twiddles;
Packit 0652a1
  kiss_fft_s16_cpx t;
Packit 0652a1
Packit 0652a1
  Fout2 = Fout + m;
Packit 0652a1
  do {
Packit 0652a1
    C_FIXDIV (*Fout, 2);
Packit 0652a1
    C_FIXDIV (*Fout2, 2);
Packit 0652a1
Packit 0652a1
    C_MUL (t, *Fout2, *tw1);
Packit 0652a1
    tw1 += fstride;
Packit 0652a1
    C_SUB (*Fout2, *Fout, t);
Packit 0652a1
    C_ADDTO (*Fout, t);
Packit 0652a1
    ++Fout2;
Packit 0652a1
    ++Fout;
Packit 0652a1
  } while (--m);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
static void
Packit 0652a1
kf_bfly4 (kiss_fft_s16_cpx * Fout,
Packit 0652a1
    const size_t fstride, const kiss_fft_s16_cfg st, const size_t m)
Packit 0652a1
{
Packit 0652a1
  kiss_fft_s16_cpx *tw1, *tw2, *tw3;
Packit 0652a1
  kiss_fft_s16_cpx scratch[6];
Packit 0652a1
  size_t k = m;
Packit 0652a1
  const size_t m2 = 2 * m;
Packit 0652a1
  const size_t m3 = 3 * m;
Packit 0652a1
Packit 0652a1
  tw3 = tw2 = tw1 = st->twiddles;
Packit 0652a1
Packit 0652a1
  do {
Packit 0652a1
    C_FIXDIV (*Fout, 4);
Packit 0652a1
    C_FIXDIV (Fout[m], 4);
Packit 0652a1
    C_FIXDIV (Fout[m2], 4);
Packit 0652a1
    C_FIXDIV (Fout[m3], 4);
Packit 0652a1
Packit 0652a1
    C_MUL (scratch[0], Fout[m], *tw1);
Packit 0652a1
    C_MUL (scratch[1], Fout[m2], *tw2);
Packit 0652a1
    C_MUL (scratch[2], Fout[m3], *tw3);
Packit 0652a1
Packit 0652a1
    C_SUB (scratch[5], *Fout, scratch[1]);
Packit 0652a1
    C_ADDTO (*Fout, scratch[1]);
Packit 0652a1
    C_ADD (scratch[3], scratch[0], scratch[2]);
Packit 0652a1
    C_SUB (scratch[4], scratch[0], scratch[2]);
Packit 0652a1
    C_SUB (Fout[m2], *Fout, scratch[3]);
Packit 0652a1
    tw1 += fstride;
Packit 0652a1
    tw2 += fstride * 2;
Packit 0652a1
    tw3 += fstride * 3;
Packit 0652a1
    C_ADDTO (*Fout, scratch[3]);
Packit 0652a1
Packit 0652a1
    if (st->inverse) {
Packit 0652a1
      Fout[m].r = scratch[5].r - scratch[4].i;
Packit 0652a1
      Fout[m].i = scratch[5].i + scratch[4].r;
Packit 0652a1
      Fout[m3].r = scratch[5].r + scratch[4].i;
Packit 0652a1
      Fout[m3].i = scratch[5].i - scratch[4].r;
Packit 0652a1
    } else {
Packit 0652a1
      Fout[m].r = scratch[5].r + scratch[4].i;
Packit 0652a1
      Fout[m].i = scratch[5].i - scratch[4].r;
Packit 0652a1
      Fout[m3].r = scratch[5].r - scratch[4].i;
Packit 0652a1
      Fout[m3].i = scratch[5].i + scratch[4].r;
Packit 0652a1
    }
Packit 0652a1
    ++Fout;
Packit 0652a1
  } while (--k);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
static void
Packit 0652a1
kf_bfly3 (kiss_fft_s16_cpx * Fout,
Packit 0652a1
    const size_t fstride, const kiss_fft_s16_cfg st, size_t m)
Packit 0652a1
{
Packit 0652a1
  size_t k = m;
Packit 0652a1
  const size_t m2 = 2 * m;
Packit 0652a1
  kiss_fft_s16_cpx *tw1, *tw2;
Packit 0652a1
  kiss_fft_s16_cpx scratch[5];
Packit 0652a1
  kiss_fft_s16_cpx epi3;
Packit 0652a1
Packit 0652a1
  epi3 = st->twiddles[fstride * m];
Packit 0652a1
Packit 0652a1
  tw1 = tw2 = st->twiddles;
Packit 0652a1
Packit 0652a1
  do {
Packit 0652a1
    C_FIXDIV (*Fout, 3);
Packit 0652a1
    C_FIXDIV (Fout[m], 3);
Packit 0652a1
    C_FIXDIV (Fout[m2], 3);
Packit 0652a1
Packit 0652a1
    C_MUL (scratch[1], Fout[m], *tw1);
Packit 0652a1
    C_MUL (scratch[2], Fout[m2], *tw2);
Packit 0652a1
Packit 0652a1
    C_ADD (scratch[3], scratch[1], scratch[2]);
Packit 0652a1
    C_SUB (scratch[0], scratch[1], scratch[2]);
Packit 0652a1
    tw1 += fstride;
Packit 0652a1
    tw2 += fstride * 2;
Packit 0652a1
Packit 0652a1
    Fout[m].r = Fout->r - HALF_OF (scratch[3].r);
Packit 0652a1
    Fout[m].i = Fout->i - HALF_OF (scratch[3].i);
Packit 0652a1
Packit 0652a1
    C_MULBYSCALAR (scratch[0], epi3.i);
Packit 0652a1
Packit 0652a1
    C_ADDTO (*Fout, scratch[3]);
Packit 0652a1
Packit 0652a1
    Fout[m2].r = Fout[m].r + scratch[0].i;
Packit 0652a1
    Fout[m2].i = Fout[m].i - scratch[0].r;
Packit 0652a1
Packit 0652a1
    Fout[m].r -= scratch[0].i;
Packit 0652a1
    Fout[m].i += scratch[0].r;
Packit 0652a1
Packit 0652a1
    ++Fout;
Packit 0652a1
  } while (--k);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
static void
Packit 0652a1
kf_bfly5 (kiss_fft_s16_cpx * Fout,
Packit 0652a1
    const size_t fstride, const kiss_fft_s16_cfg st, int m)
Packit 0652a1
{
Packit 0652a1
  kiss_fft_s16_cpx *Fout0, *Fout1, *Fout2, *Fout3, *Fout4;
Packit 0652a1
  int u;
Packit 0652a1
  kiss_fft_s16_cpx scratch[13];
Packit 0652a1
  kiss_fft_s16_cpx *twiddles = st->twiddles;
Packit 0652a1
  kiss_fft_s16_cpx *tw;
Packit 0652a1
  kiss_fft_s16_cpx ya, yb;
Packit 0652a1
Packit 0652a1
  ya = twiddles[fstride * m];
Packit 0652a1
  yb = twiddles[fstride * 2 * m];
Packit 0652a1
Packit 0652a1
  Fout0 = Fout;
Packit 0652a1
  Fout1 = Fout0 + m;
Packit 0652a1
  Fout2 = Fout0 + 2 * m;
Packit 0652a1
  Fout3 = Fout0 + 3 * m;
Packit 0652a1
  Fout4 = Fout0 + 4 * m;
Packit 0652a1
Packit 0652a1
  tw = st->twiddles;
Packit 0652a1
  for (u = 0; u < m; ++u) {
Packit 0652a1
    C_FIXDIV (*Fout0, 5);
Packit 0652a1
    C_FIXDIV (*Fout1, 5);
Packit 0652a1
    C_FIXDIV (*Fout2, 5);
Packit 0652a1
    C_FIXDIV (*Fout3, 5);
Packit 0652a1
    C_FIXDIV (*Fout4, 5);
Packit 0652a1
    scratch[0] = *Fout0;
Packit 0652a1
Packit 0652a1
    C_MUL (scratch[1], *Fout1, tw[u * fstride]);
Packit 0652a1
    C_MUL (scratch[2], *Fout2, tw[2 * u * fstride]);
Packit 0652a1
    C_MUL (scratch[3], *Fout3, tw[3 * u * fstride]);
Packit 0652a1
    C_MUL (scratch[4], *Fout4, tw[4 * u * fstride]);
Packit 0652a1
Packit 0652a1
    C_ADD (scratch[7], scratch[1], scratch[4]);
Packit 0652a1
    C_SUB (scratch[10], scratch[1], scratch[4]);
Packit 0652a1
    C_ADD (scratch[8], scratch[2], scratch[3]);
Packit 0652a1
    C_SUB (scratch[9], scratch[2], scratch[3]);
Packit 0652a1
Packit 0652a1
    Fout0->r += scratch[7].r + scratch[8].r;
Packit 0652a1
    Fout0->i += scratch[7].i + scratch[8].i;
Packit 0652a1
Packit 0652a1
    scratch[5].r =
Packit 0652a1
        scratch[0].r + S_MUL (scratch[7].r, ya.r) + S_MUL (scratch[8].r, yb.r);
Packit 0652a1
    scratch[5].i =
Packit 0652a1
        scratch[0].i + S_MUL (scratch[7].i, ya.r) + S_MUL (scratch[8].i, yb.r);
Packit 0652a1
Packit 0652a1
    scratch[6].r = S_MUL (scratch[10].i, ya.i) + S_MUL (scratch[9].i, yb.i);
Packit 0652a1
    scratch[6].i = -S_MUL (scratch[10].r, ya.i) - S_MUL (scratch[9].r, yb.i);
Packit 0652a1
Packit 0652a1
    C_SUB (*Fout1, scratch[5], scratch[6]);
Packit 0652a1
    C_ADD (*Fout4, scratch[5], scratch[6]);
Packit 0652a1
Packit 0652a1
    scratch[11].r =
Packit 0652a1
        scratch[0].r + S_MUL (scratch[7].r, yb.r) + S_MUL (scratch[8].r, ya.r);
Packit 0652a1
    scratch[11].i =
Packit 0652a1
        scratch[0].i + S_MUL (scratch[7].i, yb.r) + S_MUL (scratch[8].i, ya.r);
Packit 0652a1
    scratch[12].r = -S_MUL (scratch[10].i, yb.i) + S_MUL (scratch[9].i, ya.i);
Packit 0652a1
    scratch[12].i = S_MUL (scratch[10].r, yb.i) - S_MUL (scratch[9].r, ya.i);
Packit 0652a1
Packit 0652a1
    C_ADD (*Fout2, scratch[11], scratch[12]);
Packit 0652a1
    C_SUB (*Fout3, scratch[11], scratch[12]);
Packit 0652a1
Packit 0652a1
    ++Fout0;
Packit 0652a1
    ++Fout1;
Packit 0652a1
    ++Fout2;
Packit 0652a1
    ++Fout3;
Packit 0652a1
    ++Fout4;
Packit 0652a1
  }
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/* perform the butterfly for one stage of a mixed radix FFT */
Packit 0652a1
static void
Packit 0652a1
kf_bfly_generic (kiss_fft_s16_cpx * Fout,
Packit 0652a1
    const size_t fstride, const kiss_fft_s16_cfg st, int m, int p)
Packit 0652a1
{
Packit 0652a1
  int u, k, q1, q;
Packit 0652a1
  kiss_fft_s16_cpx *twiddles = st->twiddles;
Packit 0652a1
  kiss_fft_s16_cpx t;
Packit 0652a1
  int Norig = st->nfft;
Packit 0652a1
Packit 0652a1
  CHECKBUF (scratchbuf, nscratchbuf, p);
Packit 0652a1
Packit 0652a1
  for (u = 0; u < m; ++u) {
Packit 0652a1
    k = u;
Packit 0652a1
    for (q1 = 0; q1 < p; ++q1) {
Packit 0652a1
      scratchbuf[q1] = Fout[k];
Packit 0652a1
      C_FIXDIV (scratchbuf[q1], p);
Packit 0652a1
      k += m;
Packit 0652a1
    }
Packit 0652a1
Packit 0652a1
    k = u;
Packit 0652a1
    for (q1 = 0; q1 < p; ++q1) {
Packit 0652a1
      int twidx = 0;
Packit 0652a1
Packit 0652a1
      Fout[k] = scratchbuf[0];
Packit 0652a1
      for (q = 1; q < p; ++q) {
Packit 0652a1
        twidx += fstride * k;
Packit 0652a1
        if (twidx >= Norig)
Packit 0652a1
          twidx -= Norig;
Packit 0652a1
        C_MUL (t, scratchbuf[q], twiddles[twidx]);
Packit 0652a1
        C_ADDTO (Fout[k], t);
Packit 0652a1
      }
Packit 0652a1
      k += m;
Packit 0652a1
    }
Packit 0652a1
  }
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
static void
Packit 0652a1
kf_work (kiss_fft_s16_cpx * Fout,
Packit 0652a1
    const kiss_fft_s16_cpx * f,
Packit 0652a1
    const size_t fstride,
Packit 0652a1
    int in_stride, int *factors, const kiss_fft_s16_cfg st)
Packit 0652a1
{
Packit 0652a1
  kiss_fft_s16_cpx *Fout_beg = Fout;
Packit 0652a1
  const int p = *factors++;     /* the radix  */
Packit 0652a1
  const int m = *factors++;     /* stage's fft length/p */
Packit 0652a1
  const kiss_fft_s16_cpx *Fout_end = Fout + p * m;
Packit 0652a1
Packit 0652a1
#ifdef _OPENMP
Packit 0652a1
  // use openmp extensions at the 
Packit 0652a1
  // top-level (not recursive)
Packit 0652a1
  if (fstride == 1) {
Packit 0652a1
    int k;
Packit 0652a1
Packit 0652a1
    // execute the p different work units in different threads
Packit 0652a1
#       pragma omp parallel for
Packit 0652a1
    for (k = 0; k < p; ++k)
Packit 0652a1
      kf_work (Fout + k * m, f + fstride * in_stride * k, fstride * p,
Packit 0652a1
          in_stride, factors, st);
Packit 0652a1
    // all threads have joined by this point
Packit 0652a1
Packit 0652a1
    switch (p) {
Packit 0652a1
      case 2:
Packit 0652a1
        kf_bfly2 (Fout, fstride, st, m);
Packit 0652a1
        break;
Packit 0652a1
      case 3:
Packit 0652a1
        kf_bfly3 (Fout, fstride, st, m);
Packit 0652a1
        break;
Packit 0652a1
      case 4:
Packit 0652a1
        kf_bfly4 (Fout, fstride, st, m);
Packit 0652a1
        break;
Packit 0652a1
      case 5:
Packit 0652a1
        kf_bfly5 (Fout, fstride, st, m);
Packit 0652a1
        break;
Packit 0652a1
      default:
Packit 0652a1
        kf_bfly_generic (Fout, fstride, st, m, p);
Packit 0652a1
        break;
Packit 0652a1
    }
Packit 0652a1
    return;
Packit 0652a1
  }
Packit 0652a1
#endif
Packit 0652a1
Packit 0652a1
  if (m == 1) {
Packit 0652a1
    do {
Packit 0652a1
      *Fout = *f;
Packit 0652a1
      f += fstride * in_stride;
Packit 0652a1
    } while (++Fout != Fout_end);
Packit 0652a1
  } else {
Packit 0652a1
    do {
Packit 0652a1
      // recursive call:
Packit 0652a1
      // DFT of size m*p performed by doing
Packit 0652a1
      // p instances of smaller DFTs of size m, 
Packit 0652a1
      // each one takes a decimated version of the input
Packit 0652a1
      kf_work (Fout, f, fstride * p, in_stride, factors, st);
Packit 0652a1
      f += fstride * in_stride;
Packit 0652a1
    } while ((Fout += m) != Fout_end);
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  Fout = Fout_beg;
Packit 0652a1
Packit 0652a1
  // recombine the p smaller DFTs 
Packit 0652a1
  switch (p) {
Packit 0652a1
    case 2:
Packit 0652a1
      kf_bfly2 (Fout, fstride, st, m);
Packit 0652a1
      break;
Packit 0652a1
    case 3:
Packit 0652a1
      kf_bfly3 (Fout, fstride, st, m);
Packit 0652a1
      break;
Packit 0652a1
    case 4:
Packit 0652a1
      kf_bfly4 (Fout, fstride, st, m);
Packit 0652a1
      break;
Packit 0652a1
    case 5:
Packit 0652a1
      kf_bfly5 (Fout, fstride, st, m);
Packit 0652a1
      break;
Packit 0652a1
    default:
Packit 0652a1
      kf_bfly_generic (Fout, fstride, st, m, p);
Packit 0652a1
      break;
Packit 0652a1
  }
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/*  facbuf is populated by p1,m1,p2,m2, ...
Packit 0652a1
    where 
Packit 0652a1
    p[i] * m[i] = m[i-1]
Packit 0652a1
    m0 = n                  */
Packit 0652a1
static void
Packit 0652a1
kf_factor (int n, int *facbuf)
Packit 0652a1
{
Packit 0652a1
  int p = 4;
Packit 0652a1
  double floor_sqrt;
Packit 0652a1
Packit 0652a1
  floor_sqrt = floor (sqrt ((double) n));
Packit 0652a1
Packit 0652a1
  /*factor out powers of 4, powers of 2, then any remaining primes */
Packit 0652a1
  do {
Packit 0652a1
    while (n % p) {
Packit 0652a1
      switch (p) {
Packit 0652a1
        case 4:
Packit 0652a1
          p = 2;
Packit 0652a1
          break;
Packit 0652a1
        case 2:
Packit 0652a1
          p = 3;
Packit 0652a1
          break;
Packit 0652a1
        default:
Packit 0652a1
          p += 2;
Packit 0652a1
          break;
Packit 0652a1
      }
Packit 0652a1
      if (p > floor_sqrt)
Packit 0652a1
        p = n;                  /* no more factors, skip to end */
Packit 0652a1
    }
Packit 0652a1
    n /= p;
Packit 0652a1
    *facbuf++ = p;
Packit 0652a1
    *facbuf++ = n;
Packit 0652a1
  } while (n > 1);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/*
Packit 0652a1
 *
Packit 0652a1
 * User-callable function to allocate all necessary storage space for the fft.
Packit 0652a1
 *
Packit 0652a1
 * The return value is a contiguous block of memory, allocated with malloc.  As such,
Packit 0652a1
 * It can be freed with free(), rather than a kiss_fft-specific function.
Packit 0652a1
 * */
Packit 0652a1
kiss_fft_s16_cfg
Packit 0652a1
kiss_fft_s16_alloc (int nfft, int inverse_fft, void *mem, size_t * lenmem)
Packit 0652a1
{
Packit 0652a1
  kiss_fft_s16_cfg st = NULL;
Packit 0652a1
  size_t memneeded = sizeof (struct kiss_fft_s16_state)
Packit 0652a1
      + sizeof (kiss_fft_s16_cpx) * (nfft - 1); /* twiddle factors */
Packit 0652a1
Packit 0652a1
  if (lenmem == NULL) {
Packit 0652a1
    st = (kiss_fft_s16_cfg) KISS_FFT_S16_MALLOC (memneeded);
Packit 0652a1
  } else {
Packit 0652a1
    if (mem != NULL && *lenmem >= memneeded)
Packit 0652a1
      st = (kiss_fft_s16_cfg) mem;
Packit 0652a1
    *lenmem = memneeded;
Packit 0652a1
  }
Packit 0652a1
  if (st) {
Packit 0652a1
    int i;
Packit 0652a1
Packit 0652a1
    st->nfft = nfft;
Packit 0652a1
    st->inverse = inverse_fft;
Packit 0652a1
Packit 0652a1
    for (i = 0; i < nfft; ++i) {
Packit 0652a1
      const double pi =
Packit 0652a1
          3.141592653589793238462643383279502884197169399375105820974944;
Packit 0652a1
      double phase = -2 * pi * i / nfft;
Packit 0652a1
Packit 0652a1
      if (st->inverse)
Packit 0652a1
        phase *= -1;
Packit 0652a1
      kf_cexp (st->twiddles + i, phase);
Packit 0652a1
    }
Packit 0652a1
Packit 0652a1
    kf_factor (nfft, st->factors);
Packit 0652a1
  }
Packit 0652a1
  return st;
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
Packit 0652a1
Packit 0652a1
Packit 0652a1
void
Packit 0652a1
kiss_fft_s16_stride (kiss_fft_s16_cfg st, const kiss_fft_s16_cpx * fin,
Packit 0652a1
    kiss_fft_s16_cpx * fout, int in_stride)
Packit 0652a1
{
Packit 0652a1
  if (fin == fout) {
Packit 0652a1
    CHECKBUF (tmpbuf, ntmpbuf, st->nfft);
Packit 0652a1
    kf_work (tmpbuf, fin, 1, in_stride, st->factors, st);
Packit 0652a1
    memcpy (fout, tmpbuf, sizeof (kiss_fft_s16_cpx) * st->nfft);
Packit 0652a1
  } else {
Packit 0652a1
    kf_work (fout, fin, 1, in_stride, st->factors, st);
Packit 0652a1
  }
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
void
Packit 0652a1
kiss_fft_s16 (kiss_fft_s16_cfg cfg, const kiss_fft_s16_cpx * fin,
Packit 0652a1
    kiss_fft_s16_cpx * fout)
Packit 0652a1
{
Packit 0652a1
  kiss_fft_s16_stride (cfg, fin, fout, 1);
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
Packit 0652a1
/* not really necessary to call, but if someone is doing in-place ffts, they may want to free the 
Packit 0652a1
   buffers from CHECKBUF
Packit 0652a1
 */
Packit 0652a1
void
Packit 0652a1
kiss_fft_s16_cleanup (void)
Packit 0652a1
{
Packit 0652a1
  free (scratchbuf);
Packit 0652a1
  scratchbuf = NULL;
Packit 0652a1
  nscratchbuf = 0;
Packit 0652a1
  free (tmpbuf);
Packit 0652a1
  tmpbuf = NULL;
Packit 0652a1
  ntmpbuf = 0;
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
int
Packit 0652a1
kiss_fft_s16_next_fast_size (int n)
Packit 0652a1
{
Packit 0652a1
  while (1) {
Packit 0652a1
    int m = n;
Packit 0652a1
Packit 0652a1
    while ((m % 2) == 0)
Packit 0652a1
      m /= 2;
Packit 0652a1
    while ((m % 3) == 0)
Packit 0652a1
      m /= 3;
Packit 0652a1
    while ((m % 5) == 0)
Packit 0652a1
      m /= 5;
Packit 0652a1
    if (m <= 1)
Packit 0652a1
      break;                    /* n is completely factorable by twos, threes, and fives */
Packit 0652a1
    n++;
Packit 0652a1
  }
Packit 0652a1
  return n;
Packit 0652a1
}