rstmt_core/compose/impls/
impl_scale.rs

1/*
2    Appellation: impl_freq_to_scale <module>
3    Created At: 2025.12.21:08:58:02
4    Contrib: @FL03
5*/
6use crate::compose::Scale;
7use crate::freq::{
8    Frequency, IntoFrequency, RawFrequency, classify_freq_with_scale, get_frequency_of_pitch,
9};
10use num_traits::{Float, FromPrimitive};
11
12impl<T> Scale<T> {
13    pub const fn new(root: T) -> Self {
14        Self {
15            root: Frequency(root),
16        }
17    }
18    /// initialize a new scale using A4 as the root
19    pub fn a4() -> Self
20    where
21        T: FromPrimitive,
22    {
23        let root = <T>::from_usize(440).unwrap();
24        Self::new(root)
25    }
26
27    /// creates a new [`Scale`] from the given root frequency
28    pub const fn from_freq(root: Frequency<T>) -> Self {
29        Self { root }
30    }
31    /// returns a reference to the base frequency
32    pub const fn root(&self) -> &Frequency<T> {
33        &self.root
34    }
35    /// returns a mutable reference to the base frequency
36    pub const fn root_mut(&mut self) -> &mut Frequency<T> {
37        &mut self.root
38    }
39    /// classifies the given frequency as a pitch class `n`, using the formula:
40    ///
41    /// ```math
42    /// n=\text{round}(12\cdot\log_{2}(\frac{F}{\beta}))
43    /// ```
44    pub fn classify(&self, Frequency(freq): Frequency<T>) -> Option<isize>
45    where
46        T: RawFrequency + Float + FromPrimitive,
47    {
48        // Ensure frequency is positive
49        if freq <= T::zero() {
50            return None;
51        }
52        classify_freq_with_scale(freq, self.root().value())
53    }
54    /// returns the frequency $F$, in hertz [Hz], of the given pitch class `n`, using:
55    ///
56    /// ```math
57    /// F=\beta\cdot{2^{\frac{n}{12}}}
58    /// ```
59    pub fn get_freq_of_class(&self, n: isize) -> Frequency<T>
60    where
61        T: RawFrequency + Float + FromPrimitive,
62    {
63        get_frequency_of_pitch(n, self.root().value()).into_frequency()
64    }
65}