feat: add NAM neural amp modeler stage#243
Merged
Merged
Conversation
Add a Neural Amp Modeler (NAM) stage that runs WaveNet .nam models via the nam-rs crate as a registered, composable amp-chain stage. - core: nam module with a folder loader and a process-global parsed-model registry; NamStage/NamConfig wrapping nam-rs WaveNet, with input/output gain, dry/wet mix, and passthrough fallback on missing model, sample-rate mismatch, or build error (warn, never panic) - ui: NAM stage card with model pick-list, gain/mix sliders, and a read-only native-rate info line; EN + ZH_CN locale keys - standalone: nam_dir setting (default ./nam); registry populated at startup - plugin: registry populated from ~/.config/rustortion/nam in initialize(); NamSlotParams added for host visibility/automation parity with other stages Models are loaded from a nam/ folder into memory at startup and selected per stage; the choice persists in presets and DAW project state.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new Neural Amp Modeler (NAM) stage to the Rustortion amp chain, including model discovery/loading, a process-global model registry, UI controls, and standalone/plugin integration so .nam models can be selected and used at runtime.
Changes:
- Introduces
rustortion-core::nam(loader + process-global registry) and a newNamStage/NamConfigwired intoStageType/StageConfig. - Adds NAM UI stage card (model picker + gain/mix controls) and i18n/minimap support.
- Loads NAM models on startup in standalone and plugin, and adds plugin-exposed per-slot NAM parameters.
Reviewed changes
Copilot reviewed 16 out of 18 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| rustortion-ui/src/stages/nam.rs | New NAM stage UI card (model selection + gain/mix) and message/apply plumbing. |
| rustortion-ui/src/stages/mod.rs | Registers NAM stage in the GUI stage registry; de-const apply function. |
| rustortion-ui/src/i18n/mod.rs | Adds EN/ZH_CN translation keys for NAM UI labels. |
| rustortion-ui/src/components/minimap.rs | Adds “NAM” abbreviation for minimap rendering. |
| rustortion-standalone/src/settings/mod.rs | Adds nam_dir setting with serde default for backward compatibility. |
| rustortion-standalone/src/audio/manager.rs | Initializes NAM loader and populates global registry at standalone startup. |
| rustortion-plugin/src/params.rs | Adds NamSlotParams and nests an 8-slot NAM param array for host visibility/persistence. |
| rustortion-plugin/src/lib.rs | Initializes NAM loader/registry from ~/.config/rustortion/nam during plugin init. |
| rustortion-core/src/preset/stage_config.rs | Adds StageType::Nam and StageConfig::Nam, wiring NAM into runtime creation and bypass accessors. |
| rustortion-core/src/nam/registry.rs | New process-global registry for parsed NAM models (name → Arc<NamModel>). |
| rustortion-core/src/nam/mod.rs | New NAM module exports (loader + registry). |
| rustortion-core/src/nam/loader.rs | New directory scanner/parser for *.nam model files (tolerant loading). |
| rustortion-core/src/lib.rs | Exposes the new nam module from rustortion-core. |
| rustortion-core/src/amp/stages/nam.rs | Implements NamStage + NamConfig and stage parameter handling. |
| rustortion-core/src/amp/stages/mod.rs | Exposes the new nam stage module. |
| rustortion-core/Cargo.toml | Adds nam-rs dependency (currently via git branch). |
| nam/.gitkeep | Adds an (empty) default NAM models directory to the repo. |
| Cargo.lock | Records the resolved nam-rs git dependency in the lockfile. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+8
to
+11
| /// Convert decibels to a linear amplitude multiplier. | ||
| fn db_to_linear(db: f32) -> f32 { | ||
| 10.0_f32.powf(db / 20.0) | ||
| } |
Comment on lines
+52
to
+55
| "input_gain_db" => { | ||
| self.input_gain = db_to_linear(value); | ||
| Ok(()) | ||
| } |
Comment on lines
+56
to
+59
| "output_gain_db" => { | ||
| self.output_gain = db_to_linear(value); | ||
| Ok(()) | ||
| } |
Comment on lines
+128
to
+135
| let native_sample_rate = model.sample_rate() as f32; | ||
| let sample_rate_mismatch = (native_sample_rate - sample_rate).abs() > 1.0; | ||
| if sample_rate_mismatch { | ||
| warn!( | ||
| "NAM model '{name}' native rate {native_sample_rate} Hz differs from engine \ | ||
| rate {sample_rate} Hz; tone may be affected" | ||
| ); | ||
| } |
Comment on lines
+38
to
+40
| for entry in entries.flatten() { | ||
| let path = entry.path(); | ||
| if path.extension().and_then(|e| e.to_str()) != Some("nam") { |
Comment on lines
+71
to
+72
| // Read-only model info: native rate / mismatch warning. | ||
| let info_line: Element<'_, Message> = match model_name.as_deref() { |
Comment on lines
+60
to
+66
| let model_selector = row![ | ||
| text(tr!(nam_model)).width(Length::FillPortion(3)), | ||
| pick_list(models, model_name.clone(), move |name| { | ||
| Message::Stage(idx, StageMessage::Nam(NamMessage::ModelSelected(name))) | ||
| }) | ||
| .placeholder(tr!(nam_no_model)) | ||
| .width(Length::FillPortion(7)), |
| realfft = "3.5" | ||
| arc-swap = "1.8" | ||
| assert_no_alloc = { version = "1.1", features = ["warn_debug"] } | ||
| nam-rs = { git = "https://github.com/OpenSauce/nam-rs", branch = "main" } |
Switch from the git branch dependency to the crates.io release now that nam-rs 0.1.0 is published. The lockfile records a checksum, so builds are fully reproducible.
- validate input/output gain to +/-24 dB in set_parameter (rejects NaN/inf) and clamp gain/mix in to_stage for hand-edited presets - reuse shared db_to_lin helper instead of a local duplicate - log read_dir entry errors in the NAM loader instead of silently dropping them - add a '(None)' pick-list entry so a selected model can be cleared to passthrough - correct the misleading info-line comment (engine rate isn't available in the view)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a Neural Amp Modeler (NAM) stage that runs WaveNet
.nammodels (via thenam-rscrate) as a registered, composable amp-chain stage. Drop.namfiles into a folder; all models load into memory at startup and are selectable per stage.What's included
Core (
rustortion-core)src/nam/—NamLoaderscans a folder and parses every*.naminto memory (tolerant: bad files skipped, missing dir is fine), feeding a process-globalregistrysoto_runtimeresolves models by name without changing its signature.src/amp/stages/nam.rs—NamStage(wraps nam-rsWaveNet) +NamConfig.process()= input-gain → model → output-gain → dry/wet mix. Passthrough on no model / not found / sample-rate mismatch / build error (warns, never panics).Namwired intoStageType/StageConfig(category: Amp).UI (
rustortion-ui)NeedsStageRebuild → rebuild_stage → ReplaceStagepath.gui_stage_registry!;apply_stage_configde-consted (model name is aString). EN + ZH_CN keys; minimap abbreviationNAM.Standalone
nam_dirsetting (default./nam, serde-defaulted so old configs load); registry populated inManager::new.Plugin
~/.config/rustortion/namininitialize()(off the audio thread).NamSlotParamsadded (input/output/mix/bypass) for host visibility, automation lanes, and persistence — parity with the other 10 stages.Behaviour
chain_stateserializesmodel_name).Notes
Testing
make lintclean (-D warnings -D clippy::all -D clippy::pedantic -D clippy::nursery).make test— all tests pass, including the RT no-alloc suite.