Skip to content

Commit 22651b9

Browse files
committed
feat(nam): support LSTM models via nam-rs 0.2 arch-agnostic Model
Bump nam-rs 0.1 -> 0.2 and swap the hardcoded WaveNet for nam_rs::Model, which dispatches over the .nam architecture (WaveNet or LSTM). LSTM .nam files previously parsed into the registry but WaveNet::new rejected them, falling back to silent passthrough; they now run. Processing stays per-sample for now.
1 parent 0b9b180 commit 22651b9

4 files changed

Lines changed: 18 additions & 17 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rustortion-core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ rustfft = "6.4"
1717
realfft = "3.5"
1818
arc-swap = "1.8"
1919
assert_no_alloc = { version = "1.1", features = ["warn_debug"] }
20-
nam-rs = "0.1.0"
20+
nam-rs = "0.2.0"
2121

2222
[dev-dependencies]
2323
criterion = { version = "0.8", features = ["html_reports"] }

rustortion-core/src/amp/stages/nam.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use log::warn;
2-
use nam_rs::WaveNet;
2+
use nam_rs::Model;
33
use serde::{Deserialize, Serialize};
44

55
use crate::amp::stages::Stage;
@@ -10,12 +10,13 @@ use crate::nam::registry;
1010
const GAIN_DB_MIN: f32 = -24.0;
1111
const GAIN_DB_MAX: f32 = 24.0;
1212

13-
/// A Neural Amp Modeler stage running a WaveNet `.nam` model.
13+
/// A Neural Amp Modeler stage running a `.nam` model of any supported architecture
14+
/// (WaveNet or LSTM), via the architecture-agnostic [`nam_rs::Model`].
1415
///
1516
/// With no model loaded the stage is a passthrough. Input/output gain are applied
1617
/// around the model and the wet output is blended with the dry signal via `mix`.
1718
pub struct NamStage {
18-
wavenet: Option<WaveNet>,
19+
model: Option<Model>,
1920
input_gain: f32,
2021
output_gain: f32,
2122
mix: f32,
@@ -28,7 +29,7 @@ pub struct NamStage {
2829
impl NamStage {
2930
const fn passthrough(input_gain: f32, output_gain: f32, mix: f32) -> Self {
3031
Self {
31-
wavenet: None,
32+
model: None,
3233
input_gain,
3334
output_gain,
3435
mix,
@@ -46,7 +47,7 @@ impl NamStage {
4647
native_sample_rate: f32,
4748
) -> Self {
4849
Self {
49-
wavenet: None,
50+
model: None,
5051
input_gain,
5152
output_gain,
5253
mix,
@@ -58,10 +59,10 @@ impl NamStage {
5859

5960
impl Stage for NamStage {
6061
fn process(&mut self, input: f32) -> f32 {
61-
let Some(wavenet) = self.wavenet.as_mut() else {
62+
let Some(model) = self.model.as_mut() else {
6263
return input;
6364
};
64-
let wet = wavenet.process_sample(input * self.input_gain) * self.output_gain;
65+
let wet = model.process_sample(input * self.input_gain) * self.output_gain;
6566
self.mix.mul_add(wet - input, input)
6667
}
6768

@@ -136,7 +137,7 @@ impl Default for NamConfig {
136137

137138
impl NamConfig {
138139
/// Build a runnable stage. Resolves the model from the global registry and
139-
/// allocates the `WaveNet` here (off the real-time thread). On any failure the
140+
/// allocates the model here (off the real-time thread). On any failure the
140141
/// stage falls back to passthrough with a warning.
141142
pub fn to_stage(&self, sample_rate: f32) -> NamStage {
142143
let input_gain = db_to_lin(self.input_gain_db.clamp(GAIN_DB_MIN, GAIN_DB_MAX));
@@ -168,9 +169,9 @@ impl NamConfig {
168169
);
169170
}
170171

171-
match WaveNet::new(&model) {
172-
Ok(wavenet) => NamStage {
173-
wavenet: Some(wavenet),
172+
match Model::from_nam(&model) {
173+
Ok(runtime) => NamStage {
174+
model: Some(runtime),
174175
input_gain,
175176
output_gain,
176177
mix,
@@ -201,9 +202,9 @@ mod tests {
201202

202203
#[test]
203204
fn mismatch_bypass_is_dry_passthrough() {
204-
// A rate-mismatch stage is built without a WaveNet but records the real native
205+
// A rate-mismatch stage is built without a model but records the real native
205206
// rate and the mismatch flag. We construct it directly here because building a
206-
// real `WaveNet` requires loading a `.nam` model into the registry, which unit
207+
// real model requires loading a `.nam` file into the registry, which unit
207208
// tests can't do; this still verifies the RT-path passthrough contract and the
208209
// params reported to the UI.
209210
let mut stage =

rustortion-core/src/nam/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! NAM (Neural Amp Modeler) model loading and a process-global parsed-model
22
//! registry.
33
//!
4-
//! `.nam` models are parsed (and the `WaveNet` allocated) off the real-time thread.
4+
//! `.nam` models are parsed (and the runtime model allocated) off the real-time thread.
55
//! The [`loader`] scans a directory and parses every `*.nam` file into memory at
66
//! startup; the [`registry`] makes those parsed models reachable from
77
//! `StageConfig::to_runtime`, which has no other handle to the loader.

0 commit comments

Comments
 (0)