### 背景 最近小區旁邊工地施工,今一大早就被工地傳來的guang!guang!...吵醒了。很響很響的那種,你們肯定會問具體有多響?具體要多響?怎麼描述呢?頓時就萌生出開發一款記錄聲音響度的app,忙活了一下午於是就出了這個聲音檢測儀 ### 簡介 android端的聲音檢測程式,實時獲取當前周... ...
android聲音檢測儀---分貝儀
文章出處:大黑個人博客--android聲音檢測儀---分貝儀
源碼下載地址:https://github.com/halibobo/SoundMeter
背景
最近小區旁邊工地施工,今一大早就被工地傳來的guang!guang!...吵醒了。很響很響的那種,你們肯定會問具體有多響?具體要多響?怎麼描述呢?頓時就萌生出開發一款記錄聲音響度的app,忙活了一下午於是就出了這個聲音檢測儀
簡介
android端的聲音檢測程式,實時獲取當前周圍環境的聲壓級,也就是平常所說的分貝值
源碼
聲音採集利用系統的MediaRecorder
/**
* 錄音
* @return 是否成功開始錄音
*/
public boolean startRecorder(){
if (myRecAudioFile == null) {
return false;
}
try {
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
mMediaRecorder.setOutputFile(myRecAudioFile.getAbsolutePath());
mMediaRecorder.prepare();
mMediaRecorder.start();
isRecording = true;
return true;
} catch(IOException exception) {
mMediaRecorder.reset();
mMediaRecorder.release();
mMediaRecorder = null;
isRecording = false ;
exception.printStackTrace();
}catch(IllegalStateException e){
stopRecording();
e.printStackTrace();
isRecording = false ;
}
return false;
}
/**
* 獲取聲壓值
*/
public float getMaxAmplitude() {
if (mMediaRecorder != null) {
try {
return mMediaRecorder.getMaxAmplitude();
} catch (IllegalArgumentException e) {
e.printStackTrace();
return 0;
}
} else {
return 5;
}
}
在MainActivity中開啟一個線程定時獲取聲壓值並轉為分貝
private void startListenAudio() {
thread = new Thread(new Runnable() {
@Override
public void run() {
while (isThreadRun) {
try {
if(bListener) {
volume = mRecorder.getMaxAmplitude(); //獲取聲壓值
if(volume > 0 && volume < 1000000) {
World.setDbCount(20 * (float)(Math.log10(volume))); //將聲壓值轉為分貝值
}
}
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
bListener = false;
}
}
}
});
thread.start();
}
自定義顯示分貝值得大圓盤View 取名SoundDiscView
private float scaleWidth, scaleHeight;
private int newWidth, newHeight;
private Matrix mMatrix = new Matrix();
private Bitmap indicatorBitmap;
private Paint paint = new Paint();
static final long ANIMATION_INTERVAL = 100;
private void init() {
Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.noise_index);
int bitmapWidth = myBitmap.getWidth();
int bitmapHeight = myBitmap.getHeight();
newWidth = getWidth();
newHeight = getHeight();
scaleWidth = ((float) newWidth) /(float) bitmapWidth; // 獲取縮放比例
scaleHeight = ((float) newHeight) /(float) bitmapHeight; //獲取縮放比例
mMatrix.postScale(scaleWidth, scaleHeight); //設置mMatrix的縮放比例
indicatorBitmap = Bitmap.createBitmap(myBitmap, 0, 0, bitmapWidth, bitmapHeight, mMatrix,true); //獲取同等和背景寬高的指針圖的bitmap
paint = new Paint();
paint.setTextSize(55);
paint.setAntiAlias(true);
paint.setTextAlign(Paint.Align.CENTER); //抗鋸齒
paint.setColor(Color.WHITE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
currentAngle = getAngle(World.dbCount); //獲取指針應該顯示的角度
mMatrix.setRotate(getAngle(World.dbCount), newWidth / 2, newHeight * 215 / 460); //片相對位置
canvas.drawBitmap(indicatorBitmap, mMatrix, paint);
postInvalidateDelayed(ANIMATION_INTERVAL);
canvas.drawText((int)World.dbCount+" DB", newWidth/2,newHeight*36/46, paint); //圖片相對位置
}
運行發現指針滑動的太突兀,做個緩慢過度
public static float dbCount = 40;
private static float lastDbCount = dbCount;
public static void setDbCount(float dbValue) {
dbCount = lastDbCount + (dbValue - lastDbCount) * 0.2f;
lastDbCount = dbCount;
}
結果
這裡的分貝值是手機系統錄音時獲取的,手機廠商都對這個值設置了上限而且手機廠商之間都是有差別的,所以獲取聲音的分貝值會有點偏差。但是最終運行起來的效果還是很滿意的。下麵附上源碼
源碼下載地址