1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
use crate::context::{generate_id, Dynamic};
use amm_internal::amm_prelude::*;
use amm_macros::{JsonDeserialize, JsonSerialize, ModOrder};
/// Represents a type of pedal used in piano playing.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, ModOrder, JsonDeserialize, JsonSerialize)]
pub enum PedalType {
/// 
#[default]
Sustain,
/// Usually denoted as `sost.` in sheet music.
Sostenuto,
/// Usually denoted as `una corda` in sheet music.
Soft,
}
/// Represents a type of modification to a phrase.
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, ModOrder, JsonDeserialize, JsonSerialize)]
pub enum PhraseModificationType {
/// 
///
/// Represents a gradual increase in volume over a series of notes.
///
/// The `final_dynamic` field is optional and represents the dynamic
/// level that the crescendo should reach by the end of the phrase.
Crescendo { final_dynamic: Option<Dynamic> },
/// 
///
/// Represents a gradual decrease in volume over a series of notes.
///
/// The `final_dynamic` field is optional and represents the dynamic
/// level that the decrescendo should reach by the end of the phrase.
Decrescendo { final_dynamic: Option<Dynamic> },
/// 
Glissando,
/// 
///
/// Represents a gradual increase in volume followed by a gradual
/// decrease in volume over a series of notes.
///
/// The `maximum_dynamic` field is optional and represents the dynamic
/// level that the hairpin should reach by the middle of the phrase.
Hairpin { maximum_dynamic: Option<Dynamic> },
/// 
#[default]
Legato,
/// 
OctaveShift { num_octaves: i8 },
/// Represents a change in the use of a pedal for the current phrase.
Pedal { pedal_type: PedalType },
/// 
Portamento,
/// 
Tremolo { relative_speed: u8 },
/// 
///
/// 
Tuplet { num_beats: u8, into_beats: u8 },
}
/// Represents a modification to a phrase.
#[derive(Debug, Default, Eq, JsonDeserialize, JsonSerialize)]
pub struct PhraseModification {
/// The unique identifier for this modification.
id: usize,
/// The type of phrase modification.
pub r#type: PhraseModificationType,
}
impl PhraseModification {
/// Creates a new phrase modification based on the given type.
#[must_use]
pub fn new(r#type: PhraseModificationType) -> Self {
Self {
id: generate_id(),
r#type,
}
}
/// Returns the unique identifier for this modification.
#[must_use]
pub fn get_id(&self) -> usize {
self.id
}
}
impl Clone for PhraseModification {
fn clone(&self) -> Self {
Self {
id: generate_id(),
r#type: self.r#type,
}
}
}
impl PartialEq for PhraseModification {
fn eq(&self, other: &Self) -> bool {
self.r#type == other.r#type
}
}
impl Ord for PhraseModification {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.r#type.cmp(&other.r#type)
}
}
impl PartialOrd for PhraseModification {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[cfg(feature = "print")]
impl core::fmt::Display for PedalType {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(
f,
"{}",
match self {
Self::Sustain => "Sustain",
Self::Sostenuto => "Sostenuto",
Self::Soft => "Soft",
}
)
}
}
#[cfg(feature = "print")]
impl core::fmt::Display for PhraseModificationType {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self {
Self::Crescendo {
final_dynamic: Some(dynamic),
} => write!(f, "Crescendo to {dynamic}"),
Self::Crescendo { final_dynamic: None } => write!(f, "Crescendo"),
Self::Decrescendo {
final_dynamic: Some(dynamic),
} => write!(f, "Decrescendo to {dynamic}"),
Self::Decrescendo { final_dynamic: None } => write!(f, "Decrescendo"),
Self::Glissando => write!(f, "Glissando"),
Self::Hairpin {
maximum_dynamic: Some(dynamic),
} => write!(f, "Hairpin to {dynamic}"),
Self::Hairpin { maximum_dynamic: None } => write!(f, "Hairpin"),
Self::Legato => write!(f, "Legato"),
Self::OctaveShift { num_octaves } => write!(f, "Octave Shift: by {num_octaves}"),
Self::Pedal { pedal_type } => write!(f, "Pedal: {pedal_type}"),
Self::Portamento => write!(f, "Portamento"),
Self::Tremolo { relative_speed } => write!(f, "Tremolo: {relative_speed}x speed"),
Self::Tuplet { num_beats, into_beats } => write!(f, "Tuplet: {num_beats}:{into_beats}"),
}
}
}
#[cfg(feature = "print")]
impl core::fmt::Display for PhraseModification {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{}", self.r#type)
}
}