miniaudio_player banner

miniaudio_player icon miniaudio_player

pub package License: MIT Platform Dart FFI Tests Donate (Buy me a coffee) Donate (Patreon) Donate (Ko-fi)

An ultra-low-resource, high-performance cross-platform audio player and DSP engine for Flutter and Dart. Powered by the industry-standard miniaudio C engine, Sonic DSP, and Dart Native Assets with 100% pure FFI bindings.

Engineered from the ground up for professional electroacoustic fidelity, sub-millisecond command latency, deterministic real-time execution ($\mathcal{O}(1)$), and zero UI stutter by leveraging miniaudio's dedicated real-time native OS audio threads.


miniaudio_player - Audio Player Controls
miniaudio_player - Real-Time Reactive Visualizer


✨ Features at a Glance

  • ⚑ Strict Real-Time Determinism ($\mathcal{O}(1)$) & Zero Allocations: Direct native C memory management guarantees 0 dynamic heap allocations in the real-time audio thread, ensuring completely glitch-free audio playback even under intense UI activity or system load.
  • πŸ”€ 100% Pure FFI & Zero-Isolate Architecture: Commands execute directly via FFI in sub-microseconds without message-passing latency or Dart VM isolate memory bloat. Automatic resource management via NativeFinalizer prevents native memory leaks.
  • πŸ›‘οΈ Hardware-Grade Output Limiter (True-Peak Soft-Knee): True-Peak brickwall limiter operating before DAC handoff. Mathematically transparent in the linear zone ($|x| \le 0.95$ FS) with 0.00000% THD and 141.4 dB SNR, smoothly compressing digital overshoots (+3.5 dBFS capped safely at 0.996 FS) to eliminate digital clipping.
  • 🎧 Binaural Headphone Crossfeed (Bauer bs2b): Acoustic speaker crosstalk emulation for fatigue-free headphone listening with standard Moffat-Bauer and Chu Moy presets.
  • πŸŽ›οΈ Standard ISO 266 10-Band Parametric Equalizer: Native Direct Form II Transposed (DF2T) biquad cascade centered at standard preferred 1/1 octave frequencies (31Hz to 16kHz) with analytical RBJ curves (0.00 dB analytical error) and built-in acoustic presets (Rock, Pop, Jazz, Classical, Bass Boost, Flat).
  • πŸ›οΈ Studio-Grade Algorithmic Reverb (Freeverb Topology): Native C stereophonic algorithmic reverb featuring 8 parallel lowpass feedback comb filters and 4 cascaded allpass filters per channel with stereo decorrelation. Includes studio acoustic presets (Small Room, Studio, Concert Hall, Cathedral, Plate, Ambient) and full dynamic control over room size, damping, stereo width, and wet/dry mix with 0 real-time heap allocations and hardware anti-denormal protection.
  • πŸ“ˆ Real-Time Reactive Visualizer & Spectrum Analyzer: 10-band hardware BPF filter bank embedded directly in the native C playback pipeline matching the ISO 266 equalizer, stereo VU meters (L/R), RMS, and peak metrics (< 0.5% CPU active, 0% idle CPU via automatic on-demand streaming at ~30 fps).
  • πŸ”‡ Dynamic Silence Skipping & Edge Trimming: Native C real-time silence detector upstream of time-stretching and EQ. Trims lead-in/lead-out silence for gapless music and dynamically skips conversational pauses for podcasts and audiobooks with a 5ms anti-click crossfade ramp and cumulative saved time tracking.
  • 🎚️ Mono Downmix, Channel Balance & Stereo Spatializer: Built-in channel routing for mono accessibility, precision stereo balance panning, and stereo field widening.
  • πŸ“Š Unified Single-Pass Audio Analysis (Loudness, ReplayGain & Waveform): High-speed, non-blocking offline analysis in a single decoding pass on background native C OS threads (< 100 KB constant RAM). Computes ITU-R BS.1770-4 / EBU R128 loudness (LUFS), true peak, recommended gain (dB), anti-clipping defense, and normalized amplitude waveform points for UI seekbars without spawning Dart Isolates or freezing Flutter frames.
  • πŸš€ High-Definition Pitch & Speed (Sonic DSP): Real-time time-stretching and independent pitch shifting (0.25x to 4.0x rate, 0.5x to 2.0x pitch) with pristine acoustic clarity and seamless rate transitions.
  • πŸ”Œ Dynamic Audio Device Routing: Real-time switching between audio output endpoints (speakers, wired headphones, Bluetooth A2DP/SCO) with automatic hotplug detection and seamless reconnection recovery across all supported platforms.
  • 🌐 Background Playback & Standalone Isolate Support: Fully compatible with background audio services (e.g. audio_service, flutter_background_service) and standalone Dart isolates thanks to a 100% pure FFI design.
  • πŸ“¦ Extensive Audio Codec Support: Built-in native decoding for MP3, WAV, FLAC, OGG, Opus, AAC, M4A (AAC & ALAC), AIFF, W64, and more without external system dependencies.
  • πŸ”„ Dual State Paradigm: Access synchronous instant state snapshots (player.state.*) or listen to reactive broadcast streams (player.stream.*).

