annotate ext/kissfft/tools/kiss_fftndr.c @ 206:335be766a54d

Fix erroneous header guard
author Chris Cannam
date Fri, 30 Sep 2016 19:04:06 +0100
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_fftndr.h"
Chris@184 16 #include "_kiss_fft_guts.h"
Chris@184 17 #define MAX(x,y) ( ( (x)<(y) )?(y):(x) )
Chris@184 18
Chris@184 19 struct kiss_fftndr_state
Chris@184 20 {
Chris@184 21 int dimReal;
Chris@184 22 int dimOther;
Chris@184 23 kiss_fftr_cfg cfg_r;
Chris@184 24 kiss_fftnd_cfg cfg_nd;
Chris@184 25 void * tmpbuf;
Chris@184 26 };
Chris@184 27
Chris@184 28 static int prod(const int *dims, int ndims)
Chris@184 29 {
Chris@184 30 int x=1;
Chris@184 31 while (ndims--)
Chris@184 32 x *= *dims++;
Chris@184 33 return x;
Chris@184 34 }
Chris@184 35
Chris@184 36 kiss_fftndr_cfg kiss_fftndr_alloc(const int *dims,int ndims,int inverse_fft,void*mem,size_t*lenmem)
Chris@184 37 {
Chris@184 38 kiss_fftndr_cfg st = NULL;
Chris@184 39 size_t nr=0 , nd=0,ntmp=0;
Chris@184 40 int dimReal = dims[ndims-1];
Chris@184 41 int dimOther = prod(dims,ndims-1);
Chris@184 42 size_t memneeded;
Chris@184 43
Chris@184 44 (void)kiss_fftr_alloc(dimReal,inverse_fft,NULL,&nr);
Chris@184 45 (void)kiss_fftnd_alloc(dims,ndims-1,inverse_fft,NULL,&nd);
Chris@184 46 ntmp =
Chris@184 47 MAX( 2*dimOther , dimReal+2) * sizeof(kiss_fft_scalar) // freq buffer for one pass
Chris@184 48 + dimOther*(dimReal+2) * sizeof(kiss_fft_scalar); // large enough to hold entire input in case of in-place
Chris@184 49
Chris@184 50 memneeded = sizeof( struct kiss_fftndr_state ) + nr + nd + ntmp;
Chris@184 51
Chris@184 52 if (lenmem==NULL) {
Chris@184 53 st = (kiss_fftndr_cfg) malloc(memneeded);
Chris@184 54 }else{
Chris@184 55 if (*lenmem >= memneeded)
Chris@184 56 st = (kiss_fftndr_cfg)mem;
Chris@184 57 *lenmem = memneeded;
Chris@184 58 }
Chris@184 59 if (st==NULL)
Chris@184 60 return NULL;
Chris@184 61 memset( st , 0 , memneeded);
Chris@184 62
Chris@184 63 st->dimReal = dimReal;
Chris@184 64 st->dimOther = dimOther;
Chris@184 65 st->cfg_r = kiss_fftr_alloc( dimReal,inverse_fft,st+1,&nr);
Chris@184 66 st->cfg_nd = kiss_fftnd_alloc(dims,ndims-1,inverse_fft, ((char*) st->cfg_r)+nr,&nd);
Chris@184 67 st->tmpbuf = (char*)st->cfg_nd + nd;
Chris@184 68
Chris@184 69 return st;
Chris@184 70 }
Chris@184 71
Chris@184 72 void kiss_fftndr(kiss_fftndr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata)
Chris@184 73 {
Chris@184 74 int k1,k2;
Chris@184 75 int dimReal = st->dimReal;
Chris@184 76 int dimOther = st->dimOther;
Chris@184 77 int nrbins = dimReal/2+1;
Chris@184 78
Chris@184 79 kiss_fft_cpx * tmp1 = (kiss_fft_cpx*)st->tmpbuf;
Chris@184 80 kiss_fft_cpx * tmp2 = tmp1 + MAX(nrbins,dimOther);
Chris@184 81
Chris@184 82 // timedata is N0 x N1 x ... x Nk real
Chris@184 83
Chris@184 84 // take a real chunk of data, fft it and place the output at correct intervals
Chris@184 85 for (k1=0;k1<dimOther;++k1) {
Chris@184 86 kiss_fftr( st->cfg_r, timedata + k1*dimReal , tmp1 ); // tmp1 now holds nrbins complex points
Chris@184 87 for (k2=0;k2<nrbins;++k2)
Chris@184 88 tmp2[ k2*dimOther+k1 ] = tmp1[k2];
Chris@184 89 }
Chris@184 90
Chris@184 91 for (k2=0;k2<nrbins;++k2) {
Chris@184 92 kiss_fftnd(st->cfg_nd, tmp2+k2*dimOther, tmp1); // tmp1 now holds dimOther complex points
Chris@184 93 for (k1=0;k1<dimOther;++k1)
Chris@184 94 freqdata[ k1*(nrbins) + k2] = tmp1[k1];
Chris@184 95 }
Chris@184 96 }
Chris@184 97
Chris@184 98 void kiss_fftndri(kiss_fftndr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata)
Chris@184 99 {
Chris@184 100 int k1,k2;
Chris@184 101 int dimReal = st->dimReal;
Chris@184 102 int dimOther = st->dimOther;
Chris@184 103 int nrbins = dimReal/2+1;
Chris@184 104 kiss_fft_cpx * tmp1 = (kiss_fft_cpx*)st->tmpbuf;
Chris@184 105 kiss_fft_cpx * tmp2 = tmp1 + MAX(nrbins,dimOther);
Chris@184 106
Chris@184 107 for (k2=0;k2<nrbins;++k2) {
Chris@184 108 for (k1=0;k1<dimOther;++k1)
Chris@184 109 tmp1[k1] = freqdata[ k1*(nrbins) + k2 ];
Chris@184 110 kiss_fftnd(st->cfg_nd, tmp1, tmp2+k2*dimOther);
Chris@184 111 }
Chris@184 112
Chris@184 113 for (k1=0;k1<dimOther;++k1) {
Chris@184 114 for (k2=0;k2<nrbins;++k2)
Chris@184 115 tmp1[k2] = tmp2[ k2*dimOther+k1 ];
Chris@184 116 kiss_fftri( st->cfg_r,tmp1,timedata + k1*dimReal);
Chris@184 117 }
Chris@184 118 }