diff --git a/src/tone.rs b/src/tone.rs index ae76ff0..d8c8929 100644 --- a/src/tone.rs +++ b/src/tone.rs @@ -8,7 +8,7 @@ pub fn new(s: S) -> Tone { impl Tone { fn new(s: String) -> Tone { - let re = regex::Regex::new(r"^((?^[a-g])(?[+-]?)(?[1-5]?)|(?[0-9]+)|(?[^a-zA-Z0-9]))$").unwrap(); + let re = regex::Regex::new(r"^(((?^[a-g])(?[+-]?)|(?[A-G]M[0-6])|(?[A-G]m[0-6]))(?[1-5]?)|(?[0-9]+)|(?[^a-gA-G0-9]))$").unwrap(); let captures = re .captures(&s) .expect(format!("tone '{}' does not match regex", s).as_ref()); @@ -17,14 +17,31 @@ impl Tone { None => match captures.name("rest") { Some(_) => 0, _ => { - let mut result = match captures.name("letter").unwrap().as_str() { - "a" => 57, - "b" => 59, - "c" => 60, - "d" => 62, - "e" => 64, - "f" => 65, - _ => 67, + let mut result = match captures.name("letter") { + Some(letter) => Tone::char_to_middle_i32(letter.as_str()), + None => match captures.name("major") { + Some(major) => Tone::char_to_middle_i32(&major.as_str()[..1]) + match &major.as_str()[2..] { + "0" => 0, + "1" => 2, + "2" => 4, + "3" => 5, + "4" => 7, + "5" => 9, + _ => 11, + }, + None => { + let minor = captures.name("minor").unwrap(); + Tone::char_to_middle_i32(&minor.as_str()[..1]) + match &minor.as_str()[2..] { + "0" => 0, + "1" => 2, + "2" => 3, + "3" => 5, + "4" => 7, + "5" => 8, + _ => 10, + } + }, + }, } as i32; result += match captures.name("sharpness") { @@ -50,6 +67,18 @@ impl Tone { }) } + fn char_to_middle_i32(c: &str) -> i32 { + match c.to_lowercase().as_str() { + "a" => 57, + "b" => 59, + "c" => 60, + "d" => 62, + "e" => 64, + "f" => 65, + _ => 67, + } + } + pub fn i32(&self) -> i32 { self.0 } @@ -82,4 +111,48 @@ mod test { eprintln!("alpha mod octave"); assert_eq!(super::new("c+4").i32(), 60 + 12 + 1); } + + #[test] + fn test_tone_c_major() { + assert_eq!(super::new("CM0"), super::new("c")); + assert_eq!(super::new("CM1"), super::new("d")); + assert_eq!(super::new("CM2"), super::new("e")); + assert_eq!(super::new("CM3"), super::new("f")); + assert_eq!(super::new("CM4"), super::new("g")); + assert_eq!(super::new("CM5"), super::new("a4")); + assert_eq!(super::new("CM6"), super::new("b4")); + } + + #[test] + fn test_tone_c_minor() { + assert_eq!(super::new("Cm0"), super::new("c")); + assert_eq!(super::new("Cm1"), super::new("d")); + assert_eq!(super::new("Cm2"), super::new("e-")); + assert_eq!(super::new("Cm3"), super::new("f")); + assert_eq!(super::new("Cm4"), super::new("g")); + assert_eq!(super::new("Cm5"), super::new("a-4")); + assert_eq!(super::new("Cm6"), super::new("b-4")); + } + + #[test] + fn test_tone_a_major() { + assert_eq!(super::new("AM0"), super::new("a")); + assert_eq!(super::new("AM1"), super::new("b")); + assert_eq!(super::new("AM2"), super::new("c+")); + assert_eq!(super::new("AM3"), super::new("d")); + assert_eq!(super::new("AM4"), super::new("e")); + assert_eq!(super::new("AM5"), super::new("f+")); + assert_eq!(super::new("AM6"), super::new("g+")); + } + + #[test] + fn test_tone_a_minor() { + assert_eq!(super::new("Am0"), super::new("a")); + assert_eq!(super::new("Am1"), super::new("b")); + assert_eq!(super::new("Am2"), super::new("c")); + assert_eq!(super::new("Am3"), super::new("d")); + assert_eq!(super::new("Am4"), super::new("e")); + assert_eq!(super::new("Am5"), super::new("f")); + assert_eq!(super::new("Am6"), super::new("g")); + } } diff --git a/todo.yaml b/todo.yaml index ebbdfc5..9935048 100755 --- a/todo.yaml +++ b/todo.yaml @@ -1,9 +1,9 @@ todo: +- can output .wav +- can output .midi +scheduled: [] +done: - change define offset instead of only c==60 - change change offset instead of only c==60 in file - can choose minor/major/other scale - can change minor/major/other scale in file -- can output .wav -- can output .midi -scheduled: [] -done: []