I am feeding audio from an electric cello into the mic port on my computer, and I would like my program to understand when no audio is being inputted and if audio is being inputted, what note/frequency is being played.
I am able to get the cello to play through the targetdataline and out to the sourcedataline in java. I also implemented a live frequency detection portion using fft according to Java: How to get current frequency of audio input?, but it doesn't work that well with the cello. It does perform somewhat well when I whistle, however.
I would appreciate any guidance into understanding how to use the information gained by the targetdataline and the cello output to see what is being played. Alternative approaches such as using different applications are welcome.
AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);
try {
//making SourceDataLine for writing
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
final SourceDataLine sourceLine = (SourceDataLine)AudioSystem.getLine(info);
sourceLine.open(format/*, #*/);
//#5800 is the smallest i got it to work so far
//making TargetDataLine for getting in
info = new DataLine.Info(TargetDataLine.class, format);
final TargetDataLine targetLine = (TargetDataLine)AudioSystem.getLine(info);
targetLine.open(format);
final byte[] buf = new byte[2048]; // <--- increase this for higher frequency resolution
final int numberOfSamples = buf.length / format.getFrameSize();
final JavaFFT fft = new JavaFFT(numberOfSamples);
Thread liveThread = new Thread() {
@Override public void run() {
int readBytes;
try {
while(true) {
readBytes = targetLine.read(buf, 0, buf.length);
sourceLine.write(buf, 0, readBytes);
final float[] samples = decode(buf, format);
final float[][] transformed = fft.transform(samples);
final float[] realPart = transformed[0];
final float[] imaginaryPart = transformed[1];
final double[] magnitudes = toMagnitudes(realPart, imaginaryPart);
System.out.println("length" + magnitudes.length);
System.out.println(ecello.findMaxMagnitude(magnitudes));
}
}
catch(Exception e) {
e.printStackTrace();
}
}
};
targetLine.start();
sourceLine.start();
liveThread.start();
System.out.println("Started recording...");
Thread.sleep(3000000);
targetLine.stop();
targetLine.close();
System.out.println("Ended recording");
System.exit(0);
}
catch(Exception e) {
e.printStackTrace();
}
}
private int findMaxMagnitude(double[] input){
//Calculates Maximum Magnitude of the array
double max = input[0];
double temp;
int index = 0;
for(int i = 1; i<input.length; i++){
temp = input[i];
if(temp>max){
max = temp;;
index = i;
}
}
return index;
}
Using this fft on the cello input has not given good results. I think I can detect when no input is being played by checking the magnitude of the biggest frequency and see if it passes a threshold, but that is future work.