36

Using MediaRecorder I capture sound from device's microphone. From the sound I get I need only to analyze the sound volume (sound loudness), without saving the sound to a file.

Two questions:

  1. How do I get the loudness for the sound at a given moment in time?
  2. How do I do the analyze without saving the sound to a file?

Thank you.

GrIsHu
  • 29,068
  • 10
  • 64
  • 102
Zelter Ady
  • 6,266
  • 12
  • 48
  • 75

3 Answers3

53
  1. Use mRecorder.getMaxAmplitude();

  2. For the analysis of sound without saving all you need is use mRecorder.setOutputFile("/dev/null");

Here´s an example, I hope this helps

public class SoundMeter {

    private MediaRecorder mRecorder = null;

    public void start() {
            if (mRecorder == null) {
                    mRecorder = new MediaRecorder();
                    mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                    mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
                    mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                    mRecorder.setOutputFile("/dev/null"); 
                    mRecorder.prepare();
                    mRecorder.start();
            }
    }

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

    public double getAmplitude() {
            if (mRecorder != null)
                    return  mRecorder.getMaxAmplitude();
            else
                    return 0;

    }
}
Piotr Olaszewski
  • 6,017
  • 5
  • 38
  • 65
Ana Llera
  • 1,376
  • 16
  • 32
  • 1
    I like the /dev/null, but I don't understand how to get the MaxAmplitude few times per second. – Zelter Ady Jan 06 '13 at 12:13
  • 1
    I need to continuously record the sound level (100 times per second). The recorded sound level (loudness) should be from the moment I record it. – Zelter Ady Jan 06 '13 at 12:18
  • 1
    I solved. The getMaxAmplitude() returns is explained like this on android development website: the maximum absolute amplitude measured since the last call, or 0 when called for the first time, and to get any seconds this value I used a Timer. – Zelter Ady Jan 06 '13 at 13:26
  • Perfect, I'm glad it works for you. If you have any questions about the code let me know. – Ana Llera Jan 06 '13 at 13:44
  • For now works ok, but if I think to the future I'd like to ask one more question: Do you know any better way to get the loudness of a sound? I try to analyze the background sound on the place where the phone is (some medical experimental app) and it is possible to be in need for more details (like wave frequency, voice detection, etc). – Zelter Ady Jan 06 '13 at 14:23
  • MediaRecorder compress the audio. If your app is analyzing audio data for information beyond maximum amplitude, you should use the data from AudioRecord instead of MediaRecorder. – Ana Llera Jan 06 '13 at 16:41
  • 1
    Thank you Anna. Do you know any tutorial about using AudioRecorder and sound analyze? I cannot ffind more good information on this domain - or I;m not good in chosing between information's sources. – Zelter Ady Jan 07 '13 at 12:49
  • 1
    Ana Llera , getAmplitude() return int. MB best use int getAmplitude()? – Fortran Oct 14 '17 at 08:50
9

If you want to analyse a sample of sound taken directly from the microphone without saving the data in a file, you need to make use of the AudioRecord Object as follows:

int sampleRate = 8000;
try {
    bufferSize = AudioRecord.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_IN_MONO,
        AudioFormat.ENCODING_PCM_16BIT);
    audio = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate,
            AudioFormat.CHANNEL_IN_MONO,
            AudioFormat.ENCODING_PCM_16BIT, bufferSize);
} catch (Exception e) {
    android.util.Log.e("TrackingFlow", "Exception", e);
}

Then you have to start recording when ready:

audio.startRecording();

Now it's time to start reading samples as follows:

short[] buffer = new short[bufferSize];

    int bufferReadResult = 1;

    if (audio != null) {

        // Sense the voice...
        bufferReadResult = audio.read(buffer, 0, bufferSize);
        double sumLevel = 0;
        for (int i = 0; i < bufferReadResult; i++) {
            sumLevel += buffer[i];
        }
        lastLevel = Math.abs((sumLevel / bufferReadResult));

The last code combines all the different samples amplitudes and assigns the average to the lastLeveL variable, for more details you can go to this post.

Regards!

Martin Cazares
  • 13,637
  • 10
  • 47
  • 54
  • 4
    This algorithm is broken - you can't add up values like that, as these are signed values. You have to take the *magnitudes* and average those. – Chris Stratton May 01 '15 at 04:41
  • @Martin: Is the "lastLevel" is the MaxAmplitude ?? Actually i need to calculate the 'dbValue' and 'MeanLevelTotal' value, and i am not using prerecorded file. I am working on live recording. – Mitesh Shah Jun 30 '15 at 10:04
4

I played around with a few sound recording source code apps but it took a while to get it.

You can copy Google's NoiseAlert source code - the SoundMeter code, which is what I've used.

getMaxAmplitude ranges from 0 to 32768. The EMA stuff I didn't bother using.

In your main activity, you have to declare a MediaRecorder object and call its start() function as Anna quoted.

For more info, you can refer to my project: http://kaitagsd.wordpress.com/2013/03/25/arduino-project-amplify-part-2-i-e-how-to-transmit-send-data-from-android-to-arduino-bluesmirf-silver-using-bluetooth/ Where I needed to send the value of the sound amplitude over BlueTooth.

Exact code is here: https://github.com/garytse89/Amplify/tree/master/Android%20Code/src/com/garytse89/allin

Just skim through the parts that have anything to do with the MediaRecorder object associated.

Gary
  • 831
  • 7
  • 15
  • The web page http://kaitagsd.wordpress.com/2013/03/25/arduino-project-amplify-part-2-i-e-how-to-transmit-send-data-from-android-to-arduino-bluesmirf-silver-using-bluetooth is "no longer available" according to Wordpress. – CODE-REaD May 28 '16 at 14:50