Что на самом деле дает мне функция Android getMaxAmplitude() для MediaRecorder?

Android MediaRecorder имеет функцию

.getMaxAmplitude(); 
который, как говорит мне API, "возвращает максимальную абсолютную амплитуду, которая была выбрана с момента последнего вызова этого метода". но я не могу найти, что это за амплитуда? Это в паскалях или ваттах?

На нескольких страницах в Интернете я обнаружил, что можно вычислить значение, тесно связанное с децибелами (как предлагается здесь).

double db = (20 * Math.log10(amplitude / REFERENCE)); 

что позволило бы мне предположить, что возвращаемое значение находится в некотором линейном масштабе (вероятно, что-то вроде милипаскаля...)

СПРАВКА =0.1 (я знаю, что это должно быть что-то вроде 2*10^(-5) Паскаль ((20 uPascal)), но это возвращает странные значения... 0.1 странно работает лучше.)

Прямо сейчас я измеряю MaxAmplitude (), используя

 getMaxAmplitude () 
и поместите это в переменную амплитуду.

Это метод:

public double getNoiseLevel() 
{
    //Log.d("SPLService", "getNoiseLevel() ");
    int x = mRecorder.getMaxAmplitude();
    double x2 = x;
    Log.d("SPLService", "x="+x);
    double db = (20 * Math.log10(x2 / REFERENCE));
    //Log.d("SPLService", "db="+db);
    if(db>0)
    {
        return db;
    }
    else
    {
        return 0;
    }
}

Это делается 5 раз за полсекунды, что в среднем

for(int i=0; i<5; i++)
{
    try 
    {
            Thread.sleep(100);
    } 
    catch (InterruptedException e) 
    {
            e.printStackTrace();
            return 0;
    }
    level = level+getNoiseLevel();
    if(level>0)
    {
        counter++;
    }
}
level=level/counter;
Log.d(LOG_TAG, "level="+level);

Я получаю что-то похожее на децибел, но я не уверен, что это действительно децибел на всех...

Итак, кто-нибудь может мне помочь в этом? Кажется очень странным, что API не уточняет, что возвращается...

2 ответа

Я мог бы найти ответ на этот вопрос, и я поделюсь им здесь для всех, кто заботится: функция MediaRecorder.getMaxAmplitude() возвращает 16-разрядные целочисленные значения без знака (0-32767). Вероятно, это всего лишь abs() значений выборки качества CD, которые варьируются от -32768 до 32767. Это означает, что они, вероятно, представляют собой 16-разрядную цифровизацию электрического выхода в диапазоне максимального напряжения 0-100% при сборке микрофона. в этот мобильный телефон. Поскольку даже в одной марке мобильного телефона эти микрофоны иногда различаются по своему точному диапазону, даже в аналогичных телефонах обязательно будет возвращаться одинаковое значение при одинаковом расстоянии до одного и того же источника звука.

Однако это значение соответствует звуковому давлению в Паскале, поскольку это также линейное количественное определение давления растворенного вещества в области, где звук может быть измерен с помощью данного микрофона (который не будет охватывать весь спектрум из-за ограничений телефона).

Работал над этим еще немного. Используя некоторые тесты, выполненные с откалиброванными SPL-метрами и смартфонами с разными чистыми частотами, белым шумом и розовым шумом, я теперь знаю, что микрофоны мобильных телефонов не пригодны для чего-либо, что должно регистрироваться где-то выше 90-100 дБ (SPL) в зависимости от телефона,

Предполагая, что 90 дБ (SPL) - максимум, можно рассчитать, что это будет соответствовать давлению 0,6325 Па на микрофоне. Теперь, предполагая, что p0=0,0002 Па является эталонным минимумом, и предполагая, что это будет зарегистрировано как 0 (что никогда бы не произошло) из getMaxAmplitude(), мы можем согласовать значения из функции getMaxAmplitude() с максимальным давлением на микрофоне. Это означает, что результат 16375 от getMaxAmplitude() будет соответствовать максимальному давлению 0,3165 Па. Это, конечно, не очень научно, так как максимальные и минимальные значения - чистая конъюнктура, но это дает нам отправную точку. Теперь мы можем рассчитать р с

р =getMaxAmplitude()/51805,5336

Зная давление в микрофоне, мы можем вычислить значение дБ (SPL) по известной формуле

X = 20 log_10 (p/p0)

Это все еще даст значение, которое является высоким, поскольку в расчетах используется только максимальная амплитуда. Чтобы решить эту проблему, нельзя использовать getMaxAmplitude(), и хотя это не входит в суть этого вопроса, я в любом случае помещу код в надежде, что это поможет

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-секундной выборке и, следовательно, более точны. После этого выполняются описанные выше расчеты. Это даст более реалистичное значение в децибелах. Обратите внимание, что микрофоны мобильных телефонов по-прежнему плохо работают, и что этот алгоритм не будет генерировать фактический дБ (SPL), а лишь немного лучше приближает его по сравнению с предыдущим.

Чтобы повысить производительность некоторых приложений, потребуется еще кое-что сделать. В большинстве этих приложений используются скользящие окна, то есть сохраняйте запись и перемещайте окно по x секунд, чтобы непрерывно оценить уровень звука. Также я выполню некоторую оценку того, какое значение дБ лучше всего подходит для использования в качестве максимума, сейчас оно составляет 90 дБ (SPL)/0,6325 Па, что является лишь разумным предположением, вероятно, оно будет немного выше этого.

Как только у меня будет больше, я обновлю информацию.

Другие вопросы по тегам