
The live studio: audio-reactive Three.js visuals center stage, the Visual Bank and VJ presets on the left, and the synchronized Lyria RealTime decks (Main / Sequence / Vocalize) with the genre grid on the right — over a 16-step Lyria beat with SFX and loop lanes, MIDI + MX Console control, and one-click capture. The first run opens with the Cognitum One sign-in gate — sign in and Lyria audio just works, no bring-your-own key.
Musica VJ is a free desktop app for musicians, producers, and DJs. Hit play and it generates a live, evolving beat in real time, then lights up the screen with visuals that react to the music automatically — no timeline to program, no separate VJ software, no second laptop. Point a MIDI controller, your keyboard, or a Logitech MX Creative Console at it and perform the whole set — music and visuals — like one instrument.
Under the hood it's also an agent-directed music workstation, a governed creative-AI provider shell, and a Rust DSP research engine — but you don't need to know any of that to use it.
👉 See it in action, screenshots, and download links →
| 🎧 Get the app | Download for macOS, Windows, or Linux — free, no account required to start |
| 🖥️ See it first | Live site with screenshots + a 60-second tour |
| 📖 Go deeper | apps/musica-vj/README.md — full controls, MIDI mapping, and provider setup |
The flagship app is apps/musica-vj: a Tauri 2 desktop studio with synchronized Lyria RealTime arrangement and beat streams, a guarded vocalization lane, editable rhythm guidance, AI-directed performance templates, one-click Demo automation, Meta-LLM set planning, governed Gemini/Lyria song and loop generation, audio-reactive Three.js visuals, temporal VJ controls, Logitech MX Creative Console integration, browser MIDI, and release workflows for macOS, Linux, and Windows.
The table below is the detailed technical status, mainly useful for contributors. For a plain-language tour, see the website.
| Layer | What Musica does now |
|---|---|
| Agentic direction | Local planners work by default; an optional Cognitum One sign-in (OAuth 2.1 + PKCE) unlocks AI set-arc planning (30-90 min timelines across styles, scenes, decks, and FX), Auto DJ phrase briefs with memory walking a musical adjacency graph, mood-to-FX and mood-to-look direction, AI style packs, AI vocal guidance, and AI-generated parametric plugin scenes (ADR-175/176/177). Used directions are learned locally in IndexedDB. |
| Music performance | Lyria RealTime is the live output: main, beat, and vocal decks with bar-synced connection, per-stream volume/pitch/nudge, 20 detailed style presets plus user custom styles, a seven-effect master FX rack (flanger/phaser/drive/crush/sweep/reverb/echo with per-effect editors, locks, and generators), a two-stage mastering chain, synthesized SFX pads, and bar-synced loop pads. |
| Visual performance | Nine scenes including the Winamp-style Retro Scope, AI plugin scenes, MilkDrop-style frame feedback with a dedicated echo floor, bloom controls, per-scene rendering characters, spectral-flux onset reactivity, five VJ presets, shuffle-look randomizer, and temporal controls for speed, strobe, trail, morph, camera, and phase. |
| Live control | Keyboard, Shift+1 through Shift+4 multi-track deck scenes, magnetically snapping customizable DJ windows, F13-F24 shortcuts, Logitech/Loupedeck Actions SDK bridge, and browser MIDI mapping for pads, scenes, templates, color looks, macros, and temporal controls. |
| AI providers | Rust-only governed boundaries for Gemini/Lyria music generation and Cognitum Meta-LLM planning; tokens stay out of React bundles and are checked by CI secret canaries. |
| Musica core | STFT/ISTFT, graph mincut separation, sparse Lanczos, six-stem separation, streaming separation, HearMusica compressor/limiter/mixer/filter blocks, WAV I/O, visualization helpers, and transcription hooks. |
| Release path | GitHub Actions build frontend plus unsigned macOS .app/.dmg, Linux .deb/AppImage, Windows NSIS artifacts, then gate release publishing behind the ci-guard job. |
The v0.3.0 release ships the AI performance layer end to end. Everything degrades gracefully: with no account, every feature falls back to deterministic local planners, keyword mappings, and the operator's remembered history.
| Capability | Where | Backed by |
|---|---|---|
| Set-arc autopilot | COGNITUM AI panel | cognitum_set_arc + local energy-curve planner |
| Auto DJ phrase briefs with memory | Auto DJ | cognitum_autodj_brief + musical adjacency graph |
| Mood-to-FX automation (lock-aware) | STREAM FX · AI MOOD | cognitum_fx_direction + curated local shapes |
| AI visual direction | VJ PRESETS · AI LOOK | cognitum_visual_direction + keyword looks |
| AI plugin scenes (pure data, never code) | VJ PRESETS · AI SCENE | cognitum_visual_plugin (ADR-177 tier 1) |
| AI style packs | COGNITUM AI panel | cognitum_style_pack → editable custom styles |
| AI vocal guidance | VOCALIZE dialog | cognitum_vocal_guidance + style-family templates |
| Performance memory (LEARNING) | automatic | IndexedDB similarity recall (ADR-176) |
The browser version should use Web Audio and Three.js for the performance UI, then load Musica core through WASM for heavier analysis and structure-aware DSP. The repo already has a feature-gated src/wasm_bridge.rs FFI surface for the graph separation pipeline:
rustup target add wasm32-unknown-unknown
cargo build --target wasm32-unknown-unknown --features wasm --release
The intended split is pragmatic:
| Runtime | Responsibility |
|---|---|
| Browser TypeScript | UI, transport, Web Audio scheduling, Tone.js MIDI parsing, WEBMIDI.js controller input, file import, visual rendering, local fallback analysis |
| Musica WASM | STFT, graph masks, stem confidence, separation witnesses, structural section features, and low-latency DSP primitives |
| Tauri Rust | Provider credentials, paid generation, private asset storage, controller socket, native dialogs, packaged export validation |
That keeps the web app usable without a server while preserving the stronger native security boundary for API tokens and paid generation.
cd apps/musica-vj
npm ci
npm run dev
# Native desktop shell with provider commands, global shortcuts, and packaged-app behavior
npm run tauri dev
Optional AI providers are configured only through the Tauri process environment. Do not commit API tokens, .env files, generated provider responses, or shell snippets containing secrets.
MUSICA_META_LLM_ENABLED=true \
MUSICA_META_LLM_API_BASE=https://api.cognitum.one \
MUSICA_META_LLM_API_TOKEN=replace_with_token \
MUSICA_META_LLM_MODEL=meta-llm \
npm run tauri dev
Google Lyria/Gemini generation can use either a Rust-only GEMINI_API_KEY or local GCP CLI application-default credentials with MUSICA_GCP_AUTH=gcloud.
See apps/musica-vj/README.md for the complete studio documentation, controller mappings, MIDI notes, import behavior, provider setup, screenshots, release artifacts, and verification commands.
Under the live studio is the original Rust audio engine: structure-first audio source separation via graph Laplacian spectral clustering and dynamic mincut refinement. It remains useful as a standalone library for low-latency audio analysis, separation, embedded processing, and research.
| Metric | Value |
|---|---|
| Core separation latency | 0.20 ms avg / 0.26 ms max in the benchmark suite |
| Model size | 0 bytes for the graph DSP path |
| Core dependency count | 1 required dependency: ruvector-mincut |
| Workspace tests | Rust workspace plus VJ frontend/provider/controller tests |
| License | MIT OR Apache-2.0 |
Traditional audio separation is frequency-first: FFT masking, ICA, NMF, neural networks. These approaches separate by learned spectral patterns.
Musica is structure-first: reframe audio as a graph partitioning problem, then find where signals naturally divide.
Nodes = time-frequency atoms (STFT bins, critical bands)
Edges = similarity (spectral proximity, phase coherence, harmonic alignment, temporal continuity)
Weights = how strongly two elements "belong together"
Dynamic mincut finds the minimum-cost boundary where signals separate, preserving maximum internal coherence within each source. The Fiedler vector (2nd smallest eigenvector of the graph Laplacian) provides the geometric partition that approximates the normalized cut.
| System | Latency | Type | Model Size |
|---|---|---|---|
| Musica | 0.20 ms | Graph-based (Rust) | 0 bytes |
| Widex ZeroDelay | 0.48 ms | Commercial hearing aid | Proprietary chip |
| DNN for CI (2025) | 1.0 ms | Research neural | Unknown |
| RT-STT (2025) | 1.01 ms | Neural (GPU) | 383K params |
| TinyLSTM (Bose) | 2.39 ms | Compressed LSTM | ~2 MB |
| RNNoise (Mozilla) | 10 ms | Hybrid DSP+GRU | 85 KB |
| System | Size | Hardware | Dependencies |
|---|---|---|---|
| Musica | 0 bytes model | Any CPU / WASM / MCU | None |
| RNNoise | 85 KB | Any CPU | Minimal C |
| RT-STT | ~1.5 MB | GPU required | PyTorch |
| Phonak DEEPSONIC | Proprietary | Custom AI chip (7,700 MOPS) | Proprietary |
| System | Vocals SDR | Approach |
|---|---|---|
| BS-RoFormer | ~10.5 dB | Transformer (trained on hundreds of hours) |
| HTDemucs | ~9.0 dB | Hybrid transformer |
| Open-Unmix | ~6.3 dB | LSTM baseline |
| Musica | 1-5 dB | Unsupervised graph partitioning |
Musica is 5-8 dB behind neural SOTA on raw SDR. That gap is expected — learned models have seen thousands of labeled songs. Musica's advantages are latency, size, interpretability, and edge deployability.
Raw Audio
|
v
STFT / Filterbank ──────── Zero-dep radix-2 Cooley-Tukey FFT + Hann window
|
v
Graph Construction ──────── Spectral + temporal + harmonic + phase edges
|
v
Laplacian Eigenvectors ──── Fiedler vector via Lanczos / power iteration
| SIMD-friendly (chunk-of-4 auto-vectorization)
v
Spectral Clustering ─────── Balanced initial partition (normalized cut)
|
v
MinCut Refinement ───────── Boundary optimization via ruvector-mincut
|
v
Soft Mask Generation ────── Distance-weighted softmax, Wiener normalization
|
v
Overlap-Add Reconstruction
| Module | Lines | Tests | Purpose |
|---|---|---|---|
stft.rs | 260 | 2 | Zero-dep radix-2 FFT, STFT/ISTFT with Hann window |
lanczos.rs | 729 | 6 | Sparse Lanczos eigensolver, CSR format, SIMD-optimized |
audio_graph.rs | 268 | 0 | Graph construction from STFT (spectral/temporal/harmonic/phase edges) |
separator.rs | 632 | 4 | Fiedler vector spectral clustering + mincut refinement |
hearing_aid.rs | 803 | 5 | Binaural streaming speech enhancer, <8ms latency |
multitrack.rs | 801 | 5 | 6-stem music separator (vocals/bass/drums/guitar/piano/other) |
crowd.rs | 819 | 5 | Distributed speaker identity tracking (thousands of speakers) |
wav.rs | 342 | 2 | 16/24-bit PCM WAV reader/writer |
benchmark.rs | 379 | 5 | SDR/SIR/SAR evaluation (BSS_EVAL style) |
hearmusica/ | ~1,200 | — | Hearing aid DSP pipeline (Tympan-compatible processing blocks) |
# Build
cargo build --release
# Run full 6-part benchmark suite
cargo run --release
# Run tests (34 tests)
cargo test
apps/musica-vj is a Mac-first Tauri 2 performance instrument built on Musica. It combines synchronized Lyria RealTime decks, an editable beat-guidance grid, one-click Demo automation, audio-reactive Three.js scenes, official Logitech MX Creative Console controls, prompt-driven performance mutation, governed creative-music providers, and capability-probed vertical social capture that prefers H.264 and AAC.
cd apps/musica-vj
npm ci
npm run dev
# Launch the native Tauri application on macOS
npm run tauri dev
The official Logi Actions SDK companion maps the Keypad LCD buttons, Dialpad, and roller into Musica controls. An Options+ F13-F24 profile works as an installation-free fallback. Creative provider credentials remain in the Rust process. Google Lyria 3 Pro Preview is optional and disabled by default, while the Suno partner adapter stays disabled until documented official access is configured.
Reproducible vertical preview fixtures are checked in for quick review:
See Musica VJ documentation, the Lyria integration specification, and ADRs 160-169 for architecture, security, controller setup, performance budgets, export rules, paid generation, provenance, and release gates.
use musica::{stft, audio_graph, separator};
let stft_result = stft::stft(&signal, 256, 128, 8000.0);
let graph = audio_graph::build_audio_graph(&stft_result, &audio_graph::GraphParams::default());
let config = separator::SeparatorConfig {
num_sources: 2,
..separator::SeparatorConfig::default()
};
let result = separator::separate(&graph, &config);
// result.masks[i] — soft mask per source
// result.cut_value — mincut witness (separation confidence)
use musica::hearing_aid::{HearingAidConfig, StreamingState, Audiogram};
let config = HearingAidConfig {
audiogram: Audiogram {
frequencies: vec![250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0],
gains_db: vec![10.0, 15.0, 20.0, 30.0, 40.0, 50.0], // mild sloping loss
},
..HearingAidConfig::default()
};
let mut state = StreamingState::new(&config);
// Per-frame streaming (call every 4ms hop)
let result = state.process_frame(&left_mic, &right_mic, &config);
// result.mask — per-band speech/noise mask
// result.speech_score — overall speech probability
// result.latency_us — processing time for this frame
Pipeline per frame:
use musica::multitrack::{separate_multitrack, MultitrackConfig, Stem};
let config = MultitrackConfig {
window_size: 4096,
hop_size: 1024,
sample_rate: 44100.0,
..MultitrackConfig::default()
};
let result = separate_multitrack(&audio_signal, &config);
for stem in &result.stems {
println!("{:?}: confidence={:.3}", stem.stem, stem.confidence);
// stem.signal — reconstructed time-domain audio for this stem
// stem.mask — T-F soft mask
}
// result.replay_log — every mincut decision for reproducibility
Default frequency priors:
| Stem | Low Hz | High Hz | Key Features |
|---|---|---|---|
| Vocals | 80 | 8,000 | High harmonicity, moderate transient |
| Bass | 20 | 300 | Low freq, high harmonicity |
| Drums | 30 | 15,000 | High transient, low harmonicity |
| Guitar | 80 | 6,000 | Moderate harmonicity |
| Piano | 27 | 4,200 | High harmonicity |
| Other | 20 | 20,000 | Catch-all remainder |
use musica::crowd::{CrowdTracker, CrowdConfig, SpeechEvent};
let config = CrowdConfig {
max_identities: 500,
association_threshold: 0.4,
..CrowdConfig::default()
};
let mut tracker = CrowdTracker::new(config);
// Register sensors
tracker.add_sensor((0.0, 0.0));
tracker.add_sensor((10.0, 0.0));
// Ingest events from sensor 0
tracker.ingest_events(0, vec![SpeechEvent {
time: 0.0, freq_centroid: 200.0, energy: 0.5,
voicing: 0.8, harmonicity: 0.7, direction: 0.0, sensor_id: 0,
}]);
// Update pipeline
tracker.update_local_graphs(); // Layer 2: local Fiedler clustering
tracker.associate_cross_sensor(0.5); // Layer 3: cross-node embedding match
tracker.update_global_identities(0.5); // Layer 4: global identity memory
let stats = tracker.get_stats();
4-layer hierarchy:
use musica::lanczos::{SparseMatrix, LanczosConfig, lanczos_eigenpairs, batch_lanczos};
// Build graph Laplacian from weighted edges
let laplacian = SparseMatrix::from_edges(20, &edges); // L = D - W
// Compute smallest k eigenpairs
let config = LanczosConfig { k: 4, max_iter: 50, tol: 1e-8, reorthogonalize: true };
let result = lanczos_eigenpairs(&laplacian, &config);
// result.eigenvalues — sorted ascending
// result.eigenvectors — Fiedler vector is eigenvectors[0] (smallest non-trivial)
// Batch mode with cross-frame alignment (Procrustes sign consistency)
let results = batch_lanczos(&laplacians, &config);
use musica::wav;
// Read
let data = wav::read_wav("input.wav")?;
// data.channel_data[0] — first channel as Vec<f64>
// data.sample_rate, data.channels, data.bits_per_sample
// Write
wav::write_wav("output.wav", &samples, 16000, 1)?;
// Generate binaural test signal with ITD model
wav::generate_binaural_test_wav("test.wav", 16000, 0.5, 300.0, &[800.0], 30.0)?;
Run cargo run --release for the full 6-part suite:
Three test scenarios at 8 kHz, 256-sample window:
| Scenario | Nodes | Edges | SDR (source 0) | SDR (source 1) |
|---|---|---|---|---|
| Well-separated (200 Hz + 2000 Hz) | 834 | 3,765 | +0.2 dB | -3.0 dB |
| Close tones (400 Hz + 600 Hz) | 1,786 | 8,480 | -0.1 dB | -0.1 dB |
| Harmonic 3rd (300 Hz + 900 Hz) | 1,882 | 8,738 | +1.5 dB | -2.9 dB |
| Metric | Result |
|---|---|
| Frames processed | 100 |
| Avg latency | 0.20 ms |
| Max latency | 0.26 ms |
| Latency budget | PASS (target <8ms) |
| Stem | Confidence | Energy |
|---|---|---|
| Vocals | 0.168 | 0.023 |
| Bass | 0.120 | 0.137 |
| Drums | 0.205 | 0.023 |
| Guitar | 0.158 | 0.022 |
| Piano | 0.154 | 0.060 |
| Other | 0.195 | 0.015 |
Graph: 24,230 nodes, 55,541 edges. Mask sum error: 0.0000.
20-node graph, 2 clusters with weak bridge:
20 sensors, 1,500 events, 50 simulated speakers:
16-bit PCM roundtrip: max error = 0.000046. PASS.
The graph Laplacian L = D - W encodes structure. Its second-smallest eigenvector (the Fiedler vector) provides the continuous relaxation of the normalized cut — nodes with the same sign in the Fiedler vector belong to the same cluster.
Given weighted adjacency W and degree matrix D:
L = D - W
Solve Lv = λv for smallest eigenvalues
Fiedler vector = eigenvector for λ₂ (smallest non-zero eigenvalue)
Partition: {nodes where v[i] > 0} vs {nodes where v[i] ≤ 0}
All vector operations (dot, norm, axpy, scale) process in chunks of 4 f64 values for auto-vectorization. Selective reorthogonalization prevents ghost eigenvalues. Tridiagonal QR with Wilkinson shift extracts eigenpairs.
After spectral clustering provides balanced initial partitions, ruvector-mincut refines boundaries by finding the exact minimum cut. The cut value serves as a structural witness — a provable certificate of separation quality.
The hearing aid module uses 32 Equivalent Rectangular Bandwidth (ERB) spaced bands, matching the human cochlea's frequency resolution:
ERB(f) = 24.7 * (4.37 * f/1000 + 1)
The only sub-1ms, zero-dependency, fully explainable speech enhancer. Runs on a $2 microcontroller. No custom silicon required. An audiologist can inspect why any decision was made — which binaural features drove the speech/noise classification, what the graph partition looks like, what the mincut witness value means.
Regulatory advantage: FDA/CE medical device approval increasingly requires explainability. Black-box DNNs face scrutiny. Full auditability is a structural advantage for certification.
Compiles to WASM via wasm-pack with zero changes. Real-time separation in any browser AudioWorklet — no server round-trip. Applications: live transcription, teleconferencing, accessibility tools.
Use Musica's Fiedler partition as a preprocessing stage for lightweight neural models. The graph provides structural priors, reducing what the neural model needs to learn. Potential to reach 8+ dB SDR at <2ms latency by combining graph structure with a small learned refinement network.
CI users need even lower latency than hearing aid users. At 0.20ms, Musica leaves headroom for additional processing stages (vocoder, electrode mapping) within tight latency budgets.
Crowd-scale tracking enables: smart buildings with per-room speaker awareness, transit hub safety monitoring, stadium crowd analytics, search and rescue with distributed microphone arrays.
wasm-pack build + browser demo with Web Audio APIdocs/examples/musica/
├── Cargo.toml
├── README.md
└── src/
├── lib.rs # Module declarations
├── main.rs # 6-part benchmark suite
├── stft.rs # FFT + STFT/ISTFT
├── lanczos.rs # Sparse eigensolver (CSR, SIMD)
├── audio_graph.rs # Graph construction from STFT
├── separator.rs # Spectral clustering + mincut
├── hearing_aid.rs # Binaural streaming enhancer
├── multitrack.rs # 6-stem music separator
├── crowd.rs # Distributed speaker tracking
├── wav.rs # WAV file I/O
├── benchmark.rs # SDR/SIR/SAR evaluation
└── hearmusica/ # Hearing aid DSP pipeline
├── mod.rs # Pipeline orchestrator + AudioBlock
├── block.rs # ProcessingBlock trait
├── filter.rs # BiquadFilter (8 filter types)
├── compressor.rs # WDRCompressor (multi-band WDRC)
├── feedback.rs # FeedbackCanceller (NLMS adaptive)
├── gain.rs # GainProcessor (NAL-R prescription)
├── separator_block.rs # GraphSeparator (Fiedler + mincut)
├── delay.rs # DelayLine (circular buffer)
├── limiter.rs # Limiter (brick-wall protection)
├── mixer.rs # Mixer (weighted combination)
└── presets.rs # 4 preset pipelines
Single dependency:
[dependencies]
ruvector-mincut = { path = "../../../crates/ruvector-mincut", features = ["monitoring", "approximate", "exact"] }
Everything else — FFT, filterbank, eigensolver, WAV I/O, metrics — is implemented from scratch with zero external crates.
High-fidelity Rust port of Tympan's MIT-licensed hearing aid DSP, integrated with musica's graph-based separation. HEARmusica provides a modular pipeline of processing blocks that can be composed into complete hearing aid signal chains, from microphone input to speaker output. Each block implements the ProcessingBlock trait for uniform pipeline orchestration.
| Block | Tympan Equivalent | Key Feature |
|---|---|---|
| BiquadFilter | AudioFilterBiquad_F32 | 8 filter types (LP/HP/BP/notch/allpass/peaking/shelves) |
| WDRCompressor | AudioEffectCompressor_F32 | Multi-band WDRC with soft knee |
| FeedbackCanceller | AudioEffectFeedbackCancel_F32 | NLMS adaptive filter |
| GainProcessor | AudioEffectGain_F32 | Audiogram fitting + NAL-R prescription |
| GraphSeparator | (novel) | Fiedler vector + dynamic mincut |
| DelayLine | AudioEffectDelay_F32 | Sample-accurate circular buffer |
| Limiter | (custom) | Brick-wall output protection |
| Mixer | AudioMixer_F32 | Weighted signal combination |
Input -> BiquadFilter -> FeedbackCanceller -> GraphSeparator -> WDRCompressor -> GainProcessor -> Limiter -> Output
The pipeline processes stereo AudioBlock frames. Each block reads from and writes to the block's left and right sample buffers in place, minimizing allocations. The GraphSeparator block bridges musica's spectral clustering into the hearing aid chain, providing structure-aware noise reduction that traditional DSP pipelines lack.
Four preset configurations cover common hearing aid use cases:
| Preset | Description | Key Blocks |
|---|---|---|
standard_hearing_aid | General-purpose amplification with feedback cancellation | BiquadFilter, FeedbackCanceller, WDRCompressor, GainProcessor, Limiter |
speech_in_noise | Optimized for noisy environments with graph-based separation | BiquadFilter, FeedbackCanceller, GraphSeparator, WDRCompressor, GainProcessor, Limiter |
music_mode | Wide bandwidth, gentle compression for music listening | BiquadFilter, WDRCompressor (low ratio), GainProcessor, Limiter |
maximum_clarity | Aggressive noise reduction for severe hearing loss | BiquadFilter, FeedbackCanceller, GraphSeparator, WDRCompressor (high ratio), GainProcessor, Limiter |
All presets accept an Audiogram, sample rate, and block size, and return a fully configured Pipeline.
use musica::hearmusica::{self, Pipeline, AudioBlock};
use musica::hearing_aid::Audiogram;
let audiogram = Audiogram::default(); // mild sloping loss
let mut pipeline = hearmusica::presets::speech_in_noise(&audiogram, 16000.0, 128);
pipeline.prepare();
let mut block = AudioBlock::new(128, 16000.0);
// Fill block.left and block.right with mic samples...
pipeline.process_block(&mut block);
// block now contains enhanced audio
| Feature | Tympan (C++) | HEARmusica (Rust) |
|---|---|---|
| Latency | 2.9-5.7 ms | < 1 ms target |
| Platform | Teensy only | Any (MCU/WASM/desktop) |
| Separation | None | Graph-based (Fiedler + mincut) |
| Memory safety | Manual | Compile-time |
| License | MIT | MIT |
| Audiogram fitting | Basic | NAL-R prescription |
HEARmusica's primary advantage is the GraphSeparator block, which has no equivalent in Tympan or any other open-source hearing aid framework. By embedding musica's spectral clustering directly into the DSP pipeline, noise reduction becomes structure-aware rather than purely energy-based.
4 preset pipelines benchmarked at 16 kHz, 128-sample blocks, 200 blocks each:
| Preset | Avg Block | Max Block | Pipeline Latency | Chain |
|---|---|---|---|---|
| Standard HA | 0.011 ms | 0.047 ms | 0.00 ms | Filter→WDRC→Gain→Limiter |
| Speech-in-Noise | 0.539 ms | 0.705 ms | 4.00 ms | Filter→FeedbackCancel→GraphSep→WDRC→Gain→Limiter |
| Music Mode | 0.010 ms | 0.015 ms | 0.00 ms | WDRC→Gain→Limiter |
| Max Clarity | 0.664 ms | 0.751 ms | 6.00 ms | Filter→FeedbackCancel→GraphSep→Delay→WDRC→Gain→Mixer→Limiter |
Key findings:
Frame-by-frame multitrack separation at 44.1 kHz:
| Metric | Value |
|---|---|
| Avg frame latency | 0.35 ms |
| Max frame latency | 0.68 ms |
| All 6 stems | Non-zero energy |
See ADR-143 for the full architecture decision record.
37 commits
Rust
46.6%
TypeScript
40.3%
CSS
5.5%
JavaScript
3.7%
C#
1.7%
HTML
1.2%

