I finally have a working FFT implemented, but the frequency doesn't seem to work correctly. For example, while playing a musical instrument, the notes give (somewhat) consistent but random frequency values (a "C" on my alto sax gives a 602Hz and an "E" gives a 387hz, should be ~312 and ~397 respectively, at least according to an app I have) Here's the code:
public static void main(final String[] args) throws Exception {
final AudioFormat format = new AudioFormat(
AudioFormat.Encoding.PCM_SIGNED,
44100,
16,
1,
2,
44100,
false
);
final DataLine.Info info = new DataLine.Info(
TargetDataLine.class,
format
);
final TargetDataLine targetLine = (TargetDataLine) AudioSystem.getLine(info);
targetLine.open();
targetLine.start();
final AudioInputStream audioInputStream = new AudioInputStream(targetLine);
final byte[] buf = new byte[1024];
final int numberOfSamples = buf.length / format.getFrameSize();
final JavaFFT fft = new JavaFFT(numberOfSamples);
while (true) {
audioInputStream.read(buf);
final float[] samples = decode(buf, format);
final float[][] transformed = fft.transform(samples);
final float[] real = transformed[0];
final float[] imaginary = transformed[1];
final double[] magnitudes = toMagnitudes(real, imaginary);
// do something with magnitudes
printDetectedIndex(magnitudes);
}
}
private static void printDetectedIndex(double[] magnitudes) {
int index = maxIndex(magnitudes);
float frequency = (float) index * 44100 / 1024;
int fInt = (int) frequency; // remove decimal part
System.out.println("Frequency: " + frequency + "Hz (" + fInt + "Hz)");
}
// function to return index of the largest element in array
public static int maxIndex(double[] array) {
int maxIndex = 9;
for (int i = 9; i < array.length; i++) {
if (array[i] > array[maxIndex]) {
maxIndex = i;
}
}
return maxIndex;
}
Any help would be much appreciated!