paramsen / noise

Noise is an Android wrapper for kissfft, a FFT implementation written in C.
Apache License 2.0
325 stars 41 forks source link

Show calculation of the magic number in FFTBandView #6

Closed cypherdare closed 4 years ago

cypherdare commented 4 years ago

Since the AudioRecord uses AudioFormat.ENCODING_PCM_16BIT, the range of the recorded floats are Short.MIN_VALUE..Short.MAX_VALUE.

Then in MainActivity, the energy values are doubled before applying the FFT. (I'm also curious about the reason for doubling them.)

I would therefore expect the max magnitude to be

val maxConst = (2.0 * Short.MIN_VALUE).pow(2.0) + (2.0 * Short.MAX_VALUE).pow(2.0)

which evaluates to very close to exactly 8 times bigger than what you have.

How did you come up with the value 175M? Clearly there's a problem in my reasoning, because it looks correct with 175M.

paramsen commented 4 years ago

Hi, you are correct about the range! So, the doubling is actually just a step from the first iteration of the sample project, and serves no purpose in the current implementation (but some hard coded constants depend on it now).

The constant on the other hand was simply approximated on a couple of devices to get a somewhat visually appealing histogram (the var name maxConst is misleading) - it turns out that the average max value of each FFT band magnitude is close to 1/8 of the max magnitude (on Android).

Note that I created the sample project to give others a simple reference on how to record audio on Android, and how to render some real time graphs :)

cypherdare commented 4 years ago

Thank you for the explanation. I see why this works differently than the math I've been using in my project. You're averaging magnitudes across a somewhat wide band. The average is rarely going to be anywhere close to the true maximum because that would mean every bin in that range is at full power. Even more so because you're averaging linear magnitudes rather than decibels.

And thank you for these bindings! I'll be using it in the next version of my music visualizer for reacting to the microphone. It has been a breeze getting it working--very clean API. Up until now I've only been using Android's finicky Visualizer class to get the output mix with the FFT already applied.