tags:

views:

783

answers:

3

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.

+8  A: 

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)
Nils Pipenbrinck
Does he want voltage gain or power gain for the conversion? I can never remember.
Nosredna
I think it's voltage gain. Nils seems to be right. Source: http://www.sengpielaudio.com/calculator-gainloss.htm
Nosredna
Thanks, Nils. I always learn better from a good formula than anything else.
MusiGenesis
Digital audio is a representation of sound pressure (just like analog audio's voltage is a representation of sound pressure) so you want 20.
endolith
+1  A: 

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.

Norman Ramsey
This is actually for a software synthesizer, for normalizing notes at different pitches. The normalize package in your link just uses RMS, which doesn't change significantly as I vary the pitch (I have no idea what wavnorm does). I've found that attenuating the volume of a note by about 5 decibels (using the function from Nils) per octave above a base pitch results in a constant perceived volume throughout the range of a scale.
MusiGenesis
+1  A: 

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 :(.

Larry Osterman
Sorry, "WAV file" was just shorthand for sampled audio data, generically. I know all about WAV and MP3 file formats, although I have to say I have never encountered 24bit or 32bit PCM files in the wild.
MusiGenesis
I'm trying to guess what the purpose of a 24 bit unpacked PCM WAV file would be. Meant to record output from a 24-bit mixer, I would guess?
MusiGenesis
I just finished reading a good chunk of your blog. As an audio programmer, I bow before you. :)
MusiGenesis
And obviously, I know less about the WAV file format than I thought.
MusiGenesis
MusiGenesis: I believe the point of the unpacked 24 bit PCM is ease of use - 24bits gives you a LOT more precision than 16 bits but it's far easier to deal with the data as DWORD values instead of cracking the stream 3 bytes at a time. But you're right, there are relatively few files that are WAV files encoded with 24bit PCM.
Larry Osterman