math behind logarithmic volume control?

Status
Not open for further replies.
First, I am a software guy and know little to nothing about audio. I was tasked with converting a linear volume scale to a logarithmic one on an existing system. I'm not sure this is the right place to ask this, so please point me in the right direction if it is not.

As an overview, my software runs in a DSP, which sends a 16 bit value to a DAC. From my understanding, the DAC converts it to voltage and that goes to an amplifier and then that goes to a speaker.

The volume control is just a multiplier to the 16 bit value. There are 9 volume levels which correspond to a table lockup of 9 multipliers. The values go from 0 to 1, in increments of .125. That is the linear volume scale. I need to make this into a logarithmic volume lockup table. Does that make sense? What equation do I need to use?

From just asking and research, the following are my guesses. I think I want to relate voltage to dbA (sound pressure level). But I don't know how to do that.
 
In a logarithmic scale you need to define the step value. Common is 3 dB, which is a clearly audible volume difference. The problem is that the range between the lowest and highest volume will be only 30 dB if you use 10 steps. This is not sufficient for audio volume control in general, you need at least 60 dB and a bit finer resolution (1.5 or 2 dB). That means 30 to 40 steps. 1 dB = 20 * log (V2/V1). You can do it in the digital domain, but you will lose the 16 bit resolution at low volume level. (BTW shifting the 16-bit word to the left yields 6 dB attenuation). Better do do it in 24 or 32 bit arithmetic, and then truncate to 16 bit.
 
In a logarithmic scale you need to define the step value. Common is 3 dB, which is a clearly audible volume difference. The problem is that the range between the lowest and highest volume will be only 30 dB if you use 10 steps. This is not sufficient for audio volume control in general, you need at least 60 dB and a bit finer resolution (1.5 or 2 dB). That means 30 to 40 steps. 1 dB = 20 * log (V2/V1). You can do it in the digital domain, but you will lose the 16 bit resolution at low volume level. (BTW shifting the 16-bit word to the left yields 6 dB attenuation). Better do do it in 24 or 32 bit arithmetic, and then truncate to 16 bit.

I think we would use 6db steps. The audio we produce is alarms for equipment, so it doesn't need to be that great of resolution. In fact, I think once the volume is set, it probably is never looked at again. So at 6 db, 9 steps would be 54 db range. I think we go up to about 80 dbA. So I would make step 0 be 0 db and step1 be ~32 db and then go 6db every other step.

It sounds like left shifting is nearly what I want. But I want a look-up table, not an algorithm. How do I make a look-up table that does the same thing as a left shift?
 
For a rough approximation to a log scale, use 1000, 0110, 0100, 0011, 0010 etc. as multipliers. This gives alternate steps of 3.52 dB and 2.50dB, which are close enough to 3dB and have the advantage that multiplication will be quick - just a shift, or two shifts and an add.

I think I didn't give enough information in the OP. The original 16 bit number i start with is already at full volume. The look-up table decreases the volume by multiplying times a fraction. So I don't think left shift or multiplying works in my case I need to divide or right shift?

So will my table will look like { 0, 1/128,1/64, 1/32,1/16,1/8,1/4,1/2,1}???
But that doesn't make sense to me since the last two steps since too great a difference. The current table has .5 as the 4th step. ({0,.125,.25,.375,.5, .625, .75, .875, 1})
 
May i help? 🙂
First, calculate lookup table in MS Excel. 1 dB step is overkill, 3 dB is not accurate. For power(!) dB = 10*lg(P1/P0). As i understand, P1/P0 (or, may be U1/U0) is equal to volume control register content. Try 1 dB step, at minus 60 dB disable DAC output (MUTE function).
 
The standard 10 position attenuator uses 3 db steps except for the last three which are 6, 6 and off. A normal carbon control has 45 db range then essentially off.

So values of 1, .707, .5, .35, .25, .18, .9, .045. 0, would give you smooth sounding values from full on to off.
 
According to some authorities, 10dB represents a halving or doubling of perceived volume.

I would think 6dB would be a not unreasonable step.

Left or right shift is a question of bigendian or littleendian, regardless you would want to divide by 1, 2, 4, 8, 16, 32, 64, 128. This will still leave you with a reasonable number out of 16 bits.

This isn't something with an absolute hard-and-fast solution, so you can just pull the numbers out of your imagination, try the effect, and tweak the table if you don't like the result.

You could do worse than look at the Dallas/Maxim linear -> log digipot appnote, AN3996. Although it is specifically about digipots, it's a mathematical treatment of a related subject.
 
How do I make a look-up table that does the same thing as a left shift?
I gave you values for approx 3db per step - you can zero pad at either end as necessary. For 6db per step it is even easier: 1000, 0100, 0010, 0001, 0000. Just multiply the number by the relevant entry from the table.

I'm not sure what is puzzling you. As a software guy I assume you can think in binary? When I wrote code I had to think in octal and hexadecimal too.
 
The standard 10 position attenuator uses 3 db steps except for the last three which are 6, 6 and off. A normal carbon control has 45 db range then essentially off.

I've done 1dB step down to -60 dB. And every time I ask myself: "What is the reason to have 60 dB range, if I use only first 20 steps and MUTE?"

😀

But, may be it is better to have 20 steps for fine tuning. 1.5 dB steps except last five, which are 3, 3, 3, 3, MUTE. I need to try.
 
The standard 10 position attenuator uses 3 db steps except for the last three which are 6, 6 and off. A normal carbon control has 45 db range then essentially off.

So values of 1, .707, .5, .35, .25, .18, .9, .045. 0, would give you smooth sounding values from full on to off.

Thanks all for the help.

I think the quoted post is what I am looking for. What equation did you use to calculate the multipliers? I used y=10log(v2/v1). I knew what I wanted y to be, so then I use x = 10^(y/10) and got the values on the attached table. Don't worry about column D, that is just my guess at measured sound pressure.

As you can see my numbers are not the same, so I must of done something wrong.
 

Attachments

  • volume.JPG
    volume.JPG
    23.5 KB · Views: 279
Status
Not open for further replies.