Centralised audio session manager that owns a single shared VPIO (Voice Processing I/O) AudioUnit. More...
Instance Methods | |
| (NSException *_Nullable) | - registerMediaWithMediaId:isSend:isReceive: |
| Registers a media component (source or sink) with the AudioSessionManager. More... | |
| (void) | - unregisterMediaWithMediaId: |
| Unregisters a media component from the AudioSessionManager. More... | |
| (void) | - setUseVoiceProcessingIO: |
| Sets whether to use Voice Processing I/O (VPIO) or standard Remote I/O. More... | |
| (BOOL) | - useVoiceProcessingIO |
| Gets whether Voice Processing I/O is enabled. More... | |
| (void) | - setBypassVoiceProcessing: |
| Sets whether to bypass voice processing in VPIO. More... | |
| (BOOL) | - bypassVoiceProcessing |
| Gets whether voice processing is bypassed. More... | |
| (void) | - setVoiceProcessingEnableAGC: |
| Sets whether Automatic Gain Control (AGC) is enabled in VPIO. More... | |
| (BOOL) | - voiceProcessingEnableAGC |
| Gets whether AGC is enabled. More... | |
| (void) | - setChannelCount: |
| Sets the number of audio channels for VPIO. More... | |
| (UInt32) | - channelCount |
| Gets the configured number of audio channels. More... | |
| (AudioUnit _Nullable) | - getSharedVPIOUnit |
| Gets the shared VPIO (Voice Processing I/O) AudioUnit. More... | |
| (BOOL) | - registerMicrophoneInputCallback:refCon:mediaId: |
| Registers a callback to receive microphone input from the shared VPIO unit. More... | |
| (void) | - unregisterMicrophoneInputCallbackWithMediaId: |
| Unregisters the microphone input callback for a given media ID. More... | |
| (BOOL) | - registerSpeakerOutputWithMediaId:sampleRate:channelCount:bufferSize: |
| Registers a speaker output (sink) with the audio mixer. More... | |
| (void) | - unregisterSpeakerOutputWithMediaId: |
| Unregisters a speaker output (sink) from the audio mixer. More... | |
| (BOOL) | - writeSpeakerDataWithMediaId:data:length: |
| Writes audio data from a sink to the mixer's buffer. More... | |
| (void) | - updateSsrcForMediaId:ssrc: |
| Associates a remote RTP SSRC with a previously registered speaker output (sink). More... | |
| (NSArray< NSString * > *) | - registeredSpeakerOutputMediaIds |
| Returns the media IDs of all currently registered speaker output sinks. More... | |
| (BOOL) | - isSessionActive |
| Checks if the AVAudioSession is currently active. More... | |
| (NSString *) | - getDiagnostics |
| Gets diagnostic information about the current audio session state. More... | |
| (NSString *_Nullable) | - getTelemetryJson |
| Returns a JSON string snapshot of AudioSessionManager state for telemetry. More... | |
| (void) | - addObserver: |
| Registers an observer to receive audio quality events. More... | |
| (void) | - removeObserver: |
| Unregisters a previously registered observer. More... | |
| (void) | - notifySinkFrameDropEventWithMediaId:consecutive:total: |
| Called by AudioUnitSink when it detects frame drops (write buffer full). More... | |
| (void) | - reportSourceAudioActivityWithMediaId: |
| Called by AudioUnitSource when the microphone first produces non-silent audio. More... | |
| (void) | - reportSourceResamplingWithMediaId:captureRate:outputRate:isResampling: |
| Called by AudioUnitSource to record its sample rate conversion (resampling) state. More... | |
Class Methods | |
| (instancetype) | + sharedInstance |
| Returns the shared singleton instance of the AudioSessionManager. More... | |
Properties | |
| NSString * | microphoneInputMediaId |
Centralised audio session manager that owns a single shared VPIO (Voice Processing I/O) AudioUnit.
@discussion This manager provides a centralised approach to audio handling in WebRTC applications, solving common iOS audio issues including:
The manager owns a single VPIO AudioUnit that handles:
Architecture:
Thread Safety:
Usage Pattern:
| - (void) addObserver: | (id<FMLiveSwitchCocoaAudioSessionManagerObserver>) | observer |
Registers an observer to receive audio quality events.
| observer | The observer to register. Stored as a weak reference. |
@discussion Observers are called on the main queue when significant audio events occur. Safe to call from any thread. Registering the same observer twice has no effect.
| - (BOOL) bypassVoiceProcessing |
Gets whether voice processing is bypassed.
| - (UInt32) channelCount |
Gets the configured number of audio channels.
| - (NSString *) getDiagnostics |
Gets diagnostic information about the current audio session state.
@discussion This provides detailed information about the audio session for debugging:
Example Output:
Thread Safety: Safe to call from any thread.
Example:
| - (AudioUnit) getSharedVPIOUnit |
Gets the shared VPIO (Voice Processing I/O) AudioUnit.
@discussion The VPIO unit is created lazily when first accessed after AVAudioSession is active. This unit is configured for:
The returned AudioUnit is owned by AudioSessionManager - do NOT dispose it. Do NOT call AudioUnitInitialize, AudioOutputUnitStart, or AudioOutputUnitStop on this unit. Do NOT set properties on this unit (format, callbacks, etc.) - use the registration methods instead.
This method is primarily used by AudioUnitSource to call AudioUnitRender for pulling mic data.
Thread Safety: Safe to call from any thread.
Example:
| - (NSString *_Nullable) getTelemetryJson |
Returns a JSON string snapshot of AudioSessionManager state for telemetry.
@discussion Captures a point-in-time snapshot for connection-level telemetry:
Thread Safety: Safe to call from any thread.
| - (BOOL) isSessionActive |
Checks if the AVAudioSession is currently active.
@discussion The session becomes active when the first media component registers and becomes inactive when the last media component unregisters.
An active session means:
Thread Safety: Safe to call from any thread.
Example:
| - (void) notifySinkFrameDropEventWithMediaId: | (NSString *) | mediaId | |
| consecutive: | (UInt32) | consecutive | |
| total: | (UInt64) | total | |
Called by AudioUnitSink when it detects frame drops (write buffer full).
| mediaId | The sink's media ID. |
| consecutive | Consecutive frames dropped in the current run. |
| total | Total frames dropped by this sink since creation. |
@discussion Dispatches a "sinkFrameDrop" observer event, rate-limited to once per 5 minutes per sink. The caller should only invoke this on the first frame of each new drop run (i.e., when consecutive transitions from 0 to 1).
Thread Safety: Safe to call from any thread.
| - (NSArray< NSString * > *) registeredSpeakerOutputMediaIds |
Returns the media IDs of all currently registered speaker output sinks.
Used by ServerConnectionTelemetry to send asmSsrcMap at trigger time, bypassing [audioStream outputs] which may be empty early in the connection. Thread Safety: Safe to call from any thread.
| - (NSException *) registerMediaWithMediaId: | (NSString *) | mediaId | |
| isSend: | (BOOL) | isSend | |
| isReceive: | (BOOL) | isReceive | |
Registers a media component (source or sink) with the AudioSessionManager.
| mediaId | Unique identifier for this media component (e.g., generated GUID). |
| isSend | YES if this media sends audio (microphone), NO otherwise. |
| isReceive | YES if this media receives audio (speaker), NO otherwise. |
@discussion This method must be called before any audio operations for a media component. The AudioSessionManager:
If the media component has neither send nor receive audio, this method does nothing.
Call Order:
Thread Safety: Safe to call from any thread.
Example:
| - (BOOL) registerMicrophoneInputCallback: | (AURenderCallback) | inputCallback | |
| refCon: | (FMLiveSwitchZeroingWeakRef *) | refCon | |
| mediaId: | (NSString *) | mediaId | |
Registers a callback to receive microphone input from the shared VPIO unit.
| inputCallback | The AURenderCallback function to call when mic data is available. |
| refCon | User data pointer to pass to the callback (typically self or weakSelf). |
| mediaId | The media ID of the source registering this callback. |
@discussion Only ONE source can register a microphone input callback at a time. The callback will be invoked on the real-time audio thread when the VPIO unit has captured microphone data.
The callback receives data AFTER echo cancellation and noise suppression have been applied.
Callback Signature:
In your callback, you must call AudioUnitRender on the shared VPIO unit to actually pull the microphone data:
Thread Safety: Safe to call from any thread, but callback runs on real-time audio thread.
Example:
| - (BOOL) registerSpeakerOutputWithMediaId: | (NSString *) | mediaId | |
| sampleRate: | (Float64) | sampleRate | |
| channelCount: | (UInt32) | channelCount | |
| bufferSize: | (UInt32) | bufferSize | |
Registers a speaker output (sink) with the audio mixer.
| mediaId | Unique identifier for this sink. |
| sampleRate | Sample rate of the audio data this sink will write (e.g., 48000). |
| channelCount | Number of audio channels (1 for mono, 2 for stereo). |
| bufferSize | Size in bytes of the circular buffer to allocate for this sink. |
@discussion This registers a sink with the AudioSessionManager's mixer. A circular buffer is allocated for this sink to store audio data before playback.
Buffer Size Recommendations:
After registering, the sink should call writeSpeakerDataWithMediaId to provide audio data.
The mixer will combine audio from all registered sinks and play through the VPIO speaker output.
Thread Safety: Safe to call from any thread.
Example:
| - (void) removeObserver: | (id<FMLiveSwitchCocoaAudioSessionManagerObserver>) | observer |
Unregisters a previously registered observer.
| observer | The observer to remove. |
@discussion Safe to call from any thread. No-op if the observer is not registered.
| - (void) reportSourceAudioActivityWithMediaId: | (NSString *) | mediaId |
Called by AudioUnitSource when the microphone first produces non-silent audio.
| mediaId | The source's media ID. |
@discussion Sets an internal flag that is included as "sourceHadAudio" in all subsequent observer event detail dictionaries and in getTelemetryJson. Idempotent — safe to call multiple times; only the first call has any effect.
Thread Safety: Safe to call from any thread.
| - (void) reportSourceResamplingWithMediaId: | (NSString *) | mediaId | |
| captureRate: | (int) | captureRate | |
| outputRate: | (int) | outputRate | |
| isResampling: | (BOOL) | isResampling | |
Called by AudioUnitSource to record its sample rate conversion (resampling) state.
| mediaId | The source's media ID. |
| captureRate | The hardware capture rate (e.g., 16000 for Bluetooth SCO). |
| outputRate | The pipeline output rate (e.g., 48000). |
| isResampling | YES if an AudioConverter is active to bridge the two rates. |
@discussion Stored and included in getTelemetryJson as: "sourceResamplingActive": bool "sourceCaptureRateHz": int (only when isResampling is YES) "sourceOutputRateHz": int (only when isResampling is YES) Should be called after configureVPIOFormatAndConverter and again after recovery if rates change.
Thread Safety: Safe to call from any thread.
| - (void) setBypassVoiceProcessing: | (BOOL) | bypassVoiceProcessing |
Sets whether to bypass voice processing in VPIO.
| bypassVoiceProcessing | YES to bypass voice processing, NO to enable it. |
@discussion When bypassed, VPIO acts more like RemoteIO but maintains the same I/O structure. This disables echo cancellation and noise suppression while keeping the VPIO AudioUnit.
Default: NO (voice processing enabled)
Use Cases:
IMPORTANT: Only effective when useVoiceProcessingIO is YES. This property can be set before or after VPIO initialization.
Thread Safety: Safe to call from any thread.
Example:
| - (void) setChannelCount: | (UInt32) | channelCount |
Sets the number of audio channels for VPIO.
| channelCount | Number of channels: 1 for mono, 2 for stereo. |
@discussion This configures both microphone input and speaker output channel count.
Default: 1 (mono)
Channel Count Guidelines:
IMPORTANT:
Thread Safety: Safe to call from any thread.
Example:
| - (void) setUseVoiceProcessingIO: | (BOOL) | useVoiceProcessingIO |
Sets whether to use Voice Processing I/O (VPIO) or standard Remote I/O.
| useVoiceProcessingIO | YES to use VPIO (with echo cancellation), NO to use RemoteIO. |
@discussion VPIO provides built-in echo cancellation, noise suppression, and automatic gain control. This setting must be configured BEFORE any media registers.
Default: YES (VPIO enabled)
Use Cases:
IMPORTANT: This property can only be set before the VPIO unit is initialised. Attempting to change it after VPIO initialization will log a warning and have no effect.
Thread Safety: Safe to call from any thread.
Example:
| - (void) setVoiceProcessingEnableAGC: | (BOOL) | enableAGC |
Sets whether Automatic Gain Control (AGC) is enabled in VPIO.
| enableAGC | YES to enable AGC, NO to disable it. |
@discussion AGC automatically adjusts microphone gain to maintain consistent audio levels. When enabled, quiet speech is amplified and loud speech is attenuated.
Default: YES (AGC enabled)
Use Cases:
IMPORTANT: Only effective when useVoiceProcessingIO is YES and bypassVoiceProcessing is NO. This property can be set before or after VPIO initialization.
Thread Safety: Safe to call from any thread.
Example:
| + (instancetype) sharedInstance |
Returns the shared singleton instance of the AudioSessionManager.
@discussion This is the primary way to access the AudioSessionManager. The instance is created lazily on first access and persists for the lifetime of the application.
| - (void) unregisterMediaWithMediaId: | (NSString *) | mediaId |
Unregisters a media component from the AudioSessionManager.
| mediaId | The unique identifier of the media component to unregister. |
@discussion This method should be called when a media component is being destroyed. The AudioSessionManager:
If the mediaId was not registered, this method does nothing.
Thread Safety: Safe to call from any thread.
Example:
| - (void) unregisterMicrophoneInputCallbackWithMediaId: | (NSString *) | mediaId |
Unregisters the microphone input callback for a given media ID.
| mediaId | The media ID of the source that registered the callback. |
@discussion This removes the microphone callback registration. After calling this, the source will no longer receive microphone data.
If the provided mediaId does not match the currently registered callback, this method does nothing.
Thread Safety: Safe to call from any thread.
Example:
| - (void) unregisterSpeakerOutputWithMediaId: | (NSString *) | mediaId |
Unregisters a speaker output (sink) from the audio mixer.
| mediaId | The unique identifier of the sink to unregister. |
@discussion This removes the sink from the mixer and frees its circular buffer. After calling this, the sink can no longer write audio data.
If the provided mediaId was not registered, this method does nothing.
Thread Safety: Safe to call from any thread.
Example:
| - (void) updateSsrcForMediaId: | (NSString *) | mediaId | |
| ssrc: | (UInt32) | ssrc | |
Associates a remote RTP SSRC with a previously registered speaker output (sink).
| mediaId | The unique identifier of the sink (as returned during registration). |
| ssrc | The 32-bit SSRC of the remote RTP stream feeding this sink. |
@discussion The SSRC is not available at sink creation time — it is known from SDP negotiation, which completes after the sink is registered. Call this method once the SSRC is determined (e.g. from the audio stream's RTP receiver after connection setup).
The SSRC is included in subsequent getDiagnostics and getTelemetryJson output so that the server can correlate sink media IDs with remote participants.
If mediaId is not registered, this method does nothing. Thread Safety: Safe to call from any thread.
| - (BOOL) useVoiceProcessingIO |
Gets whether Voice Processing I/O is enabled.
| - (BOOL) voiceProcessingEnableAGC |
Gets whether AGC is enabled.
| - (BOOL) writeSpeakerDataWithMediaId: | (NSString *) | mediaId | |
| data: | (const void *) | data | |
| length: | (UInt32) | length | |
Writes audio data from a sink to the mixer's buffer.
| mediaId | The unique identifier of the sink writing data. |
| data | Pointer to audio data in 16-bit signed integer (short) format. |
| length | Length of data in bytes. |
@discussion This writes audio data to the sink's circular buffer in the mixer. The data will be mixed with other sinks and played through the VPIO speaker output.
Data Format Requirements:
Buffer Full Handling:
Thread Safety: Safe to call from any thread, typically called from media decode thread.
Example:
|
readnonatomicassign |