user1352331
user1352331

Reputation: 91

Compiling and Linking KISSFFT

I have a newb problem with compiling and linking the kissfft library 'out of the box'. I've downloaded the kissfft library and extracted it to a test directory. Upon entering the directory and running 'make testall' I get the following errors, which look like the std c math library is not being linked to properly.

sharkllama@quaaludes:~/KISSFFT/kiss_fft129$ make testall
# The simd and int32_t types may or may not work on your machine 
make -C test DATATYPE=simd CFLAGADD="" test
make[1]: Entering directory `/home/sharkllama/KISSFFT/kiss_fft129/test'
cd ../tools && make all
make[2]: Entering directory `/home/sharkllama/KISSFFT/kiss_fft129/tools'
cc -o fft_simd -Wall -O3 -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Waggregate-return -Wcast-align -Wcast-qual -Wnested-externs -Wshadow -Wbad-function-cast -Wwrite-strings  -I.. -DUSE_SIMD=1 -msse -lm ../kiss_fft.c fftutil.c kiss_fftnd.c kiss_fftr.c kiss_fftndr.c
/tmp/ccFbS0yK.o: In function `kiss_fft_alloc':
kiss_fft.c:(.text+0xd17): undefined reference to `sincos'
kiss_fft.c:(.text+0xd6b): undefined reference to `floor'
kiss_fft.c:(.text+0xe07): undefined reference to `sincos'
kiss_fft.c:(.text+0xeba): undefined reference to `sqrt'
/tmp/ccbYqDcf.o: In function `kiss_fftr_alloc':
kiss_fftr.c:(.text+0x118): undefined reference to `sincos'
kiss_fftr.c:(.text+0x188): undefined reference to `sincos'
collect2: ld returned 1 exit status
make[2]: *** [fft_simd] Error 1
make[2]: Leaving directory `/home/sharkllama/KISSFFT/kiss_fft129/tools'
make[1]: *** [tools] Error 2
make[1]: Leaving directory `/home/sharkllama/KISSFFT/kiss_fft129/test'
make: *** [testall] Error 2
sharkllama@quaaludes:~/KISSFFT/kiss_fft129$ 

Clearly, the makefile is trying to link to the math library as the -lm option has been included. Can't make any sense of this. I've compiled numerous programs that properly link to the math library before. Any help would be appreciated. Thanks, -B

Upvotes: 2

Views: 4899

Answers (3)

kyr0
kyr0

Reputation: 535

As a total noob, just copy the following files into a new directory called "kiss_fft":

- _kiss_fft_guts.h
- kiss_fft.c
- kiss_fft.h
- kiss_fft_log.h

Add them to your build system, linker arguments etc. (e.g. cmake FILE(..)) just like any of your other source files.

e.g.:

file(GLOB SOURCES 
    "src/*.c"       
    "src/audio/*.c" 
    "src/audio/kiss_fft/*.c"
)

Now just do #include "./kiss_fft/kiss_fft.h" in one of your header files. You can now call any KISS FFT function without any issues. Link to the repo where you can find the code: https://github.com/mborgerding/kissfft/tree/master

Upvotes: 0

karlphillip
karlphillip

Reputation: 93468

Just wanted to share a practical example on how to build a simple application using 1D FFT/IFFT from kissfft:

g++ example.cpp -o example -I kissfft kissfft/kiss_fft.c 

example.cpp:

#include "kissfft/kiss_fft.h"

int main()
{
    // initialize input data for FFT
    float input[] = { 11.0f, 3.0f, 4.05f, 9.0f, 10.3f, 8.0f, 4.934f, 5.11f };
    int nfft = sizeof(input) / sizeof(float); // nfft = 8

    // allocate input/output 1D arrays
    kiss_fft_cpx* cin = new kiss_fft_cpx[nfft];
    kiss_fft_cpx* cout = new kiss_fft_cpx[nfft];

    // initialize data storage
    memset(cin, 0, nfft * sizeof(kiss_fft_cpx));
    memset(cout, 0, nfft * sizeof(kiss_fft_cpx));

    // copy the input array to cin
    for (int i = 0; i < nfft; ++i)
    {
        cin[i].r = input[i];
    }

    // setup the size and type of FFT: forward
    bool is_inverse_fft = false;
    kiss_fft_cfg cfg_f = kiss_fft_alloc(nfft, is_inverse_fft, 0, 0); // typedef: struct kiss_fft_state*

    // execute transform for 1D
    kiss_fft(cfg_f, cin , cout);

    // transformed: DC is stored in cout[0].r and cout[0].i
    printf("\nForward Transform:\n");
    for (int i = 0; i < nfft; ++i)
    {
        printf("#%d  %f %fj\n", i, cout[i].r,  cout[i].i);
    }

    // setup the size and type of FFT: backward
    is_inverse_fft = true;
    kiss_fft_cfg cfg_i = kiss_fft_alloc(nfft, is_inverse_fft, 0, 0);

    // execute the inverse transform for 1D
    kiss_fft(cfg_i, cout, cin);

    // original input data
    printf("\nInverse Transform:\n");
    for (int i = 0; i < nfft; ++i)
    {
        printf("#%d  %f\n", i, cin[i].r / nfft); // div by N to scale data back to the original range
    }

    // release resources
    kiss_fft_free(cfg_f);
    kiss_fft_free(cfg_i);
    delete[] cin;
    delete[] cout;

    return 0;
}    

To use the 2D transforms, include the appropriate header "kissfft/tools/kiss_fftnd.h" and adjust the build command to:

g++ example.cpp -o example -I kissfft kissfft/kiss_fft.c kissfft/tools/kiss_fftnd.c

Simple enough!

Upvotes: 2

Mark Borgerding
Mark Borgerding

Reputation: 8506

Kissfft is not really something you need to make and install like other libraries. If you need complex ffts, then all you need to do is compile the kiss_fft.c in your project. If you need something more specialized like multidimensional or real ffts, then you should also compile the apropriate file(s) from the tools dir.

The make targets are largely for development testing of kissfft. There are a lot of system requirements to do that testing. Unless you are changing the internals of kissfft, you won't need to use those testing targets.

Upvotes: 4

Related Questions