use crate::cli::{Args, PeqModel};
use crate::loss::LossType;
#[derive(Debug, Clone)]
pub struct OptimParams {
pub num_filters: usize,
pub peq_model: PeqModel,
pub sample_rate: f64,
pub min_freq: f64,
pub max_freq: f64,
pub min_q: f64,
pub max_q: f64,
pub min_db: f64,
pub max_db: f64,
pub loss: LossType,
pub smooth: bool,
pub smooth_n: usize,
pub min_spacing_oct: f64,
pub spacing_weight: f64,
pub algo: String,
pub population: usize,
pub maxeval: usize,
pub refine: bool,
pub local_algo: String,
pub strategy: String,
pub tolerance: f64,
pub atolerance: f64,
pub recombination: f64,
pub adaptive_weight_f: f64,
pub adaptive_weight_cr: f64,
pub no_parallel: bool,
pub parallel_threads: usize,
pub seed: Option<u64>,
pub quiet: bool,
}
impl From<&Args> for OptimParams {
fn from(args: &Args) -> Self {
Self {
num_filters: args.num_filters,
peq_model: args.effective_peq_model(),
sample_rate: args.sample_rate,
min_freq: args.min_freq,
max_freq: args.max_freq,
min_q: args.min_q,
max_q: args.max_q,
min_db: args.min_db,
max_db: args.max_db,
loss: args.loss,
smooth: args.smooth,
smooth_n: args.smooth_n,
min_spacing_oct: args.min_spacing_oct,
spacing_weight: args.spacing_weight,
algo: args.algo.clone(),
population: args.population,
maxeval: args.maxeval,
refine: args.refine,
local_algo: args.local_algo.clone(),
strategy: args.strategy.clone(),
tolerance: args.tolerance,
atolerance: args.atolerance,
recombination: args.recombination,
adaptive_weight_f: args.adaptive_weight_f,
adaptive_weight_cr: args.adaptive_weight_cr,
no_parallel: args.no_parallel,
parallel_threads: args.parallel_threads,
seed: args.seed,
quiet: args.qa.is_some(),
}
}
}
impl From<&crate::roomeq::OptimizerConfig> for OptimParams {
fn from(config: &crate::roomeq::OptimizerConfig) -> Self {
let peq_model = config
.peq_model
.parse::<PeqModel>()
.unwrap_or(PeqModel::Pk);
let loss = match config.loss_type.as_str() {
"flat" => {
if config.asymmetric_loss {
LossType::SpeakerFlatAsymmetric
} else {
LossType::SpeakerFlat
}
}
"score" => LossType::SpeakerScore,
"epa" => LossType::Epa,
other => {
log::warn!("Unknown loss_type '{}' in OptimizerConfig, defaulting to SpeakerFlat", other);
LossType::SpeakerFlat
}
};
Self {
num_filters: config.num_filters,
peq_model,
sample_rate: 48000.0, min_freq: config.min_freq,
max_freq: config.max_freq,
min_q: config.min_q,
max_q: config.max_q,
min_db: config.min_db,
max_db: config.max_db,
loss,
smooth: true,
smooth_n: config.smooth_n,
min_spacing_oct: 0.2,
spacing_weight: 20.0,
algo: config.algorithm.clone(),
population: config.population,
maxeval: config.max_iter,
refine: config.refine,
local_algo: config.local_algo.clone(),
strategy: config.strategy.clone(),
tolerance: config.tolerance,
atolerance: config.atolerance,
recombination: 0.9,
adaptive_weight_f: 0.9,
adaptive_weight_cr: 0.9,
no_parallel: false,
parallel_threads: num_cpus::get(),
seed: config.seed,
quiet: false,
}
}
}
impl std::str::FromStr for PeqModel {
type Err = String;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
"pk" => Ok(PeqModel::Pk),
"hp-pk" => Ok(PeqModel::HpPk),
"hp-pk-lp" => Ok(PeqModel::HpPkLp),
"ls-pk" => Ok(PeqModel::LsPk),
"ls-pk-hs" => Ok(PeqModel::LsPkHs),
"free-pk-free" => Ok(PeqModel::FreePkFree),
"free" => Ok(PeqModel::Free),
_ => Err(format!("Unknown PEQ model: {}", s)),
}
}
}