πŸš€ Performance & Architecture

1. Audio DSP Processing Chain

The native DSP pipeline inside ma_equalizer_node_process_pcm_frames is ordered strategically to maximize signal-to-noise ratio, minimize phase distortion, and guarantee headroom before final DAC output:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                                Audio PCM Frames In                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                            β”‚
                                            β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚    1. Preamp & ReplayGain Volume Ramping      β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                            β”‚
                                            β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚  2. 10-Band Biquad Cascade SIMD (DF2T, RBJ)   β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                            β”‚
                                            β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚ 3. Algorithmic Stereo Reverb (Freeverb 8C+4A) β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                            β”‚
                                            β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚ 4. Binaural Crossfeed / Stereo Spatializer    β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                            β”‚
                                            β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚          5. Mono Downmixing (Optional)        β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                            β”‚
                                            β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚       6. Stereo Balance / Panning Pan         β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚                               β”‚
                            β–Ό                               β–Ό
      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
      β”‚  7. Visualizer Tap (10-Band BPF)  β”‚   β”‚  8. Master Volume Fader   β”‚
      β”‚     (On-Demand Seqlock Telemetry) β”‚   β”‚     (Steady-State Bypass) β”‚
      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                            β”‚
                                                            β–Ό
                                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                      β”‚ 9. True-Peak Soft-Knee Limiter    β”‚
                                      β”‚    (Branchless SSE/NEON Safeguard)β”‚
                                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                            β”‚
                                                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                             Hardware Audio DMA Output                                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

2. Multi-Threaded Lock-Free Architecture

Unlike traditional plugins that hop through platform channels with UI thread contention and serialization overhead, miniaudio_player separates execution across three fully decoupled asynchronous domains:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                             Flutter UI / Dart Main Thread                              β”‚
β”‚  β€’ Sub-microsecond direct FFI invocations (< 1 Β΅s latency)                             β”‚
β”‚  β€’ Reactive broadcast telemetry streams (player.stream.*)                              β”‚
β”‚  β€’ Automatic memory cleanup via NativeFinalizer (Finalizable)                          β”‚
β”‚  β€’ Single-call atomic status snapshot (miniaudio_player_get_status)                    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–²β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚ Commands                               β”‚ Seqlock Telemetry
                        β”‚ (play, seek, eq...)                    β”‚ (Atomic 56-byte snapshot)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚     C Background Decoder Worker Thread         β”‚   β”‚   RT Audio Device Callback Thread β”‚
