music21_rs/tuningsystem/
adaptive.rs1use crate::{
2 FloatType, TuningSystem, UnsignedIntegerType,
3 tuningsystem::{get_frequency_at, get_ratio_at},
4};
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub enum AdaptiveTuningSystem {
10 Recursive {
19 root_tuning_system: TuningSystem,
21
22 local_tuning_system: TuningSystem,
24 },
25}
26
27pub const RECURSIVE_JI: AdaptiveTuningSystem = AdaptiveTuningSystem::Recursive {
31 root_tuning_system: TuningSystem::JustIntonation,
32 local_tuning_system: TuningSystem::JustIntonation,
33};
34
35impl AdaptiveTuningSystem {
36 pub fn frequency_at(
48 self,
49 context: FloatType,
50 index: FloatType,
51 size: Option<UnsignedIntegerType>,
52 ) -> FloatType {
53 match self {
54 Self::Recursive {
55 root_tuning_system,
56 local_tuning_system,
57 } => {
58 let root_ratio = get_ratio_at(root_tuning_system, context, size);
59 let local_frequency = get_frequency_at(local_tuning_system, index, size);
60
61 root_ratio * local_frequency
62 }
63 }
64 }
65
66 pub fn cents_at(
71 self,
72 context: FloatType,
73 index: FloatType,
74 size: Option<UnsignedIntegerType>,
75 ) -> FloatType {
76 let octave_size = size.unwrap_or_else(|| match self {
77 Self::Recursive {
78 root_tuning_system, ..
79 } => root_tuning_system.octave_size(),
80 });
81
82 let reference_frequency = get_frequency_at(
83 TuningSystem::EqualTemperament { octave_size },
84 context + index,
85 Some(octave_size),
86 );
87
88 let comparison_frequency = self.frequency_at(context, index, size);
89
90 1200.0 * (comparison_frequency / reference_frequency).log2()
91 }
92
93 pub fn cents_vs_fixed_at(
97 self,
98 fixed_tuning_system: TuningSystem,
99 context: FloatType,
100 index: FloatType,
101 size: Option<UnsignedIntegerType>,
102 ) -> FloatType {
103 let fixed_frequency = get_frequency_at(fixed_tuning_system, context + index, size);
104 let comparison_frequency = self.frequency_at(context, index, size);
105
106 1200.0 * (comparison_frequency / fixed_frequency).log2()
107 }
108}