OxygenCobalt / Auxio

A simple, rational music player for android
GNU General Public License v3.0
2.16k stars 144 forks source link

Add support for MP4 `----` ReplayGain tags #292

Closed bodayw closed 1 year ago

bodayw commented 1 year ago

Describe the bug/crash:

Replaygain is not working on the .m4a files that I have, either from iTunes store or encoded by myself using qaac, with replaygain tags written by foobar2000 on Windows.

Replaygain on .mp3 files is working fine (although I did come across one situation that it temporarily stopped working , which I will report in a separate issue).

I could confirm this by using serveral files at hand that have significant replaygain values (> +-10 dB) and compare the volume between Auxio and foobar2000 Android.

Could it be some non-standard replaygain tags? I'm pasting the mediainfo of one of those files below, or if necessary, I can upload a file if you want.

General
Complete name                            : Music\Adele\21\01 Rolling in the Deep.m4a
Format                                   : MPEG-4
Format profile                           : Apple audio with iTunes info
Codec ID                                 : M4A  (M4A /mp42/isom)
File size                                : 7.24 MiB
Duration                                 : 3 min 48 s
Overall bit rate mode                    : Variable
Overall bit rate                         : 266 kb/s
Album                                    : 21
Album/Performer                          : Adele
Part/Position                            : 1
Part/Total                               : 1
Track name                               : Rolling in the Deep
Track name/Position                      : 1
Track name/Total                         : 12
Performer                                : Adele
ContentType                              : Music
Encoded date                             : UTC 2004-09-06 11:26:03
Tagged date                              : UTC 2014-01-19 00:43:01
Cover                                    : Yes
replaygain_track_peak                    : 1.101957
replaygain_track_gain                    : -9.86 dB
replaygain_album_peak                    : 1.101957
replaygain_album_gain                    : -9.86 dB
AppleStoreCatalogID                      : 420075084
AlbumTitleID                             : 262836961
cmID                                     : 65415307
PlayListID                               : 420075073
GenreID                                  : 14

Audio
ID                                       : 1
Format                                   : AAC LC
Format/Info                              : Advanced Audio Codec Low Complexity
Codec ID                                 : mp4a-40-2
Duration                                 : 3 min 48 s
Bit rate mode                            : Variable
Bit rate                                 : 256 kb/s
Maximum bit rate                         : 343 kb/s
Channel(s)                               : 2 channels
Channel layout                           : L R
Sampling rate                            : 44.1 kHz
Frame rate                               : 43.066 FPS (1024 SPF)
Compression mode                         : Lossy
Stream size                              : 7.11 MiB (98%)
Language                                 : English
Encoded date                             : UTC 2004-09-06 11:26:03
Tagged date                              : UTC 2014-01-19 00:43:01

Expected behavior

Replaygain should be applied as tagged in the file when playing.

Steps To Reproduce the bug/crash:

Play any .m4a files on Auxio. Replaygain settings (prefer track/album) doesn't matter.

Phone Information:

Redmi Note 10 Pro (China), MIUI 13.0.11 (based on Android 12)

Due Diligence:

OxygenCobalt commented 1 year ago

I don't think ReplayGain tags are directly supported from M4A atoms. They have to be in a COMM ID3v2 tag within an ID3v2 atom, which Kid3 supports I think.

Can I have a sample file? You can remove all the audio, I just want the tags.

bodayw commented 1 year ago

~That would explain the issue. Just had a look (never paid attention to this actually) into foobar2000 - Preferences - Advanced, and looks like it always use native (?) MP4 container for tagging~. For MP3s, it uses ID3v2.3 by default.

