rlx_neutts/decoder/mod.rs
1// RLX — versatile ML compiler + runtime.
2// Copyright (C) 2026 Eugene Hauptmann, Nataliya Kosmyna.
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, version 3.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program. If not, see <https://www.gnu.org/licenses/>.
15
16//! NeuCodec decoder — FSQ lookup + Vocos backbone + ISTFT head.
17//!
18//! | Feature | Path |
19//! |-------------|-------------------------------------------|
20//! | `codec` | Eager ndarray CPU ([`eager`]) — default |
21//! | `burn` | Burn wgpu → NdArray → eager fallback |
22//! | `rlx` | RLX runtime (eager parity until graph) |
23//!
24//! Decoder weights are **not** shipped in this crate. Set [`decoder_weights_path`] via
25//! `NEUTTS_DECODER_PATH` (path to `neucodec_decoder.safetensors`).
26
27use std::path::PathBuf;
28
29use anyhow::{Result, bail};
30
31mod eager;
32
33#[cfg(feature = "burn")]
34mod burn;
35
36#[cfg(feature = "rlx")]
37mod rlx;
38
39pub use eager::{
40 ENCODER_DEFAULT_INPUT_SAMPLES, ENCODER_SAMPLE_RATE, ENCODER_SAMPLES_PER_TOKEN, NeuCodecDecoder,
41 NeuCodecEncoder, SAMPLE_RATE, SAMPLES_PER_TOKEN,
42};
43
44pub use crate::features::{burn_feature_enabled, rlx_feature_enabled, wgpu_feature_enabled};
45
46/// Resolve NeuCodec decoder weights from `NEUTTS_DECODER_PATH`.
47pub fn decoder_weights_path() -> Result<PathBuf> {
48 let path = std::env::var("NEUTTS_DECODER_PATH")
49 .ok()
50 .filter(|p| !p.is_empty())
51 .map(PathBuf::from)
52 .ok_or_else(|| {
53 anyhow::anyhow!(
54 "NEUTTS_DECODER_PATH is not set (NeuCodec weights are not bundled in rlx-neutts)"
55 )
56 })?;
57 if !path.exists() {
58 bail!("NEUTTS_DECODER_PATH does not exist: {}", path.display());
59 }
60 Ok(path)
61}
62
63/// Like [`decoder_weights_path`], but returns `None` when unset or missing (for tests).
64pub fn decoder_weights_path_if_available() -> Option<PathBuf> {
65 let path = std::env::var("NEUTTS_DECODER_PATH")
66 .ok()
67 .filter(|p| !p.is_empty())
68 .map(PathBuf::from)?;
69 if path.exists() { Some(path) } else { None }
70}