May 08, 2012, 13:29:00 Last Edit: May 08, 2012, 19:06:30 by Einhard
I have several tracks that are too quiet and this feature will be really helpful. I know there is ReplayGain but it doesn't work with other backends than gstreamer and I hardly ever got satisfying results with it. My proposition is adding one more tag/option which stores volume values. Whenever track will be played the volume should be set according to tag (<0-100> range, where everything outside means default volume).

Quite frankly, replaygain is the standard, and it seems to be working well, so adding another tag to do the same job doesn't look like a good idea.

About replaygain only working with gstreamer, I took a quick look at mplayer, and it looks like using the options "-af volume=x" were x is the replaygain value, would do most of the job, and would be very easy to add.

About replaygain not satisfying you, maybe what you need is a way to edit the gain manually ? That would definitely allow you to change the loudness of a track as you wish.

Note that currently scanning replaygain from within gmb is extremely unstable, it will be stable when using libglib-perl 1.251 or later.

Quote from: Quentin Sculo on May 10, 2012, 17:44:49
Quite frankly, replaygain is the standard, and it seems to be working well, so adding another tag to do the same job doesn't look like a good idea.

About replaygain only working with gstreamer, I took a quick look at mplayer, and it looks like using the options "-af volume=x" were x is the replaygain value, would do most of the job, and would be very easy to add.

About replaygain not satisfying you, maybe what you need is a way to edit the gain manually ? That would definitely allow you to change the loudness of a track as you wish.
Fair enough. Adding replaygain support for mplayer backend and some option to manually edit the gain within gmb would be great and solve my problem completely.

Quote
Note that currently scanning replaygain from within gmb is extremely unstable, it will be stable when using libglib-perl 1.251 or later.
Yeah, I noticed. With 1.241 gmb crashes almost every time I try to scan a track.

#3 June 13, 2012, 14:46:11 Last Edit: June 13, 2012, 15:43:22 by Einhard
Ok, I've checked the latest git version and there are several problems with replaygain.

