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
use util;
pub fn chromatic_notes(root: (char, i8)) -> Vec<(char, i8)> {
let mut v = vec![];
v.push(('a', 0));
v.push(('a', 1));
v.push(('b', 0));
v.push(('c', 0));
v.push(('c', 1));
v.push(('d', 0));
v.push(('d', 1));
v.push(('e', 0));
v.push(('f', 0));
v.push(('f', 1));
v.push(('g', 0));
v.push(('g', 1));
let root_index = v.iter().position(|¬e| note == root || note == util::alt_note(root)).unwrap();
let a = v[..root_index].to_vec();
let b = v[root_index..].to_vec();
let mut v = vec![];
v.extend(b);
v.extend(a);
v
}
pub fn print_supported_scales() {
println!("Supported scales:");
for scale in supported_scales() {
println!("\t{}", scale);
}
println!("Custom scale syntax: --scale 1,2,1,3,2,1");
}
pub fn supported_scales() -> Vec<String> {
vec!["major", "minor", "harmonicminor", "melodicminor",
"dorian", "phrygian", "lydian", "locrian", "mixolydian",
"overtone", "augmented", "wholetone"
].iter().map(|s| s.to_string()).collect()
}
pub fn get_scale(scale: &str) -> Vec<u8> {
vec_sum(match scale {
"major" | "ionian" => vec![2,2,1,2,2,2,1],
"minor" | "naturalminor" | "aeolian" => vec![2,1,2,2,1,2,2],
"harmonicminor" => vec![2,1,2,2,1,3,1],
"melodicminor" => vec![2,1,2,2,2,2],
"dorian" => vec![2,1,2,2,2,1,2],
"phrygian" => vec![1,2,2,2,1,2,2],
"lydian" => vec![2,2,2,1,2,2,1],
"locrian" => vec![1,2,2,1,2,2,2],
"mixolydian" => vec![2,2,1,2,2,1,2],
"overtone" => vec![2,2,2,1,2,1],
"augmented" => vec![1,3,1,3,1],
"wholetone" => vec![2,2,2,2,2,2],
"chromatic" => vec![1,1,1,1,1,1,1,1,1,1,1,1],
_ => parse_scale(scale)
})
}
fn parse_scale(scalestr: &str) -> Vec<u8> {
scalestr.split(",").map(|s| s.parse::<u8>().unwrap_or(1)).collect()
}
fn vec_sum(interval: Vec<u8>) -> Vec<u8> {
let mut vec: Vec<u8> = vec![0];
vec.extend(interval.into_iter().scan(0, |sum, step| {
*sum = *sum + step;
Some(*sum)
}));
vec
}
pub fn friendly_name(name: &str) -> String {
String::from(match name {
"major" => "Major",
"minor" | "naturalminor" => "Natural minor",
"hmin" | "harmonicminor" => "Harmonic minor",
"augmented" => "Augmented",
"wholetone" => "Wholetone",
"melodicminor" => "Melodic minor",
"overtone" => "Overtone",
"chromatic" => "Chromatic",
_ => name
})
}