Skip to main content

nam_rs/
lib.rs

1//! # nam-rs
2//!
3//! Pure-Rust, real-time-safe inference for [Neural Amp Modeler] (NAM) `.nam` models.
4//!
5//! This crate loads a `.nam` model file and runs its neural network forward pass —
6//! a whole buffer at a time (WaveNet uses a cache-friendly block kernel), or one
7//! sample at a time — with no heap allocation on the audio (hot) path. It is a
8//! from-scratch Rust port of NAM's inference, written against the reference
9//! implementations below and validated for **bit-level parity** against them.
10//!
11//! Both NAM architectures are supported — WaveNet and LSTM — and run through the
12//! architecture-agnostic [`Model`] enum, which dispatches on the `.nam`'s declared
13//! architecture so you never have to branch on it yourself.
14//!
15//! ## Design contract
16//!
17//! 1. **Parity with the reference.** The forward pass must produce output equal
18//!    (within float tolerance) to the canonical Python/C++ NAM implementations for
19//!    the same `.nam` file and input. This is enforced by `tests/parity.rs`.
20//! 2. **Real-time safety.** The runtime's `process_buffer` (on both [`WaveNet`] and
21//!    [`Lstm`], reached via [`Model`]) performs zero heap allocations, locks, or
22//!    system calls. All scratch buffers are pre-allocated at construction. This is
23//!    enforced by `tests/rt_safety.rs`.
24//!
25//! ## Example
26//!
27//! ```
28//! use nam_rs::{NamModel, Model};
29//!
30//! // From disk you'd use `NamModel::from_file("model.nam")?`.
31//! // Here we use a tiny in-line model for illustration.
32//! let json = r#"{
33//!     "version": "0.5.4", "architecture": "WaveNet",
34//!     "config": {
35//!         "layers": [{
36//!             "input_size": 1, "condition_size": 1, "channels": 1, "head_size": 1,
37//!             "kernel_size": 1, "dilations": [1], "activation": "ReLU",
38//!             "gated": false, "head_bias": false
39//!         }],
40//!         "head": null, "head_scale": 1.0
41//!     },
42//!     "weights": [1.0, 2.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0]
43//! }"#;
44//!
45//! let model = NamModel::from_json_str(json)?;
46//! let mut amp = Model::from_nam(&model)?;   // picks WaveNet or Lstm from the file
47//!
48//! // On the audio thread: process in place, no allocation.
49//! let mut buffer = [0.1_f32, 0.2, 0.3, 0.4];
50//! amp.process_buffer(&mut buffer);
51//! # Ok::<(), nam_rs::Error>(())
52//! ```
53//!
54//! ## Attribution
55//!
56//! This is a derivative work. The algorithm and weight layout are ported from the
57//! following projects (see `NOTICE` for license texts):
58//!
59//! - [neural-amp-modeler] — Steven Atkinson's reference trainer + `.nam` exporter
60//!   (Python, MIT). The source of truth for `export_weights` / `export_config`.
61//! - [NeuralAmpModelerCore] — the canonical C++ inference library (MIT).
62//! - [NeuralAudio] — Mike Oliphant's high-performance C++ NAM/RTNeural runtime,
63//!   designed to match NAM Core exactly (MIT). Primary porting reference.
64//! - [waveny] — a Go port of NAM (Apache-2.0). Used as a conceptual cross-check only.
65//!
66//! [Neural Amp Modeler]: https://www.neuralampmodeler.com/
67//! [neural-amp-modeler]: https://github.com/sdatkinson/neural-amp-modeler
68//! [NeuralAmpModelerCore]: https://github.com/sdatkinson/NeuralAmpModelerCore
69//! [NeuralAudio]: https://github.com/mikeoliphant/NeuralAudio
70//! [waveny]: https://github.com/nlpodyssey/waveny
71
72mod error;
73mod lstm;
74mod model;
75mod model_runtime;
76mod reader;
77mod wavenet;
78
79pub use error::Error;
80pub use lstm::Lstm;
81pub use model::{
82    LayerArrayConfig, LstmConfig, Metadata, ModelConfig, NamModel, WaveNetConfig,
83    DEFAULT_SAMPLE_RATE,
84};
85pub use model_runtime::Model;
86pub use wavenet::WaveNet;