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