use crate::Variant;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct Factors {
pub x_ratio: f64,
pub y_ratio: f64,
pub treble_offset: f64,
}
impl Default for Factors {
fn default() -> Self {
Self::init(655.0, &Variant::default(), 43.0, 56.0)
}
}
impl Factors {
pub fn init(scale: f64, variant: &Variant, nut: f64, bridge: f64) -> Self {
let height = (bridge - nut) / 2.0;
let y_ratio = height / scale;
let x_ratio = y_ratio.acos().sin();
let pfret = variant.pfret().unwrap_or(8.0);
let factor = 2.0_f64.powf(pfret / 12.0);
let length_bass = scale / factor;
let length_treble = match variant {
Variant::Monoscale => length_bass,
Variant::Multiscale { scale: s, .. } => s / factor,
};
let bass_pfret = x_ratio * length_bass;
let treble_pfret = x_ratio * length_treble;
let treble_offset = bass_pfret - treble_pfret;
Self {
x_ratio,
y_ratio,
treble_offset,
}
}
}
#[cfg(test)]
mod tests {
use crate::Specs;
#[test]
fn factors_default() {
let specs = Specs::default();
assert_eq!(specs.factors.x_ratio, 0.9999507592328689);
assert_eq!(specs.factors.y_ratio, 0.009923664122137405);
assert_eq!(specs.factors.treble_offset, 0.0);
}
#[test]
fn factors_multi() {
let specs = Specs::multi();
assert_eq!(specs.factors.x_ratio, 0.9999507592328689);
assert_eq!(specs.factors.y_ratio, 0.009923664122137405);
assert_eq!(specs.factors.treble_offset, 28.346827734356623);
}
}