Android Get microphone Volume (decibels)

Source: Internet
Author: User
Tags getmessage
Basic knowledge
Measure the sound intensity. The most familiar unit is decibel (decibel, abbreviated as dB). This is a relative unit of dimensionless quantity. The calculation formula is as follows:


The numerator is the sound pressure of the measured value, and the denominator is the sound pressure of the reference value (20 micropascals. The smallest sound pressure that humans can hear).

Therefore, in daily speaking, how many decibels the sound intensity is. All have a very small reference value by default.

The physical quantity that Android device sensors can provide is the amplitude of the field, and the following formula is often used to calculate the decibel value:


After reading the amplitude of a certain piece of audio data from the SDK, take the maximum amplitude or average amplitude (it can be averaged by the square and the sum of the absolute values). Substitute into A1 of the above formula.

The question now is, what is the amplitude A0 as a reference value?

Bloggers read a lot of posts and blog posts, and here is the most muddy place.

Some blog posts take 600, which is based on the if it considers the amplitude of noise to be 600. What is calculated at this time is the decibel value relative to the background noise. If the user does not make a sound from the microphone correctly, the calculated value is basically 0 decibels. The amount of background noise in the actual use scene of the user varies greatly. It would be wrong if we also draw a gourd. Especially for those who need to make absolute decibel meters, the amplitude corresponding to the sound pressure value of 20 micropascals should be found (or a standard decibel meter can also be used as a calibration reference).

The blogger is lazy and sets A0 to 1, which is the smallest sound amplitude that the microphone of the Android device can "hear".

In this way, the measured value amplitude is directly substituted into A1 of the second formula, and the decibel value can be calculated.

Android API
To use the microphone, you need to apply for corresponding permissions in AndroidManifest.xml:
<uses-permission android:name="android.permission.RECORD_AUDIO" />
There are two classes that can obtain audio source data: android.media.MediaRecorder and android.media.AudioRecord.
MediaRecorder:
Object initialization of this class is more troublesome. Because it is designed to record a complete audio and write it into the file system. However, it is more convenient to obtain the amplitude after initialization. We can directly use its parameterless method getMaxAmplitude to obtain the maximum amplitude in the audio source data within a short period of time.

The possible drawback of just taking the maximum value is that it will be affected by extreme data. As a result, the decibel value calculated later fluctuates relatively greatly. It's just that this method is used by many recording applications to calculate the volume level.

This method returns a 16-bit integer in the range of 0 to 32767. The principle may be to take the largest absolute value of a piece of audio source data with a value range of -32768 to 32767 and return it. This value has a linear function relationship with the sound pressure value in Pascals. In addition, it should be noted that the value obtained by calling this method for the first time is 0, and the decibel value calculated by substituting into the formula is negative infinity. Therefore, it is necessary to infer this situation in the code. Can work out. Because the maximum value returned by getMaxAmplitude is 32767, the calculated maximum decibel value is 90.3.

In other words. The blogger sets the reference amplitude value to 1. The normal range of the calculated decibel value is 0 dB to 90.3 dB.

Code piece:



package com.example.atest;

import java.io.File;
import java.io.IOException;

import android.media.MediaRecorder;
import android.os.Handler;
import android.util.Log;

/**
 * amr audio processing
 */
public class MediaRecorderDemo {
    private final String TAG = "MediaRecord";
    private MediaRecorder mMediaRecorder;
    public static final int MAX_LENGTH = 1000 * 60 * 10;// Maximum recording duration 1000*60*10;
    private String filePath;

    public MediaRecorderDemo(){
        this.filePath = "/dev/null";
    }

    public MediaRecorderDemo(File file) {
        this.filePath = file.getAbsolutePath();
    }

    private long startTime;
    private long endTime;

    /**
     * Start recording using amr format
     *
     *            Recording files
     * @return
     */
    public void startRecord() {
        // start recording
/* ①Initial: instantiate the MediaRecorder object */
        if (mMediaRecorder == null)
            mMediaRecorder = new MediaRecorder();
        try {
/* ②setAudioSource/setVedioSource */
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// Set the microphone
/* ②Set the encoding of the audio file: AAC/AMR_NB/AMR_MB/Default sound (waveform) sampling */
            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
            /*
* ②Set the format of the output file: THREE_GPP/MPEG-4/RAW_AMR/Default THREE_GPP (3gp format
*. H263 video/ARM audio encoding), MPEG-4, RAW_AMR (only supports audio and the audio encoding requirement is AMR_NB)
*/
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

/* ③Preparation */
            mMediaRecorder.setOutputFile(filePath);
            mMediaRecorder.setMaxDuration(MAX_LENGTH);
            mMediaRecorder.prepare();
/* ④Start */
            mMediaRecorder.start();
            // AudioRecord audioRecord.
/* Get start time* */
            startTime = System.currentTimeMillis();
            updateMicStatus();
            Log.i("ACTION_START", "startTime" + startTime);
        } catch (IllegalStateException e) {
            Log.i(TAG,
                    "call startAmr(File mRecAudioFile) failed!"
                            + e.getMessage());
        } catch (IOException e) {
            Log.i(TAG,
                    "call startAmr(File mRecAudioFile) failed!"
                            + e.getMessage());
        }
    }

