diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c61131ac..1f121f950 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,13 @@ #### What's Improved - Tags formatted as `artistssort` or `albumartistssort` are now recognized by Auxio +- Non-english digit strings are now sorted better - Reduced visual loading time #### What's Fixed - Disc number is no longer mis-aligned when no subtitle is present - Fixed selection not updating when playlists are changed +- Fixed duplicate albums appearing in certain cases ## 3.1.1 diff --git a/app/src/main/java/org/oxycblt/auxio/music/Music.kt b/app/src/main/java/org/oxycblt/auxio/music/Music.kt index edb5a69e1..395b17d93 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/Music.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/Music.kt @@ -257,7 +257,7 @@ interface Song : Music { /** The duration of the audio file, in milliseconds. */ val durationMs: Long /** The ReplayGain adjustment to apply during playback. */ - val replayGainAdjustment: ReplayGainAdjustment? + val replayGainAdjustment: ReplayGainAdjustment /** The date the audio file was added to the device, as a unix epoch timestamp. */ val dateAdded: Long /** diff --git a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt index 08e312ed5..9ec43ee9b 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceLibrary.kt @@ -215,9 +215,8 @@ class DeviceLibraryFactoryImpl @Inject constructor(private val musicSettings: Mu is SongImpl -> body.raw = PrioritizedRaw(rawArtist, album) is AlbumImpl -> { // Album information from later dates is prioritized, as it is more - // likely to - // contain the "modern" name of the artist if the information really is - // in-consistent. Fall back to the name otherwise. + // likely to contain the "modern" name of the artist if the information + // really is in-consistent. Fall back to the name otherwise. val dateEarlier = album.dates != null && (prioritized.dates == null || album.dates < prioritized.dates) diff --git a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt index aaad318b3..82827b59b 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/device/DeviceMusicImpl.kt @@ -90,14 +90,9 @@ class SongImpl(private val rawSong: RawSong, musicSettings: MusicSettings) : Son override val size = requireNotNull(rawSong.size) { "Invalid raw: No size" } override val durationMs = requireNotNull(rawSong.durationMs) { "Invalid raw: No duration" } override val replayGainAdjustment = - if (rawSong.replayGainTrackAdjustment != null && - rawSong.replayGainAlbumAdjustment != null) { - ReplayGainAdjustment( - track = unlikelyToBeNull(rawSong.replayGainTrackAdjustment), - album = unlikelyToBeNull(rawSong.replayGainAlbumAdjustment)) - } else { - null - } + ReplayGainAdjustment( + track = rawSong.replayGainTrackAdjustment, album = rawSong.replayGainAlbumAdjustment) + override val dateAdded = requireNotNull(rawSong.dateAdded) { "Invalid raw: No date added" } private var _album: AlbumImpl? = null override val album: Album diff --git a/app/src/main/java/org/oxycblt/auxio/music/device/RawMusic.kt b/app/src/main/java/org/oxycblt/auxio/music/device/RawMusic.kt index 5358f0244..5828ac75a 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/device/RawMusic.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/device/RawMusic.kt @@ -128,7 +128,6 @@ data class RawAlbum( // - If we do not have a MusicBrainz ID, compare by the lowercase album name and lowercase // artist name. This allows for case-insensitive artist/album grouping, which can be common // for albums/artists that have different naming (ex. "RAMMSTEIN" vs. "Rammstein"). - private val artistKeys = inner.rawArtists.map { it.key } // Cache the hash-code for HashMap efficiency. diff --git a/app/src/main/java/org/oxycblt/auxio/music/metadata/TextTags.kt b/app/src/main/java/org/oxycblt/auxio/music/metadata/TextTags.kt index cecd572ba..a3d916b69 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/metadata/TextTags.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/metadata/TextTags.kt @@ -28,6 +28,8 @@ import androidx.media3.extractor.metadata.vorbis.VorbisComment * * @param metadata The [Metadata] to wrap. * @author Alexander Capehart (OxygenCobalt) + * + * TODO: Merge with TagWorker */ class TextTags(metadata: Metadata) { private val _id3v2 = mutableMapOf>() diff --git a/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromArtistDialog.kt b/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromArtistDialog.kt index c8fc134e7..e42e6ff61 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromArtistDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromArtistDialog.kt @@ -81,7 +81,7 @@ class PlayFromArtistDialog : override fun onDestroyBinding(binding: DialogMusicChoicesBinding) { super.onDestroyBinding(binding) - choiceAdapter + binding.choiceRecycler.adapter = null } override fun onClick(item: Artist, viewHolder: RecyclerView.ViewHolder) { diff --git a/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromGenreDialog.kt b/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromGenreDialog.kt index 1f2693a10..6811e3510 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromGenreDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromGenreDialog.kt @@ -81,7 +81,7 @@ class PlayFromGenreDialog : override fun onDestroyBinding(binding: DialogMusicChoicesBinding) { super.onDestroyBinding(binding) - choiceAdapter + binding.choiceRecycler.adapter = null } override fun onClick(item: Genre, viewHolder: RecyclerView.ViewHolder) { diff --git a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGain.kt b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGain.kt index 8a85b73e2..1495fd6fb 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGain.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGain.kt @@ -53,10 +53,11 @@ enum class ReplayGainMode { /** * Represents a ReplayGain adjustment to apply during song playback. * - * @param track The track-specific adjustment that should be applied. - * @param album A more general album-specific adjustment that should be applied. + * @param track The track-specific adjustment that should be applied. Null if not available. + * @param album A more general album-specific adjustment that should be applied. Null if not + * available. */ -data class ReplayGainAdjustment(val track: Float, val album: Float) +data class ReplayGainAdjustment(val track: Float?, val album: Float?) /** * The current ReplayGain pre-amp configuration. diff --git a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt index d74e45543..5c039ab8c 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/ReplayGainAudioProcessor.kt @@ -99,58 +99,58 @@ constructor( * @param song The [Format] of the currently playing track, or null if nothing is playing. */ private fun applyReplayGain(song: Song?) { + if (song == null) { + logD("Nothing playing, disabling adjustment") + volume = 1f + return + } + logD("Applying ReplayGain adjustment for $song") - val gain = song?.replayGainAdjustment + + val gain = song.replayGainAdjustment val preAmp = playbackSettings.replayGainPreAmp - val adjust = - if (gain != null) { - logD("Found ReplayGain adjustment $gain") - // ReplayGain is configurable, so determine what to do based off of the mode. - val useAlbumGain = - when (playbackSettings.replayGainMode) { - // User wants track gain to be preferred. Default to album gain only if - // there is no track gain. - ReplayGainMode.TRACK -> { - logD("Using track strategy") - gain.track == 0f - } - // User wants album gain to be preferred. Default to track gain only if - // here is no album gain. - ReplayGainMode.ALBUM -> { - logD("Using album strategy") - gain.album != 0f - } - // User wants album gain to be used when in an album, track gain otherwise. - ReplayGainMode.DYNAMIC -> { - logD("Using dynamic strategy") - playbackManager.parent is Album && - playbackManager.queue.currentSong?.album == playbackManager.parent - } + // ReplayGain is configurable, so determine what to do based off of the mode. + val resolvedAdjustment = + when (playbackSettings.replayGainMode) { + // User wants track gain to be preferred. Default to album gain only if + // there is no track gain. + ReplayGainMode.TRACK -> { + logD("Using track strategy") + gain.track ?: gain.album + } + // User wants album gain to be preferred. Default to track gain only if + // here is no album gain. + ReplayGainMode.ALBUM -> { + logD("Using album strategy") + gain.album ?: gain.track + } + // User wants album gain to be used when in an album, track gain otherwise. + ReplayGainMode.DYNAMIC -> { + logD("Using dynamic strategy") + gain.album?.takeIf { + playbackManager.parent is Album && + playbackManager.queue.currentSong?.album == playbackManager.parent } + ?: gain.track + } + } - val resolvedGain = - if (useAlbumGain) { - logD("Using album gain") - gain.album - } else { - logD("Using track gain") - gain.track - } - - // Apply the adjustment specified when there is ReplayGain tags. - resolvedGain + preAmp.with + val amplifiedAdjustment = + if (resolvedAdjustment != null) { + // Successfully resolved an adjustment, apply the corresponding pre-amp + logD("Applying with pre-amp") + resolvedAdjustment + preAmp.with } else { - // No ReplayGain tags existed, or no tags were parsable, or there was no metadata - // in the first place. Return the gain to use when there is no ReplayGain value. - logD("No ReplayGain tags present") + // No adjustment found, use the corresponding user-defined pre-amp + logD("Applying without pre-amp") preAmp.without } - logD("Applying ReplayGain adjustment ${adjust}db") + logD("Applying ReplayGain adjustment ${amplifiedAdjustment}db") // Final adjustment along the volume curve. - volume = 10f.pow(adjust / 20f) + volume = 10f.pow(amplifiedAdjustment / 20f) } // --- AUDIO PROCESSOR IMPLEMENTATION ---