slight restructuring, clean up

This commit is contained in:
Mark Borgerding 2003-08-09 14:22:30 +00:00
parent db556661ed
commit b95e3ea18a
6 changed files with 24 additions and 193 deletions

View File

@ -1,5 +1,7 @@
SPEEDTESTFILE=/dev/shm/kissfft_speedtest
SPEEDTESTNSAMPS=1000
all: kiss_fft_s kiss_fft_f kiss_fft_d freqpeak tones testsig
all: kiss_fft_s kiss_fft_f kiss_fft_d
kiss_fft_s: kiss_fft.h kiss_fft.c
gcc -Wall -O3 -o kiss_fft_s -DFIXED_POINT -DFFT_UTIL kiss_fft.c -lm
@ -10,27 +12,17 @@ kiss_fft_f: kiss_fft.h kiss_fft.c
kiss_fft_d: kiss_fft.h kiss_fft.c
gcc -Wall -O3 -o kiss_fft_d -Dkiss_fft_scalar=double -DFFT_UTIL kiss_fft.c -lm
freqpeak: kiss_fft.h kiss_fft.c freqpeak.c
gcc -Wall -O3 -o freqpeak freqpeak.c kiss_fft.c -lm
testsig: testsig.c
gcc -Wall -O3 -o testsig testsig.c -lm
tones: tones.c
gcc -Wall -O3 -o tones tones.c -lm
clean:
rm -f kiss_fft_s kiss_fft_f kiss_fft_d *~ fftin.dat fftout.dat \
freqpeak testsig tones
rm -f kiss_fft_s kiss_fft_f kiss_fft_d *~ fftin.dat fftout.dat $(SPEEDTESTFILE)
test: all
./test.oct
speedtest: /dev/shm/junk kiss_fft_f
time ./kiss_fft_f < /dev/shm/junk > /dev/null
speedf: kiss_fft_f $(SPEEDTESTFILE)
time ./kiss_fft_f < $(SPEEDTESTFILE) > /dev/null
/dev/shm/junk:
dd if=/dev/urandom bs=8192 count=1000 of=/dev/shm/junk
$(SPEEDTESTFILE):
dd if=/dev/zero bs=8192 count=$(SPEEDTESTNSAMPS) of=$(SPEEDTESTFILE)
tarball: clean
tar -czf kiss_fft.tar.gz .

25
README
View File

@ -12,10 +12,14 @@ USAGE:
void * cfg = kiss_fft_alloc( nfft ,inverse_fft );
while ...
...
... // put kth sample in cx_buf_in_out[k].r and cx_buf_in_out[k].i
kiss_fft( cfg , cx_buf_in_out );
...
... // transformed
free(cfg);
Note: frequency-domain data is stored from dc to 2pi.
so cx_buf_in_out[0] is the dc bin of the FFT
and cx_buf_in_out[nfft/2] is the Nyquist bin
Declarations are in "kiss_fft.h", along with a brief description of the
two functions you'll need to use. Code definitions are in kiss_fft.c, along
@ -53,8 +57,8 @@ last bit of performance.
PERFORMANCE:
(on Athlon XP 2100+, with gcc 2.96, optimization O3, float data type)
Kiss performed 1000 1024-pt ffts in 136 ms. This translates to 7.5 Msamples/s.
Just for comparison, it took md5sum 160 ms to process the same amount of data
Kiss performed 1000 1024-pt ffts in 110 ms of cpu time (132ms real time).
For comparison, it took md5sum 160ms cputime to process the same amount of data
DO NOT:
... use Kiss if you need the absolute fastest fft in the world
@ -67,13 +71,16 @@ UNDER THE HOOD:
addressing is corrected as the last step in the transform. No scaling is done.
LICENSE:
BSD, see COPYING for details.
BSD, see COPYING for details. Basically, "free to use, give credit where due, no guarantees"
TODO:
Make the fixed point scaling and bit shifts more easily configurable.
Document/revisit the input/output fft scaling
See if the fixed point code can be optimized a little without adding complexity.
*) Add sample code for parallel ffts (stereo) packed into re,im components of time sequence.
*) Add simple windowing function, e.g. Hamming : w(i)=.54-.46*cos(2pi*i/(n-1))
*) Could mixed-radix FFTs be made simple enough to stand by the KISS principle?
*) Make the fixed point scaling and bit shifts more easily configurable.
*) Document/revisit the input/output fft scaling
*) See if the fixed point code can be optimized a little without adding complexity.
AUTHOR:
Mark Borgerding
mark@borgerding.net
Mark@Borgerding.net

View File

