diff --git a/CHANGELOG.md b/CHANGELOG.md index b7f65701a..186558c62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 3.4.1 + +#### What's Fixed +- R128 adjustments are now adjusted to -18 LUFS to be consistent with MP3 +- Fixed double application of opus base gain +- Fixed playback state not restoring + ## 3.4.0 #### What's New diff --git a/README.md b/README.md index 084ea5a5a..85006d016 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@

Auxio

A simple, rational music player for android.

- - Latest Version + + Latest Version Releases diff --git a/app/build.gradle b/app/build.gradle index af0bf21bb..d17211886 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,8 +21,8 @@ android { defaultConfig { applicationId namespace - versionName "3.4.0" - versionCode 41 + versionName "3.4.1" + versionCode 42 minSdk 24 targetSdk 34 diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt index 1d5c5bdde..41a1055a7 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -222,19 +222,17 @@ class HomeFragment : collect(detailModel.toShow.flow, ::handleShow) } - override fun onStart() { - super.onStart() + override fun onResume() { + super.onResume() // Stock bottom sheet overlay won't work with our nested UI setup, have to replicate // it ourselves. requireBinding().root.rootView.apply { - post { - findViewById(R.id.main_scrim).setOnTouchListener { _, event -> - handleSpeedDialBoundaryTouch(event) - } - findViewById(R.id.sheet_scrim).setOnTouchListener { _, event -> - handleSpeedDialBoundaryTouch(event) - } + findViewById(R.id.main_scrim).setOnTouchListener { _, event -> + handleSpeedDialBoundaryTouch(event) + } + findViewById(R.id.sheet_scrim).setOnTouchListener { _, event -> + handleSpeedDialBoundaryTouch(event) } } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/cache/CacheDatabase.kt b/app/src/main/java/org/oxycblt/auxio/music/cache/CacheDatabase.kt index f64345de2..63e4ccf98 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/cache/CacheDatabase.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/cache/CacheDatabase.kt @@ -32,7 +32,7 @@ import org.oxycblt.auxio.music.info.Date import org.oxycblt.auxio.music.metadata.correctWhitespace import org.oxycblt.auxio.music.metadata.splitEscaped -@Database(entities = [CachedSong::class], version = 38, exportSchema = false) +@Database(entities = [CachedSong::class], version = 42, exportSchema = false) abstract class CacheDatabase : RoomDatabase() { abstract fun cachedSongsDao(): CachedSongsDao } diff --git a/app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt b/app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt index 2167c195d..78669caee 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt @@ -20,7 +20,6 @@ package org.oxycblt.auxio.music.metadata import androidx.core.text.isDigitsOnly import androidx.media3.common.MediaItem -import androidx.media3.common.MimeTypes import androidx.media3.exoplayer.MetadataRetriever import androidx.media3.exoplayer.source.MediaSource import androidx.media3.exoplayer.source.TrackGroupArray @@ -99,22 +98,26 @@ private class TagWorkerImpl( populateWithId3v2(textTags.id3v2) populateWithVorbis(textTags.vorbis) - // If this metadata is of a vorbis file, we actually need to extract it's base gain - // and divide it by 256 to get the gain in decibels. - if (format.sampleMimeType == MimeTypes.AUDIO_OPUS && - format.initializationData.isNotEmpty() && - format.initializationData[0].size >= 18) { - val header = format.initializationData[0] - val gain = (((header[16]).toInt() and 0xFF) or ((header[17].toInt() shl 8))) / 256f - logD("Obtained opus base gain: $gain dB") - if (gain != 0f) { - logD("Applying opus base gain") - rawSong.replayGainTrackAdjustment = - (rawSong.replayGainTrackAdjustment ?: 0f) + gain - rawSong.replayGainAlbumAdjustment = - (rawSong.replayGainAlbumAdjustment ?: 0f) + gain - } - } + // OPUS base gain interpretation code: This is likely not needed, as the media player + // should be using the base gain already. Uncomment if that's not the case. + // if (format.sampleMimeType == MimeTypes.AUDIO_OPUS + // && format.initializationData.isNotEmpty() + // && format.initializationData[0].size >= 18) { + // val header = format.initializationData[0] + // val gain = + // (((header[16]).toInt() and 0xFF) or ((header[17].toInt() shl 8))) + // .R128ToLUFS18() + // logD("Obtained opus base gain: $gain dB") + // if (gain != 0f) { + // logD("Applying opus base gain") + // rawSong.replayGainTrackAdjustment = + // (rawSong.replayGainTrackAdjustment ?: 0f) + gain + // rawSong.replayGainAlbumAdjustment = + // (rawSong.replayGainAlbumAdjustment ?: 0f) + gain + // } else { + // logD("Ignoring opus base gain") + // } + // } } else { logD("No metadata could be extracted for ${rawSong.name}") } @@ -317,14 +320,24 @@ private class TagWorkerImpl( // the base adjustment intrinsic to the format to create the normalized adjustment. This is // normally the only tag used for opus files, but some software still writes replay gain // tags anyway. - (comments["r128_track_gain"]?.parseReplayGainAdjustment()?.div(256) + (comments["r128_track_gain"]?.parseR128Adjustment() ?: comments["replaygain_track_gain"]?.parseReplayGainAdjustment()) ?.let { rawSong.replayGainTrackAdjustment = it } - (comments["r128_album_gain"]?.parseReplayGainAdjustment()?.div(256) + (comments["r128_album_gain"]?.parseR128Adjustment() ?: comments["replaygain_album_gain"]?.parseReplayGainAdjustment()) ?.let { rawSong.replayGainAlbumAdjustment = it } } + private fun List.parseR128Adjustment() = + first() + .replace(REPLAYGAIN_ADJUSTMENT_FILTER_REGEX, "") + .toFloatOrNull() + ?.nonZeroOrNull() + ?.run { + // Convert to fixed-point and adjust to LUFS 18 to match the ReplayGain scale + this / 256f + 5 + } + /** * Parse a ReplayGain adjustment into a float value. * diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt index 0ebaf669f..7498c8e0b 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt @@ -418,12 +418,12 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager { } this.stateHolder = stateHolder - if (isInitialized && stateMirror.index > -1) { + if (isInitialized && currentSong != null) { stateHolder.applySavedState(stateMirror.parent, stateMirror.rawQueue, null) stateHolder.seekTo(stateMirror.progression.calculateElapsedPositionMs()) stateHolder.playing(false) - pendingDeferredPlayback?.let(stateHolder::handleDeferred) } + pendingDeferredPlayback?.let(stateHolder::handleDeferred) } @Synchronized diff --git a/fastlane/metadata/android/en-US/changelogs/42.txt b/fastlane/metadata/android/en-US/changelogs/42.txt new file mode 100644 index 000000000..dcea6e4e6 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/42.txt @@ -0,0 +1,3 @@ +Auxio 3.4.0 adds gapless playback and new widget designs, alongside a variety of fixes. +This release fixes critical issues with ReplayGain and playback persistence. +For more information, see https://github.com/OxygenCobalt/Auxio/releases/tag/v3.4.1 \ No newline at end of file