For 90/100 volume in gmb without track gain set, album mode 0ff, pre-amp 0, fallback-gain 0   I get
gain=0 peak=1 => scale factor=min(1,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 72.9

the same but with pre-amp 10
gain=10 peak=1 => scale factor=min(3,16227766016838,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 72.9

For 87/100 volume
gain=9,99999999999999 peak=1 => scale factor=min(3,16227766016838,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 65.8503

For 0,3 dB track gain (set with advanced tag edit) and pre-amp 0
gain=0 peak=1 => scale factor=min(1,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 65.8503

For 1 dB and pre-amp 0
gain=1 peak=1 => scale factor=min(1,12201845430196,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 65.8503

For 4 dB and pre-amp 10
gain=14 peak=1 => scale factor=min(5,01187233627272,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 65.8503

For 10 dB and pre-amp 10
gain=20 peak=1 => scale factor=min(9,99999999999999,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 65.8503

For 20 dB and pre-amp 0
gain=20 peak=1 => scale factor=min(10,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 65.8503

For -1dB and pre-amp 10
gain=8,99999999999999 peak=1 => scale factor=min(2,81838293126445,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 65.8503

For -10 dB and pre-amp 10
gain=-1,06581410364015e-14 peak=1 => scale factor=min(0,999999999999999,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 65.8502999999999

For -1 dB and pre-amp 0
gain=-1 peak=1 => scale factor=min(0,891250938133746,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 58.6891416513886

For -10 dB and pre-amp 0
gain=-10 peak=1 => scale factor=min(0,316227766016838,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 20.8236932605386

For -15 dB and pre-amp 0
gain=-15 peak=1 => scale factor=min(0,177827941003892,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 11.7100232634886

For -20 dB and pre-amp 0
gain=-20 peak=1 => scale factor=min(0,1,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 6.58503

It seems everything above 0 gain is ignored. Changing pre-amp and fallback-gain doesn't change anything (gain changes but volume not). You can allow higher values of -volume than 100 but I think you should use mplayer -softvol -softvol-max <10.0-10000.0> instead. There is also mplayer -softvol -af volume=x (where x is dB gain) but this won't work with mplayer -softvol -volume which you use. There are errors in mplayer documentation (or maybe it's so outdated) because you can set volume in range <0-10000> and setting softvol-max higher than 100 gives you louder sound without touching volume despite of what's written there. From my experience volume is usable in range <0-150>, 150 is about +11 dB which makes sense, with higher values there will be too much distortions in most cases.
mplayer -softvol -volume 150
and
mplayer - softvol - volume 100 -softvol-max 150
seems the same for me




There are also tracks that won't play using replaygain because of division by zero error. Output for track gain 0.389999999999986 dB and 0.702288627624512 peak (values from replaygain analyze)

Quote
Argument "0,39" isn't numeric in addition (+) at /usr/bin/../share/gmusicbrowser/gmusicbrowser_mplayer.pm line 225, <$OUTPUTfh> line 1113.
Argument "0,702289" isn't numeric in division (/) at /usr/bin/../share/gmusicbrowser/gmusicbrowser_mplayer.pm line 228, <$OUTPUTfh> line 1113.
*** unhandled exception in callback:
***   Illegal division by zero at /usr/bin/../share/gmusicbrowser/gmusicbrowser_mplayer.pm line 228, <$OUTPUTfh> line 1113.
***  ignoring at /usr/bin/gmusicbrowser line 1412, <$OUTPUTfh> line 1113.

Replaygain analyze doesn't work in debug mode but it works great in normal mode without crashes with 1.260 glib-perl now ;D

Thanks for testing this, I forgot to post a reply saying it was in git.
The problem with gain>0 is simply that it makes a scale factor >1 and with a peak=1, scaling with a factor >1 would result in clipping. More generally the replaygain standard says that the scale factor shouldn't be higher than 1/peak to prevent clipping.
The replaygain standard recommend a default peak of 1, which of course prevent a scale factor>1.
You can remove this limitation by commenting the line "$GainFactor= $invpeak if $invpeak<$GainFactor; #clipping prevention, make it an option ?" in gmusicbrowser_mplayer.pm
Some solutions :
1) ignore clipping prevention if there is no peak value, or use a higher default peak
2) make clipping prevention an option (with the additional problem that the gstreamer plugin doesn't offer this option, I'm not sure what its hard-limiter option do)
3) allow editing of peak

About the division by zero error, thanks, it should be fixed in git. It was a problem with your locale using a comma as decimal separator.
Don't hesitate to tell me if you see other errors.

What happens exactly with Replaygain analyze in debug mode ? (I'll test it later)

#5 June 13, 2012, 19:03:42 Last Edit: June 13, 2012, 20:02:53 by Einhard
Thanks for fast reply, support from your side is always the best ;D

QuoteAbout the division by zero error, thanks, it should be fixed in git. It was a problem with your locale using a comma as decimal separator.
Yeah, the problem is gone now.

QuoteSome solutions :
1) ignore clipping prevention if there is no peak value, or use a higher default peak
2) make clipping prevention an option (with the additional problem that the gstreamer plugin doesn't offer this option, I'm not sure what its hard-limiter option do)
3) allow editing of peak
From solutions you've mentioned I would pick 1 (except I would completely ignore scale factor limitation) and 3. Why? Because if you use replaygain analysis it will stick to the standard one way or another (no clipping possible) and if you manually change replaygain values it means you don't like the effect of that analysis so why stick to it's boundaries. For global volume lower than 100 (in linear scale of mplayer)  there is no possibility of clipping so this is in some way unnatural. In my previous post volume stayed at 65.8503 where it shouldn't be any problem if it would rise to 100. For the third solution, we can edit peak with Advanced Tag Editing but making replaygain_track/album_peak editable in song properties dialog would be helpful, even if it's only for testing purposes.

I have commented the line you've suggested and the effect is what I was looking for. ;D

gain=0 peak=1 => scale factor=min(1,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 65.8503

gain=2 peak=1 => scale factor=min(1,25892541179417,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 82.9006160442694

gain=2 peak=2 => scale factor=min(1,25892541179417,0,5)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 82.9006160442694

with clipping prevention

gain=2 peak=1 => scale factor=min(1,25892541179417,1)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 65.8503

gain=2 peak=0,5 => scale factor=min(1,25892541179417,2)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 82.9006160442694

gain=2 peak=2 => scale factor=min(1,25892541179417,0,5)
/usr/bin/mplayer -nocache -slave -vo null -nolirc -hr-mp3-seek -msglevel all=1:statusline=5 -softvol -volume 32.92515

It seems to work well, except that in any case above (without clipping prevention) there wasn't any sign of clipping at all. Replaygain analysis really fails with live music and amateur productions.


I found another bug:
1. Scan track with replaygain analisis
2. In song properities click save (no changes made)
3. Replaygain values are reset
It's related to the problem below. It happens with and without debug option

QuoteWhat happens exactly with Replaygain analyze in debug mode ? (I'll test it later)
Some sort of problem with tag saving/encoding. Replaygain tags are reset (rewritten with nan) after this. I don't have this issue outside debug mode.


*** GPerl asked to invoke callback from a foreign thread; handing it over to the main loop
done for ID=3267
replaygain-track-peak : 1
replaygain-reference-level : 89
replaygain-track-gain : -8,44000000000001
Wide character in warn at /usr/bin/../share/gmusicbrowser/gmusicbrowser_songs.pm line 1841.
Songs::Set(3267 ARRAY(0x4993fc0) abortmsg Przerwij analiz? Replay Gain error_prefix B??d zapisu znaczników Replay Gain :
abortcb CODE(0x49943e0) callback_finish CODE(0x49941a0)) called from : GMB::GST_ReplayGain:/usr/bin/../share/gmusicbrowser/gmusicbrowser_gstreamer-0.10.pm:658
HasChanged Progress -> updating Gtk2::HBox=HASH(0x52619b8)
HasChanged Progress -> updating Gtk2::HBox=HASH(0x52619b8)
FileTag::Write(3267,[replaygain_track_gain -nan replaygain_reference_level 89],CODE(0x50ec920))
new : Tag::ID3v2 Tag::MP3=HASH(0x50497f0)
ID3v2.3.0 : 69911 bytes
TIT3 (55 bytes)
TIT2 (13 bytes)
TIT1 (77 bytes)
TSSE (62 bytes)
TPE1 (21 bytes)
TCON (9 bytes)
TCOM (49 bytes)
TOPE (49 bytes)
TALB (19 bytes)
TYER (6 bytes)
USLT (29 bytes)
APIC (17457 bytes)
GEOB (51539 bytes)
TXXX (31 bytes)
TXXX (44 bytes)
TXXX (25 bytes)
........padding
length estimation : 185.88 s
startaudio=69911 copybegin=69911 length(towritebefore)=69601
endaudio=7505111 copyend=7505111 length(towriteafter)=128
in place editing.
ID=3267 towrite : replaygain_track_gain -nan replaygain_reference_level 89
HasChanged Progress -> updating Gtk2::HBox=HASH(0x52619b8)
new : Tag::ID3v2 Tag::MP3=HASH(0x4fbd598)
ID3v2.3.0 : 69911 bytes
TIT3 (55 bytes)
TIT2 (13 bytes)
TIT1 (77 bytes)
TSSE (62 bytes)
TPE1 (21 bytes)
TCON (9 bytes)
TCOM (49 bytes)
TOPE (49 bytes)
TALB (19 bytes)
TYER (6 bytes)
USLT (29 bytes)
APIC (17457 bytes)
GEOB (51539 bytes)
TXXX (31 bytes)
TXXX (25 bytes)
........padding
length estimation : 185,88 s
Songs::Changed : IDs=3267 fields=replaygain_track_gain modif
SongsChanged ARRAY(0x50e82d8) ARRAY(0x50d0fd8)
HasChanged CurSong -> updating CODE(0x3c4e3a8) Gtk2::Label=HASH(0x5246060) Stars=HASH(0x510ffa0) Layout::Label=HASH(0x5248a98) Layout::Label=HASH(0x5248510) Layout::Label=HASH(0x524c9a8) Gtk2::Table=HASH(0x524da80) Layout::AAPicture=HASH(0x5249ef8) Layout::Label::Time=HASH(0x510f048) Layout::Bar=HASH(0x52508d0) GMB::Plugin::LYRICS=HASH(0x51103a8) Layout::PictureBrowser=HASH(0x510f5c8) Gtk2::Label=HASH(0x52501b0) Gtk2::Label=HASH(0x525bee0) GMB::Plugin::LYRICS=HASH(0x510ddf0) Gtk2::Label=HASH(0x525d3a8) Gtk2::Label=HASH(0x525ff88) Layout::Label=HASH(0x510efa0) Layout::Window=HASH(0x510f550) GMB::DBus::Object=HASH(0x4f1daa8)
HasChanged SelectedID_Global(84997720-2) -> updating
HasChanged SelectedID_Global(84997720-3) -> updating
HasChanged SelectedID_Global(84997720-0) -> updating Layout::NoteBook=HASH(0x510f658)
HasChanged SongsChanged -> updating CODE(0x2cb0be8) SongList=HASH(0x5245708) FilterPane=HASH(0x51103d8) FilterPane=HASH(0x3081858) SongList=HASH(0x191b4d8) SongList=HASH(0x5110348) SongList=HASH(0x52600d8) SongList=HASH(0x525cd18) FilterPane=HASH(0x5250f88)
makesub filter=
makesub filter=
makesub filter=
HasChanged RecentSongs -> updating CODE(0x3c4e1b0)
IdleLoop End


It seems that everything works well with
LC_ALL=C gmusicbrowser -debug
*** GPerl asked to invoke callback from a foreign thread; handing it over to the main loop
done for ID=3267
replaygain-track-peak : 1
replaygain-reference-level : 89
replaygain-track-gain : -8.44000000000001
Songs::Set(3267 ARRAY(0x3bd2b58) abortmsg Abort ReplayGain analysis error_prefix Error writing replaygain tags :
abortcb CODE(0x3bd2f78) callback_finish CODE(0x3bd2d38)) called from : GMB::GST_ReplayGain:/usr/bin/../share/gmusicbrowser/gmusicbrowser_gstreamer-0.10.pm:658
HasChanged Progress -> updating Gtk2::HBox=HASH(0x44a1138)
HasChanged Progress -> updating Gtk2::HBox=HASH(0x44a1138)
FileTag::Write(3267,[replaygain_track_gain -8.44000000000001 replaygain_reference_level 89],CODE(0x432b1f8))
new : Tag::ID3v2 Tag::MP3=HASH(0x3946c70)
ID3v2.3.0 : 69911 bytes
TIT3 (55 bytes)
TIT2 (13 bytes)
TIT1 (77 bytes)
TSSE (62 bytes)
TPE1 (21 bytes)
TCON (9 bytes)
TCOM (49 bytes)
TOPE (49 bytes)
TALB (19 bytes)
TYER (6 bytes)
USLT (29 bytes)
APIC (17457 bytes)
GEOB (51539 bytes)
TXXX (31 bytes)
TXXX (25 bytes)
........padding
length estimation : 185.88 s
startaudio=69911 copybegin=69911 length(towritebefore)=69655
endaudio=7505111 copyend=7505111 length(towriteafter)=128
in place editing.
ID=3267 towrite : replaygain_track_gain -8.44000000000001 replaygain_reference_level 89
HasChanged Progress -> updating Gtk2::HBox=HASH(0x44a1138)
new : Tag::ID3v2 Tag::MP3=HASH(0x41fe220)
ID3v2.3.0 : 69911 bytes
TIT3 (55 bytes)
TIT2 (13 bytes)
TIT1 (77 bytes)
TSSE (62 bytes)
TPE1 (21 bytes)
TCON (9 bytes)
TCOM (49 bytes)
TOPE (49 bytes)
TALB (19 bytes)
TYER (6 bytes)
USLT (29 bytes)
APIC (17457 bytes)
GEOB (51539 bytes)
TXXX (31 bytes)
TXXX (44 bytes)
TXXX (25 bytes)
........padding
length estimation : 185.88 s
Songs::Changed : IDs=3267 fields=replaygain_track_gain modif
SongsChanged ARRAY(0x4303510) ARRAY(0x421eab0)
HasChanged CurSong -> updating CODE(0x2e7b010) Gtk2::Label=HASH(0x44857e0) Stars=HASH(0x4482de0) Layout::Label=HASH(0x4488218) Layout::Label=HASH(0x4487c90) Layout::Label=HASH(0x448c128) Gtk2::Table=HASH(0x448d200) Layout::AAPicture=HASH(0x4489678) Layout::Label::Time=HASH(0x434f848) Layout::Bar=HASH(0x4490050) GMB::Plugin::LYRICS=HASH(0x44831e8) Layout::PictureBrowser=HASH(0x434fda0) Gtk2::Label=HASH(0x448f780) Gtk2::Label=HASH(0x449b660) GMB::Plugin::LYRICS=HASH(0x434e5f0) Gtk2::Label=HASH(0x449cb28) Gtk2::Label=HASH(0x449f708) Layout::Label=HASH(0x434f7a0) Layout::Window=HASH(0x434fd28) GMB::DBus::Object=HASH(0x415dfe8)
HasChanged SelectedID_Global(71836824-0) -> updating Layout::NoteBook=HASH(0x4482498)
HasChanged SelectedID_Global(71836824-3) -> updating
HasChanged SelectedID_Global(71836824-2) -> updating
HasChanged SongsChanged -> updating CODE(0x1ee3e70) SongList=HASH(0x4484e88) FilterPane=HASH(0x4483218) FilterPane=HASH(0x22b4550) SongList=HASH(0xb97540) SongList=HASH(0x4483188) SongList=HASH(0x449f858) SongList=HASH(0x449c780) FilterPane=HASH(0x4499378)
makesub filter=
makesub filter=
makesub filter=
HasChanged RecentSongs -> updating CODE(0x2e7ae18)
IdleLoop End