The live studio: audio-reactive Three.js visuals center stage, the Visual Bank and VJ presets on the left, and the synchronized Lyria RealTime decks (Main / Sequence / Vocalize) with the genre grid on the right — over a 16-step Lyria beat with SFX and loop lanes, MIDI + MX Console control, and one-click capture. The first run opens with the Cognitum One sign-in gate — sign in and Lyria audio just works, no bring-your-own key.
Musica VJ is a free desktop app for musicians, producers, and DJs. Hit play and it generates a live, evolving beat in real time, then lights up the screen with visuals that react to the music automatically — no timeline to program, no separate VJ software, no second laptop. Point a MIDI controller, your keyboard, or a Logitech MX Creative Console at it and perform the whole set — music and visuals — like one instrument.
Under the hood it's also an agent-directed music workstation, a governed creative-AI provider shell, and a Rust DSP research engine — but you don't need to know any of that to use it.
👉 See it in action, screenshots, and download links →
| 🎧 Get the app | Download for macOS, Windows, or Linux — free, no account required to start |
| 🖥️ See it first | Live site with screenshots + a 60-second tour |
| 📖 Go deeper | apps/musica-vj/README.md — full controls, MIDI mapping, and provider setup |
The flagship app is apps/musica-vj: a Tauri 2 desktop studio with synchronized Lyria RealTime arrangement and beat streams, a guarded vocalization lane, editable rhythm guidance, AI-directed performance templates, one-click Demo automation, Meta-LLM set planning, governed Gemini/Lyria song and loop generation, audio-reactive Three.js visuals, temporal VJ controls, Logitech MX Creative Console integration, browser MIDI, and release workflows for macOS, Linux, and Windows.
The table below is the detailed technical status, mainly useful for contributors. For a plain-language tour, see the website.
| Layer | What Musica does now |
|---|---|
| Agentic direction | Local planners work by default; an optional Cognitum One sign-in (OAuth 2.1 + PKCE) unlocks AI set-arc planning (30-90 min timelines across styles, scenes, decks, and FX), Auto DJ phrase briefs with memory walking a musical adjacency graph, mood-to-FX and mood-to-look direction, AI style packs, AI vocal guidance, and AI-generated parametric plugin scenes (ADR-175/176/177). Used directions are learned locally in IndexedDB. |
| Music performance | Lyria RealTime is the live output: main, beat, and vocal decks with bar-synced connection, per-stream volume/pitch/nudge, 20 detailed style presets plus user custom styles, a seven-effect master FX rack (flanger/phaser/drive/crush/sweep/reverb/echo with per-effect editors, locks, and generators), a two-stage mastering chain, synthesized SFX pads, and bar-synced loop pads. |
| Visual performance | Nine scenes including the Winamp-style Retro Scope, AI plugin scenes, MilkDrop-style frame feedback with a dedicated echo floor, bloom controls, per-scene rendering characters, spectral-flux onset reactivity, five VJ presets, shuffle-look randomizer, and temporal controls for speed, strobe, trail, morph, camera, and phase. |
| Live control | Keyboard, Shift+1 through Shift+4 multi-track deck scenes, magnetically snapping customizable DJ windows, F13-F24 shortcuts, Logitech/Loupedeck Actions SDK bridge, and browser MIDI mapping for pads, scenes, templates, color looks, macros, and temporal controls. |
| AI providers | Rust-only governed boundaries for Gemini/Lyria music generation and Cognitum Meta-LLM planning; tokens stay out of React bundles and are checked by CI secret canaries. |
| Musica core | STFT/ISTFT, graph mincut separation, sparse Lanczos, six-stem separation, streaming separation, HearMusica compressor/limiter/mixer/filter blocks, WAV I/O, visualization helpers, and transcription hooks. |
| Release path | GitHub Actions build frontend plus unsigned macOS .app/.dmg, Linux .deb/AppImage, Windows NSIS artifacts, then gate release publishing behind the ci-guard job. |
The v0.3.0 release ships the AI performance layer end to end. Everything degrades gracefully: with no account, every feature falls back to deterministic local planners, keyword mappings, and the operator's remembered history.
| Capability | Where | Backed by |
|---|---|---|
| Set-arc autopilot | COGNITUM AI panel | cognitum_set_arc + local energy-curve planner |
| Auto DJ phrase briefs with memory | Auto DJ | cognitum_autodj_brief + musical adjacency graph |
| Mood-to-FX automation (lock-aware) | STREAM FX · AI MOOD | cognitum_fx_direction + curated local shapes |
| AI visual direction | VJ PRESETS · AI LOOK | cognitum_visual_direction + keyword looks |
| AI plugin scenes (pure data, never code) | VJ PRESETS · AI SCENE | cognitum_visual_plugin (ADR-177 tier 1) |
| AI style packs | COGNITUM AI panel | cognitum_style_pack → editable custom styles |
| AI vocal guidance | VOCALIZE dialog | cognitum_vocal_guidance + style-family templates |
| Performance memory (LEARNING) | automatic | IndexedDB similarity recall (ADR-176) |
The browser version should use Web Audio and Three.js for the performance UI, then load Musica core through WASM for heavier analysis and structure-aware DSP. The repo already has a feature-gated src/wasm_bridge.rs FFI surface for the graph separation pipeline:
rustup target add wasm32-unknown-unknown
cargo build --target wasm32-unknown-unknown --features wasm --release
The intended split is pragmatic:
| Runtime | Responsibility |
|---|---|
| Browser TypeScript | UI, transport, Web Audio scheduling, Tone.js MIDI parsing, WEBMIDI.js controller input, file import, visual rendering, local fallback analysis |
| Musica WASM | STFT, graph masks, stem confidence, separation witnesses, structural section features, and low-latency DSP primitives |
| Tauri Rust | Provider credentials, paid generation, private asset storage, controller socket, native dialogs, packaged export validation |
That keeps the web app usable without a server while preserving the stronger native security boundary for API tokens and paid generation.
cd apps/musica-vj
npm ci
npm run dev
# Native desktop shell with provider commands, global shortcuts, and packaged-app behavior
npm run tauri dev
Optional AI providers are configured only through the Tauri process environment. Do not commit API tokens, .env files, generated provider responses, or shell snippets containing secrets.
MUSICA_META_LLM_ENABLED=true \
MUSICA_META_LLM_API_BASE=https://api.cognitum.one \
MUSICA_META_LLM_API_TOKEN=replace_with_token \
MUSICA_META_LLM_MODEL=meta-llm \
npm run tauri dev
Google Lyria/Gemini generation can use either a Rust-only GEMINI_API_KEY or local GCP CLI application-default credentials with MUSICA_GCP_AUTH=gcloud.
See apps/musica-vj/README.md for the complete studio documentation, controller mappings, MIDI notes, import behavior, provider setup, screenshots, release artifacts, and verification commands.
Under the live studio is the original Rust audio engine: structure-first audio source separation via graph Laplacian spectral clustering and dynamic mincut refinement. It remains useful as a standalone library for low-latency audio analysis, separation, embedded processing, and research.
| Metric | Value |
|---|---|
| Core separation latency | 0.20 ms avg / 0.26 ms max in the benchmark suite |
| Model size | 0 bytes for the graph DSP path |
| Core dependency count | 1 required dependency: ruvector-mincut |
| Workspace tests | Rust workspace plus VJ frontend/provider/controller tests |
| License | MIT OR Apache-2.0 |
Traditional audio separation is frequency-first: FFT masking, ICA, NMF, neural networks. These approaches separate by learned spectral patterns.
Musica is structure-first: reframe audio as a graph partitioning problem, then find where signals naturally divide.
Nodes = time-frequency atoms (STFT bins, critical bands)
Edges = similarity (spectral proximity, phase coherence, harmonic alignment, temporal continuity)
Weights = how strongly two elements "belong together"
Dynamic mincut finds the minimum-cost boundary where signals separate, preserving maximum internal coherence within each source. The Fiedler vector (2nd smallest eigenvector of the graph Laplacian) provides the geometric partition that approximates the normalized cut.
| System | Latency | Type | Model Size |
|---|---|---|---|
| Musica | 0.20 ms | Graph-based (Rust) | 0 bytes |
| Widex ZeroDelay | 0.48 ms | Commercial hearing aid | Proprietary chip |
| DNN for CI (2025) | 1.0 ms | Research neural | Unknown |
| RT-STT (2025) | 1.01 ms | Neural (GPU) | 383K params |
| TinyLSTM (Bose) | 2.39 ms | Compressed LSTM | ~2 MB |
| RNNoise (Mozilla) | 10 ms | Hybrid DSP+GRU | 85 KB |
| System | Size | Hardware | Dependencies |
|---|---|---|---|
| Musica | 0 bytes model | Any CPU / WASM / MCU | None |
| RNNoise | 85 KB | Any CPU | Minimal C |
| RT-STT | ~1.5 MB | GPU required | PyTorch |
| Phonak DEEPSONIC | Proprietary | Custom AI chip (7,700 MOPS) | Proprietary |
| System | Vocals SDR | Approach |
|---|---|---|
| BS-RoFormer | ~10.5 dB | Transformer (trained on hundreds of hours) |
| HTDemucs | ~9.0 dB | Hybrid transformer |
| Open-Unmix | ~6.3 dB | LSTM baseline |
| Musica | 1-5 dB | Unsupervised graph partitioning |
Musica is 5-8 dB behind neural SOTA on raw SDR. That gap is expected — learned models have seen thousands of labeled songs. Musica's advantages are latency, size, interpretability, and edge deployability.
Raw Audio
|
v
STFT / Filterbank ──────── Zero-dep radix-2 Cooley-Tukey FFT + Hann window
|
v
Graph Construction ──────── Spectral + temporal + harmonic + phase edges
|
v
Laplacian Eigenvectors ──── Fiedler vector via Lanczos / power iteration
| SIMD-friendly (chunk-of-4 auto-vectorization)
v
Spectral Clustering ─────── Balanced initial partition (normalized cut)
|
v
MinCut Refinement ───────── Boundary optimization via ruvector-mincut
|
v
Soft Mask Generation ────── Distance-weighted softmax, Wiener normalization
|
v
Overlap-Add Reconstruction
| Module | Lines | Tests | Purpose |
|---|---|---|---|
stft.rs | 260 | 2 | Zero-dep radix-2 FFT, STFT/ISTFT with Hann window |
lanczos.rs | 729 | 6 | Sparse Lanczos eigensolver, CSR format, SIMD-optimized |
audio_graph.rs | 268 | 0 | Graph construction from STFT (spectral/temporal/harmonic/phase edges) |
separator.rs | 632 | 4 | Fiedler vector spectral clustering + mincut refinement |
hearing_aid.rs | 803 | 5 | Binaural streaming speech enhancer, <8ms latency |
multitrack.rs | 801 | 5 | 6-stem music separator (vocals/bass/drums/guitar/piano/other) |
crowd.rs | 819 | 5 | Distributed speaker identity tracking (thousands of speakers) |
wav.rs | 342 | 2 | 16/24-bit PCM WAV reader/writer |
benchmark.rs | 379 | 5 | SDR/SIR/SAR evaluation (BSS_EVAL style) |
hearmusica/ | ~1,200 | — | Hearing aid DSP pipeline (Tympan-compatible processing blocks) |
# Build
cargo build --release
# Run full 6-part benchmark suite
cargo run --release
# Run tests (34 tests)
cargo test
apps/musica-vj is a Mac-first Tauri 2 performance instrument built on Musica. It combines synchronized Lyria RealTime decks, an editable beat-guidance grid, one-click Demo automation, audio-reactive Three.js scenes, official Logitech MX Creative Console controls, prompt-driven performance mutation, governed creative-music providers, and capability-probed vertical social capture that prefers H.264 and AAC.
cd apps/musica-vj
npm ci
npm run dev
# Launch the native Tauri application on macOS
npm run tauri dev
The official Logi Actions SDK companion maps the Keypad LCD buttons, Dialpad, and roller into Musica controls. An Options+ F13-F24 profile works as an installation-free fallback. Creative provider credentials remain in the Rust process. Google Lyria 3 Pro Preview is optional and disabled by default, while the Suno partner adapter stays disabled until documented official access is configured.
Reproducible vertical preview fixtures are checked in for quick review:
See Musica VJ documentation, the Lyria integration specification, and ADRs 160-169 for architecture, security, controller setup, performance budgets, export rules, paid generation, provenance, and release gates.
use musica::{stft, audio_graph, separator};
let stft_result = stft::stft(&signal, 256, 128, 8000.0);
let graph = audio_graph::build_audio_graph(&stft_result, &audio_graph::GraphParams::default());
let config = separator::SeparatorConfig {
num_sources: 2,
..separator::SeparatorConfig::default()
};
let result = separator::separate(&graph, &config);
// result.masks[i] — soft mask per source
// result.cut_value — mincut witness (separation confidence)
use musica::hearing_aid::{HearingAidConfig, StreamingState, Audiogram};
let config = HearingAidConfig {
audiogram: Audiogram {
frequencies: vec![250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0],
gains_db: vec![10.0, 15.0, 20.0, 30.0, 40.0, 50.0], // mild sloping loss
},
..HearingAidConfig::default()
};
let mut state = StreamingState::new(&config);
// Per-frame streaming (call every 4ms hop)
let result = state.process_frame(&left_mic, &right_mic, &config);
// result.mask — per-band speech/noise mask
// result.speech_score — overall speech probability
// result.latency_us — processing time for this frame
Pipeline per frame:
use musica::multitrack::{separate_multitrack, MultitrackConfig, Stem};
let config = MultitrackConfig {
window_size: 4096,
hop_size: 1024,
sample_rate: 44100.0,
..MultitrackConfig::default()
};
let result = separate_multitrack(&audio_signal, &config);
for stem in &result.stems {
println!("{:?}: confidence={:.3}", stem.stem, stem.confidence);
// stem.signal — reconstructed time-domain audio for this stem
// stem.mask — T-F soft mask
}
// result.replay_log — every mincut decision for reproducibility
Default frequency priors:
| Stem | Low Hz | High Hz | Key Features |
|---|---|---|---|
| Vocals | 80 | 8,000 | High harmonicity, moderate transient |
| Bass | 20 | 300 | Low freq, high harmonicity |
| Drums | 30 | 15,000 | High transient, low harmonicity |
| Guitar | 80 | 6,000 | Moderate harmonicity |
| Piano | 27 | 4,200 | High harmonicity |
| Other | 20 | 20,000 | Catch-all remainder |
use musica::crowd::{CrowdTracker, CrowdConfig, SpeechEvent};
let config = CrowdConfig {
max_identities: 500,
association_threshold: 0.4,
..CrowdConfig::default()
};
let mut tracker = CrowdTracker::new(config);
// Register sensors
tracker.add_sensor((0.0, 0.0));
tracker.add_sensor((10.0, 0.0));
// Ingest events from sensor 0
tracker.ingest_events(0, vec![SpeechEvent {
time: 0.0, freq_centroid: 200.0, energy: 0.5,
voicing: 0.8, harmonicity: 0.7, direction: 0.0, sensor_id: 0,
}]);
// Update pipeline
tracker.update_local_graphs(); // Layer 2: local Fiedler clustering
tracker.associate_cross_sensor(0.5); // Layer 3: cross-node embedding match
tracker.update_global_identities(0.5); // Layer 4: global identity memory
let stats = tracker.get_stats();
4-layer hierarchy:
use musica::lanczos::{SparseMatrix, LanczosConfig, lanczos_eigenpairs, batch_lanczos};
// Build graph Laplacian from weighted edges
let laplacian = SparseMatrix::from_edges(20, &edges); // L = D - W
// Compute smallest k eigenpairs
let config = LanczosConfig { k: 4, max_iter: 50, tol: 1e-8, reorthogonalize: true };
let result = lanczos_eigenpairs(&laplacian, &config);
// result.eigenvalues — sorted ascending
// result.eigenvectors — Fiedler vector is eigenvectors[0] (smallest non-trivial)
// Batch mode with cross-frame alignment (Procrustes sign consistency)
let results = batch_lanczos(&laplacians, &config);
use musica::wav;
// Read
let data = wav::read_wav("input.wav")?;
// data.channel_data[0] — first channel as Vec<f64>
// data.sample_rate, data.channels, data.bits_per_sample
// Write
wav::write_wav("output.wav", &samples, 16000, 1)?;
// Generate binaural test signal with ITD model
wav::generate_binaural_test_wav("test.wav", 16000, 0.5, 300.0, &[800.0], 30.0)?;
Run cargo run --release for the full 6-part suite:
Three test scenarios at 8 kHz, 256-sample window:
| Scenario | Nodes | Edges | SDR (source 0) | SDR (source 1) |
|---|---|---|---|---|
| Well-separated (200 Hz + 2000 Hz) | 834 | 3,765 | +0.2 dB | -3.0 dB |
| Close tones (400 Hz + 600 Hz) | 1,786 | 8,480 | -0.1 dB | -0.1 dB |
| Harmonic 3rd (300 Hz + 900 Hz) | 1,882 | 8,738 | +1.5 dB | -2.9 dB |
| Metric | Result |
|---|---|
| Frames processed | 100 |
| Avg latency | 0.20 ms |
| Max latency | 0.26 ms |
| Latency budget | PASS (target <8ms) |
| Stem | Confidence | Energy |
|---|---|---|
| Vocals | 0.168 | 0.023 |
| Bass | 0.120 | 0.137 |
| Drums | 0.205 | 0.023 |
| Guitar | 0.158 | 0.022 |
| Piano | 0.154 | 0.060 |
| Other | 0.195 | 0.015 |
Graph: 24,230 nodes, 55,541 edges. Mask sum error: 0.0000.
20-node graph, 2 clusters with weak bridge:
20 sensors, 1,500 events, 50 simulated speakers:
16-bit PCM roundtrip: max error = 0.000046. PASS.
The graph Laplacian L = D - W encodes structure. Its second-smallest eigenvector (the Fiedler vector) provides the continuous relaxation of the normalized cut — nodes with the same sign in the Fiedler vector belong to the same cluster.
Given weighted adjacency W and degree matrix D:
L = D - W
Solve Lv = λv for smallest eigenvalues
Fiedler vector = eigenvector for λ₂ (smallest non-zero eigenvalue)
Partition: {nodes where v[i] > 0} vs {nodes where v[i] ≤ 0}
All vector operations (dot, norm, axpy, scale) process in chunks of 4 f64 values for auto-vectorization. Selective reorthogonalization prevents ghost eigenvalues. Tridiagonal QR with Wilkinson shift extracts eigenpairs.
After spectral clustering provides balanced initial partitions, ruvector-mincut refines boundaries by finding the exact minimum cut. The cut value serves as a structural witness — a provable certificate of separation quality.
The hearing aid module uses 32 Equivalent Rectangular Bandwidth (ERB) spaced bands, matching the human cochlea's frequency resolution:
ERB(f) = 24.7 * (4.37 * f/1000 + 1)
The only sub-1ms, zero-dependency, fully explainable speech enhancer. Runs on a $2 microcontroller. No custom silicon required. An audiologist can inspect why any decision was made — which binaural features drove the speech/noise classification, what the graph partition looks like, what the mincut witness value means.
Regulatory advantage: FDA/CE medical device approval increasingly requires explainability. Black-box DNNs face scrutiny. Full auditability is a structural advantage for certification.
Compiles to WASM via wasm-pack with zero changes. Real-time separation in any browser AudioWorklet — no server round-trip. Applications: live transcription, teleconferencing, accessibility tools.
Use Musica's Fiedler partition as a preprocessing stage for lightweight neural models. The graph provides structural priors, reducing what the neural model needs to learn. Potential to reach 8+ dB SDR at <2ms latency by combining graph structure with a small learned refinement network.
CI users need even lower latency than hearing aid users. At 0.20ms, Musica leaves headroom for additional processing stages (vocoder, electrode mapping) within tight latency budgets.
Crowd-scale tracking enables: smart buildings with per-room speaker awareness, transit hub safety monitoring, stadium crowd analytics, search and rescue with distributed microphone arrays.
wasm-pack build + browser demo with Web Audio APIdocs/examples/musica/
├── Cargo.toml
├── README.md
└── src/
├── lib.rs # Module declarations
├── main.rs # 6-part benchmark suite
├── stft.rs # FFT + STFT/ISTFT
├── lanczos.rs # Sparse eigensolver (CSR, SIMD)
├── audio_graph.rs # Graph construction from STFT
├── separator.rs # Spectral clustering + mincut
├── hearing_aid.rs # Binaural streaming enhancer
├── multitrack.rs # 6-stem music separator
├── crowd.rs # Distributed speaker tracking
├── wav.rs # WAV file I/O
├── benchmark.rs # SDR/SIR/SAR evaluation
└── hearmusica/ # Hearing aid DSP pipeline
├── mod.rs # Pipeline orchestrator + AudioBlock
├── block.rs # ProcessingBlock trait
├── filter.rs # BiquadFilter (8 filter types)
├── compressor.rs # WDRCompressor (multi-band WDRC)
├── feedback.rs # FeedbackCanceller (NLMS adaptive)
├── gain.rs # GainProcessor (NAL-R prescription)
├── separator_block.rs # GraphSeparator (Fiedler + mincut)
├── delay.rs # DelayLine (circular buffer)
├── limiter.rs # Limiter (brick-wall protection)
├── mixer.rs # Mixer (weighted combination)
└── presets.rs # 4 preset pipelines
Single dependency:
[dependencies]
ruvector-mincut = { path = "../../../crates/ruvector-mincut", features = ["monitoring", "approximate", "exact"] }
Everything else — FFT, filterbank, eigensolver, WAV I/O, metrics — is implemented from scratch with zero external crates.
High-fidelity Rust port of Tympan's MIT-licensed hearing aid DSP, integrated with musica's graph-based separation. HEARmusica provides a modular pipeline of processing blocks that can be composed into complete hearing aid signal chains, from microphone input to speaker output. Each block implements the ProcessingBlock trait for uniform pipeline orchestration.
| Block | Tympan Equivalent | Key Feature |
|---|---|---|
| BiquadFilter | AudioFilterBiquad_F32 | 8 filter types (LP/HP/BP/notch/allpass/peaking/shelves) |
| WDRCompressor | AudioEffectCompressor_F32 | Multi-band WDRC with soft knee |
| FeedbackCanceller | AudioEffectFeedbackCancel_F32 | NLMS adaptive filter |
| GainProcessor | AudioEffectGain_F32 | Audiogram fitting + NAL-R prescription |
| GraphSeparator | (novel) | Fiedler vector + dynamic mincut |
| DelayLine | AudioEffectDelay_F32 | Sample-accurate circular buffer |
| Limiter | (custom) | Brick-wall output protection |
| Mixer | AudioMixer_F32 | Weighted signal combination |
Input -> BiquadFilter -> FeedbackCanceller -> GraphSeparator -> WDRCompressor -> GainProcessor -> Limiter -> Output
The pipeline processes stereo AudioBlock frames. Each block reads from and writes to the block's left and right sample buffers in place, minimizing allocations. The GraphSeparator block bridges musica's spectral clustering into the hearing aid chain, providing structure-aware noise reduction that traditional DSP pipelines lack.
Four preset configurations cover common hearing aid use cases:
| Preset | Description | Key Blocks |
|---|---|---|
standard_hearing_aid | General-purpose amplification with feedback cancellation | BiquadFilter, FeedbackCanceller, WDRCompressor, GainProcessor, Limiter |
speech_in_noise | Optimized for noisy environments with graph-based separation | BiquadFilter, FeedbackCanceller, GraphSeparator, WDRCompressor, GainProcessor, Limiter |
music_mode | Wide bandwidth, gentle compression for music listening | BiquadFilter, WDRCompressor (low ratio), GainProcessor, Limiter |
maximum_clarity | Aggressive noise reduction for severe hearing loss | BiquadFilter, FeedbackCanceller, GraphSeparator, WDRCompressor (high ratio), GainProcessor, Limiter |
All presets accept an Audiogram, sample rate, and block size, and return a fully configured Pipeline.
use musica::hearmusica::{self, Pipeline, AudioBlock};
use musica::hearing_aid::Audiogram;
let audiogram = Audiogram::default(); // mild sloping loss
let mut pipeline = hearmusica::presets::speech_in_noise(&audiogram, 16000.0, 128);
pipeline.prepare();
let mut block = AudioBlock::new(128, 16000.0);
// Fill block.left and block.right with mic samples...
pipeline.process_block(&mut block);
// block now contains enhanced audio
| Feature | Tympan (C++) | HEARmusica (Rust) |
|---|---|---|
| Latency | 2.9-5.7 ms | < 1 ms target |
| Platform | Teensy only | Any (MCU/WASM/desktop) |
| Separation | None | Graph-based (Fiedler + mincut) |
| Memory safety | Manual | Compile-time |
| License | MIT | MIT |
| Audiogram fitting | Basic | NAL-R prescription |
HEARmusica's primary advantage is the GraphSeparator block, which has no equivalent in Tympan or any other open-source hearing aid framework. By embedding musica's spectral clustering directly into the DSP pipeline, noise reduction becomes structure-aware rather than purely energy-based.
4 preset pipelines benchmarked at 16 kHz, 128-sample blocks, 200 blocks each:
| Preset | Avg Block | Max Block | Pipeline Latency | Chain |
|---|---|---|---|---|
| Standard HA | 0.011 ms | 0.047 ms | 0.00 ms | Filter→WDRC→Gain→Limiter |
| Speech-in-Noise | 0.539 ms | 0.705 ms | 4.00 ms | Filter→FeedbackCancel→GraphSep→WDRC→Gain→Limiter |
| Music Mode | 0.010 ms | 0.015 ms | 0.00 ms | WDRC→Gain→Limiter |
| Max Clarity | 0.664 ms | 0.751 ms | 6.00 ms | Filter→FeedbackCancel→GraphSep→Delay→WDRC→Gain→Mixer→Limiter |
Key findings:
Frame-by-frame multitrack separation at 44.1 kHz:
| Metric | Value |
|---|---|
| Avg frame latency | 0.35 ms |
| Max frame latency | 0.68 ms |
| All 6 stems | Non-zero energy |
See ADR-143 for the full architecture decision record.
37 commits
Rust
46.6%
TypeScript
40.3%
CSS
5.5%
JavaScript
3.7%
C#
1.7%
HTML
1.2%