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