playback: fix regression regarding partial rgadj

Fix a regression where partial ReplayGain adjustments missing an album
or track component would not be indexed.

This was an oversight made when moving adjustments to the cache, as the
nullability model of ReplayGain adjustments changed.
This commit is contained in:
Alexander Capehart 2023-06-09 10:07:27 -06:00
parent 672c256b1e
commit 4ee20bc112
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
10 changed files with 57 additions and 59 deletions

View file

@ -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

View file

@ -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
/**

View file

@ -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)

View file

@ -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
}
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

View file

@ -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.

View file

@ -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<String, List<String>>()

View file

@ -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) {

View file

@ -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) {

View file

@ -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.

View file

@ -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 =
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 == 0f
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 != 0f
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
val amplifiedAdjustment =
if (resolvedAdjustment != null) {
// Successfully resolved an adjustment, apply the corresponding pre-amp
logD("Applying with pre-amp")
resolvedAdjustment + preAmp.with
} else {
logD("Using track gain")
gain.track
}
// Apply the adjustment specified when there is ReplayGain tags.
resolvedGain + 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 ---