Bom dia Galera, estava tentando implementar um software de detecção de frequência, e estou usando de base essa referência:
http://ww2.ce.pdn.ac.lk/users/roshanr/research/papers/herath07implementation.pdf
Eu vi o algoritmo para calculo de FFT usado por ele:
Main:
While there is data in data chunk
Call Subroutine1 with 256 samples
End while
For (i = 0 to 256)
FindMax (|totalCos[i] + totalSin[i]|)
location = i
End
Frequency = SampleRate * location / (2*255)
End Main
Subroutine1: Input data[]
For (i=0 to 256)
For (j=0 to 256)
X = (-2 * π * i * j ) / 256
cosPart [i] = cosPart [i] + data [j] * Cos (X)
sinPart [i] = sinPart [i] + data [j] * Sin (X)
End For
totalCos [i] = totalCos [i] + cosPart [i]
totalSin [i] = totalSin [i] + sinPart [i]
End For
End Subroutine1
Com base neste algoritmo desenvolvi uma classe:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package conversor;
/**
*
* @author tiagor
*/
public class FFT {
private int interval=0;
private double[]totalCos;
private double[]totalSin;
private double[]soma;
public double getFrequencia(byte[]data, int sampleRate, int bitsPerSample){
totalCos = new double[bitsPerSample];
totalSin = new double[bitsPerSample];
soma = new double[bitsPerSample];
byte[] temp = new byte[bitsPerSample];
double sMajor = 0;
interval = bitsPerSample;
while(interval<data.length){
int h=0;
for(int g=(interval-bitsPerSample);g<data.length;g++){
if(g<interval){
temp[h]=data[g];
System.out.println(g+"Inicia de novo: "+temp[h]+" "+h);
h = h+1;
}
}
fft(bitsPerSample, temp);
interval +=bitsPerSample;
}
sMajor = findMax(soma);
return (sampleRate*sMajor/(2*bitsPerSample));
}
private void fft(int bitsPerSample, byte[]temp){
double[] cosPart = new double[bitsPerSample];
double[] sinPart = new double[bitsPerSample];
for(int i=0;i<bitsPerSample;i++){
for(int j=0;j<bitsPerSample;j++){
double X = ((-2 * Math.PI * i * j) / bitsPerSample);
cosPart[i] += temp[j]* Math.cos(X);
sinPart[i] += temp[j]* Math.sin(X);
}
/*if(i==0){
totalCos[i] = cosPart[i];
totalSin[i] = sinPart[i];
}else{
totalCos[i] = totalCos[i-1] + cosPart[i];
totalSin[i] = totalSin[i-1] + sinPart[i];
}*/
totalCos[i] += cosPart[i];
totalSin[i] += sinPart[i];
soma[i] = totalCos[i] + totalSin[i];
}
}
private double findMax(double[]soma){
double major=0;
for(int i=0;i<soma.length;i++){
if(soma[i]>major){
major = soma[i];
//major = i;
}
}
return major;
}
}
Porém estou com uma dificuldade. Ao mandar um som de exemplo, o valor me sai um tanto quanto alto:
os parâmetros do audio são esses: Channels: 1 SampleRate: 11025 ByteRate: 11025 BlockAlign: 1 BitsPerSample: 8 DataSize: 5071
e a frequencia retornada é esta: 1668165.[telefone removido]
Gostaria de ver com alguém que entende melhor de matemática, ou já lidou com implementações deste tipo, o ponto que estou errando, para eu melhor implementar meu código.
Desde já, valeu!!!