annotate src/vamp-sdk/ext/kiss_fftr.c @ 434:e979a9c4ffb6 vampipe

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