Basic knowledge
The most familiar unit for measuring sound intensity is decibels (decibel, abbreviated to DB). This is an dimensionless relative unit , and the formula is as follows:
The molecule is the measured sound pressure, the denominator is the reference value of the sound pressure (20 micro-PA, human can hear the minimum sound pressure). So in daily speaking, the sound intensity is how many decibels, is the default of a very small reference value.
and the Android device sensor can provide the physical quantity is the field amplitude (amplitude), commonly used the following formula calculates the decibel value:
After reading the amplitude of a segment of audio data from the SDK, take the maximum amplitude or average amplitude (which can be both square and average, or the absolute value of the peace), into the A1 of the above formula.
Now the question is, how much do the amplitude A0 as a reference value take ?
Bloggers check a lot of posts, Bowen, here is the most paste place. Some blog to take 600, based on the noise amplitude of the assumption that it is 600, this time to calculate the relative background noise decibel value, if the user does not sound to the microphone, the calculation of the basic is 0 db. And the user actual use scene background noise size is very different, if I also divert is wrong, especially for those who make absolute decibel requirements, should find 20 micro-PA value corresponding to the amplitude (or can also take a standard decibel meter to do calibration reference).
Bloggers are lazy, setting the A0 at 1, the minimum sound amplitude that the Android microphone can "listen" to. The decibel value can be calculated by taking the amplitude of the measured value directly into the A1 of the second formula.
Android API
Using a microphone requires that you apply the appropriate permissions in the Androidmanifest.xml:
<uses-permission android:name= "Android.permission.RECORD_AUDIO"/>
There are two classes that can get the audio source data: Android.media.MediaRecorder and Android.media.AudioRecord.
Mediarecorder:
The object initialization of this class is cumbersome because it is designed to record a complete audio and write to the file system. But it is more convenient to get the amplitude after initialization, so we can obtain the maximum amplitude of the getmaxamplitude data in a short period of time by using its parameter-free method directly. However, the possible disadvantage of maximizing value is that it will be affected by extreme data, so that the decibel value of later calculation is more volatile. But this approach is a way for many recording applications to calculate volume levels.
The method returns a range of 16-bit integers ranging from 0 to 32767, and the principle may be to take a value that is the highest in absolute values for a period of one domain-32768 to 32767 and return it. This value is linearly related to the sound pressure value of the unit Pascal. Also note that the first call to this method to obtain the value is 0, the value of the DB in the formula is negative infinity, it is necessary in the code to judge this situation. It can be calculated that the maximum decibel value is 90.3 because the Getmaxamplitude returns a maximum of 32767. That is to say, Bo Main order reference amplitude value is 1, the computed decibel value domain is 0 db to 90.3 DB.
The demo code is as follows, based on HONGFA.YY code rewriting:
Package Com.example.myapp;
Import Java.io.File;
Import java.io.IOException;
Import Android.media.MediaRecorder;
Import Android.os.Handler;
Import Android.util.Log; /** * AMR Audio processing * @author HONGFA.YY * @version creation time 2012-11-21 pm 4:33:28/public class Mediarecorderdemo {private
Final String TAG = "Mediarecord";
Private Mediarecorder Mmediarecorder;
public static final int max_length = 1000 * 60 * 10;//maximum recording length 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 * * Audio file * @return/public void Startrecord () {//Start recording/*①initial: Instantiated Med
Iarecorder Object */if (Mmediarecorder = null) Mmediarecorder = new Mediarecorder (); try {/*②setaudiosource/setvediosource */Mmediarecorder.setaudiosource (mediarecorder.audiosourCe. MIC)/Set the microphone/*② to set the encoding of the audio file: Aac/amr_nb/amr_mb/default sound (waveform) sampling/Mmediarecorder.setoutputformat (MEDIARECORDER.O
Utputformat.default); /* *② format output file: Three_gpp/mpeg-4/raw_amr/default three_gpp (3gp format *, H263 video/arm audio encoding), MPEG-4, RAW_AMR (audio only supported and audio encoding required for 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;//db if (ratio > 1) db = * MATH.LOG10 (ratio);
LOG.D (TAG, "decibel value:" +db);
Mhandler.postdelayed (Mupdatemicstatustimer, space);
}
}
}
Audiorecord:
This class can obtain a specific sound source data value. You can manipulate a segment of the audio source data using the Read (byte[] audiodata, int offsetinbytes, int sizeinbytes) method from the buffer to the byte array we passed in Audiodata. such as the average of the sum of squares or absolute values. This avoids the effects of individual extreme values and makes the results of the calculations more stable. After the average value is obtained, if the sum of the squares is in the formula with a constant coefficient of 10, the decibel values are calculated in the formula with a constant coefficient of 20.
The demo code is as follows:
Package Com.example.myapp;
Import Android.media.AudioFormat;
Import Android.media.AudioRecord;
Import Android.media.MediaRecorder;
Import Android.util.Log;
/** * Created by greatpresident on 2014/8/5.
* * 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, A
Udioformat.encoding_pcm_16bit);
Audiorecord Maudiorecord;
Boolean isgetvoicerun;
Object Mlock;
Public Audiorecorddemo () {mlock = new Object ();
public void Getnoiselevel () {if (Isgetvoicerun) {LOG.E (TAG, "still recording");
Return } Maudiorecord = new Audiorecord (MediaRecorder.AudioSource.MIC, Sample_rate_in_hz, Audioformat.channel_in_defa
ULT, 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 the data read, generally r is less than buffersize int r = maudiorecord.read (buffer, 0, buffer_s
ize);
Long v = 0;
Remove the buffer contents for the square and operation for (int i = 0; i < buffer.length i++) {v + + buffer[i] * Buffer[i];
}//squared and divided by the total length of the data to get the volume size.
Double mean = v/(double) r;
Double volume = ten * MATH.LOG10 (mean);
LOG.D (TAG, "db Value:" + volume);
About 10 times a second synchronized (Mlock) {try {mlock.wait (100);
catch (Interruptedexception e) {e.printstacktrace ();
}} maudiorecord.stop ();
Maudiorecord.release ();
Maudiorecord = null;
}). Start ();
}
}
Measured results (equipment millet 2S), mediarecorderdemo fluctuations, as long as the microphone a blow, the decibel value can be 90:
And Audiorecorddemo is very stable, very hard to blow gas is also difficult to more than 88: