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

Packit 971217
/*
Packit 971217
Copyright (c) 2003-2004, Mark Borgerding
Packit 971217
Packit 971217
All rights reserved.
Packit 971217
Packit 971217
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Packit 971217
Packit 971217
    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Packit 971217
    * 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 971217
    * 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 971217
Packit 971217
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 971217
*/
Packit 971217
#ifdef HAVE_CONFIG_H
Packit 971217
#include "config.h"
Packit 971217
#endif
Packit 971217
Packit 971217
#include "kiss_fftr_s32.h"
Packit 971217
#include "_kiss_fft_guts_s32.h"
Packit 971217
Packit 971217
struct kiss_fftr_s32_state
Packit 971217
{
Packit 971217
  kiss_fft_s32_cfg substate;
Packit 971217
  kiss_fft_s32_cpx *tmpbuf;
Packit 971217
  kiss_fft_s32_cpx *super_twiddles;
Packit 971217
#ifdef USE_SIMD
Packit 971217
  long pad;
Packit 971217
#endif
Packit 971217
};
Packit 971217
Packit 971217
kiss_fftr_s32_cfg
Packit 971217
kiss_fftr_s32_alloc (int nfft, int inverse_fft, void *mem, size_t * lenmem)
Packit 971217
{
Packit 971217
  int i;
Packit 971217
  kiss_fftr_s32_cfg st = NULL;
Packit 971217
  size_t subsize, memneeded;
Packit 971217
Packit 971217
  if (nfft & 1) {
Packit 971217
    fprintf (stderr, "Real FFT optimization must be even.\n");
Packit 971217
    return NULL;
Packit 971217
  }
Packit 971217
  nfft >>= 1;
Packit 971217
Packit 971217
  kiss_fft_s32_alloc (nfft, inverse_fft, NULL, &subsize);
Packit 971217
  memneeded = ALIGN_STRUCT (sizeof (struct kiss_fftr_s32_state))
Packit 971217
      + ALIGN_STRUCT (subsize)
Packit 971217
      + sizeof (kiss_fft_s32_cpx) * (nfft * 3 / 2);
Packit 971217
Packit 971217
  if (lenmem == NULL) {
Packit 971217
    st = (kiss_fftr_s32_cfg) KISS_FFT_S32_MALLOC (memneeded);
Packit 971217
  } else {
Packit 971217
    if (*lenmem >= memneeded)
Packit 971217
      st = (kiss_fftr_s32_cfg) mem;
Packit 971217
    *lenmem = memneeded;
Packit 971217
  }
Packit 971217
  if (!st)
Packit 971217
    return NULL;
Packit 971217
Packit 971217
  st->substate = (kiss_fft_s32_cfg) (((char *) st) + ALIGN_STRUCT (sizeof (struct kiss_fftr_s32_state)));       /*just beyond kiss_fftr_s32_state struct */
Packit 971217
  st->tmpbuf =
Packit 971217
      (kiss_fft_s32_cpx *) (((char *) st->substate) + ALIGN_STRUCT (subsize));
Packit 971217
  st->super_twiddles = st->tmpbuf + nfft;
Packit 971217
  kiss_fft_s32_alloc (nfft, inverse_fft, st->substate, &subsize);
Packit 971217
Packit 971217
  for (i = 0; i < nfft / 2; ++i) {
Packit 971217
    double phase =
Packit 971217
        -3.14159265358979323846264338327 * ((double) (i + 1) / nfft + .5);
Packit 971217
Packit 971217
    if (inverse_fft)
Packit 971217
      phase *= -1;
Packit 971217
    kf_cexp (st->super_twiddles + i, phase);
Packit 971217
  }
Packit 971217
  return st;
Packit 971217
}
Packit 971217
Packit 971217
void
Packit 971217
kiss_fftr_s32 (kiss_fftr_s32_cfg st, const kiss_fft_s32_scalar * timedata,
Packit 971217
    kiss_fft_s32_cpx * freqdata)