β”‚  β€’ Asynchronous multi-codec file decoding      β”‚   β”‚  β€’ High-priority OS real-time RT  β”‚
β”‚  β€’ FTZ/DAZ denormal purging (map_disable_...)  β”‚   β”‚  β€’ 0 heap allocations (O(1))      β”‚
β”‚  β€’ Sonic varispeed with 64K frame headroom     β”‚   β”‚  β€’ Lock-free SPSC ring buffer readβ”‚
β”‚  β€’ Pre-faulted cache-aligned buffers (64B)     β”‚   β”‚  β€’ Complete DSP processing chain  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚  β€’ Branchless True-Peak limiter   β”‚
                        β”‚ SPSC Commit                β”‚  β€’ Seqlock write (< 2 cycles)     β”‚
                        β–Ό                            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚ Lock-Free SPSC Ring Bufferβ”‚
          β”‚ (64-byte Cache-Line Split)β”‚
          β”‚ worker_is_sleeping flag   β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. Zero UI Thread Blocking: All decoding, Sonic time-stretching, equalizer filtering, and audio output run on dedicated native OS audio threads with real-time priority. Commands (play, pause, seek, setVolume, setEqualizer) execute in sub-microseconds without dropping Flutter frames.
  2. Zero Dynamic Memory Allocations in RT: Real-time audio callbacks operate in $\mathcal{O}(1)$ time without calling malloc, free, or OS memory allocators.
  3. Lock-Free Seqlock Synchronization: Telemetry data (visualizer, VU levels, position) is written atomically inside a minimal 56-byte critical section (< 2 CPU cycles) with explicit hardware memory barriers (DMB ISH on ARM, compiler fences on x86 TSO).
  4. Priority Inversion Protection: The RT thread signals the decoder worker via atomic flag check (worker_is_sleeping) with hysteresis, completely bypassing POSIX mutex acquisitions.

3. Low-Level Platform Engineering & Microarchitecture

For systems engineers, embedded developers, and performance specialists, miniaudio_player incorporates enterprise-grade low-level optimizations across target operating systems and CPU architectures:

  • Android 15+ 16 KB ELF Page Alignment:
    • Enforces -Wl,-z,max-page-size=16384 link flags via Dart Native Assets (hook/build.dart) to comply strictly with Android 15's mandatory 16 KB kernel memory page requirements.
    • Generates optimized ARM NEON vfpv4 vectorization on 32-bit ARM (armeabi-v7a) and AArch64 SIMD instructions on 64-bit devices.
  • Pure C JNI Android Bridge (Zero MethodChannels & Zero Kotlin):
    • Interfaces directly with Android's AudioManager and AudioDeviceInfo using an autonomous embedded C JNI bridge.
    • Requires zero Kotlin code in MainActivity.kt and eliminates Flutter MethodChannel IPC bottlenecks.
    • Autonomous 6-tier JavaVM discovery across Android API 21 through 35+ (via JNI_OnLoad, libnativehelper.so, libart.so, and dl_iterate_phdr linker memory traversal).
    • Acquires application context via reflection on ActivityThread.currentApplication(), enabling headless background execution.
    • Automatically handles AAUDIO_SERVICE_EVENT_DISCONNECTED (-899) route changes during Bluetooth hotplug events without audio stalls.
  • Windows WASAPI MMCSS Pro Audio & 1 ms High-Precision Timers:
    • Automatically registers audio threads with the Windows Multimedia Class Scheduler Service (MMCSS) via AvSetMmThreadCharacteristicsA("Pro Audio") for guaranteed real-time scheduling priority.
    • Enforces 1 ms Win32 timer resolution using timeBeginPeriod(1) (and clean release via timeEndPeriod(1)), eliminating decoder starvation caused by default 15.6 ms Windows sleep jitter.
  • Universal Hardware FTZ/DAZ Denormal Mitigation:
    • Systematically executes map_disable_denormals() on all worker and real-time audio threads.
    • Configures Flush-to-Zero (FTZ) and Denormals-are-Zero (DAZ) bits directly in CPU control registers (x86/x86_64 MXCSR 0x8040, ARM64 FPCR, ARMv7 FPSCR, and MSVC _controlfp_s).
    • Completely prevents 100x CPU penalties and audio glitching during decaying IIR filter tails.
  • Microarchitectural Concurrency & Atomic Memory Barriers:
    • Weak memory model support on ARM64/ARMv7: explicit hardware release (DMB ISH) and acquire (DMB ISHLD) barriers, plus pipeline yield instructions (isb; yield).
    • Total Store Order (TSO) on x86/x86_64: pure compiler barriers (__atomic_thread_fence / _ReadWriteBarrier), eliminating bus-locking _mm_mfence instructions and saving 30–100 CPU cycles per read.
    • Lock-free Seqlock (src/map_seqlock.h): pre-check backoff loop and local staging struct, reducing the writer critical section to a single atomic 56-byte snapshot (< 2 CPU cycles), certified over 35+ million concurrent contention reads.
  • Strict Real-Time Determinism & Zero Heap Allocations:
    • Audio callback runs in $\mathcal{O}(1)$ time with 0 dynamic heap allocations, empirically verified via memory interceptor wrappers (--wrap=malloc/calloc/realloc/free).
    • Cache-line 64-byte alignment (MAP_ALIGN_CACHE_LINE, ma_aligned_malloc) preventing multi-core false sharing on ring buffer cursors.
    • Contiguous 64-frame SIMD processing with delay registers ($s_1, s_2$) hoisted into CPU vector registers.

