1. 程式人生 > >Android 實時獲取麥克風輸入音量的程式碼

Android 實時獲取麥克風輸入音量的程式碼

Android 上有一些很有趣的應用,例如《吹裙子》、《吹氣球》之類的。利用的是實時獲取麥克風輸入音量,然後進行相應的處理。錄音過程中怎樣獲得聲音的大小呢?網上也不少人問如何處理這個事情,也有一些解答,不過都沒有實際的程式碼。簡單摸索了一下,寫了個小 Demo 試了試,果然可以。給大家共享一下。

不解釋程式碼了,大家看註釋。

  1. package com.xxiyy.spl;  
  2. import android.media.AudioFormat;  
  3. import android.media.AudioRecord;  
  4. import android.media.MediaRecorder;  
  5. import android.util.Log;  
  6. publicclass RecordThread extends Thread {  
  7.     private AudioRecord ar;  
  8.     privateint bs;  
  9.     privatestaticint SAMPLE_RATE_IN_HZ = 8000;  
  10.     privateboolean isRun = false;  
  11.     public RecordThread() {  
  12.         super();  
  13.         bs = AudioRecord.getMinBufferSize(SAMPLE_RATE_IN_HZ,  
  14.                 AudioFormat.CHANNEL_CONFIGURATION_MONO,  
  15.                 AudioFormat.ENCODING_PCM_16BIT);  
  16.         ar = new AudioRecord(MediaRecorder.AudioSource.MIC, SAMPLE_RATE_IN_HZ,  
  17.                 AudioFormat.CHANNEL_CONFIGURATION_MONO,  
  18.                 AudioFormat.ENCODING_PCM_16BIT, bs);  
  19.     }  
  20.     publicvoid run() {  
  21.         super.run();  
  22.         ar.startRecording();  
  23.                 // 用於讀取的 buffer
  24.         byte[] buffer = newbyte[bs];  
  25.         isRun = true;  
  26.         while (isRun) {  
  27.             int r = ar.read(buffer, 0, bs);  
  28.             int v = 0;  
  29.                         // 將 buffer 內容取出,進行平方和運算
  30.             for (int i = 0; i < buffer.length; i++) {  
  31.                 // 這裡沒有做運算的優化,為了更加清晰的展示程式碼
  32.                 v += buffer[i] * buffer[i];  
  33.             }  
  34.             // 平方和除以資料總長度,得到音量大小。可以獲取白噪聲值,然後對實際取樣進行標準化。
  35.             // 如果想利用這個數值進行操作,建議用 sendMessage 將其丟擲,在 Handler 裡進行處理。
  36.             Log.d("spl", String.valueOf(v / (float) r));  
  37.         }  
  38.         ar.stop();  
  39.     }  
  40.     publicvoid pause() {  
  41.                 // 在呼叫本執行緒的 Activity 的 onPause 裡呼叫,以便 Activity 暫停時釋放麥克風
  42.         isRun = false;  
  43.     }  
  44.     publicvoid start() {  
  45.                 // 在呼叫本執行緒的 Activity 的 onResume 裡呼叫,以便 Activity 恢復後繼續獲取麥克風輸入音量
  46.         if (!isRun) {  
  47.             super.start();  
  48.         }  
  49.     }  
  50. }  

轉評:

原文中提到“平方和除以資料總長度,得到音量大小”,有些文章中提到這個音量值在不同的手機中表現得不一樣,同樣的發聲,但出來的值相差很大。進而有通過一些計算,調整“音量”的演算法,其中有兩個,分別是:

1、計算了噪音,對音量進行調整:
value 的 值 控制 為 0 到 100 之間 0為最小 》= 100為最大!!
 int value = (int) (Math.abs((int)(v /(float)r)/10000) >> 1);

2、計算分貝值:

那個值應該是聲音的振幅,並不是音量的大小,
聲音的大小應該是用分貝為單位的吧,
double dB = 10*Math.log10(v/(double)r);

即:經傅立葉變化後得到的複數陣列是個二維陣列,實部和虛部的平方和取對數後乘以10就大致等於我們通常表示音量的分貝了。