IPB

Welcome Guest ( Log In | Register )

 
Reply to this topicStart new topic
Player implementation of ReplayGain (Android)
Havin_it
post Oct 8 2012, 11:53
Post #1





Group: Members
Posts: 6
Joined: 7-October 12
Member No.: 103677



Hello,

I'm hoping some folks here can help me get my head around the task of adding ReplayGain functionality to the stock Android music player app. My lack of training in maths and audio science is making it hard for me to ask the right questions probably, so please bear with me if you can.

I've read through the replaygain spec (original proposal on your minisite and the updated version in the wiki) but there's still a lot that I'm unclear on. A sound engineeer friend helped me along a little further, but I think I exhausted his patience :(

Now I understand that all replaygain adjustments start from -14 dBFS, and RG treats this as equivalent to 89 dB (SPL). Where I get lost is how I'd translate that to the logarithmic scale used by the volume control function I have to work with, which takes a float value (0-1 = mute-max) to attenuate the playback volume for the app (normally it stays at 1 and is used mainly for fading; it's independent of the master volume controls for the device). It can be abstracted to a linear scale (of the type that a physical volume control would use, I believe) of 0-<number of your choice>. The value is calculated from a linear-scale value like this:
CODE
#Example to set volume to 50/100 on the linear scale
int maxvol = 100;
int newvol = 50;
float ratio = (float) (1 - (Math.log(maxvol - newvol) / Math.log(maxvol)));


But to get to that point, I need somehow to abstract that starting-point of -14 dBFS / 89 dB SPL onto that linear scale. From what I've read so far, I get the feeling there is no "pure" way to do this and I'll be required to make some educated guesses. So that's where being uneducated lets me down :(

I'd just be grateful for any suggestions, help or references in how I might understand the task better and construct a *reasonably* accurate equation for it.
Go to the top of the page
+Quote Post
Lear
post Oct 8 2012, 12:40
Post #2


VorbisGain developer


Group: Developer
Posts: 140
Joined: 10-January 02
Member No.: 973



You could take a look at the Vorbis plugin in XMMS. The ReplayGain implementation there is pretty straight-forwward (vorbis_update_replaygain translates the adjustment to a scale factor, and vorbis_process_replaygain applies it). I used it as a reference when implementing ReplayGain in Rockbox (not as straight-forward; the math is done in fixed-point, and the implementation is shared by many decoders).
Go to the top of the page
+Quote Post
saratoga
post Oct 8 2012, 16:03
Post #3





Group: Members
Posts: 4907
Joined: 2-September 02
Member No.: 3264



QUOTE (Havin_it @ Oct 8 2012, 06:53) *
But to get to that point, I need somehow to abstract that starting-point of -14 dBFS / 89 dB SPL onto that linear scale. From what I've read so far, I get the feeling there is no "pure" way to do this and I'll be required to make some educated guesses. So that's where being uneducated lets me down sad.gif

I'd just be grateful for any suggestions, help or references in how I might understand the task better and construct a *reasonably* accurate equation for it.


full scale = 1.0
-14dBFS = 14 dB below full scale

http://en.wikipedia.org/wiki/Decibel#Power_quantities

P=10^(dbFS/10)*FS
P=10^(-14/10)*1.0
P= 0.0398

Go to the top of the page
+Quote Post
[JAZ]
post Oct 8 2012, 18:57
Post #4





Group: Members
Posts: 1772
Joined: 24-June 02
From: Catalunya(Spain)
Member No.: 2383



@saratoga: Since we're talking about volume, shouldn't we use the amplitude formula, instead of the power formula?

A=10^(dBFS/20)*FS
A=10^(-14/20)*1.0
A=0.1995262

@Havin_it: If you are just interested in applying replaygain on playback, you don't need to understand how it is calculated. You just need to understand what means the data stored in the tags, and how to modify the volume (amplitude) in relation to those tags.

1) The value stored in the tag is the difference in dBs between the calculated "loudness" of the file versus the 89dB reference.
This means, in the tag, you might have values like -7dB, -4dB, -11dB , 2.5dB...
This is translated to: 89- (-7) = 96dB, 89 -(-4) = 93dB, 89- (-11) = 100dB, 89- (2.5) = 86.5dB

2) To apply replaygain (and so, make all files to have a similar loudness), the dB values are converted to amplitude, relative to the 89dB value.
83dB = 89dB - (6dB) = 6dB softer -> increase volume by 6dB
96dB = 89dB - (-7dB) = 7dB stronger -> reduce volume by 7dB

In the end, you simply have to apply the formula that I've pasted above, and using the value from the tag directly in place of dBFS. The calculated gain is then used as the volume (in a 0...1 range volume)
Go to the top of the page
+Quote Post
Havin_it
post Oct 8 2012, 22:05
Post #5





Group: Members
Posts: 6
Joined: 7-October 12
Member No.: 103677



Hi, thanks all for replying :)

@Lear, I actually did look at the RockBox src already, but I agree the XMMS is easier to follow ;) Thanks for suggesting it.

@[JAZ], am I right in understanding then that the formula needs to be 10^((<replaygain tag value> -14) / 20)? Otherwise the results for all +ve adjustments are >1.
Go to the top of the page
+Quote Post
[JAZ]
post Oct 8 2012, 22:30
Post #6





Group: Members
Posts: 1772
Joined: 24-June 02
From: Catalunya(Spain)
Member No.: 2383



No, you don't need to substract 14.

Usually, stored replaygain values are negative. Of course, with positive values, you are supposed to increase the volume.

Just let's be clear that i am talking about the replaygain value, not the peak value.
Go to the top of the page
+Quote Post
Havin_it
post Oct 9 2012, 00:21
Post #7





