tone accepts T,t,f for majorThird, minorThird, perfectFifth lazily

This commit is contained in:
Bel LaPointe
2026-03-13 13:01:05 -06:00
parent fedd6abbff
commit 5b9d3a8bb7
5 changed files with 89 additions and 19 deletions

View File

@@ -2,4 +2,4 @@
# f -> c -> g -> d -> a -> e -> b
f c g d a e b
ff cf gf df af ef bf

View File

@@ -0,0 +1,19 @@
CM0 CM3 CM4 CM0
CM0T CM3T CM4T CM0T
CM0f CM3f CM4f CM0f
.
.
.
CM1 CM4 CM0
CM1T CM4T CM0T
CM1f CM4f CM0f
.
.
.
CM0 CM4 CM5 CM3
CM0T CM4T CM5T CM3T
CM0f CM4f CM5f CM3f

View File

@@ -3,16 +3,16 @@
# c,e c+,f d,f+
c c+ d
e f f+
cT c+T dT
# d+,g e,g+ f,a
d+ e f
g g+ a
d+T eT fT
# f+,a+ g,b g+,c
f+ g g+
a+ b c
f+T gT g+T
# a,c+ a+,d b,d+
a a+ b
c+ d d+
aT a+T bT

View File

@@ -3,16 +3,16 @@
# c,e- c+,e d,f
c c+ d
e- e f
ct c+t dt
# d+,f+ e,g f,g+
d+ e f
f+ g g+
d+t et ft
# f+,a g,a+ g+,b
f+ g g+
a a+ b
f+t gt g+t
# a,c a+,c+ b,d
a a+ b
c c+ d
at a+t bt

View File

@@ -8,7 +8,7 @@ pub fn new<S: ToString>(s: S) -> Tone {
impl Tone {
fn new(s: String) -> Tone {
let re = regex::Regex::new(r"^(((?<letter>^[a-g])(?<sharpness>[+-]?)|(?<major>[A-G]M[0-6])|(?<minor>[A-G]m[0-6]))(?<octave>[1-5]?)|(?<numeric>[0-9]+)|(?<rest>[^a-gA-G0-9]))$").unwrap();
let re = regex::Regex::new(r"^(((?<letter>^[a-g])(?<sharpness>[+-]?)|(?<major>[A-G]M[0-6])|(?<minor>[A-G]m[0-6]))(?<octave>[1-5]?)((?<major_third>T)|(?<minor_third>t)|(?<fifth>f))?|(?<numeric>[0-9]+)|(?<rest>[^a-gA-G0-9]))$").unwrap();
let captures = re
.captures(&s)
.expect(format!("tone '{}' does not match regex", s).as_ref());
@@ -65,6 +65,21 @@ impl Tone {
None => 0,
} as i32;
result += match captures.name("major_third") {
Some(_) => 4, // TODO not all are good
None => 0,
} as i32;
result += match captures.name("minor_third") {
Some(_) => 3, // TODO not all are good
None => 0,
} as i32;
result += match captures.name("fifth") {
Some(_) => 7,
None => 0,
} as i32;
result
}
},
@@ -144,6 +159,42 @@ mod test {
assert_eq!(super::new("c+4").i32(), 60 + 12 + 1);
}
#[test]
fn test_tone_new_major_third() {
assert_eq!(super::new("cT").i32(), 60 + 4);
assert_eq!(super::new("c1T").i32(), 60 + 4 - 24);
assert_eq!(super::new("c+T").i32(), 60 + 1 + 4);
assert_eq!(super::new("c+1T").i32(), 60 + 1 + 4 - 24);
assert_eq!(super::new("CM0T").i32(), 60 + 4);
assert_eq!(super::new("CM01T").i32(), 60 + 4 - 24);
}
#[test]
fn test_tone_new_minor_third() {
assert_eq!(super::new("ct").i32(), 60 + 3);
assert_eq!(super::new("c1t").i32(), 60 + 3 - 24);
assert_eq!(super::new("c+t").i32(), 60 + 1 + 3);
assert_eq!(super::new("c+1t").i32(), 60 + 1 + 3 - 24);
assert_eq!(super::new("CM0t").i32(), 60 + 3);
assert_eq!(super::new("CM01t").i32(), 60 + 3 - 24);
}
#[test]
fn test_tone_new_fifth() {
assert_eq!(super::new("cf").i32(), 60 + 7);
assert_eq!(super::new("c1f").i32(), 60 + 7 - 24);
assert_eq!(super::new("c+f").i32(), 60 + 1 + 7);
assert_eq!(super::new("c+1f").i32(), 60 + 1 + 7 - 24);
assert_eq!(super::new("CM0f").i32(), 60 + 7);
assert_eq!(super::new("CM01f").i32(), 60 + 7 - 24);
}
#[test]
fn test_tone_c_major() {
assert_eq!(super::new("CM0"), super::new("c"));