πŸ“Š Platform Support Matrix

Audio Player Capability Android ^1 Windows ^2 Linux iOS macOS
Native Audio Backend AAudio / OpenSL ES WASAPI Pro Audio PulseAudio / ALSA CoreAudio CoreAudio
Playback & Streaming βœ… βœ… βœ… βœ… βœ…
10-Band Equalizer (ISO 266) βœ… βœ… βœ… βœ… βœ…
True-Peak Limiter (Soft-Knee) βœ… βœ… βœ… βœ… βœ…
Binaural Crossfeed (Bauer bs2b) βœ… βœ… βœ… βœ… βœ…
Mono Downmix & Stereo Balance βœ… βœ… βœ… βœ… βœ…
Stereo Spatializer / Widener βœ… βœ… βœ… βœ… βœ…
Algorithmic Reverb (Freeverb) βœ… βœ… βœ… βœ… βœ…
Real-Time Reactive Visualizer βœ… βœ… βœ… βœ… βœ…
Silence Detection & Skipping βœ… βœ… βœ… βœ… βœ…
Audio Analysis (LUFS & Waveform) βœ… βœ… βœ… βœ… βœ…
Speed & Pitch Scaling (Sonic DSP) βœ… βœ… βœ… βœ… βœ…
Dynamic Device Routing βœ… βœ… βœ… βœ… βœ…
Background Playback & Isolates βœ… βœ… βœ… βœ… βœ…

^1: Android: Device discovery uses an autonomous pure C JNI bridge with zero MethodChannels and no Kotlin glue code. Binaries are compiled with -Wl,-z,max-page-size=16384 for Android 15+ 16 KB memory page compatibility and ARM NEON SIMD.

^2: Windows: Audio threads automatically engage MMCSS Pro Audio real-time scheduling (AvSetMmThreadCharacteristicsA) and 1 ms high-precision timer resolution (timeBeginPeriod(1)).


πŸ“¦ Supported Audio Formats

Format Extensions Decoding Backend
MPEG Audio .mp3, .mp2, .mp1 Native miniaudio (dr_mp3)
Waveform Audio .wav, .bwf, .rifx, .w64, .rf64 Native miniaudio (dr_wav)
FLAC .flac Native miniaudio (dr_flac)
Ogg Vorbis .ogg, .oga Native miniaudio (stb_vorbis)
Opus .opus Native Opus decoder (libopus)
Apple Lossless / AAC .m4a, .aac Native ALAC / Helix AAC
Audio Interchange .aif, .aiff, .aifc Native miniaudio

