3

I'm having some trouble understanding how to use KissFFT (1.2.9) correctly. All I am trying to achieve for now is to perform an FFT and then immediately perform an iFFT to reconstruct the original signal again. The code snippet below demonstrates what I'm doing:

void test(short* timeDomainData, int length)
{
    // Create the configurations for FFT and iFFT...
    kiss_fftr_cfg fftConfiguration = kiss_fftr_alloc( length, 0, NULL, NULL );
    kiss_fftr_cfg ifftConfiguration = kiss_fftr_alloc( length, 1, NULL, NULL );

    // Allocate space for the FFT results (frequency bins)...
    kiss_fft_cpx* fftBins = new kiss_fft_cpx[ length / 2 + 1 ];

    // FFT...
    kiss_fftr( fftConfiguration, timeDomainData, fftBins );

    // iFFT...
    kiss_fftri( ifftConfiguration, fftBins, timeDomainData );
}

What I found is that this actually crashes at run-time. I found that by dividing the size by 2 when creating the KissFFT configurations stopped the crashing:

kiss_fftr_cfg fftConfiguration = kiss_fftr_alloc( length / 2, 0, NULL, NULL );
kiss_fftr_cfg ifftConfiguration = kiss_fftr_alloc( length / 2, 1, NULL, NULL );

However, when I play the reconstructed audio data it's mostly silent with the odd crackle.

Can anyone point me in the right direction?

Many thanks, P

Edit 1: This is how I include the KissFFT header file and define the FIXED_POINT variable:

#define FIXED_POINT 16
#include "kiss_fftr.h"

This ensures that the typedef'd 'kiss_fft_scalar' type is forced to int16_t (short).

Edit 2: The target platform is Android, so I have also added the following to my Android.mk file:

LOCAL_CPPFLAGS += -DFIXED_POINT
protectedmember
  • 349
  • 5
  • 20

3 Answers3

0

I noticed you are sending in shorts. Are you sure you've compiled everything to use int16_t as the DATATYPE? Sometimes a mismatch of preprocessor environments can cause a problem.

Also, the fixed point version scales downward both directions (fwd,inv). So if you expect to reconstruct your signal, you'll want to multiply things by a total of nfft. I'd recommend multiplying with saturation in two stages.

e.g. if you're doing an FFT+IFFT of size 1024, then multiply by 32 after the FFT, then again by 32 after the IFFT.

Mark Borgerding
  • 8,117
  • 4
  • 30
  • 51
  • Mark - I was really hoping you'd respond. I'm certain I've set the correct datatype, I've updated my original post with a code example of how I include the KissFFT header and define the FIXED_POINT variable. (I updated the original post because these comments won't allow me to add code snippets). A couple of questions: What am I meant to be multiplying? And how did you deduce the value of 32? My FFT size is 16384... Thankyou, P – protectedmember Jun 08 '12 at 16:18
  • Hi Mark, while I really appreciate your input I still don't understand your response? – protectedmember Jun 11 '12 at 12:14
  • I'm sorry to bump this but I still do not have the answer. I understand that scaling must take place but I do not understand, cannot find the answer to and your replies do not describe *what* needs to be scaled and by how much. Most of the questions floating around the internet asking about Kiss FFT and scaling are answered with "have you read the ReadMe?"... Mark, if you wrote the library then could you please provide a code snippet that performs an FFT on an array of shorts and then iFFT to reconstruct the original signal? Thanks, P – protectedmember Jun 28 '12 at 14:01
  • The data must be scaled. Since FFTs are linear, you can *mathematically* do it before or after the FFT or IFFT. However, in fixed-point processing, you may not be able scale values without overflow and represent values in a limited range. That is why I suggest breaking up the scaling into stages. – Mark Borgerding Jun 29 '12 at 14:20
  • 2
    It's not a case of writing my code for me - I'm perfectly fine with that thank you. However, you have released Kiss FFT and there are *many* people having trouble with this. Simply writting "read the Read Me" and giving non-direct answers to direct questions only tarnishes the reputation of the library. I am going to have one last stab at this, otherwise I shall be forced to use another library like many other people inn the same boat as myself. – protectedmember Jul 01 '12 at 15:47
0

I'm not sure about the silence, but if you're getting lots of crackles then it may because you're processing adjacent blocks independently rather than using Overlap-Add, where you effectively cross-fade between each block to get a smoother characteristic.

the_mandrill
  • 29,792
  • 6
  • 64
  • 93
  • if he is not manipulating the frequency domain data, then there should not be any discontinuities at the buffer boundaries. – Mark Borgerding Jun 08 '12 at 12:54
  • That is true. After implementing some filtering or transformations it may need overlap-add though. However in this case it wouldn't explain the clicks. The fact that the FFT call crashes suggests that the size of one of the buffers isn't correct. Is Nfft greater than length? – the_mandrill Jun 08 '12 at 14:18
  • Ahh yes, overlap-add... I'm familiar with this technique although I'm hoping that I won't need to use it. The user is allowed to modify the following frequencies: 31.5, 63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000 (ISO 1/3 Octave). Under the hood, I am smoothing the values of the frequency bins between 16 (1 before the 31.5) and 20000Hz (1 after the 16000). So, if the user cannot modify anything before 31.5 or anythign after 16000 do I still need to overlap-add? – protectedmember Jun 08 '12 at 16:28
  • I'm not sure, I'm a bit rusty on Overlap-Add. If you are just doing simple filtering then you may not need it. If you're doing signal analysis and reconstruction (as I have in the past) then O-A gives much better results as it effectively allows for interpolation between frames. – the_mandrill Jun 08 '12 at 21:13
  • If you are directly changing the values in the frequency domain, then yes -- you need overlap add (or something else to mitigate Gibb's phenomenon). But that is not the question asked. – Mark Borgerding Jun 10 '12 at 19:53
0

I'm struggling to do the same thing in Android, haven't got it yet (see here!), but I can see a problem in your code: "fftBins" needs to be "length" size. The reason is that it is the raw transform, not the frequency magnitude/phases... I think? Or have I got it wrong?

Community
  • 1
  • 1
cmbryan
  • 395
  • 2
  • 9
  • Ah - A fellow developer lost in the midst of Fourier Transforms! Now I feel better as I know I'm not alone! The size of 'fftBins' is correct - the first bin is DC (zero) then you have the first half of a symmetric set of bins. I'm not entirely sure why the results are symmetric (something to do with the fact that it's a 'real' transform), but I know that the bins you are given after the FFT would simply be mirrored. – protectedmember Jun 10 '12 at 17:00
  • Please see the complete example you requested [here.](http://stackoverflow.com/questions/10957604/kissfft-forward-inverse-is-outputting-noise-why/11264685#11264685) I think the frequency spectrum does contain the mirror and so does need to be the same length as the input, which explains your crash. – cmbryan Jun 29 '12 at 15:36