Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

How to accurately calculate audio decibels

Discussion in 'Audio & Video' started by UCoyote, Apr 27, 2015.

  1. UCoyote

    UCoyote

    Joined:
    Sep 29, 2013
    Posts:
    7
    Hi, everybody.
    Situation is that the current I got an audio file, put it in to the AudioSource, and then I by calling the AudioSource. GetOutputData (myClip. Samples, 0);Get it broadcast spectrum, then the call Mathf. Log (spectrum );, the data is not ready to db. Could you tell me what is the formula can accurately calculate audio decibels ? thanks!
     
  2. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I would like to know also. No idea.
     
  3. gregzo

    gregzo

    Joined:
    Dec 17, 2011
    Posts:
    795
    Little gift:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public static class AudioPower
    4. {
    5.     public static float ComputeRMS( float[] buffer, int offset, ref int length )
    6.     {
    7.         // sum of squares
    8.         float sos = 0f;
    9.         float val;
    10.  
    11.         if( offset + length > buffer.Length )
    12.         {
    13.             length = buffer.Length - offset;
    14.         }
    15.  
    16.         for( int i = 0; i < length; i++ )
    17.         {
    18.             val = buffer[ offset ];
    19.             sos += val * val;
    20.             offset ++;
    21.         }
    22.  
    23.         // return sqrt of average
    24.         return Mathf.Sqrt( sos / length );
    25.     }
    26.  
    27.     public static float ComputeDB( float[] buffer, int offset, ref int length )
    28.     {
    29.         float rms;
    30.  
    31.         rms = ComputeRMS( buffer, offset, ref length );
    32.  
    33.         // could divide rms by reference power, simplified version here with ref power of 1f.
    34.         // will return negative values: 0db is the maximum.
    35.         return 10 * Mathf.Log10( rms );
    36.     }
    37. }
    38.  
    Bear in mind that db is a relative measurement. Here, we assume an average power of 1f to be the maximum, 0db level. The method will return negative values.

    This particular piece of code is untested, let me know if there are issues. I've used a ref parameter for length to simplify use when computing a power graph of a larger chunk of audio. To get realtime power, the methods can be simplified. For use with OnAudioFilterRead(), one should also de-interleave first, and compute the power for both channels separately.

    Cheers,

    Gregzo

    Edit: fixed rms loop logic
     
    Last edited: Apr 28, 2015
    lyravr, andrew_pearce_ and jerotas like this.
  4. UCoyote

    UCoyote

    Joined:
    Sep 29, 2013
    Posts:
    7
    Thank you Gregzo. For audio data I'm so worried , and not have any idea about the audio data processing , too bad
     
  5. UCoyote

    UCoyote

    Joined:
    Sep 29, 2013
    Posts:
    7
    I am also
     
  6. A_munim

    A_munim

    Joined:
    Mar 11, 2017
    Posts:
    5
    @gregzo Can u help me out I really do not know how to process the negative values

    Edit: My Code
    Code (CSharp):
    1.  
    2.         int length = (int)Recording.length;
    3.         float[] buffer = new float[128];
    4.  
    5.         Recording.GetData(buffer, 0);
    6.  
    7.         DB = AudioPower.ComputeDB(buffer, 0, ref length);
     
  7. andrew_pearce_

    andrew_pearce_

    Joined:
    Nov 5, 2018
    Posts:
    167
    This is awesome code and it's working perfectly. I needed it to trim the silence at the beginning and the end of the audio clip. However, I would like to know... what is the reference power? When I read documentation, they used it to describe how much voice is lost in phone line after 1mile of distance. However... all audio editing tools actively using decibels. Human ear cannot hear anything bellow -40dB. Any practical example and information would be awesome. Thanks!

    UPD: There is a bug related to 0 sample. I have no time to dig deeper but float values close to zero cause this algorithm to fail. So here is the fix (I ignore samples with 0.1% of the max rate):

    Code (CSharp):
    1.       for (int i = 0; i < length; i++) {
    2.         val = buffer[offset];
    3.         if (val > -0.001f && val < 0.001f) continue;
    4.         sos += val * val;
    5.         offset++;
    6.       }
     
    Last edited: Apr 11, 2020
    cihadturhan_unity likes this.
  8. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    646
    Common issue with floats, you could use Mathf.Approximately.