@@ -74,7 +74,11 @@ public final class MixerEngineObserver: AudioEngineObserver, Loggable {
7474
7575 // Internal states
7676 var isInputConnected : Bool = false
77- var appAudioConverter : AudioConverter ?
77+
78+ // Cached converters
79+ var converters : [ AVAudioFormat : AudioConverter ] = [ : ]
80+
81+ // Reference to engine format
7882 var engineFormat : AVAudioFormat ?
7983 }
8084
@@ -147,6 +151,10 @@ public final class MixerEngineObserver: AudioEngineObserver, Loggable {
147151 engine. connect ( micMixerNode, to: mainMixerNode, format: format)
148152
149153 _state. mutate {
154+ if let previousEngineFormat = $0. engineFormat, previousEngineFormat != format {
155+ // Clear cached converters when engine format changes
156+ $0. converters. removeAll ( )
157+ }
150158 $0. engineFormat = format
151159 $0. isInputConnected = true
152160 }
@@ -169,22 +177,31 @@ public final class MixerEngineObserver: AudioEngineObserver, Loggable {
169177}
170178
171179extension MixerEngineObserver {
180+ // Create or use cached AudioConverter.
181+ func converter( for format: AVAudioFormat ) -> AudioConverter ? {
182+ _state. mutate {
183+ guard let engineFormat = $0. engineFormat else { return nil }
184+
185+ if let converter = $0. converters [ format] {
186+ return converter
187+ }
188+
189+ let newConverter = AudioConverter ( from: format, to: engineFormat)
190+ $0. converters [ format] = newConverter
191+ return newConverter
192+ }
193+ }
194+
172195 // Capture appAudio and apply conversion automatically suitable for internal audio engine.
173- func capture( appAudio inputBuffer: AVAudioPCMBuffer ) {
174- let ( isConnected, appNode, oldConverter , engineFormat ) = _state. read {
175- ( $0. isInputConnected, $0. appNode, $0 . appAudioConverter , $0 . engineFormat )
196+ public func capture( appAudio inputBuffer: AVAudioPCMBuffer ) {
197+ let ( isConnected, appNode) = _state. read {
198+ ( $0. isInputConnected, $0. appNode)
176199 }
177200
178- guard isConnected, let engineFormat , let engine = appNode. engine, engine. isRunning else { return }
201+ guard isConnected, let engine = appNode. engine, engine. isRunning else { return }
179202
180203 // Create or update the converter if needed
181- let converter = ( oldConverter? . inputFormat == inputBuffer. format)
182- ? oldConverter
183- : {
184- let newConverter = AudioConverter ( from: inputBuffer. format, to: engineFormat) !
185- self . _state. mutate { $0. appAudioConverter = newConverter }
186- return newConverter
187- } ( )
204+ let converter = converter ( for: inputBuffer. format)
188205
189206 guard let converter else { return }
190207
0 commit comments