从安卓手机的麦克风计算响度级别

9
我正在尝试从安卓麦克风计算响度级。我使用了AudioRecord获取了麦克风的原始数据,进行了一些正常化处理并计算了分贝值。但结果不正确。我得到的分贝值不稳定且不能反映声音。例如,即使我拍手,分贝值也无法反映声音。如果我想实时计算来自麦克风的响度级,该如何更改代码或应该做什么?非常感谢。
               recorder = new AudioRecord(AudioSource.MIC, iSampleRate, AudioFormat.CHANNEL_IN_MONO,             AudioFormat.ENCODING_PCM_16BIT, iAudioBufferSize);

               iBufferReadResult = recorder.read(buffer, 0, iAudioBufferSize);

              for (int i = 0; i < buffer.length-1; i++)
            {
                ByteBuffer bb = ByteBuffer.wrap(buffer, i, 2);
                int isample = bb.getShort();

                double dsample =(double) isample / 32768.0;
                sum += (dsample*dsample);

                double rms = Math.sqrt(sum/(buffer.length*0.5));        
                double decibel = 20*Math.log10(rms);

                sum = 0;
                }

            }   

可能的目的是基于响度检测环境声音的变化。我该怎么做?谢谢。 - Foreverniu
我觉得你应该在音频管理中检查音量。 - DjHacktorReborn
我之前没有使用过麦克风,但我认为你的计算结果应该总是相同的。假设没有噪音,那么你会有很多50%的样本,如果数字确实是有符号的,那么结果将为0。另一方面,当有声音时,你会有许多类似正负幅值的样本,这些样本也会加起来得到0。我认为你只需要取绝对值,例如,如果你真的收到了正负数,就消除符号? - class stacker
AudioRecord类支持直接读取到short[]ByteBuffer中,那么为什么要将其读入byte[],再将其包装为ByteBuffer并作为shorts访问呢? - Michael
我认为关闭这个的人是不合适的。 - brainmurphy1
1个回答

3
这里有两个问题。首先是你从单个样本计算RMS,因为你没有在整个缓冲区域内计算和 - 你在每个样本中都将其重置。因此,sum仅包含一个样本的平方幅度,但然后你又除以了样本长度。
第二个问题是你不容易能够创建一个测量响度的仪表。你计算的分贝值只是一个功率比值,其中0dB的最大值表示一个峰值。它与物理声压几乎没有任何相关性,而这通常是人们说“响度”时所指的(dB(SPL)是一个比例尺,在那里50dB是语音的响度,110dB是摇滚音乐会等)。
另请参见:sound meter android

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接