mirror of
https://github.com/mborgerding/kissfft.git
synced 2025-05-27 21:20:27 -04:00
slight restructuring, clean up
This commit is contained in:
parent
db556661ed
commit
b95e3ea18a
24
Makefile
24
Makefile
@ -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
|
kiss_fft_s: kiss_fft.h kiss_fft.c
|
||||||
gcc -Wall -O3 -o kiss_fft_s -DFIXED_POINT -DFFT_UTIL kiss_fft.c -lm
|
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
|
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
|
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:
|
clean:
|
||||||
rm -f kiss_fft_s kiss_fft_f kiss_fft_d *~ fftin.dat fftout.dat \
|
rm -f kiss_fft_s kiss_fft_f kiss_fft_d *~ fftin.dat fftout.dat $(SPEEDTESTFILE)
|
||||||
freqpeak testsig tones
|
|
||||||
|
|
||||||
test: all
|
test: all
|
||||||
./test.oct
|
./test.oct
|
||||||
|
|
||||||
speedtest: /dev/shm/junk kiss_fft_f
|
speedf: kiss_fft_f $(SPEEDTESTFILE)
|
||||||
time ./kiss_fft_f < /dev/shm/junk > /dev/null
|
time ./kiss_fft_f < $(SPEEDTESTFILE) > /dev/null
|
||||||
|
|
||||||
/dev/shm/junk:
|
$(SPEEDTESTFILE):
|
||||||
dd if=/dev/urandom bs=8192 count=1000 of=/dev/shm/junk
|
dd if=/dev/zero bs=8192 count=$(SPEEDTESTNSAMPS) of=$(SPEEDTESTFILE)
|
||||||
|
|
||||||
tarball: clean
|
tarball: clean
|
||||||
tar -czf kiss_fft.tar.gz .
|
tar -czf kiss_fft.tar.gz .
|
||||||
|
25
README
25
README
@ -12,10 +12,14 @@ USAGE:
|
|||||||
|
|
||||||
void * cfg = kiss_fft_alloc( nfft ,inverse_fft );
|
void * cfg = kiss_fft_alloc( nfft ,inverse_fft );
|
||||||
while ...
|
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 );
|
kiss_fft( cfg , cx_buf_in_out );
|
||||||
...
|
... // transformed
|
||||||
free(cfg);
|
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
|
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
|
two functions you'll need to use. Code definitions are in kiss_fft.c, along
|
||||||
@ -53,8 +57,8 @@ last bit of performance.
|
|||||||
PERFORMANCE:
|
PERFORMANCE:
|
||||||
(on Athlon XP 2100+, with gcc 2.96, optimization O3, float data type)
|
(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.
|
Kiss performed 1000 1024-pt ffts in 110 ms of cpu time (132ms real time).
|
||||||
Just for comparison, it took md5sum 160 ms to process the same amount of data
|
For comparison, it took md5sum 160ms cputime to process the same amount of data
|
||||||
|
|
||||||
DO NOT:
|
DO NOT:
|
||||||
... use Kiss if you need the absolute fastest fft in the world
|
... 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.
|
addressing is corrected as the last step in the transform. No scaling is done.
|
||||||
|
|
||||||
LICENSE:
|
LICENSE:
|
||||||
BSD, see COPYING for details.
|
BSD, see COPYING for details. Basically, "free to use, give credit where due, no guarantees"
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
Make the fixed point scaling and bit shifts more easily configurable.
|
*) Add sample code for parallel ffts (stereo) packed into re,im components of time sequence.
|
||||||
Document/revisit the input/output fft scaling
|
*) Add simple windowing function, e.g. Hamming : w(i)=.54-.46*cos(2pi*i/(n-1))
|
||||||
See if the fixed point code can be optimized a little without adding complexity.
|
*) 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:
|
AUTHOR:
|
||||||
Mark Borgerding
|
Mark Borgerding
|
||||||
mark@borgerding.net
|
Mark@Borgerding.net
|
||||||
|
87
freqpeak.c
87
freqpeak.c
@ -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;
|
|
||||||
}
|
|
14
kiss_fft.c
14
kiss_fft.c
@ -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
|
// 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(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
|
{ // declare automatic variables in here to reduce stack usage
|
||||||
int n;
|
int n;
|
||||||
kiss_fft_cpx csum,cdiff;
|
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;
|
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+N;
|
||||||
for (n=0;n<N;++n)
|
for (n=0;n<N;++n)
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
C_ADD( csum, *f1 , *f2 );
|
C_ADD( csum, *f1 , *f2 );
|
||||||
C_SUB( cdiff, *f1 , *f2 );
|
C_SUB( cdiff, *f1 , *f2 );
|
||||||
|
32
testsig.c
32
testsig.c
@ -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
35
tones.c
@ -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;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user