I'm trying to access the level of the mic through Java.
I don't need to record anything, I just want to know a relative scale of sound level.
Is this possible in real-time?
If it's impossible, maybe this could work:
Start recording when the level is over a certain value, stop when the level drops under a certain level for a certain time
Recording bits of a quarter second and reading it's volume, and if it's under the threshold stop recording.
Thanks in advance
You can access microphones through the Sound API, but it won't give you a simple loudness level. You'll just have to capture the data and make your own decision about how loud it is.
http://download.oracle.com/javase/tutorial/sound/capturing.html
Recording implies saving the data, but here you can discard the data once you've finished determining its loudness.
The root mean squared method is a good way of calculating the amplitude of a section of wave data.
In answer to your comment, yes, you'd capture a short length of data (maybe just a few milliseconds worth) and calculate the amplitude of that. Repeat this periodically depending on how often you need updates. If you want to keep track of previous loudnesses and compare them, that's up to you - at this point it's just comparing numbers. You might use the average of recent loudnesses to calculate the ambient loudness of the room, so you can detect sudden increases in noise.
I don't know how much overhead there is in turning audio capture on and off, but you may be better off keeping the TargetDataLine
open all the time, and just calculating the loudness when you need it. While the line is open you do need to keep calling read() on it though, otherwise the application will hang waiting for you to read data.
http://www.technogumbo.com/tutorials/Java-Microphone-Selection-And-Level-Monitoring/Java-Microphone-Selection-And-Level-Monitoring.php
Pretty good article on this. Helped me out a lot.
From what i can tell, this uses the root mean squared stuff talked about in @Nick's answer
Basically:
public int calculateRMSLevel(byte[] audioData)
{
long lSum = 0;
for(int i=0; i < audioData.length; i++)
lSum = lSum + audioData[i];
double dAvg = lSum / audioData.length;
double sumMeanSquare = 0d;
for(int j=0; j < audioData.length; j++)
sumMeanSquare += Math.pow(audioData[j] - dAvg, 2d);
double averageMeanSquare = sumMeanSquare / audioData.length;
return (int)(Math.pow(averageMeanSquare,0.5d) + 0.5);
}
and the usage:
int level = 0;
byte tempBuffer[] = new byte[6000];
stopCapture = false;
try {
while (!stopCapture) {
if (targetRecordLine.read(tempBuffer, 0, tempBuffer.length) > 0) {
level = calculateRMSLevel(tempBuffer);
}
}
targetRecordLine.close();
} catch (Exception e) {
System.out.println(e);
System.exit(0);
}