WAV: Fix one frame overflow at the end #96768
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This fixes AudioStreamWAV decoding one additional frame after the last
Problem
Let's assume a PCM data with exactly 3000 frames as an example. This means the range should be 0-2999.
When you
mix
in AudioStreamPlaybackWAV, it considers you have to decodep_frames
frames intop_buffer
. There is a calculation right before the decoder is called (limit
,aux
andtarget
) that is supposed to prevent the decoder (do_resample()
) to get an index beyond the PCM data range and repeat thewhile
loop in respect to the audio loop mode.Assuming the audio has no loop points and goes from the very first frame to the last, here's the problem: when playing forward, the last frame (
end_limit
in the mix function) is assumed to be the length of the audio data (3000), not the last index (2999). Because of that,target
ends up being calculated considering that additional frame, out of the range, and ends up makingdo_resample()
get one more frame than it should.The reason no errors happen when playing PCM audio data is because of the
DATA_PAD
(which reads a0
value frame at that position, leading to a barely audible pop), and doesn't crash with QOA data because the resampling workaround doesn't allow the offset to be above the last frame index.Solution
Do what should be done: subtract 1 from the length whenever you point to the last frame.
Even if the
while
loop forces the audio to stop when theoffset
is beyond the last frame, it doesn't prevent that one extra end frame request from being passed to the decoder function.If merged, any audio imported with any enabled Loop Mode and Loop End set to -1 will need to be reimported to remove the extra frame from the count. Not sure if this count as compatibility breaking, but existing projects should not be affected.
Considerations
I found this by experimenting with #83483 (makes AudioStreamWAV use PlaybackResampled, removing the need for workarounds and data pad) with a QOA audio with 4160 frames (the number becomes the decode buffer size when instantiating playback) and it would crash for not being able to get index 4160.