2017-01-23 9 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()' принимает абсолютное значение для этой цели. По умолчанию '.getMaxAmplitude()' android 'также делает это и возвращает абсолютное значение – OBX

+0

Спасибо за ответ и совет! – mino