playback: drop comments that explain rather than name

The in-repo comment rule now allows a comment only when it names an
external system, version or issue, so the ones carrying rationale move
to this message.

- why the gain rides on the media item: PlaybackService can then apply it
  the moment the item becomes current instead of after a library round
  trip
- that ReplayGainController is written from the playback thread by
  onFlush and from the app thread by the preference collector
- that an empty passthrough input is the pipeline's own shared buffer,
  which cannot be put into itself
This commit is contained in:
austinried
2026-10-16 13:07:08 +00:00
parent 62409898c1
commit aee631c08d
3 changed files with 6 additions and 13 deletions
@@ -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_TRACK_PEAK = "replayGainTrackPeak"
private const val EXTRA_REPLAY_GAIN_ALBUM_PEAK = "replayGainAlbumPeak" 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 { internal fun MediaItem?.replayGain(): ReplayGain {
val extras = this?.mediaMetadata?.extras ?: return ReplayGain() val extras = this?.mediaMetadata?.extras ?: return ReplayGain()
return ReplayGain( return ReplayGain(
@@ -9,14 +9,12 @@ internal class ReplayGainController(
private var track = ReplayGain() private var track = ReplayGain()
private var settings = ReplayGainSettings(ReplayGainMode.Track, 0f) private var settings = ReplayGainSettings(ReplayGainMode.Track, 0f)
// Called from the playback thread, by ReplayGainProcessor.onFlush.
@Synchronized @Synchronized
fun applyItem(item: MediaItem) { fun applyItem(item: MediaItem) {
track = item.replayGain() track = item.replayGain()
applyGain() applyGain()
} }
// Called from the app thread, when the preferences change.
@Synchronized @Synchronized
fun setSettings(value: ReplayGainSettings) { fun setSettings(value: ReplayGainSettings) {
settings = value settings = value
@@ -24,14 +24,13 @@ internal class ReplayGainProcessor(
override fun onConfigure(inputAudioFormat: AudioFormat): AudioFormat = inputAudioFormat override fun onConfigure(inputAudioFormat: AudioFormat): AudioFormat = inputAudioFormat
// DefaultAudioSink configures and flushes the processors at every media item transition, even // DefaultAudioSink flushes the processors on every configuration, which happens at each media
// when the format is unchanged, and hands over the timeline and the period being flushed. That // item transition even when the format is unchanged, and hands over the timeline and the period
// is early enough to set the new item's gain before any of its buffers are processed, unlike // being flushed (androidx/media#418). That is early enough to set the new item's gain before any
// Player.Listener.onMediaItemTransition, which the app thread receives afterwards. // of its buffers are processed, unlike Player.Listener.onMediaItemTransition, which the app
// See androidx/media#418. // 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) { 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) streamMetadata.currentItem()?.let(onItem)
} }
@@ -50,8 +49,6 @@ internal class ReplayGainProcessor(
} }
else -> { else -> {
// An empty input would be the pipeline's own shared buffer, which cannot be put into
// itself.
if (inputBuffer.hasRemaining()) output.put(inputBuffer) if (inputBuffer.hasRemaining()) output.put(inputBuffer)
} }
} }