Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FFT nightmare )

Tags:

c++

fft

I'm using Ooura's FFT to analyse some white noise (duration 75368 smp with 44100 samples of noise). the results i have are quite strange : even with dividing by the number of samples, i have less than 1.0 how is that?

i'm using RDFT and inverse RDFT

actually i have magnitude results like that for example :

m1 3.47157
m1 8.50726
m1 29.0233
m1 9.64618
m1 43.2969
m1 60.7396
m1 48.3495
m1 35.8336
m1 32.7611
m1 24.1925
m1 26.8244
m1 17.9448
m1 29.7936
m1 23.1585
m1 15.1243
m1 8.89132
m1 14.6676
m1 18.1515
m1 27.5357
m1 5.6661
m1 19.0589

with a FFT size of 4096 and the peak is: 79.119

i was hoping to have results close to one number only (like 1.0 or whatever)

and if i apply a simple multiplication (like a volume) to the magnitudes, the sound is altered like with a strange filter...

here are the functions i use to convert from re/im to magnitude/phase:

double SuperFFT::_GetPhase(double real, double imaginary)
 {
      return atan2(imaginary, real);
 }

 double SuperFFT::_GetMagnitude(double real, double imaginary)
 {
    return sqrt((real * real) + (imaginary * imaginary));
 } 

the phase seems good (stays between -PI and PI)

and if i pass a simple sine at 240hz (duration 75368 samples) i have these magnitudes

m1 0.262643
m1 0.369384
m1 0.543982
m1 0.851133
m1 1.44518
m1 2.76168
m1 6.37861
m1 21.2081
m1 239.998
m1 775.211
m1 585.819
m1 63.0807
m1 12.06
m1 4.37815
m1 2.07803
m1 1.14897
m1 0.701917
m1 0.460003
m1 0.317885
m1 0.228747

this is close to 1 if i divide by the duration and multiply by 100 is it normal?

why is the sound broken when i multiply the magnitudes ? Is my FFT broken or am i missing something?

thanks for any help

EDIT : i use OLA of course

Jeff

like image 753
IonOne Avatar asked Apr 28 '26 02:04

IonOne


1 Answers

FFT implementations typically neglect scaling, allowing some “natural” multiplication of values to occur during the FFT. This is because scaling is often unimportant (e.g., the phase as you have calculated it does not change with scaling, and relationships between certain aspects of the signal do not depend on scale) and because it may be more efficient to adjust the scaling all at one point in the operations instead of in each individual FFT, inverse FFT, and other operations.

You can find the scaling caused by the FFT you are using by setting an input array to 1 in the first element and 0 in all other elements, performing an FFT, and examining the results. Most likely there will be a 1 in the real part of each output element. In this case, the total “energy” of the input is multiplied by N, where N is the number of input elements.

(Since you appear to be doing a real-to-complex transform, there is some subtlety here: N real inputs produces N complex outputs. However, they are symmetrical. For two of them, the element is its own complex conjugate, which compels it to be real. For the remaining N-2, half of them are conjugates of the other half. Because of this, most FFT implementations return you only two real and N/2-1 complex elements. The remaining results are implied: the two missing imaginary components are zero, and the missing N/2-1 complex elements are conjugates of the returned elements. When calculating the total energy of the signal, I mean the energy calculated from all of the N results, not just the ones explicitly returned.)

The maximum possible magnitude any one output element can have is the total energy of all the input. This occurs when the input is a perfect sine wave (with any phase): All its energy is at one frequency, and none is at any other.

Therefore, to calculate the maximum value any output element might have, multiply the maximum energy your input might have by the scaling of your FFT. Then, to normalize the output so that no output exceeds one in magnitude, multiply by the inverse of that product.

like image 68
Eric Postpischil Avatar answered Apr 29 '26 17:04

Eric Postpischil