    /**
     * Stop recording
     *
     */
    public long stopRecord() {
        if (mMediaRecorder == null)
            return 0L;
        endTime = System.currentTimeMillis();
        Log.i("ACTION_END", "endTime" + endTime);
        mMediaRecorder.stop();
        mMediaRecorder.reset();
        mMediaRecorder.release();
        mMediaRecorder = null;
        Log.i("ACTION_LENGTH", "Time" + (endTime-startTime));
        return endTime-startTime;
    }

    private final Handler mHandler = new Handler();
    private Runnable mUpdateMicStatusTimer = new Runnable() {
        public void run() {
            updateMicStatus();
        }
    };

    /**
     * Update microphone status
     *
     */
    private int BASE = 1;
    private int SPACE = 100;//Interval sampling time

    private void updateMicStatus() {
        if (mMediaRecorder != null) {
            double ratio = (double)mMediaRecorder.getMaxAmplitude() /BASE;
            double db = 0;// decibel
            if (ratio> 1)
                db = 20 * Math.log10(ratio);
            Log.d(TAG,"dB value:"+db);
            mHandler.postDelayed(mUpdateMicStatusTimer, SPACE);
        }
    }
}



AudioRecord:
This class can obtain detailed sound source data values. Use the read(byte[] audioData, int offsetInBytes, int sizeInBytes) method to read a piece of audio source data from the buffer to the byte array audioData we passed in, and then we can operate on it. Such as finding the average of the sum of squares or absolute values. This can avoid the influence of individual extreme values. Make the calculation result more stable. After obtaining the average value. Assuming the sum of squares is substituted into the formula with a constant coefficient of 10. If it is an absolute value, substitute it into the formula with a constant coefficient of 20 to calculate the decibel value.

Code piece


package com.example.atest;

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

public class AudioRecordDemo {

    private static final String TAG = "AudioRecord";
    static final int SAMPLE_RATE_IN_HZ = 8000;
    static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ,
                    AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT);
    AudioRecord mAudioRecord;
    boolean isGetVoiceRun;
    Object mLock;

    public AudioRecordDemo() {
        mLock = new Object();
    }

    public void getNoiseLevel() {
        if (isGetVoiceRun) {
            Log.e(TAG, "Still recording it");
            return;
        }
        mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
                SAMPLE_RATE_IN_HZ, AudioFormat.CHANNEL_IN_DEFAULT,
                AudioFormat.ENCODING_PCM_16BIT, BUFFER_SIZE);
        if (mAudioRecord == null) {
            Log.e("sound", "mAudioRecord initialization failed");
        }
        isGetVoiceRun = true;

        new Thread(new Runnable() {
            @Override
            public void run() {
                mAudioRecord.startRecording();
                short[] buffer = new short[BUFFER_SIZE];
                while (isGetVoiceRun) {
                    //r is the actual length of data read, generally speaking, r will be less than buffersize
                    int r = mAudioRecord.read(buffer, 0, BUFFER_SIZE);
                    long v = 0;
                    // Take out the contents of buffer. Do the sum of squares
                    for (int i = 0; i <buffer.length; i++) {
                        v += buffer[i] * buffer[i];
                    }
                    // Divide the sum of squares by the total length of the data to get the volume.
                    double mean = v / (double) r;
                    double volume = 10 * Math.log10(mean);
                    Log.d(TAG, "Decibel value:" + volume);
                    // About ten times a second
                    synchronized (mLock) {
                        try {
                            mLock.wait(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                mAudioRecord.stop();
                mAudioRecord.release();
                mAudioRecord = null;
            }
        }).start();
    }
}




Code call Activity



package com.example.atest;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		new AudioRecordDemo().getNoiseLevel();
	}
	
}



Test Results



Source code: http://download.csdn.net/detail/pcaxb/9028495


Android gets the microphone volume (decibel)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.