Skip to main content

sim_lib_pitch_serial/
alphabet.rs

1//! The canonical chromatic pitch-class alphabet.
2
3use sim_lib_pitch_core::PitchClass;
4use sim_lib_serial_core::{AlphabetError, AlphabetId, FiniteAlphabet, SerialAlphabet};
5
6const CANONICAL_CLASSES: [PitchClass; 12] = [
7    PitchClass::C,
8    PitchClass::CS,
9    PitchClass::D,
10    PitchClass::DS,
11    PitchClass::E,
12    PitchClass::F,
13    PitchClass::FS,
14    PitchClass::G,
15    PitchClass::GS,
16    PitchClass::A,
17    PitchClass::AS,
18    PitchClass::B,
19];
20
21/// The stable twelve-symbol alphabet of canonical [`PitchClass`] values.
22///
23/// Construction delegates uniqueness and stable-id validation to
24/// [`FiniteAlphabet`]. The order is the canonical numeric order `C = 0` through
25/// `B = 11`; no spelling aliases or private pitch representation are introduced.
26#[derive(Clone, Debug, PartialEq, Eq)]
27pub struct PitchClassAlphabet {
28    inner: FiniteAlphabet<PitchClass>,
29}
30
31impl PitchClassAlphabet {
32    /// Constructs the canonical pitch-class alphabet.
33    pub fn try_new() -> Result<Self, AlphabetError> {
34        Ok(Self {
35            inner: FiniteAlphabet::try_new(
36                AlphabetId::try_new("pitch-class/12tet-v1")?,
37                CANONICAL_CLASSES.to_vec(),
38            )?,
39        })
40    }
41
42    /// Returns the stable alphabet identity.
43    pub fn id(&self) -> &AlphabetId {
44        self.inner.id()
45    }
46
47    /// Returns all twelve canonical classes in numeric order.
48    pub fn classes(&self) -> &[PitchClass] {
49        self.inner.symbols()
50    }
51}
52
53impl SerialAlphabet for PitchClassAlphabet {
54    type Symbol = PitchClass;
55
56    fn id(&self) -> &AlphabetId {
57        self.inner.id()
58    }
59
60    fn symbols(&self) -> &[Self::Symbol] {
61        self.inner.symbols()
62    }
63}