对于MediaRecorder,Android的getMaxAmplitude()函数实际上给了我什么?

Android MediaRecorder有一个function

  .getMaxAmplitude(); 

正如API告诉我的: “返回自上次调用此方法以来采样的最大绝对幅度”。 但我找不到这是什么幅度? 是帕斯卡还是瓦特?

我在网上的几个页面上发现,你可以计算一个与分贝​​密切相关的值(正如这里所build议的)。

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

这将让我假设返回的值是一些线性规模(可能类似千万级…)

参考= 0.1(我知道这应该是像2 * 10 ^( – 5)帕斯卡((20微帕)),但是返回奇怪的值… 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; } } 

这在半秒内完成了五次,这是一个平均水平

 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并不能完全满足返回的内容。

Solutions Collecting From Web of "对于MediaRecorder,Android的getMaxAmplitude()函数实际上给了我什么?"

我可以find这个问题的答案,我会在这里分享给任何关心的人:MediaRecorder.getMaxAmplitude()函数返回无符号的16位整数值(0-32767)。 这可能只是-32768到32767的CD质量样本值的abs()。这意味着它们可能代表麦克风构build的0-100%最大电压范围内的电输出的16位数字化进入那个手机。 因为即使在一个品牌的手机中,这些麦克风的精确范围有时也会有所不同,即使是类似的手机,在相同的声源下,相同的距离也必然会返回相同的值。

然而,这个值与Pascal中的声压相关,因为它也是一个线性量化的压力,在这个区域中,声音可以用给定的麦克风来测量(由于电话的限制,它不能覆盖整个sprectrum)。

在这一点上工作了一些。 使用经过校准的SPL-Meters和具有不同纯频率,白噪声和粉红噪声的智能电话进行的一些testing,我现在知道手机麦克风不能用于任何应该在90到100 dB(SPL)以上的任何地方注册,具体取决于手机。

假设90dB(SPL)是最大的,那么可以计算出这对应于麦克风的0.6325Pa的压力。 现在假定p0 = 0.0002Pa是参考最小值,并且假定它将从getMaxAmplitude()中注册为0(这实际上不会发生),所以我们可以在话筒中用来自最大压力的getMaxAmplitude()函数中的值进行核合。 这意味着来自getMaxAmplitude()的16375的结果将对应于0.3165Pa的最大压力。 这当然不是很科学,因为最大值和最小值都是纯粹的意义,但它给了我们一个起点。 我们现在可以用p来计算p

P = getMaxAmplitude()/ 51805.5336

知道麦克风的压力,我们可以用众所周知的公式计算dB(SPL)值

X = 20log_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秒样本中的所有振幅的平均值得到的,因此更精确。 之后,上述计算完成。 这将会提供更现实的分贝值。 请注意,手机话筒仍然吸引人,而且这种algorithm不会产生实际的dB(SPL),而只是比以前更好的逼近。

为了获得一些应用程序的性能,还需要做更多的工作。 大多数这些应用程序使用滑动窗口,这意味着保持logging,并滑动一个x秒的窗口,以contnuosly评估声级。 此外,我会进行一些评估什么分贝值是最适合用作最大值,现在它是90分贝(SPL)/0.6325帕这只是一个合理的猜测,它可能会略高于此。

只要我有更多,我会更新信息。