use std::path::{Path, PathBuf};
use crate::loader::loaded_model_pair::{DEFAULT_INPUT_LEVEL_DBU, DEFAULT_LOUDNESS_DB};
pub fn manifest_dir() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}
pub fn fixture_dir() -> PathBuf {
manifest_dir().join("tests/fixtures")
}
pub fn third_party_dir() -> PathBuf {
if let Ok(dir) = std::env::var("NAM_THIRD_PARTY_DIR") {
let p = PathBuf::from(dir);
if !p.as_os_str().is_empty() {
return p;
}
}
manifest_dir().join("third-party")
}
pub fn nam_core_dir() -> PathBuf {
if let Ok(dir) = std::env::var("NAM_CORE_DIR") {
let p = PathBuf::from(dir);
if !p.as_os_str().is_empty() {
return p;
}
}
third_party_dir().join("NeuralAmpModelerCore")
}
pub fn nam_plugin_dir() -> PathBuf {
if let Ok(dir) = std::env::var("NAM_PLUGIN_DIR") {
let p = PathBuf::from(dir);
if !p.as_os_str().is_empty() {
return p;
}
}
third_party_dir().join("NeuralAmpModelerPlugin")
}
pub fn community_models_dir() -> PathBuf {
third_party_dir().join("community_models")
}
pub fn resolve_repo_path(path_str: &str) -> Option<PathBuf> {
let p = Path::new(path_str);
if p.is_absolute() {
return p.exists().then(|| p.to_path_buf());
}
let cand = manifest_dir().join(p);
cand.exists().then_some(cand)
}
pub fn model_path(name: &str) -> PathBuf {
if let Ok(dir) = std::env::var("NAM_MODELS_DIR") {
let p = PathBuf::from(&dir).join(name);
if p.exists() {
return p;
}
}
let community = community_models_dir().join(name);
if community.exists() {
return community;
}
let manifest = manifest_dir();
let nondist = manifest.join("tests/fixtures/models-nondist").join(name);
if nondist.exists() {
return nondist;
}
manifest.join("tests/fixtures/models").join(name)
}
pub fn models_dir() -> PathBuf {
manifest_dir().join("tests/fixtures/models")
}
pub fn has_model(name: &str) -> bool {
model_path(name).exists()
}
pub fn golden_path(name: &str) -> PathBuf {
fixture_dir().join(name)
}
pub fn stress_signal_path(name: &str) -> PathBuf {
fixture_dir().join(name)
}
pub fn render_bin_path() -> PathBuf {
let build_dir = manifest_dir().join("build/namcore_render");
for candidate in &["tools/render", "Release/render", "Debug/render"] {
let p = build_dir.join(candidate);
if p.exists() {
return p;
}
}
if build_dir.exists() {
for entry in std::fs::read_dir(&build_dir)
.into_iter()
.flatten()
.flatten()
{
let p = entry.path();
if p.is_dir() {
let c = p.join("render");
if c.exists() {
return c;
}
}
}
}
build_dir.join("tools/render")
}
pub fn calibration_multipliers_from_model_json(model_json_path: &Path) -> (f32, f32) {
let file =
std::fs::File::open(model_json_path).expect("Failed to open model JSON for calibration");
let reader = std::io::BufReader::new(file);
let model_data: serde_json::Value =
serde_json::from_reader(reader).expect("Failed to parse model JSON for calibration");
let metadata = model_data.get("metadata");
let loudness = metadata
.and_then(|m| m.get("loudness"))
.and_then(|v| v.as_f64())
.map(|v| v as f32)
.unwrap_or(DEFAULT_LOUDNESS_DB);
let input_level_dbu = metadata
.and_then(|m| m.get("input_level_dbu"))
.and_then(|v| v.as_f64())
.map(|v| v as f32)
.unwrap_or(DEFAULT_INPUT_LEVEL_DBU);
let input_db_adj = DEFAULT_INPUT_LEVEL_DBU - input_level_dbu;
let output_db_adj = DEFAULT_LOUDNESS_DB - loudness;
let lut = crate::math::dsp::gain_lut::get_gain_lut();
let input_mult_adj = lut.db_to_linear(input_db_adj);
let output_mult_adj = lut.db_to_linear(output_db_adj);
(input_mult_adj, output_mult_adj)
}