0

So I have audio file recorded using smartphone microphone in PCM 16 bit format, 1 channel, sampling frequency 44100 Hz.

I read this file as Byte Array:

fun readFileAsByteArray(file: File = audioFile): ByteArray{
            val inputStream = FileInputStream(file)
            val dataStream = DataInputStream(inputStream)
            val byteArray = ByteArray(file.length().toInt())
            dataStream.read(x)
            dataStream.close()
            inputStream.close()
            return byteArray
        }

Then I want to calculate sound level of this file in dB. I get the data as Byte Array using readFileAsByteArray()

then I convert byte[] to short[] to double[]

var sbuf = ByteBuffer.wrap(data).asShortBuffer()
        var audioShorts = ShortArray(sbuf.capacity())
        sbuf.get(audioShorts)

        var audioDoubles = DoubleArray(audioShorts.size)

        for (i in audioShorts.indices) {
            audioDoubles[i] = java.lang.Short.reverseBytes(audioShorts[i]).toDouble() / 0x8000
        }

Then I calculate RMS value of chunked array of samples:

 val batchArray = audioDoubles.asSequence().chunked(size = 1792)
 val rmsScore = arrayListOf<Double>()
        for (batch in batchArray){
            val sum: Double =  batch.sumByDouble { it * it }
            val rms = Math.sqrt(sum/batch.size)
            rmsScore.add(rms)
        }

Then I calculate dB.

 val minrms = 2.2414737665141438E-4

 val dbArray = arrayListOf<Double>()

 rmsScore.forEach { sample -> dbArray.add(20*Math.log10(sample/minrms)) }

I use minrms as reference value (I recorded some silence and minrms is the lowest value registered).

The problem is that maximum level of dB I get is around 70. I know that microphones in smartphones has limit of ~ 100 dB. In Google Play Store one can find apps that are able to register much higher values.

I just can't see problem in my code that limit this dB value.

dawzaw
  • 419
  • 6
  • 17

1 Answers1

1

The problem has to be with your reference voltage. I'm confused about whether you are using the actual voltage or a signed 2-byte ADC value. If you are using the ADC value can you just follow the technique listed here?

Instead of 0 dB being your peak value you could use 1 as your reference. 32767 would be your peak pcm value for a dB scale from 0 to 90.3 (which is close to your quoted value from a smartphone mic).

thomas.cloud
  • 881
  • 13
  • 30