9

I am trying to calculate the loudness level from the microphone on android. I used AudioRecord to get the raw data from the microphone and also did some normalization and calculated the decibel after that. But the result is not right. The decibel values I got were not steady and cannot reflect the sound. Such as even when I clapped hands, the decibel value did not reflect the sound. How should I change the code or What should I do if I want to calculate the loudness from the microphone in real-time? Thanks a lot.

               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
  • 349
  • 1
  • 3
  • 18
  • The purpose might be detect the enviroment sound change just based on the loudness. How should I do that? Thanks. – Foreverniu Mar 11 '13 at 08:05
  • i think you check for volume in audio manage – DjHacktorReborn Mar 11 '13 at 08:05
  • I haven't worked with the microphone so far but I would assume that your computation always yields the same result. Assume there's no noise then you would have many samples at 50%, which would be 0 if the numbers are truly signed. On the other hand, when there is a sound, you would have many samples with similar positive and negative amplitude, which would add up to 0 as well. I'd say you need to take absolute values only, e.g. eliminate the sign if you really receive positive and negative numbers? – class stacker Mar 11 '13 at 08:12
  • The `AudioRecord` class supports reading directly into a `short[]` or a `ByteBuffer` - so why read into a `byte[]`, wrap is as a `ByteBuffer` and access it as shorts? – Michael Mar 11 '13 at 09:03
  • I think that whoever closed this was out of line. – brainmurphy1 Jun 02 '14 at 17:22

1 Answers1

3

There are two problems here. The first is that you are calculating the RMS from a single sample, as you aren't calculating the sum across the whole buffer - you're resetting it every sample. So sum contains the square-magnitude for one sample, but then you're dividing by the sample length.

The second problem is that you won't easily be able to create a meter to measure loudness. The decibel value you calculate will only be a power ratio where the maximum value of 0dB indicates a peak. It doesn't have any correlation with physical sound pressure, which is generally what people mean when they say 'loudness' (dB(SPL) is the scale where 50dB is the loudness of speech, 110dB a rock concert, etc).

See also: sound meter android

Community
  • 1
  • 1
the_mandrill
  • 29,792
  • 6
  • 64
  • 93