πŸ› οΈ Getting Started

Add miniaudio_player to your pubspec.yaml:

flutter pub add miniaudio_player

Or for pure Dart projects:

dart pub add miniaudio_player

πŸ’» Usage Examples

1. Basic Playback & Global Configuration

Basic Audio Playback Controls

import 'package:miniaudio_player/miniaudio_player.dart';

void main() async {
  // Optional: configure global defaults before instantiating players
  MiniaudioPlayer.config(
    defaultBufferSize: 0, // 0 = native device default
    logLevel: MiniaudioLogLevel.info,
  );

  final player = MiniaudioPlayer();

  // Open an audio file and start playback immediately
  await player.action.open('/path/to/song.flac', autoPlay: true);

  // Playback controls
  await player.action.pause();
  await player.action.play();
  await player.action.seek(const Duration(seconds: 45));
  await player.action.setVolume(0.85);

  // Clean up resources when finished (also safely garbage collected via NativeFinalizer)
  await player.dispose();
}

2. Complete DSP Chain (Limiter, Reverb, Crossfeed, Mono, Balance & Spatializer)

Complete DSP Chain - Limiter, Reverb, Crossfeed, Mono, Balance & Spatializer

// 1. Hardware Output Limiter (True-Peak soft-knee protection against digital clipping)
await player.action.setLimiter(true);

// 2. Studio-Grade Algorithmic Reverb (Freeverb with studio presets or custom acoustics)
await player.action.setReverb(Reverb.concertHall);
// Or customize dynamically:
await player.action.configureReverb(
  roomSize: 0.75,
  damping: 0.30,
  wet: 0.32,
  dry: 0.68,
  width: 1.0,
  enabled: true,
);

// 3. Binaural Crossfeed (Bauer bs2b: reduces headphone fatigue)
await player.action.setCrossfeed(CrossfeedMode.moffatBauer); // or CrossfeedMode.chuMoy

// 4. Mono Downmixing (for single speakers or accessibility)
await player.action.setMono(true);

// 5. Stereo Balance Panning (-1.0 full left, 0.0 center, +1.0 full right)
await player.action.setBalance(-0.25);

// 6. Stereo Spatializer (widens the acoustic stereo image)
await player.action.setSpatializer(enabled: true, width: 1.4);

// 7. Preamp Gain & ReplayGain Normalization with anti-clipping defense
await player.action.setPreamp(2.0); // +2.0 dB manual preamp
await player.action.setReplayGain(
  gainDb: -4.5,
  peak: 0.98,
  preampDb: 0.0,
  preventClipping: true,
);

3. Standard ISO 266 10-Band Parametric Equalizer

Shape frequency response in real time across the 10 ISO 266 standard octave bands (31Hz, 63Hz, 125Hz, 250Hz, 500Hz, 1kHz, 2kHz, 4kHz, 8kHz, 16kHz) from -24.0 dB to +24.0 dB:

Standard ISO 266 10-Band Parametric Equalizer

// Apply built-in acoustic presets
await player.action.setEqualizer(Equalizer.rock);
await player.action.setEqualizer(Equalizer.bassBoost);
await player.action.setEqualizer(Equalizer.jazz);
await player.action.setEqualizer(Equalizer.classical);
await player.action.setEqualizer(Equalizer.pop);
await player.action.setEqualizer(Equalizer.flat);

// Or create a custom equalizer configuration
final customEq = Equalizer(
  hz31: 4.5,   // Sub-bass boost (low-shelf)
  hz63: 3.0,   // Warmth
  hz125: 1.5,
  hz250: 0.0,
  hz500: -1.0,
  hz1k: -0.5,  // Tame mid-range harshness
  hz2k: 1.0,
  hz4k: 2.5,   // Presence
  hz8k: 3.5,   // Treble air
  hz16k: 4.0,  // High-shelf sparkle
);
await player.action.setEqualizer(customEq);

