Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FFT spectrum normalization #33

Open
therenotomorrow opened this issue Dec 14, 2017 · 5 comments
Open

FFT spectrum normalization #33

therenotomorrow opened this issue Dec 14, 2017 · 5 comments

Comments

@therenotomorrow
Copy link

Hello, @corbanbrook
I have some question regarding the normalization of FFT results. See the link:

https://github.com/corbanbrook/dsp.js/blob/master/dsp.js#L269

Why you choose bSi = 2 / this.bufferSize? In general, to return a FFT amplitude equal to the amplitude signal which performs in FFT, need to normalize FFT data by the number of sample points. Like this:

bSi = 1 / this.bufferSize

I think it's a bug.

@tekhedd
Copy link

tekhedd commented Mar 13, 2018

I also believe this is a bug. To test it empirically (hey why not), I calculated the RMS of the input signal and the RMS of the transformed signal. They should be ~equal. The default is simply wrong. If you change to 1 (or divide the magnitude of the output bins by 2) the results are correct within 5-6% for noise signals and look like a rounding error for a pure sine input.

@PoorWeakCat
Copy link

It's not a bug at all. After FFT processing, the frequency spectrum contains two parts: positive frequency and negative frequency, which are symmetrical to each other. The amplitude of each frequency component in each part is equal to half of the actual frequency amplitude, so the final result needs to be multiplied by 2 instead of 1.You can try to input a signal to test it.

@therenotomorrow
Copy link
Author

Yes, if it need to multiple result by 2 it is correct. Agree with you.

@tpoint75
Copy link

for me the right result is:
bSi = 2 / Math.sqrt(this.bufferSize * this.sampleRate),

If you will respect the windowing you have to calculate:
winMeansq = 0;
for(var i=0; i < this.bufferSize; i++) {
let val = window.func(this.bufferSize, i);
winMeansq += val * val;
}
winMeansq = Math.sqrt(1 / Math.sqrt( winMeansq / this.sampleRate));

then its:
winMeansq * bSi

@tpoint75
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants