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.