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