2017-01-23 80 views
1

我有一個我創建的AudioRecord功能,對於錄製的分鐘,我想獲得以分貝爲單位的平均音量。我無法弄清楚如何做到這一點。我甚至無法確定AudioRecord對象是否在緩衝區數組中記錄了數據的完整分鐘。Android AudioRecord - 如何獲得一分鐘的平均音量

這是我到目前爲止的代碼,有人可以幫我調整它嗎?我試圖找到一種方法在網上做,但我還沒有找到任何東西。

Runnable mrHandlerRunnable = new Runnable() { 
      @Override 
      public void run() { 
       ar.stop(); 
       short[] buffer = new short[minSize]; 
       Log.d("LEN: " , ""+buffer.length); 
       ar.read(buffer, 0, minSize); 
       int max = Integer.MIN_VALUE; 
       int min = Integer.MAX_VALUE; 
       Double avg = 0.0; 
       for (short s : buffer) 
       { 
        if (Math.abs(s) > max) 
        { 
         max = Math.abs(s); 
        } 
        if (Math.abs(s) < min) 
        { 
         min = Math.abs(s); 
        } 
        avg = avg+Math.abs(s); 
       } 
       avg = avg/buffer.length; 

       ar.startRecording(); 

      } 
     }; 
     mrHandler.postDelayed(mrHandlerRunnable, 60000); 

回答

1

嘗試這種情況:

public class NoiseRecorder 
{ 

private final String TAG = SoundOfTheCityConstants.TAG; 
public static double REFERENCE = 0.00002; 

public double getNoiseLevel() throws NoValidNoiseLevelException 
{ 
    Logging.e(TAG, "start new recording process"); 
    int bufferSize = AudioRecord.getMinBufferSize(44100,AudioFormat.CHANNEL_IN_DEFAULT,AudioFormat.ENCODING_PCM_16BIT); 
    //making the buffer bigger.... 
    bufferSize=bufferSize*4; 
    AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 
      44100, AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT, bufferSize); 

    short data [] = new short[bufferSize]; 
    double average = 0.0; 
    recorder.startRecording(); 
    //recording data; 
    recorder.read(data, 0, bufferSize); 

    recorder.stop(); 
    Logging.e(TAG, "stop"); 
    for (short s : data) 
    { 
     if(s>0) 
     { 
      average += Math.abs(s); 
     } 
     else 
     { 
      bufferSize--; 
     } 
    } 
    //x=max; 
    double x = average/bufferSize; 
    Logging.e(TAG, ""+x); 
    recorder.release(); 
    Logging.d(TAG, "getNoiseLevel() "); 
    double db=0; 
    if (x==0){ 
     NoValidNoiseLevelException e = new NoValidNoiseLevelException(x); 
     throw e; 
    } 
    // calculating the pascal pressure based on the idea that the max amplitude (between 0 and 32767) is 
    // relative to the pressure 
    double pressure = x/51805.5336; //the value 51805.5336 can be derived from asuming that x=32767=0.6325 Pa and x=1 = 0.00002 Pa (the reference value) 
    Logging.d(TAG, "x="+pressure +" Pa"); 
    db = (20 * Math.log10(pressure/REFERENCE)); 
    Logging.d(TAG, "db="+db); 
    if(db>0) 
    { 
     return db; 
    } 
    NoValidNoiseLevelException e = new NoValidNoiseLevelException(x); 
    throw e; 
} 
} 

此計算4秒樣品中的音頻的平均幅度。一旦獲得平均幅度,則將其轉換爲db。希望能幫助到你。

+0

謝謝!很好的答案。我猜測bufferSize = bufferSize * 4;是因爲我們在這種情況下需要4秒?我也想知道,你知道爲什麼所有的例子都是Math.abs(amp)嗎? – mino

+0

根據我的理解,幅度值介於-32768到32767之間,所以'abs()'爲此目的取絕對值。默認的Android的'.getMaxAmplitude()'也做到這一點,並返回絕對值 – OBX

+0

謝謝你的答案和建議! – mino