How to sample microphone on Android without recording to get live amplitude/level?

Tom picture Tom · Jan 23, 2011 · Viewed 47.3k times · Source

I was trying to get the amplitude level of a microphone on Android like so:

MediaRecorder recorder = new MediaRecorder();
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);

Timer timer = new Timer();
timer.scheduleAtFixedRate(new RecorderTask(recorder), 0, 1000);

private class RecorderTask extends TimerTask {
    private MediaRecorder recorder;

    public RecorderTask(MediaRecorder recorder) {
        this.recorder = recorder;
    }

    public void run() {
        Log.v("MicInfoService", "amplitude: " + recorder.getMaxAmplitude());
    }
}

Unfortunately, this only returns 0 all the time.

It appears that for this to work I have to actually start recording. Is that correct?

If so, do I need to record for 500ms, get amplitude, stop recording and repeat?

Finally, do I have to record to a file? I do not need to save this audio file, can't I just get the current amplitude or highest amplitude since last call of the current live microphone input without recording?

Any help is appreciated, thanks.

Answer

Benjamin Kaiser picture Benjamin Kaiser · Oct 30, 2014

The solution from Toumal works, however I wasn't able to get a high enough refresh rate for my needs. So I ended up using the SoundMeter.java class that Toumal linked but modified it to use the code from this answer

Here is the code I used, which provides a much better refresh rate:

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;

public class SoundMeter {

    private AudioRecord ar = null;
    private int minSize;

    public void start() {
        minSize= AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
        ar = new AudioRecord(MediaRecorder.AudioSource.MIC, 8000,AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT,minSize);
        ar.startRecording();
    }

    public void stop() {
        if (ar != null) {
            ar.stop();
        }
    }

    public double getAmplitude() {
        short[] buffer = new short[minSize];
        ar.read(buffer, 0, minSize);
        int max = 0;
        for (short s : buffer)
        {
            if (Math.abs(s) > max)
            {
                max = Math.abs(s);
            }
        }
        return max;
    }

}