annotate ext/kissfft/tools/kiss_fftr.c @ 215:eee235c4f962 msvc

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