Calculate decibels

余生长醉 提交于 2019-11-28 04:10:54

When measuring the level of a sound signal, you should calculate the dB from the RMS value. In your sample you are looking at the absolute peak level. A single (peak) sample value determines your dB value, even when all other samples are exactly 0.

try this:

double sum = 0;
for (var i = 0; i < _buffer.length; i = i + 2)
{
    double sample = BitConverter.ToInt16(_buffer, i) / 32768.0;
    sum += (sample * sample);
}
double rms = Math.Sqrt(sum / (_buffer.length / 2));
var decibel = 20 * Math.Log10(rms);

For 'instantaneous' dB levels you would normally calculate the RMS over a segment of 20-50 ms. Note that the calculated dB value is relative to full-scale. For sound the dB value should be related to 20 uPa, and you will need to calibrate your signal to find the proper conversion from digital values to pressure values.

I appreciate Han's post, and wrote a routine that can calculate decibels on 8 and 16 bit audio formats, with multiple channels using his example.

public double MeasureDecibels(byte[] samples, int length, int bitsPerSample,
        int numChannels, params int[] channelsToMeasure)
    {
        if (samples == null || length == 0 || samples.Length == 0)
        {
            throw new ArgumentException("Missing samples to measure.");
        }
        //check bits are 8 or 16.
        if (bitsPerSample != 8 && bitsPerSample != 16)
        {
            throw new ArgumentException("Only 8 and 16 bit samples allowed.");
        }
        //check channels are valid
        if (channelsToMeasure == null || channelsToMeasure.Length == 0)
        {
            throw new ArgumentException("Must have target channels.");
        }
        //check each channel is in proper range.
        foreach (int channel in channelsToMeasure)
        {
            if (channel < 0 || channel >= numChannels)
            {
                throw new ArgumentException("Invalid channel requested.");
            }
        }

        //ensure we have only full blocks. A half a block isn't considered valid.
        int sampleSizeInBytes = bitsPerSample / 8;
        int blockSizeInBytes = sampleSizeInBytes * numChannels;
        if (length % blockSizeInBytes != 0)
        {
            throw new ArgumentException("Non-integral number of bytes passed for given audio format.");
        }

        double sum = 0;
        for (var i = 0; i < length; i = i + blockSizeInBytes)
        {
            double sumOfChannels = 0;
            for (int j = 0; j < channelsToMeasure.Length; j++)
            {
                int channelOffset = channelsToMeasure[j] * sampleSizeInBytes;
                int channelIndex = i + channelOffset;
                if (bitsPerSample == 8)
                {
                    sumOfChannels = (127 - samples[channelIndex]) / byte.MaxValue;
                }
                else
                {
                    double sampleValue = BitConverter.ToInt16(samples, channelIndex);
                    sumOfChannels += (sampleValue / short.MaxValue);
                }
            }
            double averageOfChannels = sumOfChannels / channelsToMeasure.Length;
            sum += (averageOfChannels * averageOfChannels);
        }
        int numberSamples = length / blockSizeInBytes;
        double rootMeanSquared = Math.Sqrt(sum / numberSamples);
        if (rootMeanSquared == 0)
        {
            return 0;
        }
        else
        {
            double logvalue = Math.Log10(rootMeanSquared);
            double decibel = 20 * logvalue;
            return decibel;
        }
    }

I think Yann means that Decibels are a relative scale. If you're trying to measure the actual Sound Pressure Level or SPL, you would need to calibrate. What you're measuring is dBFS (decibels full-scale, I think). You're measuring how many decibels quieter the signal is than the loudest possible signal the system can represent (the "full-scale" signal, or 32768 for these 16-bit samples). That's why all the values are negative.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!