No mic capture on iOS 18.5

Hello!

We stumbled upon a problem with our karaoke app where user on iPhone 16e/iOS 18.5 has problem with mic capture, other users cannot hear him. The mic capture is working fine on 17.5, 16.8. Maybe there is something else we need when configuring AVAudioSession for iOS 18.5?

Currently it's set up like this:

override func viewDidLoad() {
        super.viewDidLoad()
        UIApplication.shared.isIdleTimerDisabled = true
        
        mRoomId = appDelegate.getRoomId()
        
        let audioSession = AVAudioSession.sharedInstance()
        try! audioSession.setCategory(.playAndRecord, mode: .voiceChat, options: [.defaultToSpeaker])
        try! audioSession.setPreferredSampleRate(48000)
        try! audioSession.setActive(true, options: [])
    }




We discovered the iOS version is not the culprit. All models starting with 14 series iPhones and onward are affected by this problem, even on iOS 17. Must be some glitched interaction of hardware and software feature.

Affected models do not produce any audio, magnitude logging from C++ engine doesn't produce anything.

  static OSStatus mixerPlaybackCallack(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) {
            AudioEngine *self = (AudioEngine*)inRefCon;
            uint32_t toget = inNumberFrames << 2;
            //printf("mixerPlaybackCallack: bus: %u, frames: %u\n", (uint32_t)inBusNumber, (uint32_t)inNumberFrames);
            if (inBusNumber < kMaxRemoteLines) {
                auto& audiobuffer = self->m_remoteBuffers[inBusNumber];
                int32_t len = 0;
                if (uint8_t *buf = audiobuffer.tail(len)) {
                    int32_t tocopy = len > toget ? toget : len;
                    memcpy(ioData->mBuffers[0].mData, buf, tocopy);
                    audiobuffer.consume(tocopy);
                    if (tocopy < toget) {
                        memset(((uint8_t*)ioData->mBuffers[0].mData) + tocopy, 0, toget - tocopy);
                    }
                } else {
                    memset((uint8_t*)ioData->mBuffers[0].mData, 0, toget);
                    *ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
                }
                
                
                
            } else if (inBusNumber == kMaxRemoteLines+0) {    // mike
                AudioBufferList bufferList = {1, {2, toget, self->m_mikeBuf}};    // stereo, size - only necessary to get
                AudioUnitRenderActionFlags tmpFlags = 0;
                if (AudioUnitRender(self->m_remoteIoUnit, &tmpFlags, inTimeStamp, 1, inNumberFrames, &bufferList) == noErr) {
                    self->m_mikeBufSize = bufferList.mBuffers[0].mDataByteSize;
                    
                    // ----------------------------------------------------------------------
                    // ✨ SIMPLIFIED MAGNITUDE LOGGING
                    // ----------------------------------------------------------------------
                    // Data is 16-bit PCM (SInt16) and stereo (2 channels)
                    int numChannels = 2;
                    int16_t *samples = (int16_t *)self->m_mikeBuf;
                    int numBytes = self->m_mikeBufSize;
                    int numSamples = numBytes / sizeof(int16_t);
                    long long magnitudeSum = 0;
                    if (samples && numSamples > 0) {
                        // Calculate the sum of absolute magnitudes
                        for (int i = 0; i < numSamples; ++i) {
                            magnitudeSum += std::abs(samples[i]);
                        }
                        
                        // Calculate the average magnitude (Max is 32767)
                        double averageMagnitude = (double)magnitudeSum / numSamples;
                        
                        // Log if the level is above a low threshold
                        static int callCount = 0;
                        if (averageMagnitude > 50.0) {
                            printf("🎤 INPUT DATA DETECTED! Frames: %u, Channels: %d, Avg Mag: %.2f\n",
                                   (unsigned int)inNumberFrames, numChannels, averageMagnitude);
                        } else {
                             if (callCount % 100 == 0) {
                                 printf("🎤 INPUT DATA CHECK: Frames: %u, Channels: %d, Avg Mag: %.2f (Silent)\n",
                                        (unsigned int)inNumberFrames, numChannels, averageMagnitude);
                             }
                             callCount++;
                        }
                    }
                    // ----------------------------------------------------------------------
                    
                    if (self->f) {
                        fwrite(bufferList.mBuffers[0].mData, 1, bufferList.mBuffers[0].mDataByteSize, self->f);
                        self->fsize += bufferList.mBuffers[0].mDataByteSize;
                        if (self->fsize > 10000000) {
                            fclose(self->f); self->f = nullptr;
                        }
                    }
                    self->m_echo.process(2, self->m_deviceSamplerate, (int16_t*)self->m_mikeBuf, (int16_t*)self->m_mikeBuf, inNumberFrames);    // TEMPORARY DISABLED !!!!!!!!!!!!!!!
                } 
No mic capture on iOS 18.5
 
 
Q