Shuttle2
Shuttle2 copied to clipboard
Fix ReplayGain Issue
Description:
Summary
Fixes #121 - ReplayGain volume adjustments are now applied before playback starts instead of after, eliminating the audible volume shift that occurred ~500ms into each track.
Problem
The original issue reported that "ReplayGain volume adjustments are only applied after the track begins playing, which leads to a noticeable change in volume a fraction of a second into the track."
Root Cause:
-
setReplayGain()was called in the success callback AFTERplayer.prepare()completed - This meant the audio processing pipeline started with incorrect gain values
- The ~500ms delay corresponded to the time it took to load, prepare, and start playback
Solution
The fix uses a proactive update model with ReplayGain values embedded in MediaItems:
1. MediaItem Tagging Architecture
fun getMediaItem(mediaInfo: MediaInfo, trackGain: Double?, albumGain: Double?): MediaItem =
MediaItem.Builder()
.setTag(ReplayGainTag(trackGain, albumGain))
.build()
2. Manual Track Changes
// In load() - BEFORE prepare()
replayGainAudioProcessor.trackGain = current.replayGainTrack
replayGainAudioProcessor.albumGain = current.replayGainAlbum
player.prepare() // Audio processing starts after gain is set
3. Automatic Track Transitions
// In onMediaItemTransition
mediaItem?.localConfiguration?.tag?.let { tag ->
if (tag is ReplayGainTag) {
replayGainAudioProcessor.trackGain = tag.trackGain
replayGainAudioProcessor.albumGain = tag.albumGain
}
}
Changes
PlaybackManager.kt: Removed reactive setReplayGain() calls
ExoPlayerPlayback.kt: Added MediaItem tagging, proactive ReplayGain updates
ReplayGainAudioProcessor.kt: Enhanced thread safety with @Volatile and documentation
Known Limitations
During gapless playback, there's a potential ~10-50ms window where a few audio buffers from the new track may be processed with the previous track's gain due to ExoPlayer's async callback model vs continuous audio rendering. This is ~90-95% smaller than the original 500ms issue and is likely imperceptible.