Here attached two (very short) files that I picked from my collection (I didn't remove the audio, though): replaygain_tag_samples.zip

edit: obivously I misread your comment earlier as I thought you meant that one would need to "hack" ID3v2 tags into the MP4 container.

bodayw commented 1 year ago

Is this related?

https://code.videolan.org/videolan/vlc/-/issues/18346

I can confirm the m4a files in my hand (tagged by foobar2000) are under the ---- atom.

Using Kid3, I deleted all the tags from an m4a file and manually added two replaygain tags, then checked with AtomicParley. I could see that the tags are also under the ---- atom:

> .\AtomicParsley.exe test1.m4a -t
Atom "----" [REPLAYGAIN_ALBUM_GAIN] contains: 10.00 dB
Atom "----" [REPLAYGAIN_TRACK_GAIN] contains: 10.00 dB
OxygenCobalt commented 1 year ago

Is this related?

Yep, this "----" atom is preferred by FooBar, while the ReplayGain spec specifies an "ID32" atom (The "open" metadata spec that is only slightly polluted by iTunes). ExoPlayer and VLC don't seem to support this, since it's an obscure and proprietary iTunes thing (sigh...).

The kid3 behavior is weird, when I use it, kid3 exclusively writes to the ID32 atom. Perhaps some kind of smart re-use is going on?

When I get time, I'll do research on this "----" atom and see if I can add it to ExoPlayer's parser For now, I'll add a minor disclaimer to the README regarding that not all MP4 files have ReplayGain support.

bodayw commented 1 year ago

VLC don't seem to support this

According to the VLC issue above, VLC should support it since then (5 years ago).

since it's an obscure and proprietary iTunes thing

Well, probably due to iTunes' popularity, seems a lot of tagging tools uses it. Apart from foobar2000, I came across another (also popular? mentioned on hydrogenaudio wiki and #7) replaygain scanner does the same: https://github.com/Moonbase59/loudgain#default-mode--s-i---tag-mode-i

kid3 exclusively writes to the ID32 atom

I couldn't reproduce this. I tried removing all atoms under moov.udta.meta.ilst with AtomicParley -P, and manually add a replaygain tag with kid3: kid3-cli.exe -c "set replaygain_album_gain '10.00 dB'" test2.m4a ...and checked with AtomicParley, it still appeared under ----.

I also noticed that most of my m4a files (those in my music library, also some other random downloaded ones) says this when using mediainfo:

Format profile                           : Apple audio with iTunes info
Codec ID                                 : M4A  (M4A /mp42/isom)

while some others says this:

Format profile                           : Base Media
Codec ID                                 : isom (isom/iso2/mp41)

No idea what are the differences, but out of curiosity, I tried the same command above to add a replaygain tag using kid3 for the latter, but I still got it under ----.

Anyway thanks for looking into this! I have to say it's a pleasant surprise to find Auxio a couple of days ago - have always been wanting a simple and elegant local music player.

OxygenCobalt commented 1 year ago

According to the VLC issue above, VLC should support it since then (5 years ago).

Oh, didn't notice that. Okay, this kind of justifies me working on this.

I couldn't reproduce this.

Oh, I accidentally tried tagging the wrong file. Yeah, it writes ---- for not just all ReplayGain tags, but all "Comment" tags for me as well. Seems like ---- represents an abstract Comment then?

I also noticed that most of my m4a files (those in my music library, also some other random downloaded ones) says this when using mediainfo:

If I were to guess, the first is going to be "MP4 + Proprietary iTunes gunk", and the second is just "Plain MP4".

OxygenCobalt commented 1 year ago

I just realized something: The entirety of your MP4 file uses MP4 metadata. Looking in kid3, "Title" tags are not ID3v2's TIT2, but rather ?nam, which is the MP4 analogue to title. ---- seems like the equivelent to ID3v2's TXXX (User-defined text), not COMM (Comment), which makes sense for why it is used for ReplayGain tags, as ReplayGain tags are written to ID3v2 tags as TXXX.

This implies a larger issue that I don't think ExoPlayer supports MP4 metadata at all. It only supports metadata in ID32 atoms. This causes much bigger issues than I thought that extend beyond the ReplayGain system and into the new metadata parser set to be stabilized in 3.0.0.

I'm renaming this issue to denote that there is no direct MP4 support at all, and I'm still stuck with the limited, broken android media extractor for now.

OxygenCobalt commented 1 year ago

Actually no: ExoPlayer does support MP4 metadata atoms. It's seemingly just mapping ---- to an ID3v2 "InternalFrame". This makes it possible for me to add support I think.

OxygenCobalt commented 1 year ago

Care to try this apk @bodayw? (It is in the zip file)

Auxio_MP4Gain.zip

I added some extra parsing for InternalFrame instances (i.e ----) and it seems to work.

bodayw commented 1 year ago

Auxio_MP4Gain.zip

Awesome. Can confirm my m4a files are played with replaygain applied.

Although, the debug apk is noticeably less responsive when I navigate through the UI, e.g. entering an album / going back. Is this expected?

OxygenCobalt commented 1 year ago

Awesome. Can confirm my m4a files are played with replaygain applied.

Yay! I'll push the change. Should show up in 3.0.0.

Although, the debug apk is noticeably less responsive when I navigate through the UI, e.g. entering an album / going back. Is this expected?

Yeah, debug builds don't apply optimizations and thus are much slower. Has no effect on release builds.