@ -1,87 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
#include <stdio.h>
#include <math.h>
#include "kiss_fft.h"
#define NFFT 1024
int main(int argc, char ** argv)
{
int k;
void * st;
float fs=44100;
short sampsin[2*NFFT];
float lmag2[NFFT/2];
float rmag2[NFFT/2];
int peakr=0,peakl=0;
int removedc=1;
kiss_fft_cpx cbuf[NFFT];
int nbufs=0;
st = kiss_fft_alloc(NFFT,0);
memset( lmag2 , 0 , sizeof(lmag2) );
memset( rmag2 , 0 , sizeof(rmag2) );
while ( fread( sampsin , sizeof(short) * 2*NFFT, 1 , stdin ) == 1 ) {
//perform two ffts in parallel by packing the left&right channels into the real and imaginary
for (k=0;k<NFFT;++k) {
cbuf[k].r = sampsin[2*k];
cbuf[k].i = sampsin[2*k+1];
}
if (removedc) {
float dcr=0,dci=0;
for (k=0;k<NFFT;++k){
dcr += cbuf[k].r;
dci += cbuf[k].i;
}
dcr /= NFFT;
dci /= NFFT;
for (k=0;k<NFFT;++k) {
cbuf[k].r -= dcr;
cbuf[k].i -= dci;
}
}
// perform the fft on the L+R packed buffer
kiss_fft( st , cbuf );
// get the half-symmetric FFTs for the Left and Right Channels
for (k=0;k<NFFT/2;++k) {
int k2 = (NFFT-k)%NFFT;
kiss_fft_cpx r,l;
r.r = (cbuf[k].r + cbuf[k2].r) * 0.5;
r.i = (cbuf[k].i - cbuf[k2].i) * 0.5;
l.r = (cbuf[k].i + cbuf[k2].i) * 0.5;
l.i = (cbuf[k].r - cbuf[k2].r) * 0.5;
rmag2[k] += r.r * r.r + r.i * r.i;
lmag2[k] += l.r * l.r + l.i * l.i;
}
++nbufs;
}
free(st);
for (k=0;k<NFFT/2;++k) {
if (rmag2[peakr] < rmag2[k])
peakr = k;
if (lmag2[peakl] < lmag2[k])
peakl = k;
}
printf("%d buffers\n",nbufs);
printf("peak frequency R:%.3fdB @ %.1f Hz\n",10*log10(rmag2[peakr]) , peakr*fs/NFFT);
printf(" L:%.3fdB @ %.1f Hz\n",10*log10(lmag2[peakl]) , peakl*fs/NFFT);
return 0;
}

View File

@ -140,7 +140,6 @@ void undo_bit_rev( kiss_fft_cpx * f, const int * swap_indices,int nswap)
}
#define OPT1
// the heart of the fft
static
void fft_work(int N,kiss_fft_cpx *f,const kiss_fft_cpx * twid,int twid_step)
@ -149,23 +148,10 @@ void fft_work(int N,kiss_fft_cpx *f,const kiss_fft_cpx * twid,int twid_step)
{ // declare automatic variables in here to reduce stack usage
int n;
kiss_fft_cpx csum,cdiff;
#ifdef OPT1
const kiss_fft_cpx * cur_twid = twid+twid_step;
kiss_fft_cpx *f1 = f;
kiss_fft_cpx *f2 = f+N;
C_SUB( cdiff, *f1 , *f2 );
C_ADD( csum, *f1 , *f2 );
*f1++ = csum;
*f2++ = cdiff;
for (n=1;n<N;++n)
#else
const kiss_fft_cpx * cur_twid = twid;
kiss_fft_cpx *f1 = f;
kiss_fft_cpx *f2 = f+N;
for (n=0;n<N;++n)
#endif
{
C_ADD( csum, *f1 , *f2 );
C_SUB( cdiff, *f1 , *f2 );

View File

@ -1,32 +0,0 @@
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int usage()
{
fprintf(stderr,"usage:testsig nsamps\n");
exit(1);
return 1;
}
double randphase()
{
return (double)rand()*2*3.14159/RAND_MAX;
}
int main(int argc, char ** argv)
{
float samps[2];
int nsamps;
if (argc != 2)
return usage();
nsamps = atoi( argv[1] );
while (nsamps-- > 0) {
samps[0]=sin( randphase() );
samps[1]=sin( randphase() );
fwrite(samps,sizeof(samps),1,stdout);
}
return 0;
}

35
tones.c
View File

@ -1,35 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <memory.h>
#include <malloc.h>
#include <stdio.h>
#include <math.h>
#include "kiss_fft.h"
#define PI 3.14159
int main(int argc, char ** argv)
{
int k;
float fs=44100;
float fr=1,fl=300;
float th[2] = {0,0};
float thinc[2] = {2*PI*fr/fs,2*PI*fl/fs };
while (1){
for (k=0;k<2;++k){
short s;
th[k] += thinc[k];
if (th[k] > 2*PI){
th[k] -= 2*PI;
}
s=(short)32767*cos( th[k] );
fwrite(&s,sizeof(s),1,stdout);
}
}
return 0;
}