Convert ReplayGain values to volume adjustments
Asked Answered
E

2

6

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?

Externalization answered 28/9, 2012 at 11:59 Comment(1)
Hey - did you ever manage to solve this problem? Also, how did you extract the replay-gain tags from the audio file?Sensor
S
4

I'm working on this same issue and I think I got it.

The first thing to realize is that it is not possible to amplify an audio file by adjusting a player's volume. You simply can't. Volume goes from 0% to 100%, and that's it.

What you actually do is attenuate everything. To do that, you'll need to decide what volume should be 0dB. That is, what should be the volume for an audio file where no attenuation nor amplification is applied.

Let's say that you want 0dB to be 60%. This will be your "base".

Knowing that vol% = 100 * 10 ^ (db / 20) - base, we can then figure out our formula to obtain the volume for a given dB value:

vol% = 100 * 10 ^ (REPLAYGAIN_TRACK_GAIN / 20) - 60

You might also want to know what's your dB range. We can do this by isolating the db variable from the above formula:

db = 20 * Log(vol% + base) / (Log(2) + Log(5)) - 40

Plugging in the volume and base values into the former formula we'll have that a 0% volume (mute) corresponds to -4.44dB and 100% (max volume) corresponds to +4.02dB.

This is helpful because you need to know what dB values your formula will be able to handle. For this same reason, you will need to tweak the vol% formula so that it "clips" dB values that are outside your supported range:

vol% = Min(100, Max(0, 100 * 10 ^ (REPLAYGAIN_TRACK_GAIN / 20) - 60)
Solidago answered 22/3, 2017 at 22:47 Comment(5)
note: because the REPLAYGAIN_TRACK_GAIN is probably a double, you should use Math.pow()Recessive
Thanks for you comment @Xerus, but why is that exactly?Solidago
I'm afraid that's incorrect @Xerus. In VB, all arithmetic operators (+-/*^ etc...) work over doubles. You can test it yourself with this simple code: Debug.Assert(1.23 ^ 4.56 = Math.Pow(1.23, 4.56))Solidago
seeing that he targets android and uses a MediaPlayer, he's using Java. But whatever, language doesn't matter, it's the formula that matters and it seems to work for me :)Recessive
It confuses me to find from this formula that we get a range of roughly +/- 4dB; esp. since the original post suggested a 103 dB linear range. And that the commonly used "normal" value is 89 dB relative to the base acoustic pressure. What is the reason for such a small range?Brockie
I
2
  • 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.

Intrusive answered 28/11, 2014 at 2:1 Comment(1)
For what it's worth, Vanilla Player for Android seems to use the logarithmic scale to linear scale conversion - github.com/vanilla-music/vanilla/blob/…Heaveho

© 2022 - 2024 — McMap. All rights reserved.