Group: Members
Posts: 6
Joined: 7-October 12
Member No.: 103677



Well, the collection I have comprises a couple of decades' worth of CDs ripped to mp3 (about 1200 tracks) tagged using mp3gain, and there are plenty of +ve gain values in there (though most are -ve).

The problem is, I'm starting from 1 = max volume so to accommodate the +ve gains I necessarily have to reduce before I can increase. From reading the spec I thought this was the purpose of the -14dB, but it's becoming clear that it's not that simple :(
Go to the top of the page
+Quote Post
saratoga
post Oct 9 2012, 00:44
Post #8





Group: Members
Posts: 4907
Joined: 2-September 02
Member No.: 3264



QUOTE (Havin_it @ Oct 8 2012, 19:21) *
The problem is, I'm starting from 1 = max volume so to accommodate the +ve gains I necessarily have to reduce before I can increase.


Why? A number greater than 1 just means you have gain, which is what should happen if the replaygain value is positive.

Edit: to be clear, replaygain doesn't adjust the volume, it changes the gain. If the function you mentioned above is just adjusting the Android volume, thats likely not what you want. You're supposed to scale the actual the samples in your decoded PCM. If you try to do it by adjusting the player volume, you won't benefit from things like clipping protection. Once you compute the gain, just multiply it by each sample. If its less than 1.0, you'll have attenuation. If its greater, you'll have amplification.

This post has been edited by saratoga: Oct 9 2012, 00:57
Go to the top of the page
+Quote Post
Havin_it
post Oct 9 2012, 01:38
Post #9





Group: Members
Posts: 6
Joined: 7-October 12
Member No.: 103677



Right, I see. The only open-source implementation that I've looked at so far that I actually comprehended the final stage of the process was the old Amarok script, which did basically adjust the UI volume slider, so I assumed this was the approach other implementations were following.

This certainly means the task's more challenging than I anticipated; the Android MediaPlayer API (for which the stock music player app I intended to build on is basically a wrapper) doesn't expose anything as low-level as PCM sample levels. In fact so far I can't see anything in the Java APIs that does, which probably means native code will be required (bit more of a learning curve for me!) though I've only started familiarising myself with it so I could be wrong.

Thanks for piercing my misapprehension anyway; hopefully this'll be the biggest one I'll make and the rest will be a little more straightforward ;)
Go to the top of the page
+Quote Post
saratoga
post Oct 9 2012, 01:46
Post #10





Group: Members
Posts: 4907
Joined: 2-September 02
Member No.: 3264



QUOTE (Havin_it @ Oct 8 2012, 20:38) *
This certainly means the task's more challenging than I anticipated; the Android MediaPlayer API (for which the stock music player app I intended to build on is basically a wrapper) doesn't expose anything as low-level as PCM sample levels.


If you don't have access to the actual audio, then its going to be hard to implement DSP effects. I guess if you don't have the ability to increase volume (which seems odd to me), you could try applying some constant volume reduction and make that 0 dB, then implement positive gain as less reduction. Depending on how the API is implemented, this might actually be equivalent to scaling the audio directly, or it might not.
Go to the top of the page
+Quote Post
Havin_it
post Oct 9 2012, 03:24
Post #11





Group: Members
Posts: 6
Joined: 7-October 12
Member No.: 103677



It's not exactly that I can't increase it, just that I'd have to somehow calibrate/estimate/pullouttamyass an appropriate value between 0 and 1 to act as the reference level and increase (or decrease) from there. The volume control function I was planning to use sets the volume just for that player app, keeping it independent of the device's master volume levels (I think the idea being that it doesn't interfere with other things like the ringer, voice, notifications etc). It always starts at 1, so its purpose is really for attenuation (e.g. fading tracks in and out).

Anyway, that one's out the window unless I'm content to resort to some sort of bodge (won't deny it's tempting, but...). However, I did turn up something in the MediaPlayer API that might serve. It's possible to attach an aux effect to the player that "directs a certain amount of its energy to" that effect (potentially all of it, if I read it right). One of the available effects is an Equalizer, whose methods include setting the gain for a series of frequency bands. Sooooo, perhaps I can use that to apply the gain across all the available bands simultanaeously. More reading ahead...
Go to the top of the page
+Quote Post
Havin_it
post Oct 14 2012, 11:32
Post #12





Group: Members
Posts: 6
Joined: 7-October 12
Member No.: 103677



Pleased to report that the Equalizer route worked out nicely. I'm able to access a 5-band equalizer for the media playback stream, each band having a -15 - 15 dB range. So for each new track I just read the tags, and add the (+/-) track gain to the default level for each band (which are +3, 0, 0, 0, +3 on my test phone).

The results sound good so far, just wondering if my logic's sound or whether I ought to be bringing all bands to zero before adding the replaygain? Also, in the above case, if I had a RG value of +15 dB would you recommend pushing all bands to +15, or to (+15, +12, +12, +12, +15) to preserve the original relative levels? I don't think I can chain multiple equalizers on the one output, so trying to complement existing settings rather than ride rough-shod over them seems the preferred approach if I were to take the app public.
Go to the top of the page
+Quote Post
lvqcl
post Oct 14 2012, 11:40
Post #13





Group: Developer
Posts: 3358
Joined: 2-December 07
Member No.: 49183



QUOTE (Havin_it @ Oct 14 2012, 14:32) *
if I had a RG value of +15 dB would you recommend pushing all bands to +15, or to (+15, +12, +12, +12, +15) to preserve the original relative levels?


Neither the former nor the latter. It's usually not a good idea to use EQ for replaygain.

This post has been edited by lvqcl: Oct 14 2012, 11:40
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 



RSS Lo-Fi Version Time is now: 23rd August 2014 - 09:09