mirror of
https://github.com/mborgerding/kissfft.git
synced 2025-05-27 21:20:27 -04:00
broken
working towards mixed radix decomposition seems to work (for 2) indices scrambled
This commit is contained in:
parent
c9ff98b2c9
commit
502211bc6a
2
Makefile
2
Makefile
@ -2,7 +2,7 @@ message:
|
|||||||
@echo "Nothing to make here. Move on down to sample_code for ... you guessed it! Sample Code!"
|
@echo "Nothing to make here. Move on down to sample_code for ... you guessed it! Sample Code!"
|
||||||
|
|
||||||
tarball: clean
|
tarball: clean
|
||||||
tar -czf kiss_fft.tar.gz .
|
tar --exclude CVS -czf kiss_fft.tar.gz .
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
cd sample_code && make clean
|
cd sample_code && make clean
|
||||||
|
126
kiss_fft.c
126
kiss_fft.c
@ -13,6 +13,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "kiss_fft.h"
|
#include "kiss_fft.h"
|
||||||
/*
|
/*
|
||||||
@ -26,10 +27,19 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int nfft;
|
int nr; // N remaining
|
||||||
kiss_fft_cpx* twiddle;
|
int radix; // radix of the stage
|
||||||
int * swap_indices;
|
kiss_fft_cpx * twiddle;
|
||||||
int nswap;
|
}kiss_fft_stage;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_STAGES 20
|
||||||
|
typedef struct {
|
||||||
|
int nstages;
|
||||||
|
int allocsize;
|
||||||
|
kiss_fft_stage stages[MAX_STAGES];
|
||||||
|
int * unscramble_indices;
|
||||||
}kiss_fft_state;
|
}kiss_fft_state;
|
||||||
|
|
||||||
#ifdef FIXED_POINT
|
#ifdef FIXED_POINT
|
||||||
@ -73,20 +83,15 @@ typedef struct {
|
|||||||
|
|
||||||
// create the twiddle factors
|
// create the twiddle factors
|
||||||
static
|
static
|
||||||
void make_twiddles(kiss_fft_cpx * twiddle,int nfft,int inverse_fft)
|
void make_twiddles(kiss_fft_cpx * twiddle,int ntwid,int symmetry,int inverse_fft)
|
||||||
{
|
{
|
||||||
const double pi=3.14159265358979323846264338327;
|
const double pi=3.14159265358979323846264338327;
|
||||||
int n;
|
int n;
|
||||||
for (n=0;n< (nfft>>1);++n) {
|
int denom = ntwid*symmetry;
|
||||||
#ifdef FIXED_POINT
|
|
||||||
// TODO: find another way to calculate these without so much floating point math
|
for (n=0;n<ntwid;++n) {
|
||||||
twiddle[n].r = (kiss_fft_scalar)(TWIDDLE_RANGE*cos(2*pi*n/nfft)+.5);
|
twiddle[n].r = cos(2*pi*n/denom);
|
||||||
twiddle[n].i = -(kiss_fft_scalar)(TWIDDLE_RANGE*sin(2*pi*n/nfft)+.5);
|
twiddle[n].i = -sin(2*pi*n/denom);
|
||||||
#else
|
|
||||||
twiddle[n].r = cos(2*pi*n/nfft);
|
|
||||||
twiddle[n].i = -sin(2*pi*n/nfft);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// inverse fft uses complex conjugate twiddle factors
|
// inverse fft uses complex conjugate twiddle factors
|
||||||
if (inverse_fft)
|
if (inverse_fft)
|
||||||
twiddle[n].i *= -1;
|
twiddle[n].i *= -1;
|
||||||
@ -141,32 +146,59 @@ void undo_bit_rev( kiss_fft_cpx * f, const int * swap_indices,int nswap)
|
|||||||
|
|
||||||
|
|
||||||
// the heart of the fft
|
// the heart of the fft
|
||||||
static
|
static
|
||||||
void fft_work(int N,kiss_fft_cpx *f,const kiss_fft_cpx * twid,int twid_step)
|
void fft_work( kiss_fft_cpx * f,const kiss_fft_stage * stage , int nstages )
|
||||||
{
|
{
|
||||||
N >>= 1;
|
int n;
|
||||||
|
// only works for 2s
|
||||||
|
|
||||||
{ // declare automatic variables in here to reduce stack usage
|
{ // declare automatic variables in here to reduce stack usage
|
||||||
int n;
|
|
||||||
kiss_fft_cpx csum,cdiff;
|
kiss_fft_cpx csum,cdiff;
|
||||||
const kiss_fft_cpx * cur_twid = twid;
|
|
||||||
kiss_fft_cpx *f1 = f;
|
kiss_fft_cpx *f1 = f;
|
||||||
kiss_fft_cpx *f2 = f+N;
|
kiss_fft_cpx *f2 = f+ stage->nr;
|
||||||
for (n=0;n<N;++n)
|
const kiss_fft_cpx * twid = stage->twiddle;
|
||||||
|
for ( n = 0 ; n < stage->nr ; ++n )
|
||||||
{
|
{
|
||||||
C_ADD( csum, *f1 , *f2 );
|
C_ADD( csum, *f1 , *f2 );
|
||||||
C_SUB( cdiff, *f1 , *f2 );
|
C_SUB( cdiff, *f1 , *f2 );
|
||||||
*f1++ = csum;
|
*f1++ = csum;
|
||||||
C_MUL(*f2, cdiff, *cur_twid);
|
C_MUL(*f2, cdiff, *twid);
|
||||||
++f2;
|
++f2;
|
||||||
cur_twid += twid_step;
|
++twid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (N==1) return;
|
if ( nstages == 1 )
|
||||||
//twid_step *= 2;
|
return;
|
||||||
fft_work(N,f+N,twid,twid_step*2);
|
|
||||||
fft_work(N,f,twid,twid_step*2);
|
for (n=0;n<stage->radix;++n)
|
||||||
|
fft_work( f + n * stage->nr ,stage+1,nstages-1);
|
||||||
}
|
}
|
||||||
|
static
|
||||||
|
kiss_fft_state * decompose( kiss_fft_state * st, int * pnfft,int radix,int inverse_fft)
|
||||||
|
{
|
||||||
|
int nfft = *pnfft;
|
||||||
|
|
||||||
|
while (nfft>1 && (nfft%radix)==0) {
|
||||||
|
int newsize;
|
||||||
|
int nstages=st->nstages;
|
||||||
|
nfft /= radix;
|
||||||
|
fprintf(stderr,"%d ",radix);
|
||||||
|
|
||||||
|
newsize = st->allocsize + nfft * sizeof(kiss_fft_cpx);
|
||||||
|
|
||||||
|
st=(kiss_fft_state*)realloc(st,newsize);
|
||||||
|
|
||||||
|
st->stages[nstages].radix=radix;
|
||||||
|
st->stages[nstages].nr=nfft;
|
||||||
|
st->stages[nstages].twiddle = (kiss_fft_cpx*)((char*)st + st->allocsize);
|
||||||
|
|
||||||
|
make_twiddles( st->stages[nstages].twiddle,nfft,radix,inverse_fft );
|
||||||
|
st->allocsize = newsize;
|
||||||
|
st->nstages = nstages+1;
|
||||||
|
}
|
||||||
|
*pnfft = nfft;
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* void * kiss_fft_alloc(int nfft,int inverse_fft)
|
* void * kiss_fft_alloc(int nfft,int inverse_fft)
|
||||||
@ -179,26 +211,36 @@ void fft_work(int N,kiss_fft_cpx *f,const kiss_fft_cpx * twid,int twid_step)
|
|||||||
void * kiss_fft_alloc(int nfft,int inverse_fft)
|
void * kiss_fft_alloc(int nfft,int inverse_fft)
|
||||||
{
|
{
|
||||||
kiss_fft_state * st=NULL;
|
kiss_fft_state * st=NULL;
|
||||||
// allocate one large buffer to hold the state, twiddle buffers, and bit-rev indices
|
int tmp;
|
||||||
int size = sizeof(kiss_fft_state) + (nfft>>1)*sizeof(kiss_fft_cpx) + nfft*sizeof(int);
|
int i;
|
||||||
|
int allocsize=sizeof(kiss_fft_state) + nfft*sizeof(int);
|
||||||
|
|
||||||
st = ( kiss_fft_state *)malloc(size);
|
st = ( kiss_fft_state *)malloc( allocsize );
|
||||||
if (st) {
|
st->nstages=0;
|
||||||
st->twiddle = (kiss_fft_cpx*)(st+1); // pointer just beyond the kiss_fft_state struct
|
st->allocsize=allocsize;
|
||||||
st->swap_indices = (int*)( st->twiddle + (nfft>>1) );// pointer just beyond the twiddle buffer
|
st->unscramble_indices = (int*)(st+1);// just past end of buffer
|
||||||
st->nfft = nfft;
|
|
||||||
// initialize the twiddle factors
|
for (i=0;i<nfft;++i)
|
||||||
make_twiddles(st->twiddle,nfft,inverse_fft);
|
st->unscramble_indices[i] = i;
|
||||||
// create list of index-swaps
|
|
||||||
st->nswap = make_bit_reverse_indices(st->swap_indices,nfft);
|
fprintf(stderr,"factoring %d: ",nfft);
|
||||||
|
|
||||||
|
tmp=nfft;
|
||||||
|
st = decompose( st,&tmp,2,inverse_fft);
|
||||||
|
fprintf(stderr,"\n");
|
||||||
|
|
||||||
|
// TODO factor 3,5,7,11 ???
|
||||||
|
if ( tmp > 1 ) {
|
||||||
|
fprintf(stderr,"%d not factorable by 2,3 (%d remaining)\n",nfft,tmp);
|
||||||
|
free(st);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return st;
|
return st;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void kiss_fft(const void * cfg,kiss_fft_cpx *f)
|
void kiss_fft(const void * cfg,kiss_fft_cpx *f)
|
||||||
{
|
{
|
||||||
const kiss_fft_state * st = cfg;
|
const kiss_fft_state * st = cfg;
|
||||||
fft_work(st->nfft, f, st->twiddle , 1 );
|
fft_work( f, st->stages , st->nstages );
|
||||||
undo_bit_rev(f,st->swap_indices,st->nswap);
|
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void fft_file(FILE * fin,FILE * fout,int nfft,int isinverse)
|
void fft_file(FILE * fin,FILE * fout,int nfft,int isinverse,int useascii)
|
||||||
{
|
{
|
||||||
void *st;
|
void *st;
|
||||||
kiss_fft_cpx * buf;
|
kiss_fft_cpx * buf;
|
||||||
@ -36,7 +36,13 @@ void fft_file(FILE * fin,FILE * fout,int nfft,int isinverse)
|
|||||||
|
|
||||||
while ( fread( buf , sizeof(kiss_fft_cpx) * nfft ,1, fin ) > 0 ) {
|
while ( fread( buf , sizeof(kiss_fft_cpx) * nfft ,1, fin ) > 0 ) {
|
||||||
kiss_fft( st , buf );
|
kiss_fft( st , buf );
|
||||||
fwrite( buf , sizeof(kiss_fft_cpx) , nfft , fout );
|
if (useascii) {
|
||||||
|
int i;
|
||||||
|
for (i=0;i<nfft;++i)
|
||||||
|
fprintf(fout, "(%g,%g) ", (double)buf[i].r,(double)buf[i].i);
|
||||||
|
}else{
|
||||||
|
fwrite( buf , sizeof(kiss_fft_cpx) , nfft , fout );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free(st);
|
free(st);
|
||||||
free(buf);
|
free(buf);
|
||||||
@ -48,11 +54,13 @@ int main(int argc,char ** argv)
|
|||||||
int isinverse=0;
|
int isinverse=0;
|
||||||
FILE *fin=stdin;
|
FILE *fin=stdin;
|
||||||
FILE *fout=stdout;
|
FILE *fout=stdout;
|
||||||
|
int useascii=0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int c=getopt(argc,argv,"n:i");
|
int c=getopt(argc,argv,"n:ia");
|
||||||
if (c==-1) break;
|
if (c==-1) break;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
case 'a':useascii=1;break;
|
||||||
case 'n':nfft = atoi(optarg);break;
|
case 'n':nfft = atoi(optarg);break;
|
||||||
case 'i':isinverse=1;break;
|
case 'i':isinverse=1;break;
|
||||||
}
|
}
|
||||||
@ -70,7 +78,7 @@ int main(int argc,char ** argv)
|
|||||||
++optind;
|
++optind;
|
||||||
}
|
}
|
||||||
|
|
||||||
fft_file(fin,fout,nfft,isinverse);
|
fft_file(fin,fout,nfft,isinverse,useascii);
|
||||||
|
|
||||||
if (fout!=stdout) fclose(fout);
|
if (fout!=stdout) fclose(fout);
|
||||||
if (fin!=stdin) fclose(fin);
|
if (fin!=stdin) fclose(fin);
|
||||||
|
Loading…
Reference in New Issue
Block a user