Skip to content
Shiny.NET
Commercial SupportGuaranteed response times on Shiny bug fixes, straight from the maintainers. Plans from US$1,500 a year.See the plans

Live Monitor

IAudioMonitor sends the microphone straight to the current audio output in near real time, like a PA system or megaphone. A typical use is talking into the phone and hearing it from a Bluetooth speaker. IAudioSource gives you PCM to process yourself. The monitor instead connects input to output inside the platform’s own audio engine, so nothing goes through your code.

Available on iOS, Mac Catalyst, macOS, Android and Linux. IAudio.Monitor throws PlatformNotSupportedException on Windows and in the browser.

using Shiny;
using Shiny.Audio;
public partial class MicViewModel(IAudio audio) : ObservableObject
{
[ObservableProperty] double level; // bind to a level meter
public async Task Toggle()
{
var monitor = audio.Monitor;
if (monitor.IsMonitoring)
{
await monitor.Stop();
return;
}
if (await monitor.RequestAccess() != AccessState.Available)
return;
monitor.InputLevelChanged += (_, l) =>
MainThread.BeginInvokeOnMainThread(() => Level = l);
// No Processing, so it can reach a Bluetooth A2DP speaker (see below)
await monitor.Start(new AudioMonitorOptions { Gain = 1.0 });
}
}

Output goes to the current route: the built-in speaker, a wired output, or a connected Bluetooth speaker (A2DP) while the phone’s own mic captures. You can change Gain (0.0–1.0) while it runs. InputLevelChanged reports a normalized level for a meter.

AudioMonitorOptions Default
Gain 1.0 Initial output level, from 0.0 (mute) to 1.0 (unity)
Processing null Echo cancellation, noise suppression and gain control. Read the iOS caution below first
DuckOtherAudio false Keep other audio, such as music, playing at a lower volume instead of interrupting it, so you can talk over it. iOS adds DuckOthers to the session and Android takes transient MayDuck audio focus
InputDevice null Preferred mic, from IAudioDevices.GetInputs()
OutputDevice null Preferred output, from IAudioDevices.GetOutputs()
Member
RequestAccess() Asks for the mic permission
Start(options, ct) / Stop() Starts the monitor, or stops it and restores the audio session
IsMonitoring true while running
Gain Output level, adjustable live
SetInputDevice(device) Switches the mic, live. null uses the OS default
SetOutputDevice(device) Switches the output, live, where the platform allows. See Devices & Routes
InputLevelChanged Input level, 0.0–1.0

AirPlay (HomePod, Apple TV) can’t carry a live mic. iOS only allows AirPlay for playback, not while recording. Use Bluetooth for a wireless live PA.

Platform Implementation
iOS / Mac Catalyst AVAudioEngine (input node → main mixer → output) in a PlayAndRecord session. It doesn’t use DefaultToSpeaker, so it follows a Bluetooth or wired route, and it uses Default mode unless processing is requested. The engine rebuilds on route changes, so monitoring moves to a newly connected output. The audio session is saved at start and restored on Stop
macOS The same engine, without AVAudioSession
Android AudioRecord → AudioTrack
Linux A PulseAudio/ALSA capture stream fed into a playback stream. See Linux