I have some code here, but the software seems to spit out incorrect values for some notes. For example, it tells me my frequency is "947" for a lower note and "775" for a slightly higher note. From there though, it seems to generally work. Why could this be?
Here's my 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
double[] hps = HPS(magnitudes);
int maxIndex = maxIndex(hps);
int freq = (int) (maxIndex * format.getSampleRate() / numberOfSamples);
System.out.println(freq);
}
}
private static final int HPS_ORDER = 2;
// Harmonic Product Spectrum
private static double[] HPS(double[] magnitudes) {
double[] hps = new double[magnitudes.length];
int hpsLength = magnitudes.length / (HPS_ORDER+1);
for (int i = 0; i < hps.length; i++) {
if (i < hpsLength) {
hps[i] = magnitudes[i];
} else {
hps[i] = Float.NEGATIVE_INFINITY;
}
}
for (int i = 1; i <= HPS_ORDER; i++) {
int dsFactor = i+1;
for (int j = 0; j < hpsLength; j++) {
float avg = 0;
for (int k = 0; k < dsFactor; k++) {
avg += magnitudes[j*dsFactor + k];
}
hps[j] += avg / dsFactor;
}
}
return hps;
}
I could be missing something very obvious, but I don't see it. If anyone can offer assistance, it would be greatly appreciated!