adash
adash

Reputation: 29

Spectral analysis using FFT, fundamental frequency derivation

I need to perform spectral analysis of a simple wav file. The things I have already done :

Read file into byte array :

ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead = 0;

while ((bytesRead = audioStream.read(buffer)) != -1) {
    baos.write(buffer, 0, bytesRead);
}

fileByteArray = baos.toByteArray();

Then I transform it to the real values (doubles). I've got sample values stored in double[] array.

How can I make FFT of those samples + estimate fundamental frequency?

Using JTranforms library I tried something like this :

DoubleFFT_1D fft = new DoubleFFT_1D(reader.getSpectrum().getYvalues().length);
double[] x = reader.getSpectrum().getYvalues();
double[] frequencyArray = new double[x.lenght/2];
double[] amplitudeArray = new double[x.lenght/2];
fft.realForward(x);
int i=0;
for (int j = 0; j < x.length-2; j += 2) {
    i++;
    this.frequencyArray[i] = i;
    this.amplitudeArray[i] = Math.sqrt(Math.pow(doub[j],2) + Math.pow(doub[j + 1],2));
}

Is it correct?

All suggestions are appreciated ;)

Upvotes: 1

Views: 1538

Answers (2)

mostar
mostar

Reputation: 4821

You should use autocorrelation which can be computed efficiently with FFT:

DoubleFFT_1D fft = new DoubleFFT_1D(reader.getSpectrum().getYvalues().length);
DoubleFFT_1D ifft = new DoubleFFT_1D(reader.getSpectrum().getYvalues().length);

fft.realForward(x);
for (int i = 0; i < x.length/2; i++) {
    x[2*i] = Math.sqrt(Math.pow(x[2*i],2) + Math.pow(x[2*i+1],2));
    x[2*i+1] = 0;
}
ifft.realInverse(x);
for (int i = 1; i < x.length; i++)
    x[i] /= x[0];
x[0] = 1.0;

This code gives you a list of values for which:

x[i]: corelation with i shifts

So, for example if you have a high value (close to 1) for x[n], that means you have a fundemental signal period that is: n*(1000/sampleRateHz) msecs. This is equivalent to a frequency of: sampleRateHz/(1000*n)

Upvotes: 2

hotpaw2
hotpaw2

Reputation: 70703

The values in the frequency array need to be related to the sample rate and the length of the FFT.

You will still need to solve the problem of determining the fundamental frequency versus the peak frequencies. For that, you may want to use a pitch detection/estimation algorithm, of which there are many (look for research papers on the topic).

Upvotes: 0

Related Questions