I have implemented fft algorithm on my Panda 2 using rlp. The problem is that I sometimes get funky results. For example when I generate sound on my comp I get good frequency reading every forth-fifth time, between that are some random results. Also thing are getting worse when I lower sound frequency, it's getting harder and harder to read right freq value. I suspect that problem lies in microphone calibration. I tried to measure relative silence and set that voltage value as zero. It helped a bit, but not enough. Maybe I should try 256 point fft instead of 128 point, but I fear that would slow things down significantly. I am using this mic:Nema strane :: SHOP Template and this amp circuit:LM386 microphone amplifier | Low voltage. Mostly harmless...
This is my code:
#define pi 3.14159265358979323846
float vReal[128];
float vImag[128];
float samples=128;
float sampling=10000;
float sqrt(float m)
{
float i=0;
float x1,x2;
while( (i*i) <= m )
i+=0.1;
x1=i;
int j;
for(j=0;j<10;j++)
{
x2=m;
x2/=x1;
x2+=x1;
x2/=2;
x1=x2;
}
return x2;
}
float cos(float x)
{
x+=1.5707963267944118;
float x2 = x*x;
float x4 = x2*x2;
float t1 = x * (1.0 - x2 / (2*3));
float x5 = x * x4;
float t2 = x5 * (1.0 - x2 / (6*7)) / (1.0* 2*3*4*5);
float x9 = x5 * x4;
float t3 = x9 * (1.0 - x2 / (10*11)) / (1.0* 2*3*4*5*6*7*8*9);
float x13 = x9 * x4;
float t4 = x13 * (1.0 - x2 / (14*15)) / (1.0* 2*3*4*5*6*7*8*9*10*11*12*13);
float result = t4;
result += t3;
result += t2;
result += t1;
return result;
}
void Windowing(float *vData,unsigned samples)
{
unsigned i;
for (i = 0; i < (samples >> 1); i++)
{
float indexMinusOne = i;
float ratio = (indexMinusOne / (samples-1));
float weighingFactor = 1.0;
weighingFactor = 0.54 - (0.46 * cos(2.0 * 3.141592653 * ratio));
vData[i] *= weighingFactor;
vData[samples - (i + 1)] *= weighingFactor;
}
}
void swap(float *i, float *j)
{
float temp;
temp = *i;
*i = *j;
*j = temp;
}
void Fft(float *vR, float *vI,unsigned samples)
{
unsigned j = 0;
unsigned i;
for (i = 0; i < (samples-1); i++)
{
if (i < j)
{
swap(&vR[i], &vR[j]);
swap(&vI[i], &vI[j]);
}
unsigned k = (samples >> 1);
while (k <= j)
{
j -= k;
k >>= 1;
}
j += k;
}
float c1 = -1.0;
float c2 = 0.0;
unsigned l2 = 1;
unsigned l;
for (l = 0; l < 7; l++)// 7=exponent(samples)
{
unsigned l1 = l2;
l2 <<= 1;
float u1 = 1.0;
float u2 = 0.0;
for (j = 0; j < l1; j++)
{
unsigned i;
for (i = j; i < samples; i += l2)
{
unsigned i1 = i + l1;
float t1 = u1 * vR[i1] - u2 * vI[i1];
float t2 = u1 * vI[i1] + u2 * vR[i1];
vR[i1] = vR[i] - t1;
vI[i1] = vI[i] - t2;
vR[i] += t1;
vI[i] += t2;
}
float z = (u1 * c1) - (u2 * c2);
u2 = (u1 * c2) + (u2 * c1);
u1 = z;
}
c2 = sqrt((1.0 - c1) / 2.0);
c2 = -c2;
c1 = sqrt((1.0 + c1) / 2.0);
}
for (i = 0; i < samples; i++)
{
vR[i] /= samples;
vI[i] /= samples;
}
}
float getFundamental(float *vR, float *vI,unsigned samples)
{
float freq,max;
unsigned i,maxIndex;
maxIndex=1;
max=0.0;
for (i = 0; i < samples; i++)
{
vR[i] = sqrt((vR[i])*(vR[i]) + (vI[i])*(vI[i]));
}
for(i=1;i<samples/2;i++)
{
if(vR[i]>max)
{
max=vR[i];
maxIndex=i;
}
}
freq = maxIndex * sampling / samples;
return freq;
}
int GHAL_AnalogIn_Read(unsigned char channel)
{
return ((*((int*)(ADC_DATA_BASE_ADDRESS) + channel)) >>8) & 0x3FF;
}
int ReadAudio(unsigned int *generalArray, void **args, unsigned int argsCount ,unsigned int *argSize)
{
int i=0;
float x;
unsigned char channel = *(unsigned char*)args[0];
while(i<samples)
{
vImag[i]=0;
vReal[i] =(unsigned char)GHAL_AnalogIn_Read(channel)-5;//-5 because of my mic
i++;
RLPext->Delay(100);
}
Windowing(vReal,samples);
Fft(vReal, vImag,samples);
x=getFundamental(vReal, vImag,samples);
return x;
}