Edit: Discard the method. It does have the problem you describe (going up with a note doesn't always give the same band amplitude).
Hello Axon.
I have another aproach that you could try out.
I am not sure if this is mathematically correct, but for my intended application (realtime power spectrum) it fits it well.
The concept is modifying the angle of the FFT analysis so that it increments exponentially instead of linearly.
Note: I know this doesn't look like an FFT analysis. It was some code I improved upon.
Input is pSamples
output is amp
l =left, r = right.
scope_spec_bands is an adjustable bar to show more or less bars. (from 16 to MAX_SCOPE_BANDS)
const int MAX_SCOPE_BANDS = 128;
const int SCOPE_SPEC_SAMPLES = 1024;
float *pSamplesL;
float *pSamplesR;
float aal[MAX_SCOPE_BANDS];
float aar[MAX_SCOPE_BANDS];
float bbl[MAX_SCOPE_BANDS];
float bbr[MAX_SCOPE_BANDS];
float ampl[MAX_SCOPE_BANDS];
float ampr[MAX_SCOPE_BANDS];
void InitSpectrum()
{
const float barsize = float(SCOPE_SPEC_SAMPLES>>1)/scope_spec_bands;
const float samplesFactor = SCOPE_SPEC_SAMPLES/16.0f;
for (int i=SCOPE_SPEC_SAMPLES-1;i>=0;i--)
{
//Linear -2pi to 2pi.
const float constant = 2.0f * helpers::math::pi_f * (-0.5f + ((float)i/(SCOPE_SPEC_SAMPLES-1)));
//Hanning window
const float window = 0.50 - 0.50 * cosf(2.0f * M_PI * i / (SCOPE_SPEC_SAMPLES - 1));
float j=0.0f;
for(int h=0;h<scope_spec_bands;h++)
{
//this makes it somewhat logaritmic.
//float th=(j*j/SCOPE_SPEC_SAMPLES)*constant;
//This simulates a constant note scale.
float th = powf(2.0f,j/samplesFactor)*constant;
//this is linear
//float th=j* constant;
cth[i][h] = cosf(th) * window;
sth[i][h] = sinf(th) * window;
j+=barsize;
}
}
}
void run() {
memset (aal,0,sizeof(aal));
memset (bbl,0,sizeof(bbl));
memset (aar,0,sizeof(aar));
memset (bbr,0,sizeof(bbr));
for (int i=0;i<SCOPE_SPEC_SAMPLES;i++)
{
const float wl=pSamplesL[i];
const float wr=pSamplesR[i];
for(int h=0;h<scope_spec_bands;h++)
{
aal[h]+=wl*cth[i][h];
bbl[h]+=wl*sth[i][h];
aar[h]+=wr*cth[i][h];
bbr[h]+=wr*sth[i][h];
}
}
for (int h=0;h<scope_spec_bands;h++)
{
ampl[h]= sqrtf(aal[h]*aal[h]+bbl[h]*bbl[h])/(SCOPE_SPEC_SAMPLES>>1);
ampr[h]= sqrtf(aar[h]*aar[h]+bbr[h]*bbr[h])/(SCOPE_SPEC_SAMPLES>>1);
}
}