Repository: Automattic/pocket-casts-ios
File: podcasts/DefaultPlayer.swift (Swift)

Code before:

        private func createAudioMix() {
            guard audioMix == nil else { return }

            let mutableMix = AVMutableAudioMix()
            let audioMixInputParameters = AVMutableAudioMixInputParameters(track: assetTrack)

            var clientInfo = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
            if FeatureFlag.useDefaultPlayerTapCookie.enabled {
                let tapCookie = AudioProcessingTapProxy(input: self)
                clientInfo = UnsafeMutableRawPointer(Unmanaged.passRetained(tapCookie).toOpaque())
            }

            var callbacks = MTAudioProcessingTapCallbacks(
                version: kMTAudioProcessingTapCallbacksVersion_0,
                clientInfo: clientInfo,
                init: tapInit,
                finalize: tapFinalize,
                prepare: tapPrepare,
                unprepare: tapUnprepare,
                process: tapProcess
            )

            var audioProcessingTap: MTAudioProcessingTap?
            if noErr == MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks, kMTAudioProcessingTapCreationFlag_PreEffects, &audioProcessingTap) {
                audioMixInputParameters.audioTapProcessor = audioProcessingTap
                mutableMix.inputParameters = [audioMixInputParameters]
                audioMix = mutableMix
            }
        }

        // MARK: - Tap Callbacks

        let tapInit: MTAudioProcessingTapInitCallback = { tap, clientInfo, tapStorageOut in
            tapStorageOut.pointee = clientInfo

            guard let referenceToSelf = DefaultPlayer.unretainedDefaultPlayer(for: tap) else {
                return
            }

            referenceToSelf.peakLimiter = nil
            referenceToSelf.highPassFilter = nil
            referenceToSelf.sampleCount = 0
        }

        let tapFinalize: MTAudioProcessingTapFinalizeCallback = { tap in
            if FeatureFlag.useDefaultPlayerTapCookie.enabled {
                FileLog.shared.console("[AudioProcessingTapProxy] Finalize tap: \(tap)\n")
                Unmanaged<AudioProcessingTapProxy>.fromOpaque(MTAudioProcessingTapGetStorage(tap)).release()
            }
        }

Review comment (suggestion):
It would be great if you can develop and test with our current Xcode version and use the beta for testing purpose only, in order to avoid these errors and make sure everything works since we don't support iOS 26 and we don't compile PC with it.

Code after:

        private func createAudioMix() {
            guard audioMix == nil else { return }

            let mutableMix = AVMutableAudioMix()
            let audioMixInputParameters = AVMutableAudioMixInputParameters(track: assetTrack)

            var clientInfo = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
            if FeatureFlag.useDefaultPlayerTapCookie.enabled {
                let tapCookie = AudioProcessingTapProxy(input: self)
                clientInfo = UnsafeMutableRawPointer(Unmanaged.passRetained(tapCookie).toOpaque())
            }

            var callbacks = MTAudioProcessingTapCallbacks(
                version: kMTAudioProcessingTapCallbacksVersion_0,
                clientInfo: clientInfo,
                init: tapInit,
                finalize: tapFinalize,
                prepare: tapPrepare,
                unprepare: tapUnprepare,
                process: tapProcess
            )

            var audioProcessingTap: Unmanaged<MTAudioProcessingTap>?
            if noErr == MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks, kMTAudioProcessingTapCreationFlag_PreEffects, &audioProcessingTap) {
                audioMixInputParameters.audioTapProcessor = audioProcessingTap?.takeRetainedValue()
                mutableMix.inputParameters = [audioMixInputParameters]
                audioMix = mutableMix
            }
        }

        // MARK: - Tap Callbacks

        let tapInit: MTAudioProcessingTapInitCallback = { tap, clientInfo, tapStorageOut in
            tapStorageOut.pointee = clientInfo

            guard let referenceToSelf = DefaultPlayer.unretainedDefaultPlayer(for: tap) else {
                return
            }

            referenceToSelf.peakLimiter = nil
            referenceToSelf.highPassFilter = nil
            referenceToSelf.sampleCount = 0
        }

        let tapFinalize: MTAudioProcessingTapFinalizeCallback = { tap in
            if FeatureFlag.useDefaultPlayerTapCookie.enabled {
                FileLog.shared.console("[AudioProcessingTapProxy] Finalize tap: \(tap)\n")
                Unmanaged<AudioProcessingTapProxy>.fromOpaque(MTAudioProcessingTapGetStorage(tap)).release()
            }
        }