[iOS] Raw PCM data corrupted with distortion/echo on subsequent recording sessions

Hello!

I am writing to report a problem I ran into when implementing voice recording on iOS via a capture DSP. Here are the details of the issue, and how I resolved it (in case someone runs into this problem).

FMOD Version: 2.03.13
Platform: iPhone SE2, iOS 26.5 ((Deployed via Unity IL2CPP)
API Used: FMOD Core API (Bypassing FMOD Studio and Unity RuntimeManager)

Description

When recording on iOS, the first recording session delivers acceptable audio data. However, if the FMOD::System object remains alive between sessions, any subsequent call to System::recordStart results in digital distortion and an additive echo loop that is baked directly into the raw captured PCM bytes. This issue does not occur on Android, high-level code is identical as the same Unity project is built for both iOS and Android.

Context & Implementation Detail

The recording pipeline captures raw microphone data dynamically via an DSP_READ_CALLBACK mapped to a custom DSP on a recording ChannelGroup. The raw PCM float data is pulled directly from this stream.

The corruption and echo are present in the raw bytes immediately upon exiting the DSP callback, before any external encoders or processing layers touch the data.

Only the Core API is used in this pipeline, nothing else. Here is what was added to the UnityAppController.mm’s startUnity method:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker error:nil]; [[AVAudioSession sharedInstance] setActive:YES error:nil];

Removing the DefaultToSpeaker option did not resolve the issue.

Steps to Reproduce

  1. Initialize the FMOD::System Core context on an iOS device.
  2. Call System::recordStart using a designated recording driver.
  3. Read raw PCM floats via the custom DSP callback. Result on Run 1: Audio bytes are clean.
  4. Stop the recording session using System::recordStop.
  5. Start a second recording session using System::recordStart under the same active FMOD::System context.
  6. Read the raw PCM floats again. Result on Run 2+: The raw bytes are immediately corrupted with distortion and a compounding echo loop.

Attempted Fixes That Failed to Resolve the Issue

  1. Using a large, non-looping (loop: false) user sound buffer instead of a looping buffer.
  2. Switching the target recording device index from Driver 0 (Core Audio input) to Driver 1 (Core Audio input (Voice)).
  3. Calling System::mixerSuspend() upon stopping and System::mixerResume() before restarting. This actually caused the distortion to appear on the very first run, signalling that maybe some residual data is not cleaned in a correct way.

Workaround

The only way to get clean raw bytes on subsequent recordings is to completely destroy and rebuild the core system context between recording sessions:

  1. Call System::release() on the active FMOD::System instance.
  2. Instantiate a brand-new system object via FMOD::System_Create().
  3. Re-initialize the Core API context from scratch before calling System::recordStart again.

In order to achieve control over the creation and release of the FMOD::System core in the context of Unity, the RuntimeManager was turned off and instantiation was disabled by editing the source code of the Unity implementation.

Thank you for bringing this to our attention and the detailed post.

Is it possible to check if the issue is present in our record CORE API example:

and let me know if the issue persists? Could I also please grab your Unity version?

Thank you for sharing your workaround.

Hello, Connor!

Thank you for your reply, much appreciated.

I did as you asked and gave it a go with the Core API examples from the website.

I had to change the info.plistand record.ccto make it work on iOS 26.5 and request the correct permissions.

I did get some echo and progressively worse artifacts initially, but it turned out to be due to usingwithOptions:AVAudioSessionCategoryOptionDefaultToSpeakerand the device microphone not filtering out its own output during recording.

Everything worked correctly once I removed it and forwarded sound to the isolated call speaker. No echo, no artifacts, perfectly fine.

Just to be sure, I turned off withOptions:AVAudioSessionCategoryOptionDefaultToSpeakeron the Unity project once again to check if it was the source of the issue. The issue persists on the Unity project, as described in the report, even with the call speaker as output device.

I am using Unity 6000.3.11f1.

I hope this helps!

Regards,

Vasil

Thank you for testing that. Unfortunately, I was not able to reproduce the issue.

In our Unity Integration | Examples Record we playback the sound on a channel rather than reading the PCM data. Could you test if that works without any artifacts? That example uses the Core API so you can still keep some of your current system as well.