AudioManager
MicroPythonOS provides a centralized audio service called AudioManager, inspired by Android's architecture. It manages audio playback and recording across different hardware outputs with priority-based audio focus control and a device registry for routing.
Overview
AudioManager provides:
- Priority-based audio focus - Higher priority streams interrupt lower priority ones
- Device registry - Register I2S outputs, PWM buzzers, and microphone inputs
- Session control - Player/Recorder sessions with start/stop/pause/resume
- WAV file support - 8/16/24/32-bit PCM, IMA ADPCM (4-bit), mono/stereo, auto-upsampling
- WAV recording - 16-bit mono PCM from I2S or ADC microphone
- RTTTL ringtone support - Full Ring Tone Text Transfer Language parser
- Thread-safe - Safe for concurrent access
- Hardware-agnostic - Apps work across all platforms without changes
Supported Audio Devices
- I2S Output: Digital audio output for WAV file playback
- I2S Input: Microphone recording (I2S mic)
- ADC Input: Analog microphone recording via ADC (Fri3d 2026)
- Buzzer: PWM-based tone/ringtone playback
Quick Start
Registering Devices
AudioManager uses a registry of device descriptors instead of direct hardware initialization. Register devices once at startup (typically in your board init file):
from mpos import AudioManager
# I2S speaker
AudioManager.add(
AudioManager.Output(
name="speaker",
kind="i2s",
channels=2,
i2s_pins={"sck": 2, "ws": 47, "sd": 16, "mck": 2},
preferred_sample_rate=44100,
)
)
# I2S microphone
AudioManager.add(
AudioManager.Input(
name="mic",
kind="i2s",
i2s_pins={"sck_in": 17, "ws": 47, "sd_in": 15},
preferred_sample_rate=16000,
)
)
# Buzzer for RTTTL
AudioManager.add(
AudioManager.Output(
name="buzzer",
kind="buzzer",
buzzer_pin=46,
)
)
Playing WAV Files
from mpos import AudioManager
player = AudioManager.player(
file_path="M:/sdcard/music/song.wav",
stream_type=AudioManager.STREAM_MUSIC,
volume=80,
on_complete=lambda msg: print(msg),
)
player.start()
Supported formats:
- Encoding: PCM (8/16/24/32-bit), IMA ADPCM (4-bit)
- Channels: Mono or stereo
- Sample rate: Any rate (auto-upsampled to ≥8000 Hz)
- Repeat: Pass repeat_count to loop playback N times
Playing RTTTL Ringtones
from mpos import AudioManager
rtttl = "Nokia:d=4,o=5,b=225:8e6,8d6,8f#,8g#,8c#6,8b,d,8p,8b,8a,8c#,8e"
player = AudioManager.rtttl_player(
rtttl,
stream_type=AudioManager.STREAM_NOTIFICATION,
)
player.start()
Recording Audio (I2S Mic)
from mpos import AudioManager
recorder = AudioManager.recorder(
file_path="data/my_recording.wav",
duration_ms=10000,
sample_rate=16000,
)
recorder.start()
Recording Audio (ADC Mic)
from mpos import AudioManager
AudioManager.record_wav_adc(
file_path="data/adc_recording.wav",
duration_ms=5000,
sample_rate=16000,
adc_pin=1,
)
Desktop WAV Playback
On Linux and macOS desktop builds, WAV playback uses an external audio player subprocess instead of I2S hardware. AudioManager automatically detects one of the following players in order of preference:
ffplay(FFmpeg)aplay(ALSA)paplay(PulseAudio)afplay(macOS)
If none is installed, the player still runs in "timing simulation" mode so apps can test playback flow without sound.
# Ubuntu/Debian
sudo apt install ffmpeg
# macOS
# afplay is pre-installed
Priority and volume controls apply conceptually on desktop, although the external player handles the actual output.
ADPCM WAV Encoding
IMA ADPCM compresses 16-bit PCM to 4 bits per sample, roughly quartering WAV file size with minimal quality loss — ideal for storage-constrained devices.
ffmpeg can encode ADPCM (-acodec adpcm_ima_wav) but has two drawbacks: it prepends silence that lengthens the file, and it only supports the default 4-bit depth. MicroPythonOS currently decodes 4-bit IMA ADPCM only. For better encoding results than ffmpeg, use adpcm-xq, which avoids the silence padding and additionally supports 2 and 3-bit ADPCM (still good quality, even smaller files). If there's demand for it, 2 and 3-bit ADPCM decoding support could be added to MicroPythonOS too.
# ffmpeg (adds silence, 4-bit only)
ffmpeg -i input.wav -acodec adpcm_ima_wav output.wav
# adpcm-xq (clean, supports 2, 3 and 4-bit)
adpcm-xq input.wav output.wav
Audio Focus Priority
AudioManager implements a 3-tier priority-based audio focus system inspired by Android:
| Stream Type | Priority | Use Case | Behavior |
|---|---|---|---|
| STREAM_ALARM | 2 (Highest) | Alarms, alerts | Interrupts all other streams |
| STREAM_NOTIFICATION | 1 (Medium) | Notifications, UI sounds | Interrupts music, rejected by alarms |
| STREAM_MUSIC | 0 (Lowest) | Music, podcasts | Interrupted by everything |
Priority Rules
- Higher priority interrupts lower priority: ALARM > NOTIFICATION > MUSIC
- Equal priority is rejected: Can't play two alarms simultaneously
- Lower priority is rejected: Can't start music while alarm is playing
Device Routing and Conflicts
AudioManager prevents conflicts by tracking pin usage and sample rates:
- Shared clocks: If two I2S sessions share
ws/sck, they must use the same sample rate. - Conflicts: Starting a new session stops conflicting sessions automatically.
Volume Control
from mpos import AudioManager
AudioManager.set_volume(70)
volume = AudioManager.get_volume()
print(f"Current volume: {volume}")
Volume changes affect active sessions when the stream supports volume adjustment.
API Reference
Device Registration
AudioManager.add(device)
Register a device descriptor.
- Parameters:
device-AudioManager.OutputorAudioManager.Input
AudioManager.get_outputs() / AudioManager.get_inputs()
Return a list of registered devices.
AudioManager.get_default_output() / AudioManager.get_default_input()
Return the default device for playback or recording.
AudioManager.set_default_output(output) / AudioManager.set_default_input(input_device)
Set the default device used when a session does not specify one.
Playback Sessions
AudioManager.player(file_path=None, rtttl=None, stream_type=None, on_complete=None, output=None, sample_rate=None, volume=None)
Create a playback session. For I2S playback use file_path. For RTTTL use rtttl.
- Returns:
Player
AudioManager.rtttl_player(rtttl, **kwargs)
Shortcut for creating an RTTTL player.
AudioManager.get_active_player(stream_type=None, file_path=None)
Return the active Player matching optional filters.
AudioManager.get_active_track(stream_type=None)
Return file path for the active track (if any).
Recording Sessions
AudioManager.recorder(file_path, input=None, sample_rate=None, on_complete=None, duration_ms=None, **adc_config)
Create a recording session. Use an AudioManager.Input descriptor for I2S or ADC input.
- Returns:
Recorder
AudioManager.record_wav_adc(file_path, duration_ms=None, sample_rate=None, adc_pin=None, on_complete=None, **adc_config)
Start an ADC recording session immediately.
Global Control
AudioManager.stop()
Stop all active playback and recording sessions.
AudioManager.set_volume(volume) / AudioManager.get_volume()
Set or get the global volume (0–100).
Player Session Methods
start()/stop()/pause()/resume()is_playing()/is_active()get_progress_percent()/get_progress_ms()/get_duration_ms()
Recorder Session Methods
start()/stop()/pause()/resume()is_recording()/is_active()get_duration_ms()
Hardware Support Matrix
| Board | I2S Output | I2S Mic | ADC Mic | Buzzer | Notes |
|---|---|---|---|---|---|
| Fri3d 2024 Badge | ✅ | ✅ | ❌ | ✅ | Full audio support |
| Fri3d 2026 Badge | ✅ | ❌ | ✅ | ✅ | ADC mic via adc_mic |
| Waveshare ESP32-S3 | ✅ | ❌ | ❌ | ❌ | I2S output only |
| Linux/macOS | ✅ (external player) | ✅ (simulated) | ✅ (simulated) | ❌ | WAV playback via ffplay/aplay/paplay/afplay |
Troubleshooting
Playback Rejected
Symptom: New playback is rejected or interrupted.
Cause: Higher-priority stream is active or device/pin conflict.
Solution:
1. Use AudioManager.get_active_player() to inspect active streams
2. Stop the active session with AudioManager.stop() if appropriate
3. Use a higher priority stream type
WAV File Not Playing
Requirements: - Encoding: PCM or IMA ADPCM (not MP3, AAC) - Bit depth: 8, 16, 24, or 32-bit (PCM); 4-bit (ADPCM) - Channels: Mono or stereo - Sample rate: Any (auto-upsampled to ≥8000 Hz)
See Also
- Creating Apps - Learn how to create MicroPythonOS apps
- WidgetAnimator - Smooth UI animations
- LightsManager - LED control for visual feedback
- SharedPreferences - Store audio preferences