Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert ReplayGain values to volume adjustments

I'm trying to implement Replay Gain (that is, responding to replaygain tags in music files) into the stock Android/AOSP music player app. This is just a personal project but down the line I could offer it as a patch or maybe make a lib or player of my own. I'm only looking at Track Gain in the first instance. The nature of my question is probably down to the fact I flunked maths ;)

The task is to do two things: A) Before playback starts, clamp the volume to device maximum -14dB (or maybe more, some sources advise -23dB). B) Before playback of each track begins, read its tag and adjust by that number of dB.

I see that adjusting the playback volume in Android involves logarithm scaling as well, but since I'm new to logarithms I'm not sure if that makes things easier or twice (10x?) as hard.

Can anyone please give me the clue I lack on how to translate the decibel values to usable params for MediaPlayer.setVolume()? Thanks for any tips.

EDIT: I have some (probably shaky) assertions that might make the connection needed, but I badly need to be told if any of them are harebrained.

  1. ReplayGain works on an assumption that the target level of -14 dBFS == 89dB SPL. I therefore pretend these scales are equivalent all the way up and down (I know this is inaccurate, but how inaccurate?)
  2. I treat MediaPlayer.setVolume(1.0f,1.0f) (the maximum volume) as 0dBFS.
  3. Based on (1), I equate this to 89+14 = 103dBSPL.
  4. I treat MediaPlayer.setVolume(0.0f,0.0f) (mute) as 0dBSPL, so I have an abstracted linear volume scale of 0-103.

If these hold water, I'd turn a Track Gain value of -1.3 into the appropriate parameter for MediaPlayer.setVolume() as follows:

  1. Target loudness = 89 - 1.3 = 87.7
  2. float newVol = 1.0f - (Math.log(103 - 87.7 / Math.log(103)) = 0.41143207395167

Is this remotely on the right track?

like image 440
Headbank Avatar asked Oct 06 '22 12:10

Headbank


1 Answers

  • a dBFS stands for deciBel Full Sound, so assigning that to the maximum level is totally sensible.
  • Decibels are a unit expressing (the log of) the ratio of two values. All you are saying when when using dBFS vs. dBSPL is which reference acoustic pressure you use.
    • -14 dBFS means that you're using a 10^(-14/20) times smaller acoustic pressure than what your reference is (i.e. the maximum possible)
    • 89 dBSPL means that youre using a 10^(89/20) times bigger value than "the commonly used reference sound pressure in air [...] p0 = 20 μPa (RMS) or 0.0002 dynes/cm2,[5] which is usually considered the threshold of human hearing (roughly the sound of a mosquito flying 3 m away)." (from wikipedia).

So once you got a common point between your two scales, they then evolve the same. You basically defined a ratio between the reference acoustic pressures of your two scales by saying that -14dbFS = 89 dBSPL.

Because multiplicative scales are a hassle, we take the logarithm of these multiplicative values, and divide them by 10, which gives us the additive values called decibels (the extra 2 factor comes from the fact we compare the square of acoustic pressures, not acoustic pressures themselves).

Now finally, if you consider you have a range of 103 dB that is mapped logarithmically (as are your dB) from 0.0f to 1.0f (which is what seams to be the case for playback volume in Android), then -14dBFS is (103 - 14)/103.

You need to get into the math of log's only if you want to make a linear scale out of this : 80% of max sound on a linear scale would be 1-log(20)/log(100) on your output scale.

like image 160
Cimbali Avatar answered Oct 10 '22 02:10

Cimbali