1
votes

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 ;)

2
One problem is that you don't appear to be applying a suitable window function prior to the FFT.Paul R
auto-correlation function is another way of getting fundamental frequency.flies

2 Answers

2
votes

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)

0
votes

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).