Repository navigation
AudioProcessor: don't abort() on a non-frame-aligned Consume() - #161
Conversation
Added a vector to hold leftover audio data between Consume() calls.
Added handling for leftover samples in Consume method.
Walkthrough
ChangesPartial Frame Buffering in AudioProcessor
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Thank you! |
|
Great! I've run into this error many times. @lalinsky would it be possible to issue a new release with this fix included? |
Fixes #90.
AudioProcessor::Consume()asserts that the input length is a whole multipleof the channel count:
When a caller passes a buffer that splits the audio mid-frame, this assertion aborts the entire host process instead of failing gracefully. It's easy to hit when feeding PCM in fixed-size byte chunks (the chunk boundary rarely lands
on a frame boundary), and especially likely with multi-channel sources where a frame spans more bytes. A library should never abort() the process that embeds it on account of input framing.
Reported downstream where an AcoustID scan of a 5.1 file took the whole application down with:
Assertion
length % m_num_channels == 0failed.Consume()now tolerates input that isn't aligned to a whole number of frames. Any trailing partial frame is buffered in a new m_leftover member and prepended to the next call, so the audio is processed losslessly and channelinterleaving stays aligned across calls. The existing whole-frame processing loop is unchanged, it's simply moved into a private
ConsumeAligned()helper thatConsume()calls once the input has been split into a whole-frame portionand a carried remainder.
Consume()splits input into complete frames + a carried remainderConsumeAligned()the originalConsume()body (still asserts alignment, which is now always satisfied)m_leftoverholds a sub-frame remainder between calls; cleared inReset()Behaviour for callers that already pass whole frames is identical as the leftover buffer stays empty, remainder is always 0, and the exact same processing path runs.