fix(ios): push the frames AVAudioConverter actually produced in the recorder callback#1097
Merged
mdydek merged 2 commits intoJun 11, 2026
Conversation
…ecorder callback convertToBuffer:error:withInputFromBlock: sets frameLength to the number of frames it wrote, but the recorder callback overwrote it with a computed estimate and pushed ceil(numFrames * ratio) frames into the circular buffer. When the SRC's filter phase produced fewer frames than the estimate, the extra pushed samples were stale data from a previous render block - an audible click at nearly every block boundary whenever the requested callback rate differs from the hardware input rate. Fixes software-mansion#1096
Collaborator
|
thank you for pointing out the issue |
mdydek
approved these changes
Jun 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Closes #1096
None.
Introduced changes
IOSRecorderCallback::taskOffloaderFunctionnow pushesconverterOutputBuffer_.frameLength— the frame countAVAudioConverteractually produced — into the circular buffer, instead of aceil(numFrames * ratio)estimate.converterOutputBuffer_.frameLength = ...assignment that was overwriting the converter's real output count with that estimate.Why
The SRC's filter phase makes per-call output fluctuate around
numFrames * ratio(a 512-frame block at 48 kHz → 16 kHz yields 170 or 171 frames depending on accumulated phase). Whenever the converter produced fewer frames than theceil()estimate, the extra pushed samples were stale data from a previous render block — a single-sample impulse (audible click) at nearly every block boundary, in every recording where the requestedonAudioReadysample rate differs from the hardware input rate. Full analysis with PCM evidence in #1096.Android is unaffected:
AndroidRecorderCallbackalready uses the produced count reported byma_data_converter_process_pcm_frames.Checklist