4. Real-Time Reactive Visualizer & Spectrum Analyzer

Build dynamic spectrum analyzers, frequency visualizers, and stereo VU meters. Subscribing to the stream automatically enables native C filtering, and unsubscribing keeps idle CPU strictly at 0%:

Real-Time Reactive Visualizer - 10-Band BPF Filter Bank & Stereo VU Meters

// 1. Listen to real-time visualizer data (~30 fps updates)
final subscription = player.stream.visualizer.listen((data) {
  // 10 frequency bands (0.0 to 1.0) matching the 10-band equalizer:
  print('Sub-bass (31Hz): ${data.hz31}');
  print('Midrange (1kHz): ${data.hz1k}');
  print('Treble (16kHz):  ${data.hz16k}');

  // Stereo channel amplitudes:
  print('VU Left: ${data.left}, VU Right: ${data.right}');

  // Global energy metrics:
  print('RMS: ${data.rms}, Peak: ${data.peak}');
});

// 2. Synchronous snapshot access:
final current = player.state.visualizer;
print('Current spectrum: ${current.bands}');

// 3. Stop observing: native DSP filtering stops automatically (0% idle CPU)
await subscription.cancel();

5. Native Silence Detection & Dynamic Skipping

Eliminate pauses and silent gaps in real time without audio glitches or pops, protected by a smooth 5ms anti-click crossfade:

Smart Silence Skipping Controls

// 1. Quick enable with standard defaults (-45 dB threshold, 300ms min silence, 50ms padding)
await player.action.setSkipSilence(true);

// 2. Podcast & Audiobook mode: skips in-between speech pauses
await player.action.setSilenceConfig(
  const SilenceSkipConfig.continuous(
    thresholdDb: -45.0,
    minSilenceDuration: Duration(milliseconds: 300),
    padding: Duration(milliseconds: 50),
  ),
);

// 3. Music Album mode: trims lead-in and lead-out silence only
await player.action.setSilenceConfig(
  const SilenceSkipConfig.trimEdges(thresholdDb: -50.0),
);

// 4. Combined mode: trims edges AND skips continuous pauses
await player.action.setSilenceConfig(const SilenceSkipConfig.all());

// 5. Track accumulated saved time synchronously or reactively:
print('Total time saved: ${player.state.silenceSavedDuration.inSeconds}s');

player.stream.silenceSavedDuration.listen((saved) {
  print('Saved time updated: ${saved.inMilliseconds} ms');
});

6. Unified Single-Pass Audio Analysis (Loudness & Waveform)

Analyze a track's acoustic properties, ITU-R BS.1770-4 / EBU R128 loudness, and visual waveform envelope in a single decoding pass on a background native OS worker thread (zero Dart Isolates, 0 ms UI blocking, preserving 60/120 fps):

Unified Audio Analysis - Waveform & ReplayGain

// 1. Non-blocking asynchronous analysis (native background OS thread)
final analysis = await MiniaudioPlayer.analyzeAudio(
  '/path/to/song.flac',
  replayGain: true,       // Loudness analysis
  waveform: true,         // Waveform envelope extraction
  waveformPoints: 100,    // Number of points to extract
  targetLufs: -18.0,      // Reference loudness (-18.0 ReplayGain, -14.0 streaming)
);

// 2. Fundamental audio metrics:
print('Duration: ${analysis.duration}');
print('Sample Rate: ${analysis.sampleRate} Hz');
print('Channels: ${analysis.channels}');
print('Bitrate: ${analysis.bitrate ~/ 1000} kbps');
print('True Peak: ${analysis.peak}');

// 3. ReplayGain & Volume Normalization:
if (analysis.replayGain != null) {
  final rg = analysis.replayGain!;
  print('Integrated Loudness: ${rg.lufs} LUFS');
  print('Recommended Gain: ${rg.gainDb} dB');

  // Convert to linear volume with built-in anti-clipping defense:
  final linearVolume = rg.getRecommendedVolume(preventClipping: true);
  await player.action.setVolume(linearVolume);
}

