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:
parent
672c256b1e
commit
4ee20bc112
10 changed files with 57 additions and 59 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>>()
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 ---
|
||||
|
|
Loading…
Reference in a new issue