Packit 971217
{
Packit 971217
  /* input buffer timedata is stored row-wise */
Packit 971217
  int k, ncfft;
Packit 971217
  kiss_fft_s32_cpx fpnk, fpk, f1k, f2k, tw, tdc;
Packit 971217
Packit 971217
  /* kiss fft usage error: improper alloc */
Packit 971217
  g_return_if_fail (st->substate->inverse == 0);
Packit 971217
Packit 971217
  ncfft = st->substate->nfft;
Packit 971217
Packit 971217
  /*perform the parallel fft of two real signals packed in real,imag */
Packit 971217
  kiss_fft_s32 (st->substate, (const kiss_fft_s32_cpx *) timedata, st->tmpbuf);
Packit 971217
  /* The real part of the DC element of the frequency spectrum in st->tmpbuf
Packit 971217
   * contains the sum of the even-numbered elements of the input time sequence
Packit 971217
   * The imag part is the sum of the odd-numbered elements
Packit 971217
   *
Packit 971217
   * The sum of tdc.r and tdc.i is the sum of the input time sequence. 
Packit 971217
   *      yielding DC of input time sequence
Packit 971217
   * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... 
Packit 971217
   *      yielding Nyquist bin of input time sequence
Packit 971217
   */
Packit 971217
Packit 971217
  tdc.r = st->tmpbuf[0].r;
Packit 971217
  tdc.i = st->tmpbuf[0].i;
Packit 971217
  C_FIXDIV (tdc, 2);
Packit 971217
  CHECK_OVERFLOW_OP (tdc.r, +, tdc.i);
Packit 971217
  CHECK_OVERFLOW_OP (tdc.r, -, tdc.i);
Packit 971217
  freqdata[0].r = tdc.r + tdc.i;
Packit 971217
  freqdata[ncfft].r = tdc.r - tdc.i;
Packit 971217
#ifdef USE_SIMD
Packit 971217
  freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps (0);
Packit 971217
#else
Packit 971217
  freqdata[ncfft].i = freqdata[0].i = 0;
Packit 971217
#endif
Packit 971217
Packit 971217
  for (k = 1; k <= ncfft / 2; ++k) {
Packit 971217
    fpk = st->tmpbuf[k];
Packit 971217
    fpnk.r = st->tmpbuf[ncfft - k].r;
Packit 971217
    fpnk.i = -st->tmpbuf[ncfft - k].i;
Packit 971217
    C_FIXDIV (fpk, 2);
Packit 971217
    C_FIXDIV (fpnk, 2);
Packit 971217
Packit 971217
    C_ADD (f1k, fpk, fpnk);
Packit 971217
    C_SUB (f2k, fpk, fpnk);
Packit 971217
    C_MUL (tw, f2k, st->super_twiddles[k - 1]);
Packit 971217
Packit 971217
    freqdata[k].r = HALF_OF (f1k.r + tw.r);
Packit 971217
    freqdata[k].i = HALF_OF (f1k.i + tw.i);
Packit 971217
    freqdata[ncfft - k].r = HALF_OF (f1k.r - tw.r);
Packit 971217
    freqdata[ncfft - k].i = HALF_OF (tw.i - f1k.i);
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
void
Packit 971217
kiss_fftri_s32 (kiss_fftr_s32_cfg st, const kiss_fft_s32_cpx * freqdata,
Packit 971217
    kiss_fft_s32_scalar * timedata)
Packit 971217
{
Packit 971217
  /* input buffer timedata is stored row-wise */
Packit 971217
  int k, ncfft;
Packit 971217
Packit 971217
  /* kiss fft usage error: improper alloc */
Packit 971217
  g_return_if_fail (st->substate->inverse != 0);
Packit 971217
Packit 971217
  ncfft = st->substate->nfft;
Packit 971217
Packit 971217
  st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
Packit 971217
  st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
Packit 971217
  C_FIXDIV (st->tmpbuf[0], 2);
Packit 971217
Packit 971217
  for (k = 1; k <= ncfft / 2; ++k) {
Packit 971217
    kiss_fft_s32_cpx fk, fnkc, fek, fok, tmp;
Packit 971217
Packit 971217
    fk = freqdata[k];
Packit 971217
    fnkc.r = freqdata[ncfft - k].r;
Packit 971217
    fnkc.i = -freqdata[ncfft - k].i;
Packit 971217
    C_FIXDIV (fk, 2);
Packit 971217
    C_FIXDIV (fnkc, 2);
Packit 971217
Packit 971217
    C_ADD (fek, fk, fnkc);
Packit 971217
    C_SUB (tmp, fk, fnkc);
Packit 971217
    C_MUL (fok, tmp, st->super_twiddles[k - 1]);
Packit 971217
    C_ADD (st->tmpbuf[k], fek, fok);
Packit 971217
    C_SUB (st->tmpbuf[ncfft - k], fek, fok);
Packit 971217
#ifdef USE_SIMD
Packit 971217
    st->tmpbuf[ncfft - k].i *= _mm_set1_ps (-1.0);
Packit 971217
#else
Packit 971217
    st->tmpbuf[ncfft - k].i *= -1;
Packit 971217
#endif
Packit 971217
  }
Packit 971217
  kiss_fft_s32 (st->substate, st->tmpbuf, (kiss_fft_s32_cpx *) timedata);
Packit 971217
}