1

So I am trying to test some code that analyzes the volume of some PCM data. I am getting some weird volume measurements that don't make sense with the data I get from audacity. It seems like my measurements are all over the place.

I am not sure if my error is in the way I am reading the WAV data or if it is in the way I am calculating the volume.

So here is where I read in the data as bytes and convert to shorts since it is PCM 16-bit.

        InputStream pcmStream = this.getClass().getClassLoader().getResourceAsStream("Test-16Bit-PCM.wav");
        ArrayList<Byte> bytes = new ArrayList<>();
        int b = pcmStream.read();
        while(b != -1)
        {
            bytes.add((byte)b);
            b = pcmStream.read();
       }

       // First 44 bytes of WAV file are file info, we already know PCM properties since we recorded test audio
        byte [] bytesArray = new byte[bytes.size()-44];
        for(int i = 44; i < bytes.size(); i++)
        {
            bytesArray[i-44] = bytes.get(i);
        }
        bytes = null;
        pcmStream = null;
        short [] pcm = new short[bytesArray.length/2];
        ByteBuffer bb = ByteBuffer.wrap(bytesArray).asShortBuffer().get(pcm);
        bb.order(ByteOrder.LITTLE_ENDIAN);
        bb.asShortBuffer().get(pcm);
        bytesArray = null;

That short [] is then passed directly to my analyzer, I then split data into timesteps of 0.1 seconds and average the volume over each timestep.

Here is where I calculate the RMS and dB

        double sumOfSamples = 0;
        double numOfSamples = settings.shortsPerTimeStep();
        for(int i = start; i < start+settings.shortsPerTimeStep(); i++)
        {
           sumOfSamples = originalPcm[i]*originalPcm[i];
        }
        double rms = Math.sqrt(sumOfSamples/numOfSamples);
        // Convert to decibels
        calculatedVolume = 20*Math.log10(rms/20);

The audio I am reading in was recorded at 44100 MONO and saved as WAV 16 Signed PCM in audacity. Not sure what I am doing wrong.

Any help will be appreciated! Thanks

EDIT: Found out I was reading the WAV data wrong. I fixed it by adding end little endianess. However I am still confused on how to calculate the volume. The values are better but still hard to decipher and I am not sure what units my RMS is in and units the reference value is supposed to be in.

Garrigan Stafford
  • 1,331
  • 9
  • 20

1 Answers1

1

You have an error in your computation - sumOfSamples = originalPcm[i]*originalPcm[i]; should by sumOfSamples += originalPcm[i]*originalPcm[i];, so you will accumulate the values.
As for the reference value - why do you use 20? Usually you use the lowest possible value (which is 1 in this case), or you can use the maximum value (which is sqrt(32768)), and all your value will be lower than that, so you'll get negative dB values.

TDG
  • 5,909
  • 3
  • 30
  • 51