Skip to content

fix(ios): vpio driver loop - #1317

Open
closetcaiman wants to merge 10 commits into
fix/ios-recording-interruptedfrom
fix/vpio-driver-loop
Open

closetcaiman wants to merge 10 commits into
fix/ios-recording-interruptedfrom
fix/vpio-driver-loop

Conversation

@closetcaiman

@closetcaiman closetcaiman commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Closes #

⚠️ Breaking changes ⚠️

  • N/A

Introduced changes

Bugfixes:

  • fixed the iOS engine restart loop with iosVoiceProcessing: true. With voice processing (VPIO) on, starting a recorder made AudioEngine rebuild itself indefinitely.
    • the loop was initiated by spaghetti handling of RouteConfigurationChange posted by engine when initiating VPIO (AudioEngine.prepare)
    • the handler rebuilt the engine which again posted the notification and initialized VPIO -> the loop
  • fixed VPIO rendering errors:
    • with recorder-only graph, the VPIO unit (which is full-duplex) tried pulling from the graph which was never explicitly connected, so crashed with render err: -1
    • with AudioContext the mainMixer was created, but format was not adjusted to 48kHz required by the VPIO which violated the assumption of setVoiceProcessingEnabled and the engine stopped shortly after starting
      • from AVAudioIONode.setVoiceProcessingEnabled: "The output format of the input node and the input format of the output node have to be the same and they can only be changed when the engine is in a stopped state."

Changes:

  • Route changes no longer restart the engine. Format changes restart the engine via AVAudioEngineConfigurationChangeNotification. A stopped engine with a tracked graph is marked for rebuild on its next start.
  • VPIO output is connceted explicitly - connectVoiceProcessingIOOutput
  • A failed start settles the state (settleStateAfterFailedStart: Paused / Idle, Interrupted kept for the interruption-end and foreground-retry paths) instead of leaving Running on a stopped engine.
  • Recorder callbacks run outside the engine lock. Downgraded std::recursive_mutex to std::mutex.
    • the callbacks are returned as InputNotficationBlock - a workaround until the proper refactor, which then are invoked by the engine. Moving callbacks out of locks makes a possible ABBA deadlock impossible, so the previously introduced std::recursive_mutex is not needed and was a smelly workaround hiding the bigger bug.
  • the conflicting options are settled silently - a proper refactor with explicit API throws/logging to come in a separate PR

Known issues:

Checklist

  • Linked relevant issue
  • Updated relevant documentation
  • Added/Conducted relevant tests
  • Performed self-review of the code
  • Updated Web Audio API coverage
  • Added support for web
  • Updated old arch android spec file

@closetcaiman closetcaiman added fix Code changes specifically addressing and resolving a bug ios Native iOS implementation, CoreAudio/AVFoundation bindings, or iOS-specific issues labels Sep 24, 2026
@github-actions github-actions Bot added the conflicts This PR has conflicts with the base branch. label Sep 24, 2026
@github-actions github-actions Bot removed the conflicts This PR has conflicts with the base branch. label Sep 24, 2026
@github-actions

github-actions Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

WPT non-regression comparison

PASS — no regressions · 0 improved section(s) · overall 3427 → 3427 (0)

Unchanged sections (28)
Spec section Base pass Head pass Delta
Processing model 1 1 0
Other 56 56 0
AnalyserNode 138 138 0
AudioBuffer 140 140 0
AudioBufferSourceNode 220 220 0
AudioContext 58 58 0
AudioNode 261 261 0
AudioParam 680 680 0
BiquadFilterNode 275 275 0
ChannelMergerNode 30 30 0
ChannelSplitterNode 7 7 0
ConstantSourceNode 64 64 0
ConvolverNode 178 178 0
DelayNode 127 127 0
DestinationNode 0 0 0
DynamicsCompressorNode 4 4 0
GainNode 15 15 0
IIRFilterNode 87 87 0
MediaElementAudioSourceNode 0 0 0
MediaStreamAudioDestinationNode 1 1 0
MediaStreamAudioSourceNode 0 0 0
OfflineAudioContext 35 35 0
OscillatorNode 104 104 0
PannerNode 727 727 0
PeriodicWave 33 33 0
ScriptProcessorNode 0 0 0
StereoPannerNode 104 104 0
WaveShaperNode 82 82 0

Baseline: dba0ad8bb05caf741bb90c899857ee287b9378fb · Candidate: 050d477a91f0bc9a2c5305622ed92e58d41510fb

Workflow run · this comment is updated on every push.

@closetcaiman
closetcaiman changed the base branch from main to fix/ios-recording-interrupted September 24, 2026 17:02
@closetcaiman
closetcaiman added this pull request to stack #1318 September 24, 2026 17:02
@github-actions github-actions Bot added conflicts This PR has conflicts with the base branch. and removed conflicts This PR has conflicts with the base branch. labels Oct 12, 2026
@mdydek mdydek mentioned this pull request Oct 14, 2026
7 tasks
@SomePersonFromMars
SomePersonFromMars removed this pull request from stack #1318 October 14, 2026 16:31
@SomePersonFromMars
SomePersonFromMars changed the base branch from fix/ios-recording-interrupted to refactor/ios-interruption-policy October 14, 2026 16:32
@github-actions github-actions Bot added the conflicts This PR has conflicts with the base branch. label Oct 14, 2026
@SomePersonFromMars
SomePersonFromMars added this pull request to stack #1347 October 14, 2026 16:34
@closetcaiman
closetcaiman marked this pull request as ready for review October 16, 2026 21:54
@SomePersonFromMars
SomePersonFromMars removed this pull request from stack #1347 October 19, 2026 13:47
@SomePersonFromMars
SomePersonFromMars changed the base branch from refactor/ios-interruption-policy to fix/ios-recording-interrupted October 19, 2026 13:47
@SomePersonFromMars
SomePersonFromMars added this pull request to stack #1353 October 19, 2026 13:47
Comment thread packages/react-native-audio-api/ios/audioapi/ios/system/AudioEngine.mm Outdated
Comment thread packages/react-native-audio-api/ios/audioapi/ios/system/AudioEngine.mm Outdated
Comment thread packages/react-native-audio-api/ios/audioapi/ios/system/AudioEngine.h Outdated

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Code changes specifically addressing and resolving a bug ios Native iOS implementation, CoreAudio/AVFoundation bindings, or iOS-specific issues

Projects

None yet

2 participants