playback: reject non-finite gains before the pow, and filter peaks first

Review follow-ups for the apply slice.

- A negative-infinite gain produced 0 dB, not unity: 10^(inf/20) is 0.0,
  which is finite, so the result guard never fired and the track played
  silent — the opposite of what the guard is for. A large-enough finite
  negative gain underflows the same way, and an infinite gain paired with
  a peak survived as the cap. The gain is now rejected before the pow and
  an underflowed result falls back to unity.
- A peak carrying no data shadowed a usable peak in the other slot, so
  trackPeak=0 with albumPeak=0.5 skipped the cap entirely — the gonic
  shape on the default mode. Both peaks are filtered before one is chosen.
- Drop the claim that a period-less flush comes from a sink reset; it does
  not, and the guard stands on its own.
- Trim two comments back to naming the Media3 types.
- Revert the observeStar rename, which was for a path that no longer
  applies the gain.
This commit is contained in:
austinried
2026-10-16 13:07:08 +00:00
parent aee631c08d
commit 8f34c958fb
6 changed files with 44 additions and 20 deletions
@@ -21,8 +21,7 @@ class ReplayGainRenderersFactoryTest {
val sink = ReplayGainRenderersFactory(context, processor).buildAudioSink(context, false, false)
// DefaultAudioSink exposes no accessor for the chain it was built with, so this is the only
// way to assert the processor is actually installed rather than merely constructed.
// DefaultAudioSink exposes no accessor for the chain it was built with.
val chain =
DefaultAudioSink::class.java
.getDeclaredField("audioProcessorChain")
@@ -160,7 +160,33 @@ class ReplayGainTest {
val settings = ReplayGainSettings(ReplayGainMode.Track, 0f)
assertEquals(1f, replayGainLinearGain(ReplayGain(trackGain = Float.POSITIVE_INFINITY), settings), TOLERANCE)
assertEquals(1f, replayGainLinearGain(ReplayGain(trackGain = Float.NEGATIVE_INFINITY), settings), TOLERANCE)
assertEquals(1f, replayGainLinearGain(ReplayGain(trackGain = Float.NaN), settings), TOLERANCE)
assertEquals(1f, replayGainLinearGain(ReplayGain(trackGain = -Float.MAX_VALUE), settings), TOLERANCE)
}
@Test
fun playsAtUnityWhenANonFiniteGainWouldOtherwiseBeCapped() {
assertEquals(
1f,
replayGainLinearGain(
ReplayGain(trackGain = Float.POSITIVE_INFINITY, trackPeak = 0.001f),
ReplayGainSettings(ReplayGainMode.Track, 0f),
),
TOLERANCE,
)
}
@Test
fun thePeakFallsBackWhenThePreferredOneCarriesNoData() {
assertEquals(
2f,
replayGainLinearGain(
ReplayGain(trackGain = 12f, trackPeak = 0f, albumPeak = 0.5f),
ReplayGainSettings(ReplayGainMode.Track, 0f),
),
TOLERANCE,
)
}
private companion object {