Question

If I wanted to reduce a WAV file's amplitude by 25%, I would write something like this:

for (int i = 0; i < data.Length; i++)
{
    data[i] *= 0.75;
}

A lot of the articles I read on audio techniques, however, discuss amplitude in terms of decibels. I understand the logarithmic nature of decibel units in principle, but not so much in terms of actual code.

My question is: if I wanted to attenuate the volume of a WAV file by, say, 20 decibels, how would I do this in code like my above example?

Update: formula (based on Nils Pipenbrinck's answer) for attenuating by a given number of decibels (entered as a positive number e.g. 10, 20 etc.):

public void AttenuateAudio(float[] data, int decibels)
{
    float gain = (float)Math.Pow(10, (double)-decibels / 20.0);
    for (int i = 0; i < data.Length; i++)
    {
        data[i] *= gain;
    }
}

So, if I want to attenuate by 20 decibels, the gain factor is .1.

Was it helpful?

Solution

I think you want to convert from decibel to gain.

The equations for audio are:

decibel to gain:

  gain = 10 ^ (attenuation in db / 20)

or in C:

  gain = powf(10, attenuation / 20.0f);

The equations to convert from gain to db are:

  attenuation_in_db = 20 * log10 (gain)

OTHER TIPS

If you just want to adust some audio, I've had good results with the normalize package from nongnu.org. If you want to study how it's done, the source code is freely available. I've also used wavnorm, whose home page seems to be out at the moment.

One thing to consider: .WAV files have MANY different formats. The code above only works for WAVE_FORMAT_FLOAT. If you're dealing with PCM files, then your samples are going to be 8, 16, 24 or 32 bit integers (8 bit PCM uses unsigned integers from 0..255, 24 bit PCM can be packed or unpacked (packed == 3 byte values packed next to each other, unpacked == 3 byte values in a 4 byte package).

And then there's the issue of alternate encodings - For instance in Win7, all the windows sounds are actually MP3 files in a WAV container.

It's unfortunately not as simple as it sounds :(.

Oops I misunderstood the question… You can see my python implementations of converting from dB to a float (which you can use as a multiplier on the amplitude like you show above) and vice-versa

https://github.com/jiaaro/pydub/blob/master/pydub/utils.py

In a nutshell it's:

10 ^ (db_gain / 10)

so to reduce the volume by 6 dB you would multiply the amplitude of each sample by:

10 ^ (-6 / 10)  ==  10 ^ (-0.6)  ==  0.2512
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top