// 4. Waveform seekbar rendering:
if (analysis.waveform != null) {
  final wf = analysis.waveform!;
  print('Waveform points (${wf.length}): ${wf.points}');

  // Sample height at 50% progress or at current playback position:
  final midHeight = wf.getPointAtProgress(0.5); // 0.0 to 1.0
  final currentHeight = wf.getPointAtPosition(player.state.position, analysis.duration);
}

Note: For CLI tools or batch preprocessing scripts, use the synchronous variant: MiniaudioPlayer.analyzeAudioSync(...).


7. Audio Output Device Selection & Dynamic Routing

Enumerate and switch hardware audio devices dynamically at runtime across Android, Windows, Linux, macOS, and iOS with zero configuration and no MethodChannels:

Hardware Audio Output Device & Buffer Size Selection

// 1. Enumerate available audio playback devices
final devices = await MiniaudioPlayer.getAudioDevices();

for (final device in devices) {
  // Use device.displayName directly in UI selectors (DropdownButton, ListTile)
  print('Device: ${device.displayName} (ID: ${device.id})');
}

// 2. Switch playback to a specific hardware output
await player.action.setDevice(devices[1]);

// 3. Return to automatic system default routing
await player.action.setDevice(AudioDevice.auto);

// 4. Listen to native device hotplug and route changes:
MiniaudioPlayer.getAudioDevicesStream().listen((updatedDevices) {
  print('Device list updated: ${updatedDevices.length} devices found');
});

Flutter UI Dropdown Binding with Localized Labels

// Optional: configure localized display name resolver globally
MiniaudioPlayer.config(
  defaultDeviceDisplayNameResolver: (resolvedName) =>
      resolvedName.isEmpty ? 'Predeterminado' : 'Predeterminado ($resolvedName)',
);

// Bind directly to Flutter DropdownButton:
DropdownButton<AudioDevice>(
  value: player.state.audioDevice,
  items: devices.map((device) {
    return DropdownMenuItem(
      value: device,
      child: Text(device.displayName),
    );
  }).toList(),
  onChanged: (newDev) {
    if (newDev != null) player.action.setDevice(newDev);
  },
)

8. Reactive Streams & Synchronous State

miniaudio_player offers both real-time broadcast streams and synchronous getters for effortless UI binding:

// Synchronous snapshot access:
print('Is Playing: ${player.state.playing}');
print('Current Position: ${player.state.position}');
print('Track Duration: ${player.state.duration}');
print('Bitrate: ${player.state.audioBitrate} kbps');
print('Active Device: ${player.state.audioDevice.displayName}');
print('Limiter Enabled: ${player.state.limiterEnabled}');
print('Reverb: ${player.state.reverb}');

// Reactive broadcast streams:
player.stream.position.listen((pos) => print('Position: $pos'));
player.stream.playing.listen((playing) => print('Playing: $playing'));
player.stream.completed.listen((done) => print('Playback finished!'));
player.stream.equalizer.listen((eq) => print('Equalizer updated: $eq'));
player.stream.reverb.listen((reverb) => print('Reverb updated: $reverb'));
player.stream.audioDevice.listen((dev) => print('Device switched: ${dev.displayName}'));

Using with Flutter StreamBuilder:

StreamBuilder<Duration>(
  stream: player.stream.position,
  builder: (context, snapshot) {
    final position = snapshot.data ?? Duration.zero;
    final total = player.state.duration;
    return Text('${position.inMinutes}:${(position.inSeconds % 60).toString().padLeft(2, '0')} / '
                '${total.inMinutes}:${(total.inSeconds % 60).toString().padLeft(2, '0')}');
  },
)

9. High-Fidelity Speed & Pitch Control (Sonic DSP)

Playback Adjustments - Volume, Rate & Pitch Control

// Playback rate: 0.25x (slow) to 4.0x (fast) without changing pitch
await player.action.setRate(1.5);

