9

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.

MusiGenesis
  • 74,184
  • 40
  • 190
  • 334

4 Answers4

13

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
  • 83,631
  • 31
  • 151
  • 221
  • Does he want voltage gain or power gain for the conversion? I can never remember. – Nosredna Jul 19 '09 at 02:42
  • 2
    I think it's voltage gain. Nils seems to be right. Source: http://www.sengpielaudio.com/calculator-gainloss.htm – Nosredna Jul 19 '09 at 02:43
  • Thanks, Nils. I always learn better from a good formula than anything else. – MusiGenesis Jul 19 '09 at 02:55
  • 1
    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 Jul 29 '09 at 00:56
1

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
  • 198,648
  • 61
  • 360
  • 533
  • 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 Jul 21 '09 at 02:53
1

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
  • 16,086
  • 32
  • 60
  • 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 Jul 21 '09 at 02:42
  • 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 Jul 21 '09 at 02:58
  • I just finished reading a good chunk of your blog. As an audio programmer, I bow before you. :) – MusiGenesis Jul 21 '09 at 03:09
  • And obviously, I know less about the WAV file format than I thought. – MusiGenesis Jul 21 '09 at 03:23
  • 1
    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 Jul 21 '09 at 15:07
1

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
Jiaaro
  • 74,485
  • 42
  • 169
  • 190