annotate constant-q-cpp/src/ext/kissfft/tools/kiss_fftr.c @ 372:af71cbdab621 tip

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