At what signal are you looking?
Compare it to other FFT representations you like.
There is always some playing, making it aesthetic, rounding. It is not 100% precise and cannot be with a limited number of output representations which are shown on LEDs or so. It is a decision for what signals that should work and look as desired. So it is your decision at what bin/frequency you exactly start and end. Even for technically oriented systems there has to be done some manual adjustmens. (what is your goal?)
Of course it is possible to calculate the distribution/mapping of the FFT bins to have a logarithmic represantion as good as possible if that is needed. This is a formula which works in Matlab ...:
Code:
matrix_width = 16;
fft_size = 1024;
freqBinIndex_vec = (2.^((0:matrix_width-1)/matrix_width * log2(fft_size/2)) -1)';
freqBinIndex_vec = floor(freqBinIndex_vec)+1;
Fs = 44100;
binFrequencies = Fs/fft_size*(0:fft_size/2);
for n = 1:matrix_width
Nbins = freqBinIndex_vec(n) - freqBinIndex_vec(max(n-1,1));
disp(['n= ' num2str(n) ...
' fftbin=' num2str(freqBinIndex_vec(n)) ...
' ->Nbins=' num2str(Nbins) ...
' left freq[Hz]=' num2str(sprintf('%4.2f ', binFrequencies (freqBinIndex_vec(n)))) ])
end
That gives:
Code:
n= 1 fftbin=1 ->Nbins=0 left freq[Hz]=0.00
n= 2 fftbin=1 ->Nbins=0 left freq[Hz]=0.00
n= 3 fftbin=2 ->Nbins=1 left freq[Hz]=43.07
n= 4 fftbin=3 ->Nbins=1 left freq[Hz]=86.13
n= 5 fftbin=4 ->Nbins=1 left freq[Hz]=129.20
n= 6 fftbin=7 ->Nbins=3 left freq[Hz]=258.40
n= 7 fftbin=10 ->Nbins=3 left freq[Hz]=387.60
n= 8 fftbin=15 ->Nbins=5 left freq[Hz]=602.93
n= 9 fftbin=22 ->Nbins=7 left freq[Hz]=904.39
n= 10 fftbin=33 ->Nbins=11 left freq[Hz]=1378.13
n= 11 fftbin=49 ->Nbins=16 left freq[Hz]=2067.19
n= 12 fftbin=72 ->Nbins=23 left freq[Hz]=3057.71
n= 13 fftbin=107 ->Nbins=35 left freq[Hz]=4565.04
n= 14 fftbin=158 ->Nbins=51 left freq[Hz]=6761.43
n= 15 fftbin=234 ->Nbins=76 left freq[Hz]=10034.47
n= 16 fftbin=346 ->Nbins=112 left freq[Hz]=14857.91
Hope this helps as a starting point and orientation.
(no guarantee that this calculation is without errors; Nbins is the difference to the last... and not displayed right for the lowest frequencies; note that in Matlab counting starts at 1 and not 0; probably you have to check the exact counting and indices; keep in mind that you want to map from the 1024 fft bins the first half from 0..511; so 511 is the last bin you want to include)
Note that in the example (SpectrumAnalyser) there is another mapping chosen which differs from this. What I am showing here is the way which is usually used in spectrum analysers.
when you define
C++:
int frequencyBinsHorizontal[matrix_width] = {
4, 4, 6, 8, 8, 12, 16, 19, 25, 30, 38, 48, 60, 74, 94
};
and matrix_width is set to 16, one entry in the array is missing.
In the example (SpectrumAnalyser) there is matrix_width set to 60, and in the array (frequencyBinsHorizontal) there are 60 entries.
That could be also a cause to have a strange behaviour of your last led part.
Another thing is the representation of level. Human perception is also logarithmic here. So it is good to use something like this and work in decibels:
C++:
level[i] = 20 * log10(level[i] + 0.000001);
I think this is not done in the example.
You can decide about the range to be used, e.g. -50 to 0 (dbFS is the unit here).
To make it look smooth, it can also make sense to have some filtering on the level. Or to use "attack and release times", i.e. a quicker reaction time, when levels go up, and then let them go down more slowly.