mux: fix the volume ramp dividing integers and going NaN - #296
Conversation
rateDenom was computed as float32(n / channelCount), an integer division. When a playing buffer had fewer samples left than the number of channels (e.g. one stereo sample with SetBufferSize), the denominator became 0 and the ramp rate 0/0 = NaN, so every sample of the ramp was dropped as non-finite and the player went silent until the next SetVolume. Divide floats instead.
…channels The ramp denominator must be computed with float division, or the ramp rate becomes NaN when a player holds fewer samples than channels and the whole ramp is dropped, silencing the player. Add a deterministic unit test covering stereo and quadrophonic players with a partial frame left in the buffer, which fails with the integer division.
|
Thanks for the review! I added a test as requested: |
|
Thanks for the review! I updated the test so the table entries use explicit member names, written across multiple lines, instead of positional literals. The behavior is unchanged: the test still fails with the old |
What issue is this addressing?
No issue filed yet. Found during an audit of the mux package.
What type of issue is this addressing?
bug
What this PR does | solves
(*playerImpl).readBufferAndAddcomputed the volume ramp denominator as:nis the number of samples to mix andchannelCountthe number of channels. When a playing buffer holds fewer samples than channels (n < channelCount, e.g. a stereo player with a single sample left in its buffer — realistic with a smallSetBufferSize),n / channelCountis0, sorateDenomis0.During a volume transition (
volume != prevVolume), the ramp rate is then:volume*Inf + prevVolume*(-Inf)is NaN, so every sample of the ramp becomes NaN. The mixing loop drops non-finite values to protect other players, so the entire ramp is dropped and the player outputs silence until the nextSetVolume.Reproduction
The following test passes on main (demonstrating the bug) and fails without this change:
On main, both samples come out as
0(dropped). With this PR, they are±0.49998…as expected.The fix
Divide floats:
The
float32(i/channelCount)numerator is left as is: it is a per-frame index and the integer division there is intentional.