Подтвердить что ты не робот

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

У Android MediaRecorder есть функция

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

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

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

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

REFERENCE = 0.1 (я знаю, что это должно быть что-то вроде 2 * 10 ^ (- 5) Pascal ((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 совсем не соответствует тому, что возвращается...

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

р = 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), а только приблизительное лучшее приближение, чем раньше.

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

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