PDA

View Full Version : Is there a logarithmic function for FFT bin selection for any given # of bands?



MrTom
01-27-2016, 07:54 AM
Here's the FFT example code:

// read the 512 FFT frequencies into 16 levels music is heard in octaves, but the
// FFT data is linear, so for the higher octaves, read many FFT bins together.
level[0] = fft1024.read(0);
level[1] = fft1024.read(1);
level[2] = fft1024.read(2, 3);
level[3] = fft1024.read(4, 6);
level[4] = fft1024.read(7, 10);
level[5] = fft1024.read(11, 15);
level[6] = fft1024.read(16, 22);
level[7] = fft1024.read(23, 32);
level[8] = fft1024.read(33, 46);
level[9] = fft1024.read(47, 66);
level[10] = fft1024.read(67, 93);
level[11] = fft1024.read(94, 131);
level[12] = fft1024.read(132, 184);
level[13] = fft1024.read(185, 257);
level[14] = fft1024.read(258, 359);
level[15] = fft1024.read(360, 511);


That's great and all for 16 bands, but what if I wanted 32, 64, or say 40 bands. I can't manually figure out all this before hand.
Is there a simple log function to reduce this to a simple for() loop?

defragster
01-27-2016, 08:36 AM
MrTom - did you see this thread? Spectrum-Analyzer (https://forum.pjrc.com/threads/28430-Spectrum-Analyzer) - it might lead you in the right direction. I put your question in Bing ("FFT bin selection for any given # of bands pjrc") (http://www.bing.com/search?q=FFT+bin+selection+for+any+given+%23+of+ba nds+pjrc) and first 'hit' found that old thread as I remembered it . . . if only Bing could find @KPC . . .

PaulStoffregen
01-27-2016, 01:10 PM
Here's a little Perl script that might help....



#! /usr/bin/perl

$e = 1.3937;
$num = 16;

$sum = 0;
$count = 0;

for ($i=0; $i < $num; $i++) {
printf "%2d ", $i;
$n = $e ** $i;
printf "%6.2f ", $n;
$d = int($n + 0.5);
printf "%3d ", $d;
$sum += $n;
printf "%6.2f ", $sum;
printf "%3d ", $count;
$count += $d - 1;
printf "%3d ", $count;
$count++;
print "\n";
}

MrTom
01-28-2016, 05:46 AM
Well I tried the above calculations for 32 bands, do you change $num? And I got the following:
Obviously there's no bin numbered "99704". I don't think this will work.


0 1.00 1 1.00 0 0
1 1.39 1 2.39 1 1
2 1.94 2 4.33 2 3
3 2.69 3 7.02 4 6
4 3.75 4 10.77 7 10
5 5.22 5 15.99 11 15
6 7.26 7 23.25 16 22
7 10.10 10 33.35 23 32
8 14.06 14 47.41 33 46
9 19.56 20 66.96 47 66
10 27.22 27 94.18 67 93
11 37.87 38 132.05 94 131
12 52.70 53 184.75 132 184
13 73.33 73 258.08 185 257
14 102.04 102 360.12 258 359
15 141.99 142 502.11 360 501
16 197.57 198 699.68 502 699
17 274.93 275 974.61 700 974
18 382.56 383 1357.16 975 1357
19 532.33 532 1889.49 1358 1889
20 740.74 741 2630.23 1890 2630
21 1030.74 1031 3660.97 2631 3661
22 1434.27 1434 5095.24 3662 5095
23 1995.79 1996 7091.02 5096 7091
24 2777.14 2777 9868.16 7092 9868
25 3864.38 3864 13732.54 9869 13732
26 5377.29 5377 19109.83 13733 19109
27 7482.50 7482 26592.33 19110 26591
28 10411.90 10412 37004.23 26592 37003
29 14488.15 14488 51492.38 37004 51491
30 20160.27 20160 71652.65 51492 71651
31 28053.01 28053 99705.66 71652 99704

defragster
01-28-2016, 05:57 AM
The linked thread indicated the problem of more bins being a compromise. Did note lower bins groups would hold the smaller sets. With 16 bins on average for 32 groups instead of 32 bins average for 16 groups.


I realized that more than 18..20 steps make not much sense for a "pretty" display with fft256, so 16 is perhaps the best choice.

PaulStoffregen
01-28-2016, 11:32 AM
Well I tried the above calculations for 32 bands, do you change $num?

You need to edit both $e and $num.

How you choose $e involves either trail-and-error or some impressive math skills. If you figure out the math way, I'd love to hear the equation!

WMXZ
01-28-2016, 03:39 PM
You need to edit both $e and $num.

How you choose $e involves either trail-and-error or some impressive math skills. If you figure out the math way, I'd love to hear the equation!

OK,
I try to take on the challenge
first,
the perl script seems to calculate not correctly
it says (as of MtTom's post)

1.3937 ** 15 = 141.99

while a matlab script says

1.3937^15 = 145.3917
I can reproduce the numbers in MrTom's post with

e=1.3915


OK, we can argue where the error is, so it does not matter

second
from an earlier post we know that the last bin was simply adjusted, so it band width is not consistent with previous values.

But ideally we wanted to generate a logarithmic scale that ends up with the last frequency bin, having the lower bins non overlapping.

so we note that a single consistent formula for the bin count could be a cumulative sum equivalent to



ee= 1.3937;
upper_bin = cumsum(round(ee^(0:15)))-1;
lower_bin = [0 upper_bin(1:end-1)+1];


resulting in


0 1 3 6 10 15 22 32 46 66 94 133 187 262 366 511
0 1 2 4 7 11 16 23 33 47 67 95 134 188 263 367


Now, if one accepts this approach, then the approach of estimating the bounds becomes easy

determine number of bands, say 16
second determine second last desired frequency bin (here 366) describing the last band width
then we note that

511 - 366 = (cumsum(round(e^(0:15)))-1) - (cumsum(round(ee^(0:14)))-1) = round(ee^15)

so a good formula for obtaining an estimate for ee is

ee = exp(log(511-366)/15) = 1.3934

which is very close to the original value.
The difference is that the formula for estimating ee can not undo the round operation
with this value of ee the bounds become

0 1 3 6 10 15 22 32 46 66 94 132 186 261 365 510
0 1 2 4 7 11 16 23 33 47 67 95 133 187 262 366

as 510 is short of 511, the value of ee should be slightly incremented (here from 1.2934 to 1.3937)

Now,
changing the number of bands to, say 20 one would simply get with

ee=1.2824

corrected to
ee=1.2829

with the following bin boundaries

0 1 3 5 8 11 15 21 28 37 49 64 84 110 143 185 239 308 397 511
0 1 2 4 6 9 12 16 22 29 38 50 65 85 111 144 186 240 309 398

PaulStoffregen
01-28-2016, 07:34 PM
I've added a comment with a link to this thread.

https://github.com/PaulStoffregen/Audio/commit/a17093d3f8214e59a7d2968eb5bde237f1fbe24e

MrTom
01-30-2016, 10:06 AM
I got the e=1.3915 from the thread in the 2nd post in this thread.

Did some experimenting and made a "brute force" function to find a given E value. Just plug in the bands and the bins and the program does the rest to find and test the correct E value.



void setup() {
float e, n;
int b, bands, bins, count=0, d;

while (!Serial && (millis() <= 6000)); // Wait for Serial interface

bands = 20; // Frequency bands; (Adjust to desired value)
bins = 512; // FFT bins; (Adjust to desired value)

e = FindE(bands, bins); // Find calculated E value
if (e) { // If a value was returned continue
Serial.printf("E = %4.4f\n", e); // Print calculated E value
for (b = 0; b < bands; b++) { // Test and print the bins from the calculated E
n = pow(e, b);
d = int(n + 0.5);

Serial.printf( "%4d ", count); // Print low bin
count += d - 1;
Serial.printf( "%4d\n", count); // Print high bin
++count;
}
}
else
Serial.println("Error\n"); // Error, something happened
}

void loop() {
// put your main code here, to run repeatedly:

}

float FindE(int bands, int bins) {
float increment=0.1, eTest, n;
int b, count, d;

for (eTest = 1; eTest < bins; eTest += increment) { // Find E through brute force calculations
count = 0;
for (b = 0; b < bands; b++) { // Calculate full log values
n = pow(eTest, b);
d = int(n + 0.5);
count += d;
}
if (count > bins) { // We calculated over our last bin
eTest -= increment; // Revert back to previous calculation increment
increment /= 10.0; // Get a finer detailed calculation & increment a decimal point lower
}
else
if (count == bins) // We found the correct E
return eTest; // Return calculated E
if (increment < 0.0000001) // Ran out of calculations. Return previous E. Last bin will be lower than (bins-1)
return (eTest - increment);
}
return 0; // Return error 0
}


EDIT: Added an increment check "< 0.0000001", because if you try FindE(123, 512), it can never find the exact high bin of 511,
it can only find either 510 or 512, and it should be (bins-1) because the bins go from 0 to (bins-1), which is 0-511 in this case.

This should work from 2+ bands and whatever bins.

Example: 27 bands, 512 bins
E = 1.1836
0 0
1 1
2 2
3 4
5 6
7 8
9 11
12 14
15 18
19 23
24 28
29 34
35 42
43 51
52 62
63 75
76 90
91 108
109 129
130 154
155 183
184 217
218 258
259 306
307 363
364 431
432 511

varind
02-16-2017, 09:10 AM
I found this thread very interesting, and useful! By combining Mr Tom's example, the Adafruit NeoMatrix Library, Paul's SpectrumAnalyzerBasic, and adding some of my own sauce, I've created a very dynamic/scalable visualizer for WS2812's.



#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#ifndef PSTR
#define PSTR // Make Arduino Due happy
#endif

AudioInputAnalog adc1;
AudioAnalyzeFFT1024 fft1024;
AudioConnection patchCord1(adc1, fft1024);

#define PIN 2
#define WIDTH 8
#define HEIGHT 5

// MATRIX DECLARATION:
// Parameter 1 = width of NeoPixel matrix
// Parameter 2 = height of matrix
// Parameter 3 = pin number (most are valid)
// Parameter 4 = matrix layout flags, add together as needed:
// NEO_MATRIX_TOP, NEO_MATRIX_BOTTOM, NEO_MATRIX_LEFT, NEO_MATRIX_RIGHT:
// Position of the FIRST LED in the matrix; pick two, e.g.
// NEO_MATRIX_TOP + NEO_MATRIX_LEFT for the top-left corner.
// NEO_MATRIX_ROWS, NEO_MATRIX_COLUMNS: LEDs are arranged in horizontal
// rows or in vertical columns, respectively; pick one or the other.
// NEO_MATRIX_PROGRESSIVE, NEO_MATRIX_ZIGZAG: all rows/columns proceed
// in the same order, or alternate lines reverse direction; pick one.
// See example below for these values in action.
// Parameter 5 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)


// Example for NeoPixel Shield. In this application we'd like to use it
// as a 5x8 tall matrix, with the USB port positioned at the top of the
// Arduino. When held that way, the first pixel is at the top right, and
// lines are arranged in columns, progressive order. The shield uses
// 800 KHz (v2) pixels that expect GRB color data.
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(WIDTH, HEIGHT, PIN,
NEO_MATRIX_BOTTOM + NEO_MATRIX_LEFT +
NEO_MATRIX_ROWS + NEO_MATRIX_ZIGZAG,
NEO_GRB + NEO_KHZ800);

int fftBins[WIDTH];
float level[WIDTH];
int shown[WIDTH];
int peaks[WIDTH];
float scale = 80.0;
uint32_t dropTimer = millis();
uint32_t peakDropTimer = millis();

void setup() {
matrix.begin();
matrix.setTextWrap(false);
matrix.setBrightness(30);
AudioMemory(12);
getFFTBins();
}

void loop() {
display_fft(50, 1000);
matrix.show();
}

void display_fft(uint32_t levelDecay, uint32_t peakDecay) {
if (fft1024.available()) {
for (int i = 0; i < WIDTH; i++) {
if (i < WIDTH - 1) {
level[i] = fft1024.read(fftBins[i], fftBins[i + 1] - 1);
} else {
level[i] = fft1024.read(fftBins[i], 511);
}
}

int val = 0;
for (int i = 0; i < WIDTH; i++) {
// Serial.print(level[i]);
val = level[i] * scale;
if (val > HEIGHT) val = HEIGHT;
if (val >= shown[i]) {
shown[i] = val;
}
if (val >= peaks[i]) {
peaks[i] = val;
}
// Serial.print(" ");
matrix.drawLine(i, 0, i, HEIGHT - 1, 0);
matrix.drawLine(i, HEIGHT - shown[i], i, HEIGHT, Wheel(180));
matrix.drawPixel(i, HEIGHT - shown[i], Wheel(20));
matrix.drawPixel(i, HEIGHT - peaks[i], Wheel(0));
}
}

if (dropTimer + levelDecay < millis()) {
for (int i = 0; i < WIDTH; i++) {
if (shown[i] > 0) {
shown[i] = shown[i] - 1;
}
dropTimer = millis();
}
}

if (peakDropTimer + peakDecay < millis()) {
for (int i = 0; i < WIDTH; i++) {
if (peaks[i] > 0) {
peaks[i] = peaks[i] - 1;
}
peakDropTimer = millis();
}
}
//Serial.print(" cpu:");
//Serial.println(AudioProcessorUsageMax());
}


uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if (WheelPos < 85) {
return matrix.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if (WheelPos < 170) {
WheelPos -= 85;
return matrix.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return matrix.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

void getFFTBins() {
float e, n;
int b, bands, bins, count = 0, d;
while (!Serial && (millis() <= 6000)); // Wait for Serial interface

bands = WIDTH; // Frequency bands; (Adjust to desired value)
bins = 512; // FFT bins; (Adjust to desired value)

e = FindE(bands, bins); // Find calculated E value
if (e) { // If a value was returned continue
Serial.printf("E = %4.4f\n", e); // Print calculated E value
for (b = 0; b < bands; b++) { // Test and print the bins from the calculated E
n = pow(e, b);
d = int(n + 0.5);
Serial.printf( "%4d ", count); // Print low bin
fftBins[b] = count;
count += d - 1;
Serial.printf( "%4d\n", count); // Print high bin
++count;
}
}
else
Serial.println("Error\n"); // Error, something happened
}

float FindE(int bands, int bins) {
float increment = 0.1, eTest, n;
int b, count, d;

for (eTest = 1; eTest < bins; eTest += increment) { // Find E through brute force calculations
count = 0;
for (b = 0; b < bands; b++) { // Calculate full log values
n = pow(eTest, b);
d = int(n + 0.5);
count += d;
}
if (count > bins) { // We calculated over our last bin
eTest -= increment; // Revert back to previous calculation increment
increment /= 10.0; // Get a finer detailed calculation & increment a decimal point lower
}
else if (count == bins) // We found the correct E
return eTest; // Return calculated E
if (increment < 0.0000001) // Ran out of calculations. Return previous E. Last bin will be lower than (bins-1)
return (eTest - increment);
}
return 0; // Return error 0
}

tombola
03-22-2017, 12:25 AM
Thank you for this thread, was able to put it to good use here building a little LED spectrum analyser to hang off the back of my Teensy-powered Radio Music module:
https://www.instagram.com/p/BR6wnzjAp2k/?taken-by=tomwhitwell
(the matrix is one of these: https://www.boldport.com/products/the-matrix/ )

0kino7ori
05-09-2017, 04:09 AM
This document (https://courses.physics.illinois.edu/phys193/Labs/Octave_Bands.pdf) explains how to calculate frequency bands LIMITS and CENTER FREQUENCIES.

Looks like your "E" number is the ratio between any two consecutive CENTER or LIMIT frequencies.

If you divide the spectrum in full-octave bands, E = 2 = (2^1 octave), and you get about 11 bands in the spectrum.
For 1/2-octave bands, E=1,4142 (2^1/2 octave), with about 21 bands.
For 1/3 octave bands, E=1,2599 = (2^1/3 octave), with about 32 bands.

So the problem here is how to translate number of bands to a precise octave-fraction, and you can then determine "E".
With the information above, one should be able to come up with the formula and not have to brute force for a solution.

In your 27 bands example, your E (1,1836) is somewhat close to that of an 1/4 octave band split (E=1,1892).
But for that bandwidth, the audio spectrum has approximately 43 bands, not 27...
The issue is that only the 27 higher bands have a bandwidth above 43Hz.
Given the lack of resolution, it's always going to be a compromise in the last few lower bands.

WMXZ
05-09-2017, 04:24 PM
So the problem here is how to translate number of bands to a precise octave-fraction, and you can then determine "E".


If you are interested in 'standard' (third) octave bands you are stuck with the iso list of center frequencies and you can use the formula given in Wikipedia https://en.wikipedia.org/wiki/Octave_band

%% Calculate Third Octave Bands in Matlab
fcentre = 10^3 * (2 .^ ([-18:13]/3))
fd = 2^(1/6);
fupper = fcentre * fd
flower = fcentre / fd



%% Calculate Third Octave Bands in Matlab
flower = 10^3 * (2 .^ ([-18.5:12.5]/3))
fcentre = 10^3 * (2 .^ ([-18:13]/3))
fupper = 10^3 * (2 .^ ([-17.5:13.5]/3))


extending this to lower bins and translating to frequency should be easy

In the earlier posts of this thread, the question was to have only log frequency bands (not necessarily (third) octave) and the question was on dividing the 512 frequency bins into a logarithmic scale of variable number of bands, so the value of E would be calculated from the number of desired bands.

So, if some approximation would be acceptable
I would use

ee= 2^(1/3);
upper_bin = min(511,cumsum(round(ee.^(0:21)))-1);
lower_bin = [0 upper_bin(1:end-1)+1];
[lower_bin;upper_bin]
round([lower_bin;upper_bin]*44100/1024)

which results to following FFT bins


0 1 2 4 6 9 12 16 21 27 35 45 58 74 94 119 151
0 1 3 5 8 11 15 20 26 34 44 57 73 93 118 150 190

191 242 306 387 489
241 305 386 488 511

or in Hz for 44.1kHz sampling and 1024 point FFT


0 43 86 172 258 388 517 689
0 43 129 215 345 474 646 861

904 1163 1507 1938 2498 3187 4048 5125
1120 1464 1895 2455 3144 4005 5082 6460

6503 8226 10422 13178 16667 21059
8183 10379 13135 16624 21016 22007

The nominal 1/3 octave bandwidth around 1k kHz is 981 - 1122, the resulting band of the above formula is 904 - 1120 Hz which IMO is fairly close

0kino7ori
05-10-2017, 06:43 AM
0 43 86 172 258 388 517 689
0 43 129 215 345 474 646 861

904 1163 1507 1938 2498 3187 4048 5125
1120 1464 1895 2455 3144 4005 5082 6460

6503 8226 10422 13178 16667 21059
8183 10379 13135 16624 21016 22007

The nominal 1/3 octave bandwidth around 1k kHz is 981 - 1122, the resulting band of the above formula is 904 - 1120 Hz which IMO is fairly close

Thanks for the reply!
I am not sure though if you are validating or correcting my comment (that "e" could be determined by the exact octave-fraction necessary to generate the number of bands desired). I understand the original problem of the thread, but I wasn't clear enough in my post. I suspect the "e" calculation used here in this discussion might not generate the bins that one really expects.

When one intends to divide the audio spectrum in N-bands (specially if one is going to measure magnitudes for something like a level bar-graph), it's important that all of the bands have the same octave-fraction, otherwise the relative magnitudes do not represent what they are supposed to. In other words, if you run pink-noise through a precise bar-graph, you should get a straight line connecting the bars (this line can be horizontal or have a slope, depending on how the magnitudes are computed, but the line should be, well, a straight line).

The more distorted the bar-graph response, the less straight will be this line. We understand that given the discrete nature of FFT and low frequency resolution in this case (SR 44.1kHz and FFT size 1024), the bar-graph would be severely distorted in the low frequency bands. There's not much we can do here unless we change the FFT parameters. This is also why it does not make sense to have more than 16 bands (or even 10) if you prioritize precision over visuals/resolution.

But my point is that the calculation used here in this thread to derive "e" seems to distort the bar-graph response even more.
If one uses this approach to divide the spectrum in, say, 20 bands, the resulting bins are smaller (less bandwidth) than would be expected for a true equal 20-bands spectrum. While the high frequency bars would be very well aligned, they would not represent the magnitude of a 1/20th spectrum band. I suppose the formula to find "e" (or the best possible "e") for this discrete case is much more complicated, although this approximation might be very good for many applications. After all, I believe what everyone is looking for here is to find a way to choose the lower and upper bins for each band in the less distorted possible way.

I guess a good experiment would be to actually run pink noise through the FFT/bar-graph and adjust the bins in real time to compare responses and choose the "less distorted". Of course this could also be done off-line in code.

I am waiting for my Teensy to arrive and I will certainly run some tests and share my findings with you.

0kino7ori
05-10-2017, 07:31 AM
0 1 2 4 6 9 12 16 21 27 35 45 58 74 94 119 151
0 1 3 5 8 11 15 20 26 34 44 57 73 93 118 150 190

191 242 306 387 489
241 305 386 488 511

or in Hz for 44.1kHz sampling and 1024 point FFT


0 43 86 172 258 388 517 689
0 43 129 215 345 474 646 861

904 1163 1507 1938 2498 3187 4048 5125
1120 1464 1895 2455 3144 4005 5082 6460

6503 8226 10422 13178 16667 21059
8183 10379 13135 16624 21016 22007


To illustrate my previous post, in my excel calculations, if you wanted 1/3 octave bands, the bins would be:



1 1 1 1 1 2 2 3 3 4 5 6 8 10 13 16 20 25 32 40 51 64 81 102 128 162 203 256 323 407
1 1 1 1 1 2 2 3 3 4 5 7 9 12 15 19 24 31 39 50 63 80 101 127 161 202 255 322 406 511


You would have 30 bands (30 bar graphs) that would represent a (possibly?) less distorted spectrum, with each bar actually measuring energy of a 1/3 octave.
Of course you would have to repeat a lot of bins in the lower bands (even for a non-discrete division, you can have infinite bands if you start with the upper limit and calculate the next band towards DC.). Here, I chose to to start where the center frequency in the continuous domain would be around 24Hz.

WMXZ
05-10-2017, 07:41 AM
When one intends to divide the audio spectrum in N-bands (specially if one is going to measure magnitudes for something like a level bar-graph), it's important that all of the bands have the same octave-fraction, otherwise the relative magnitudes do not represent what they are supposed to. In other words, if you run pink-noise through a precise bar-graph, you should get a straight line connecting the bars (this line can be horizontal or have a slope, depending on how the magnitudes are computed, but the line should be, well, a straight line).


By definition e^(0:n) gives you logarithmic scale, what ever 'e' is chosen to be (e=2^(1/3) for third octave)
when converting these bands to FFT bins, you will always have a jitter due to finite bin width.
As it was implicit assumed not to use same frequency bin twice, no bin interpolation is done.
therefore, IMO, 'round(e^(0:n))' gives you the bin-based bandwidth closest to logarithmic scaled bandwidth.

Of course, you can convert the log bands by hand and pick the one you like best, but the OP asked for

Is there a simple log function to reduce this to a simple for() loop?

I look forward to see your simple implementation.

0kino7ori
05-10-2017, 07:59 AM
By definition e^(0:n) gives you logarithmic bandwidth, what ever 'e' is chosen to be (e=2^(1/3) for third octave)
when converting these bands to FFT bins, you will always have a jitter due to finite bin width.
As it was implicit assumed not to use same frequency bin twice, no bin interpolation is done.
therefore, IMO, 'round(e^(0:n))' gives you the bin-based bandwidth closest to logarithmic scaled bandwidth.


Sure, totally agree! I did not confront the logarithmic bandwidth generated by the code, but:
1. the actual bandwidth, and
2. the center frequency of the bar-graph (center bin).

I wish I had more math skills to try and make the point, or maybe I am totally wrong.
But experimentation should shed a light, I'll let you know!

WMXZ
05-10-2017, 08:06 AM
To illustrate my previous post, in my excel calculations, if you wanted 1/3 octave bands, the bins would be:



1 1 1 1 1 2 2 3 3 4 5 6 8 10 13 16 20 25 32 40 51 64 81 102 128 162 203 256 323 407
1 1 1 1 1 2 2 3 3 4 5 7 9 12 15 19 24 31 39 50 63 80 101 127 161 202 255 322 406 511


You would have 30 bands (30 bar graphs) that would represent a (possibly?) less distorted spectrum, with each bar actually measuring energy of a 1/3 octave.
Of course you would have to repeat a lot of bins in the lower bands (even for a non-discrete division, you can have infinite bands if you start with the upper limit and calculate the next band towards DC.). Here, I chose to to start where the center frequency in the continuous domain would be around 24Hz.

Our posts crossed.
Duplicating frequencies provides redundant values and was excluded