GNOME Bugzilla – Bug 558235
does not support lame mp3 gapless tag
Last modified: 2018-05-24 13:44:07 UTC
Rhythmbox claims to support gapless playback. It does for the most part, but on mp3's, it doesn't. This is due to the design of mp3 frames. Each frame is a predetermined length of time, and the last frame is no exception, which causes a small silence at the end of each song. LAME has a workaround for this: embed a tag that tells a decoder exactly how long the song should be. iTunes, iPod, and libgpod support this. Rhythmbox neither makes use of this tag in its normal playback, nor for syncing songs to an iPod. The bug is present in all versions of Rhythmbox.
I know libgpod has some fields to put the gapless playback information, but I'm not really sure what to put in there. If you have some pointers explaining it all (what is in the lame tag and what the ipod expects), or even better, if you can write a patch ;), that would be great
I'm not exactly sure what should go in the field either, but I know that in gtkpod, if you edit the information in a file, you can see a field called "length". In this field, is a time in the format of mm:ss.### (minutes:seconds.milliseconds). Also, in audacious, you can see the length field as (I believe) milliseconds only.
If I want to try patching this, what do I have to do? Is there CVS or SVN that I can use? Or should I patch this against 0.11.x?
A patch against the 0.11.x release would be enough I think, though it's generally more convenient to work from svn, rhythmbox is hosted on svn.gnome.org. The changes for the ipod code would have to be done in plugins/ipod/rb-ipod-source.c (there's a function creating a Itdb_Track structure from a RhythmDBEntry)
The playback side of this would probably be mostly in GStreamer rather than rhythmbox.
Thanks for the tips, Christophe and Jonathan.
Here's what I've found by poking around in the 0.11.6 source. in plugins/ipod/rb-ipod-source.c, in the function create_ipod_song_from_entry(...): line 479: track->tracklen = rhythmdb_entry_get_ulong(entry, RHYTHMDB_PROP_DURATION); line 480: track->tracklen *= 1000; track is a struct of type Itdb_Track, which is typedef'd by libgpod. track->tracklen is presumably the length in seconds as returned by rhythmdb_entry_get_ulong(...) * 1000, for milliseconds. i'm not sure what's in lame's length tag, but i would venture to say that it's a value in milliseconds for the length. Somewhere along the way, a value should be read from lame's length tag, but it seems this isn't being done. It should be done right here (instead of grabbing it from rhythmbox's database) along the lines of: track->tracklen = get_id3_length_milliseconds(filename); and skip the multiplication by 1000. however, this will only solve the problem for ipods, and not for playback within rhythmbox itself. looking in rhythmdb.c at rhythmdb_entry_get_ulong(...), we see that the problem really lies in the rhythmbox database. Within the function, there are the two lines: line 4817: case RHYTHMDB_PROP_DURATION: line 4818: return entry->duration; which are being used on this specific call of the function. entry (i would guess) is directly from rhythmbox's database, and that's where we're getting the track length in seconds from. i don't know how this could be changed in order to actually work, as i'm not familiar with how the playback end of rhythmbox works. another thing to consider is other formats that ipod supports. the example of track->tracklen = get_id3_length_milliseconds(filename); should probably only be implemented for mp3's, and from the looks of it, there should be no problem discerning filetypes.
Why do we have to reinvent the wheel here? There is a fine open source MP3 decoder that supports gapless MP3 playback (skipping encoder/decoder padding/junk) and probably any feature you would ever like to support in the future. It is LGPL'ed, actively maintained and calles mpg123. Why not just use simply that? http://www.mpg123.de/features.shtml
Maybe someone has created a GStreamer plugin using mpg123. If so, you could try it out and see if it does gapless playback properly. If not, maybe you could do it yourself. What wheel do you think is being reinvented?
Well, it's probably rather a GStreamer problem then because the current GStreamer MP3 decoder plugin doesn't make use of the existing and working mpg123 library (the linux mpg123 command line tool actually plays back MP3 files with an intact LAME info tag). Maybe the "product" should be changed to GStreamer and I wonder why the component is classified as "IPod" as well. I will check if there are exsisting GStreamer plugins based on mpg123, but if not, I highly doubt that I am able to convert the mpg123 library into a GStreamer plugin. There is just too little GStreamer knowledge on my part. The bad thing is that no player seems to playback MP3 gaplessly (except for the mpg123 commandline tool). Even Audacious which doesn't depend on GStreamer and ships its own decoders instead doesn't have its MPEG decoder compiled against mpg123 but against the much older libmad library (from 2004).
There is actually a mpg123 Gstreamer plugin at http://gst.homeunix.net/ which offers even a Debian package. It is called libgst-mpg123_0.1.deb but works apparently just for the i386 architecture (I am on AMD64 here). I will report back if I can get it to work on this machine and post my results...
I uploaded good test samples to the corrispondent Ubuntu bug: https://bugs.launchpad.net/ubuntu/+source/gstreamer0.10/+bug/290150 I tried out those samples with the libgst-mpg123_0.1.deb on Rhythmbox 0.12.0 on Jaunty Jackalope (because that is my only 32 bit install on my HDD). I had to enable the crossfading option first with this version (still required to to that then) and was able to playback the ogg files fine. But altough I know that the mpg123 library can handle the info tags (the command line mpg123 tool plays eben gaplessly on Jaunty) and although the Gstreamer pipeline seems to be fine (because I can playback ogg and lossless flawlessly), there are still gaps. What am I missing here? Is there an old mpg123 library used for libgst-mpg123? Or are there some features simply not implemented?
I have no idea. Perhaps the author of the mpg123 GStreamer plugin could help you with that.
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/rhythmbox/issues/651.