Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What algorithms could I use for audio volume level? [closed]

Let's say I have a slider that can go between 0 and 1. The SoundTransform.volume also ranges between 0 (silent) and 1 (full volume), but if I use a linear function, let's say SoundTransform.volume = slider.volume, the result is rather not pleasing - the perception is that the volume dramatically changes in the lower half and does almost nothing in the upper half of the slider.

I really haven't studied the human ear, but I overheard once that human perception is logarithmic, or something similar. What algorithms should I use for setting the SoundTransform.volume?

like image 261
evilpenguin Avatar asked Jul 22 '09 12:07

evilpenguin


5 Answers

human perception in general is logarithmic, also when it comes to things as luminosity, etc. ... this enables us to register small changes to small "input signals" of our environement, or to put it another way: to always percieve a change of a perceivable physical quantity in relation to its value ...

thus, you should modify the volume to grow exponentially, like this:

y = (Math.exp(x)-1)/(Math.E-1)

you can try other bases as well:

y = (Math.pow(base,x)-1)/(base-1)

the bigger the value of base is, the stronger the effect, the slower volume starts growing in the beginning and the faster it grows in the end ...

a slighty simpler approach, giving you similar results (you are only in the interval between 0 and 1, so approximations are quite simple, actually), is to exponantiate the original value, as

y = Math.pow(x, exp);

for exp bigger than 1, the effect is, that the output (i.e. the volume in you case) first goes up slower, and then faster towards the end ... this is very similar to exponential functions ... the bigger exp, the stronger the effect ...

like image 82
back2dos Avatar answered Nov 20 '22 23:11

back2dos


Human hearing is logarithmic, so you want an exponential function (the inverse) to apply to the linear output of your slider. I don't know if human hearing is closer to ln or log:

For Ln:

e^x

For Log:

10^x

You could experiment with other bases too. You will then need to scale your output so that it covers the available range of values.

Update

After a bit of research it seems that base 2 would be appropriate since the power is related to the square of the pressure. If anyone knows better, please correct me.

I think what you want is:

v' = 2^v.a^v - 1
a  = ( 2^(log2(m+1)/n) )/2

v is your linear input value ranging from 0..n v' is your logarithmic value ranging from 0..m

The -1 in the first equation is to give you an output range from 0 instead of 1 (since k^0=1).

The m+1 is to compensate for this so you get 0..m not 0..m+1

You can of course get tweak this to suit your requirements.

like image 42
Draemon Avatar answered Nov 20 '22 22:11

Draemon


Hearing is complicated, the perceived loudness varies according to frequency, the duration of the sample, and from person to person. So this cannot be solved mathematically but by trying a variety of functions for the control and picking the one which 'feels' the best.

Do you find at the moment that varying the control at the low end of the range has little effect on the apparent volume, but that the volume increases rapidly at the upper end of the range? Or do you hear the reverse, the volume varies too quickly at the low end and not enough at the high end? Or would you like finer control over the volume at medium levels?

Increased low-volume sensitivity:

SoundTransform.volume = Math.sin(x * Math.PI / 2);

Increased high-volume sensitivity:

SoundTransform.volume = (Math.pow(base,x) - 1)/(base-1);

or

SoundTransform.volume = Math.pow(x, base);

Where base > 1, try different values and see how it feels. Or more drastically, a 90 degree circular arc:

SoundTransform.volume = 1 - Math.sqrt(1-(x * x));

Where x is slider.volume and is between 0 and 1.

Please do let us know how you get on!

like image 5
Matt Howells Avatar answered Nov 20 '22 22:11

Matt Howells


Yes, human perception is logarithmic. Considering this, you should adjust a volume exponentially, so that the percieved increase becomes linear. See decibel on Wikipedia

like image 2
Tamás Szelei Avatar answered Nov 20 '22 22:11

Tamás Szelei


Android already do such things from Audio Framework.It use decibels to adjust the volumes. User can use steps such as from 1 to 7 for ringtone or 1 to 15 for music. The formula is:

User call set volume API linearly but get amplitude exponentially. graph as below: enter image description here

like image 2
beetlej Avatar answered Nov 21 '22 00:11

beetlej