annotate ext/kissfft/tools/kiss_fftndr.c @ 409:1f1999b0f577

Bring in kissfft into this repo (formerly a subrepo, but the remote is not responding)
author Chris Cannam <c.cannam@qmul.ac.uk>
date Tue, 21 Jul 2015 07:34:15 +0100
parents
children
rev   line source
c@409 1 /*
c@409 2 Copyright (c) 2003-2004, Mark Borgerding
c@409 3
c@409 4 All rights reserved.
c@409 5
c@409 6 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
c@409 7
c@409 8 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
c@409 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.
c@409 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.
c@409 11
c@409 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.
c@409 13 */
c@409 14
c@409 15 #include "kiss_fftndr.h"
c@409 16 #include "_kiss_fft_guts.h"
c@409 17 #define MAX(x,y) ( ( (x)<(y) )?(y):(x) )
c@409 18
c@409 19 struct kiss_fftndr_state
c@409 20 {
c@409 21 int dimReal;
c@409 22 int dimOther;
c@409 23 kiss_fftr_cfg cfg_r;
c@409 24 kiss_fftnd_cfg cfg_nd;
c@409 25 void * tmpbuf;
c@409 26 };
c@409 27
c@409 28 static int prod(const int *dims, int ndims)
c@409 29 {
c@409 30 int x=1;
c@409 31 while (ndims--)
c@409 32 x *= *dims++;
c@409 33 return x;
c@409 34 }
c@409 35
c@409 36 kiss_fftndr_cfg kiss_fftndr_alloc(const int *dims,int ndims,int inverse_fft,void*mem,size_t*lenmem)
c@409 37 {
c@409 38 kiss_fftndr_cfg st = NULL;
c@409 39 size_t nr=0 , nd=0,ntmp=0;
c@409 40 int dimReal = dims[ndims-1];
c@409 41 int dimOther = prod(dims,ndims-1);
c@409 42 size_t memneeded;
c@409 43
c@409 44 (void)kiss_fftr_alloc(dimReal,inverse_fft,NULL,&nr);
c@409 45 (void)kiss_fftnd_alloc(dims,ndims-1,inverse_fft,NULL,&nd);
c@409 46 ntmp =
c@409 47 MAX( 2*dimOther , dimReal+2) * sizeof(kiss_fft_scalar) // freq buffer for one pass
c@409 48 + dimOther*(dimReal+2) * sizeof(kiss_fft_scalar); // large enough to hold entire input in case of in-place
c@409 49
c@409 50 memneeded = sizeof( struct kiss_fftndr_state ) + nr + nd + ntmp;
c@409 51
c@409 52 if (lenmem==NULL) {
c@409 53 st = (kiss_fftndr_cfg) malloc(memneeded);
c@409 54 }else{
c@409 55 if (*lenmem >= memneeded)
c@409 56 st = (kiss_fftndr_cfg)mem;
c@409 57 *lenmem = memneeded;
c@409 58 }
c@409 59 if (st==NULL)
c@409 60 return NULL;
c@409 61 memset( st , 0 , memneeded);
c@409 62
c@409 63 st->dimReal = dimReal;
c@409 64 st->dimOther = dimOther;
c@409 65 st->cfg_r = kiss_fftr_alloc( dimReal,inverse_fft,st+1,&nr);
c@409 66 st->cfg_nd = kiss_fftnd_alloc(dims,ndims-1,inverse_fft, ((char*) st->cfg_r)+nr,&nd);
c@409 67 st->tmpbuf = (char*)st->cfg_nd + nd;
c@409 68
c@409 69 return st;
c@409 70 }
c@409 71
c@409 72 void kiss_fftndr(kiss_fftndr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata)
c@409 73 {
c@409 74 int k1,k2;
c@409 75 int dimReal = st->dimReal;
c@409 76 int dimOther = st->dimOther;
c@409 77 int nrbins = dimReal/2+1;
c@409 78
c@409 79 kiss_fft_cpx * tmp1 = (kiss_fft_cpx*)st->tmpbuf;
c@409 80 kiss_fft_cpx * tmp2 = tmp1 + MAX(nrbins,dimOther);
c@409 81
c@409 82 // timedata is N0 x N1 x ... x Nk real
c@409 83
c@409 84 // take a real chunk of data, fft it and place the output at correct intervals
c@409 85 for (k1=0;k1<dimOther;++k1) {
c@409 86 kiss_fftr( st->cfg_r, timedata + k1*dimReal , tmp1 ); // tmp1 now holds nrbins complex points
c@409 87 for (k2=0;k2<nrbins;++k2)
c@409 88 tmp2[ k2*dimOther+k1 ] = tmp1[k2];
c@409 89 }
c@409 90
c@409 91 for (k2=0;k2<nrbins;++k2) {
c@409 92 kiss_fftnd(st->cfg_nd, tmp2+k2*dimOther, tmp1); // tmp1 now holds dimOther complex points
c@409 93 for (k1=0;k1<dimOther;++k1)
c@409 94 freqdata[ k1*(nrbins) + k2] = tmp1[k1];
c@409 95 }
c@409 96 }
c@409 97
c@409 98 void kiss_fftndri(kiss_fftndr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata)
c@409 99 {
c@409 100 int k1,k2;
c@409 101 int dimReal = st->dimReal;
c@409 102 int dimOther = st->dimOther;
c@409 103 int nrbins = dimReal/2+1;
c@409 104 kiss_fft_cpx * tmp1 = (kiss_fft_cpx*)st->tmpbuf;
c@409 105 kiss_fft_cpx * tmp2 = tmp1 + MAX(nrbins,dimOther);
c@409 106
c@409 107 for (k2=0;k2<nrbins;++k2) {
c@409 108 for (k1=0;k1<dimOther;++k1)
c@409 109 tmp1[k1] = freqdata[ k1*(nrbins) + k2 ];
c@409 110 kiss_fftnd(st->cfg_nd, tmp1, tmp2+k2*dimOther);
c@409 111 }
c@409 112
c@409 113 for (k1=0;k1<dimOther;++k1) {
c@409 114 for (k2=0;k2<nrbins;++k2)
c@409 115 tmp1[k2] = tmp2[ k2*dimOther+k1 ];
c@409 116 kiss_fftri( st->cfg_r,tmp1,timedata + k1*dimReal);
c@409 117 }
c@409 118 }