annotate src/vamp-sdk/ext/vamp_kiss_fftr.c @ 503:13e551657422 vamp-kiss-naming

Merge
author Chris Cannam
date Tue, 30 Jan 2018 15:28:27 +0000
parents 90571dcc371a
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@501 15 #include "vamp_kiss_fftr.h"
Chris@501 16 #include "vamp_kiss_fft_guts.h"
Chris@434 17
Chris@501 18 struct vamp_kiss_fftr_state{
Chris@501 19 vamp_kiss_fft_cfg substate;
Chris@501 20 vamp_kiss_fft_cpx * tmpbuf;
Chris@501 21 vamp_kiss_fft_cpx * super_twiddles;
Chris@434 22 };
Chris@434 23
Chris@501 24 vamp_kiss_fftr_cfg vamp_kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
Chris@434 25 {
Chris@434 26 int i;
Chris@501 27 vamp_kiss_fftr_cfg st = NULL;
Chris@434 28 size_t subsize, memneeded;
Chris@434 29
Chris@434 30 if (nfft & 1) {
Chris@434 31 fprintf(stderr,"Real FFT optimization must be even.\n");
Chris@434 32 return NULL;
Chris@434 33 }
Chris@434 34 nfft >>= 1;
Chris@434 35
Chris@501 36 vamp_kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize);
Chris@501 37 memneeded = sizeof(struct vamp_kiss_fftr_state) + subsize + sizeof(vamp_kiss_fft_cpx) * ( nfft * 3 / 2);
Chris@434 38
Chris@434 39 if (lenmem == NULL) {
Chris@501 40 st = (vamp_kiss_fftr_cfg) VAMP_KISS_FFT_MALLOC (memneeded);
Chris@434 41 } else {
Chris@434 42 if (*lenmem >= memneeded)
Chris@501 43 st = (vamp_kiss_fftr_cfg) mem;
Chris@434 44 *lenmem = memneeded;
Chris@434 45 }
Chris@434 46 if (!st)
Chris@434 47 return NULL;
Chris@434 48
Chris@501 49 st->substate = (vamp_kiss_fft_cfg) (st + 1); /*just beyond vamp_kiss_fftr_state struct */
Chris@501 50 st->tmpbuf = (vamp_kiss_fft_cpx *) (((char *) st->substate) + subsize);
Chris@434 51 st->super_twiddles = st->tmpbuf + nfft;
Chris@501 52 vamp_kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize);
Chris@434 53
Chris@434 54 for (i = 0; i < nfft/2; ++i) {
Chris@434 55 double phase =
Chris@434 56 -3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5);
Chris@434 57 if (inverse_fft)
Chris@434 58 phase *= -1;
Chris@434 59 kf_cexp (st->super_twiddles+i,phase);
Chris@434 60 }
Chris@434 61 return st;
Chris@434 62 }
Chris@434 63
Chris@501 64 void vamp_kiss_fftr_free(void *mem)
Chris@501 65 {
Chris@501 66 free(mem);
Chris@501 67 }
Chris@501 68
Chris@501 69 void vamp_kiss_fftr(vamp_kiss_fftr_cfg st,const vamp_kiss_fft_scalar *timedata,vamp_kiss_fft_cpx *freqdata)
Chris@434 70 {
Chris@434 71 /* input buffer timedata is stored row-wise */
Chris@434 72 int k,ncfft;
Chris@501 73 vamp_kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc;
Chris@434 74
Chris@434 75 if ( st->substate->inverse) {
Chris@434 76 fprintf(stderr,"kiss fft usage error: improper alloc\n");
Chris@434 77 exit(1);
Chris@434 78 }
Chris@434 79
Chris@434 80 ncfft = st->substate->nfft;
Chris@434 81
Chris@434 82 /*perform the parallel fft of two real signals packed in real,imag*/
Chris@501 83 vamp_kiss_fft( st->substate , (const vamp_kiss_fft_cpx*)timedata, st->tmpbuf );
Chris@434 84 /* The real part of the DC element of the frequency spectrum in st->tmpbuf
Chris@434 85 * contains the sum of the even-numbered elements of the input time sequence
Chris@434 86 * The imag part is the sum of the odd-numbered elements
Chris@434 87 *
Chris@434 88 * The sum of tdc.r and tdc.i is the sum of the input time sequence.
Chris@434 89 * yielding DC of input time sequence
Chris@434 90 * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
Chris@434 91 * yielding Nyquist bin of input time sequence
Chris@434 92 */
Chris@434 93
Chris@434 94 tdc.r = st->tmpbuf[0].r;
Chris@434 95 tdc.i = st->tmpbuf[0].i;
Chris@434 96 C_FIXDIV(tdc,2);
Chris@434 97 CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i);
Chris@434 98 CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
Chris@434 99 freqdata[0].r = tdc.r + tdc.i;
Chris@434 100 freqdata[ncfft].r = tdc.r - tdc.i;
Chris@434 101 freqdata[ncfft].i = freqdata[0].i = 0;
Chris@434 102
Chris@434 103 for ( k=1;k <= ncfft/2 ; ++k ) {
Chris@434 104 fpk = st->tmpbuf[k];
Chris@434 105 fpnk.r = st->tmpbuf[ncfft-k].r;
Chris@434 106 fpnk.i = - st->tmpbuf[ncfft-k].i;
Chris@434 107 C_FIXDIV(fpk,2);
Chris@434 108 C_FIXDIV(fpnk,2);
Chris@434 109
Chris@434 110 C_ADD( f1k, fpk , fpnk );
Chris@434 111 C_SUB( f2k, fpk , fpnk );
Chris@434 112 C_MUL( tw , f2k , st->super_twiddles[k-1]);
Chris@434 113
Chris@434 114 freqdata[k].r = HALF_OF(f1k.r + tw.r);
Chris@434 115 freqdata[k].i = HALF_OF(f1k.i + tw.i);
Chris@434 116 freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r);
Chris@434 117 freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i);
Chris@434 118 }
Chris@434 119 }
Chris@434 120
Chris@501 121 void vamp_kiss_fftri(vamp_kiss_fftr_cfg st,const vamp_kiss_fft_cpx *freqdata,vamp_kiss_fft_scalar *timedata)
Chris@434 122 {
Chris@434 123 /* input buffer timedata is stored row-wise */
Chris@434 124 int k, ncfft;
Chris@434 125
Chris@434 126 if (st->substate->inverse == 0) {
Chris@434 127 fprintf (stderr, "kiss fft usage error: improper alloc\n");
Chris@434 128 exit (1);
Chris@434 129 }
Chris@434 130
Chris@434 131 ncfft = st->substate->nfft;
Chris@434 132
Chris@434 133 st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
Chris@434 134 st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
Chris@434 135 C_FIXDIV(st->tmpbuf[0],2);
Chris@434 136
Chris@434 137 for (k = 1; k <= ncfft / 2; ++k) {
Chris@501 138 vamp_kiss_fft_cpx fk, fnkc, fek, fok, tmp;
Chris@434 139 fk = freqdata[k];
Chris@434 140 fnkc.r = freqdata[ncfft - k].r;
Chris@434 141 fnkc.i = -freqdata[ncfft - k].i;
Chris@434 142 C_FIXDIV( fk , 2 );
Chris@434 143 C_FIXDIV( fnkc , 2 );
Chris@434 144
Chris@434 145 C_ADD (fek, fk, fnkc);
Chris@434 146 C_SUB (tmp, fk, fnkc);
Chris@434 147 C_MUL (fok, tmp, st->super_twiddles[k-1]);
Chris@434 148 C_ADD (st->tmpbuf[k], fek, fok);
Chris@434 149 C_SUB (st->tmpbuf[ncfft - k], fek, fok);
Chris@434 150 st->tmpbuf[ncfft - k].i *= -1;
Chris@434 151 }
Chris@501 152 vamp_kiss_fft (st->substate, st->tmpbuf, (vamp_kiss_fft_cpx *) timedata);
Chris@434 153 }