diff --git a/app/src/main/kotlin/com/subtracks/playback/Media3PlayerHandle.kt b/app/src/main/kotlin/com/subtracks/playback/Media3PlayerHandle.kt index abc7b0b5..770c51db 100644 --- a/app/src/main/kotlin/com/subtracks/playback/Media3PlayerHandle.kt +++ b/app/src/main/kotlin/com/subtracks/playback/Media3PlayerHandle.kt @@ -245,8 +245,6 @@ private const val EXTRA_REPLAY_GAIN_ALBUM_GAIN = "replayGainAlbumGain" private const val EXTRA_REPLAY_GAIN_TRACK_PEAK = "replayGainTrackPeak" private const val EXTRA_REPLAY_GAIN_ALBUM_PEAK = "replayGainAlbumPeak" -// The gain rides on the MediaItem so PlaybackService can apply it the moment the item becomes -// current, rather than after an asynchronous round trip to the library. internal fun MediaItem?.replayGain(): ReplayGain { val extras = this?.mediaMetadata?.extras ?: return ReplayGain() return ReplayGain( diff --git a/app/src/main/kotlin/com/subtracks/playback/ReplayGainController.kt b/app/src/main/kotlin/com/subtracks/playback/ReplayGainController.kt index cd14f58c..602f53e7 100644 --- a/app/src/main/kotlin/com/subtracks/playback/ReplayGainController.kt +++ b/app/src/main/kotlin/com/subtracks/playback/ReplayGainController.kt @@ -9,14 +9,12 @@ internal class ReplayGainController( private var track = ReplayGain() private var settings = ReplayGainSettings(ReplayGainMode.Track, 0f) - // Called from the playback thread, by ReplayGainProcessor.onFlush. @Synchronized fun applyItem(item: MediaItem) { track = item.replayGain() applyGain() } - // Called from the app thread, when the preferences change. @Synchronized fun setSettings(value: ReplayGainSettings) { settings = value diff --git a/app/src/main/kotlin/com/subtracks/playback/ReplayGainProcessor.kt b/app/src/main/kotlin/com/subtracks/playback/ReplayGainProcessor.kt index 519a1930..414643c9 100644 --- a/app/src/main/kotlin/com/subtracks/playback/ReplayGainProcessor.kt +++ b/app/src/main/kotlin/com/subtracks/playback/ReplayGainProcessor.kt @@ -24,14 +24,13 @@ internal class ReplayGainProcessor( override fun onConfigure(inputAudioFormat: AudioFormat): AudioFormat = inputAudioFormat - // DefaultAudioSink configures and flushes the processors at every media item transition, even - // when the format is unchanged, and hands over the timeline and the period being flushed. That - // is early enough to set the new item's gain before any of its buffers are processed, unlike - // Player.Listener.onMediaItemTransition, which the app thread receives afterwards. - // See androidx/media#418. + // DefaultAudioSink flushes the processors on every configuration, which happens at each media + // item transition even when the format is unchanged, and hands over the timeline and the period + // being flushed (androidx/media#418). That is early enough to set the new item's gain before any + // of its buffers are processed, unlike Player.Listener.onMediaItemTransition, which the app + // thread receives afterwards. A flush with no period comes from a DefaultAudioSink reset rather + // than an item boundary, hence the ignore. override fun onFlush(streamMetadata: StreamMetadata) { - // A flush with no period comes from a sink reset rather than an item boundary, so leave the - // gain alone rather than resetting it to unity. streamMetadata.currentItem()?.let(onItem) } @@ -50,8 +49,6 @@ internal class ReplayGainProcessor( } else -> { - // An empty input would be the pipeline's own shared buffer, which cannot be put into - // itself. if (inputBuffer.hasRemaining()) output.put(inputBuffer) } }