Question

I'm trying to find the max volume of the microphone input because I'm trying to find how loud a certain sound is on average so my program can recognize it by volume. The RMS calculating method is from this website(https://forums.oracle.com/forums/thread.jspa?threadID=1270831), I'm just trying to figure out how everything works...

The problem is that no matter how much noise I make the RMS level is output as 0 every time! So I've either set my targetDataLine up completely wrong and it's not capturing audio...or I've done something wrong somewhere else.

Here is what I have so far:

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;


public class MicrophoneTesting {

public MicrophoneTesting() {
    // TODO Auto-generated constructor stub
}

protected static int calculateRMSLevel(byte[] audioData)
{ // audioData might be buffered data read from a data line
    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 = sumMeanSquare + Math.pow(audioData[j] - dAvg, 2d);

    double averageMeanSquare = sumMeanSquare / audioData.length;
    return (int)(Math.pow(averageMeanSquare,0.5d) + 0.5);
}

public static void main(String[] args){

    // Open a TargetDataLine for getting microphone input & sound level
    TargetDataLine line = null;
    AudioFormat format = new AudioFormat(8000, 0, 1, true, true);
    DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); //     format is an AudioFormat object
    if (!AudioSystem.isLineSupported(info)) {
        System.out.println("The line is not supported.");
    }
    // Obtain and open the line.
    try {
        line = (TargetDataLine) AudioSystem.getLine(info);
        line.open(format);
    } catch (LineUnavailableException ex) {
        System.out.println("The TargetDataLine is Unavailable.");
    }

    Timer t = new Timer(); // I used a timer here, code is below
    while(t.seconds < 2){
    byte[] bytes = new byte[line.getBufferSize() / 5];
    line.read(bytes, 0, bytes.length);
    System.out.println("RMS Level: " + calculateRMSLevel(bytes));
    }
}
}

Timer Code:

public class Timer implements Runnable{
    int seconds;
    Thread t;

public Timer() {
    this.seconds = 0;
    t = new Thread(this, "Clap Timer");
    t.start(); // Start the thread
}

@Override
public void run() {
    // TODO Auto-generated method stub
    while(seconds < 2)
    {
        //Wait 1 second
        try {                                
            Thread.sleep(1000);
        }
        catch(Exception e) {
            System.out.println("Waiting interupted.");
        }

        seconds++;
    }
}
}
Was it helpful?

Solution

It worked when i added in line.start() after line.open().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top