// Pitch scaling: 0.5x to 2.0x without changing playback speed
await player.action.setPitch(1.2);

10. Optional: Running Inside a Background Isolate

Because miniaudio_player uses 100% pure Dart FFI without platform channel restrictions, it can be instantiated inside a standalone background Dart Isolate or headless background service (audio_service, flutter_background_service, Isolate.spawn):

import 'dart:isolate';
import 'package:miniaudio_player/miniaudio_player.dart';

void audioWorkerIsolate(SendPort sendPort) async {
  final commandPort = ReceivePort();
  sendPort.send(commandPort.sendPort);

  final player = MiniaudioPlayer();

  player.stream.position.listen((pos) {
    sendPort.send({'event': 'position', 'value': pos.inMilliseconds});
  });

  player.stream.completed.listen((done) {
    if (done) sendPort.send({'event': 'completed'});
  });

  await for (final message in commandPort) {
    if (message is Map) {
      switch (message['command']) {
        case 'open':
          await player.action.open(message['path'] as String, autoPlay: true);
          break;
        case 'pause':
          await player.action.pause();
          break;
        case 'resume':
          await player.action.play();
          break;
        case 'stop':
          await player.action.stop();
          break;
        case 'dispose':
          await player.dispose();
          commandPort.close();
          return;
      }
    }
  }
}

🀝 Contributing

Contributions, bug reports, and feature requests are very welcome!
Feel free to open an issue or submit a pull request on GitHub.


πŸ“„ License & Third-Party Acknowledgements

This project is licensed under the MIT License - see the LICENSE file for complete details.

Third-Party Native Libraries & Decoders

miniaudio_player bundles and links specialized native C libraries to provide out-of-the-box decoding and DSP without external system dependencies. Each component remains governed by its respective author's license:

Component Author / Organization License Source Location Description
miniaudio David Reid Choice of Public Domain or MIT-0 src/miniaudio.h Audio engine, OS device routing, mixing, and built-in decoders (dr_mp3, dr_wav, dr_flac).
Sonic DSP Bill Cox Apache License 2.0 src/sonic/ Real-time high-fidelity time stretching and pitch scaling.
minimp4 lieff, aspt CC0 1.0 Universal (Public Domain) src/decoders/minimp4/ Lightweight MP4 / M4A ISO container demuxer.
ALAC Decoder David Hammerton MIT License src/decoders/alac/ Apple Lossless Audio Codec (ALAC) frame decoder.
stb_vorbis Sean Barrett Public Domain / MIT src/decoders/stb_vorbis.c Ogg Vorbis audio decoding backend.
libogg Xiph.Org Foundation BSD 3-Clause src/decoders/libogg/ Ogg container bitstream and framing parsing.
libopus (Opus & SILK) Xiph.Org Foundation, Skype Limited, Arm Limited BSD 3-Clause src/decoders/libopus/ High-definition Opus audio decoding pipeline.
Helix AAC Decoder RealNetworks, Inc. RealNetworks Public Source License (RPSL v1.0) src/decoders/helix-aac/ Fixed-point HE-AAC audio decoder.
Freeverb Jezar at Dreampoint Public Domain src/map_reverb.c Studio-grade algorithmic stereo reverberation model.

βš–οΈ Permissive Licensing & Commercial Use

  • Unrestricted Commercial & Proprietary Usage: Because miniaudio_player is distributed under the permissive MIT License, you are completely free to integrate, bundle, and distribute it in commercial, closed-source, proprietary, or open-source Flutter applications without copyleft restrictions.
  • Third-Party Attribution: All bundled third-party libraries retain their original author notices, copyrights, and permissive licenses (MIT, MIT-0, Apache 2.0, BSD-3-Clause, CC0, and RPSL).

Libraries

miniaudio_player
Ultra-low-resource cross-platform audio player using miniaudio and Sonic DSP via Dart Native Assets.
miniaudio_player_bindings_generated