annotate dsp/transforms/kissfft/kiss_fftr.c @ 309:d5014ab8b0e5

* Add GPL and README; some tidying
author Chris Cannam <c.cannam@qmul.ac.uk>
date Mon, 13 Dec 2010 14:55:28 +0000
parents befe5aa6b450
children
rev   line source
c@289 1 /*
c@289 2 Copyright (c) 2003-2004, Mark Borgerding
c@289 3
c@289 4 All rights reserved.
c@289 5
c@289 6 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
c@289 7
c@289 8 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
c@289 9 * 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.
c@289 10 * 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.
c@289 11
c@289 12 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.
c@289 13 */
c@289 14
c@289 15 #include "kiss_fftr.h"
c@289 16 #include "_kiss_fft_guts.h"
c@289 17
c@289 18 struct kiss_fftr_state{
c@289 19 kiss_fft_cfg substate;
c@289 20 kiss_fft_cpx * tmpbuf;
c@289 21 kiss_fft_cpx * super_twiddles;
c@289 22 #ifdef USE_SIMD
c@289 23 long pad;
c@289 24 #endif
c@289 25 };
c@289 26
c@289 27 kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
c@289 28 {
c@289 29 int i;
c@289 30 kiss_fftr_cfg st = NULL;
c@289 31 size_t subsize, memneeded;
c@289 32
c@289 33 if (nfft & 1) {
c@289 34 fprintf(stderr,"Real FFT optimization must be even.\n");
c@289 35 return NULL;
c@289 36 }
c@289 37 nfft >>= 1;
c@289 38
c@289 39 kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize);
c@289 40 memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 2);
c@289 41
c@289 42 if (lenmem == NULL) {
c@289 43 st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded);
c@289 44 } else {
c@289 45 if (*lenmem >= memneeded)
c@289 46 st = (kiss_fftr_cfg) mem;
c@289 47 *lenmem = memneeded;
c@289 48 }
c@289 49 if (!st)
c@289 50 return NULL;
c@289 51
c@289 52 st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */
c@289 53 st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize);
c@289 54 st->super_twiddles = st->tmpbuf + nfft;
c@289 55 kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize);
c@289 56
c@289 57 for (i = 0; i < nfft; ++i) {
c@289 58 double phase =
c@289 59 -3.14159265358979323846264338327 * ((double) i / nfft + .5);
c@289 60 if (inverse_fft)
c@289 61 phase *= -1;
c@289 62 kf_cexp (st->super_twiddles+i,phase);
c@289 63 }
c@289 64 return st;
c@289 65 }
c@289 66
c@289 67 void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata)
c@289 68 {
c@289 69 /* input buffer timedata is stored row-wise */
c@289 70 int k,ncfft;
c@289 71 kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc;
c@289 72
c@289 73 if ( st->substate->inverse) {
c@289 74 fprintf(stderr,"kiss fft usage error: improper alloc\n");
c@289 75 exit(1);
c@289 76 }
c@289 77
c@289 78 ncfft = st->substate->nfft;
c@289 79
c@289 80 /*perform the parallel fft of two real signals packed in real,imag*/
c@289 81 kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf );
c@289 82 /* The real part of the DC element of the frequency spectrum in st->tmpbuf
c@289 83 * contains the sum of the even-numbered elements of the input time sequence
c@289 84 * The imag part is the sum of the odd-numbered elements
c@289 85 *
c@289 86 * The sum of tdc.r and tdc.i is the sum of the input time sequence.
c@289 87 * yielding DC of input time sequence
c@289 88 * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
c@289 89 * yielding Nyquist bin of input time sequence
c@289 90 */
c@289 91
c@289 92 tdc.r = st->tmpbuf[0].r;
c@289 93 tdc.i = st->tmpbuf[0].i;
c@289 94 C_FIXDIV(tdc,2);
c@289 95 CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i);
c@289 96 CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
c@289 97 freqdata[0].r = tdc.r + tdc.i;
c@289 98 freqdata[ncfft].r = tdc.r - tdc.i;
c@289 99 #ifdef USE_SIMD
c@289 100 freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0);
c@289 101 #else
c@289 102 freqdata[ncfft].i = freqdata[0].i = 0;
c@289 103 #endif
c@289 104
c@289 105 for ( k=1;k <= ncfft/2 ; ++k ) {
c@289 106 fpk = st->tmpbuf[k];
c@289 107 fpnk.r = st->tmpbuf[ncfft-k].r;
c@289 108 fpnk.i = - st->tmpbuf[ncfft-k].i;
c@289 109 C_FIXDIV(fpk,2);
c@289 110 C_FIXDIV(fpnk,2);
c@289 111
c@289 112 C_ADD( f1k, fpk , fpnk );
c@289 113 C_SUB( f2k, fpk , fpnk );
c@289 114 C_MUL( tw , f2k , st->super_twiddles[k]);
c@289 115
c@289 116 freqdata[k].r = HALF_OF(f1k.r + tw.r);
c@289 117 freqdata[k].i = HALF_OF(f1k.i + tw.i);
c@289 118 freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r);
c@289 119 freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i);
c@289 120 }
c@289 121 }
c@289 122
c@289 123 void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata)
c@289 124 {
c@289 125 /* input buffer timedata is stored row-wise */
c@289 126 int k, ncfft;
c@289 127
c@289 128 if (st->substate->inverse == 0) {
c@289 129 fprintf (stderr, "kiss fft usage error: improper alloc\n");
c@289 130 exit (1);
c@289 131 }
c@289 132
c@289 133 ncfft = st->substate->nfft;
c@289 134
c@289 135 st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
c@289 136 st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
c@289 137 C_FIXDIV(st->tmpbuf[0],2);
c@289 138
c@289 139 for (k = 1; k <= ncfft / 2; ++k) {
c@289 140 kiss_fft_cpx fk, fnkc, fek, fok, tmp;
c@289 141 fk = freqdata[k];
c@289 142 fnkc.r = freqdata[ncfft - k].r;
c@289 143 fnkc.i = -freqdata[ncfft - k].i;
c@289 144 C_FIXDIV( fk , 2 );
c@289 145 C_FIXDIV( fnkc , 2 );
c@289 146
c@289 147 C_ADD (fek, fk, fnkc);
c@289 148 C_SUB (tmp, fk, fnkc);
c@289 149 C_MUL (fok, tmp, st->super_twiddles[k]);
c@289 150 C_ADD (st->tmpbuf[k], fek, fok);
c@289 151 C_SUB (st->tmpbuf[ncfft - k], fek, fok);
c@289 152 #ifdef USE_SIMD
c@289 153 st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
c@289 154 #else
c@289 155 st->tmpbuf[ncfft - k].i *= -1;
c@289 156 #endif
c@289 157 }
c@289 158 kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
c@289 159 }