volume scaling

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

I know this is a very noobish question, but several ideas I came up with aren't giving good results and I can't seem to find an answer otherwise.

What is a good way to scale volume in terms of % so that the % you choose actually is perceived to be of a similar proportion?

For example if I allow the user to enter in a % they want to scale the master volume I want 50% to appear half the volume.

Post

any one knows the log volume scaling algorithm ?

Post

djarago wrote:I know this is a very noobish question, but several ideas I came up with aren't giving good results and I can't seem to find an answer otherwise.

What is a good way to scale volume in terms of % so that the % you choose actually is perceived to be of a similar proportion?

For example if I allow the user to enter in a % they want to scale the master volume I want 50% to appear half the volume.
Well, i'm not an expert but if what i say is completly wrong i'm sure someone here will have the pleasure to correct me.

If you want to define a percentage is very simple. Your parameters are usally always floats between 0 and 1.

Suppose that you have you volume at half and you want to increase 50%:

Code: Select all

fActualVolume = 0.5f;
fVolumeIncrease = 0.5f;

// Your out will be:

out *= fActualIncrease * (1+fVolumeIncrease);
any one knows the log volume scaling algorithm ?
In the other day i tried to do something like that and the solution i managed came up from some experiments in my graphic calculator.

You have 3 basic functions which have a logaritmic behaviour: e, ln, log

You just have to find a way to pass an x (actual volume) to one of this functions to them give you a value between 0 and 1 (or more, if wou want to amplify a little bit, but if it is to much i think i will start cliping).

Code: Select all

out *= log(1.f+(actualVolume*1.7f));
// i designed this function to give me an logaritmic curve where the domain was [0..1] and the counter domain [0..1]. One thing i found strange was that the behaviour in the computer was completly different from the calculator... so i had to reajust the parameters.

If somebody can explain why this happens i would appreciate.

I hope this helps you out

Nuno
Imagining the future

Post

First of all, the correct way to scale a parameter in the {0..1} range is like so:

Code: Select all

real_value = value * (maxval - minval) + minval;
Where "value" is the parameter value, and maxval and minval obviously correspond to the maximum and minimum ranges you'd like to set on the parameter. As for doing this logically in the volume, set your maximum value to like 0.0dB and the minimum to -30.0dB (or whatever), and then use the logarithmic scale to convert this into a linear value:

Code: Select all

real_value = exp(value * (log(maxval) - log(minval)) + log(minval));
Where "value" is again in the range of {0..1} and minval and maxval are in decibels.

Post

Hey sqook,

Can you explain me better how does it work?

value is the parameter?

And in the min and max value i should use values in db?

Best regards,

Nuno
Imagining the future

Post

first you map the vst-parameter from the range 0...1 to the desired gain range (expressed in dB), for example from -96...+24 dB:

vol_dB = 120*parameter-96

then you calculate the factor which is to be multiplied with the signal:

factor = 10^(vol_dB/20)

done.
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post

braindoc wrote:first you map the vst-parameter from the range 0...1 to the desired gain range (expressed in dB), for example from -96...+24 dB:

vol_dB = 120*parameter-96

then you calculate the factor which is to be multiplied with the signal:

factor = 10^(vol_dB/20)

done.
Sorry, but from where comes the value 120?

About the rest, i understood.

Thx

Nuno
Imagining the future

Post

lpx wrote: Sorry, but from where comes the value 120?
only from my example: 96+24=120

parameter = 0 -> vol_dB = 0*120-96 = -96
parameter = 1 -> vol_dB = 1*120-96 = +24

in general:

vol_dB = (vol_dB_max - vol_dB_min)*parameter + vol_dB_min
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post

I should have explained in my original post more clearly, so here's a second try.

Let's say I have a variable, sample, which contains the current sample's amplitude. sample is a float in the range of -1 to 1. I want to multiply this by some scaling factor called vol_scale (normally between 0 and 1, but could be greater than 1 if amplification is desired). I wish to have the user enter a value, vol_percent, between 0 and 100 (could actually be greater) representing the perceived volume they want to hear, thus if they enter 50 I want them to hear what sounds like half the volume. I understand that because human hearing is not linear I cannot just multiply sample*0.5f. Similarly if they enter in 75 they should hear sound that appears to be 3/4ths the normal volume (100).

What I'm trying to figure out is a function, f, that will map vol_percent->vol_scale such that sample*f(vol_percent) will be perceived to the listener like sample*vol_percent if human hearing were linear.

Ideally when the user enters in 0 for the percent I would multiply sample*0.0f and when they enter 100 I wish to multiply sample*1.0f. The best f(x) I could come up with to accomplish this was f(x) = (exp(x/100)-1)/(exp(1)-1), which does satisfy the requirements of f(0) = 0 and f(100) = 1, but sounds too loud x = 0.5 for example. I must make x (vol_percent) less than 30 or so before the volume change becomes easily noticed.

Post

i think human loudness perception is related to signal power, which is proportional to the signals amplitude squared. so how about using the square-root of the value between 0...1? this way you half the power of the signal with a value of 0.5 (by multiplying the amplitude with 0.707)
My website: rs-met.com, My presences on: YouTube, GitHub, Facebook

Post

you want to use:

fraction = 10^(decibels/20)
decibels = 20*log10(fraction)

-48 is a good value to use for a floor in decibels, and it is used in almost every mixer out there with -48 being the lowest slider measurment, and a fade to infinity below that point.

an important thing to remember is that human hearing is perfectly linear. you only get a non-linear perception with single tones. a difference in amplitude between two tones will be perceived linearly. think of it as if everything you hear has a compressor applied to it. infact, it does. you might notice after hearing a very loud sound, background noise will be gone and slowly fade back in. if you try this and pay attention, you'll actually start to notice the compression taking place. it is a bit freaky, yes, that is taking place in your head. seriously try it, you'll gain some valuable insight.

when adjusting the amplitudes of different waveforms, say in the mixer section of a synthesizer, it is better to use a hybrid method with 1/2 or 1/3 linear responce. in my synth, i just use a single purely decibel based scaling for all amplitude parameters, but that is to make the interface more consistant. play with different responces and you'll find one which works best for a particular need.

you'll need to do something like:

Code: Select all

float range = -48.0f;
float scale = powf(10.0f, (1.0f - value) * range * 0.05f); // 1/20 = 0.05

Post

Ok since this is what I want to use, then how do I convert from a percentage to decibel? Do I convert from % to decibel linearly?

In your example what is "value"? Is value the percent?

Post

yes. if you have a fraction (0.0 ... 1.0) use it directly. if you have a percent (000.0, 100.0) divide by 100.0, easy.

Post

Is there any decibel log scaling algorithm?

I mean just like the faders on the real mixer...

Post

Normally you calculate dB as dB = 10*log(output/input) for gain of a system as an example. Another way to calculate dB is dB = 10*log(measured_value/minimum_value) where minimum_value is the minimum detectible amount, so in a 16bit audio the minimum would be 1/32768.0f.

Post Reply

Return to “DSP and Plugin Development”