Skip to content

Commit 34c3de9

Browse files
committed
wip
1 parent 698016c commit 34c3de9

File tree

3 files changed

+61
-10
lines changed

3 files changed

+61
-10
lines changed

apps/notation_kb/src/theory/scale.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ impl KbPage for ScalePage {
3838
for s in Scale::ALL.iter() {
3939
if ui.selectable_label(*s == scale, s.to_ident()).clicked() {
4040
self.scale = s.clone();
41+
self.key = s.get_keys()[0];
4142
}
4243
}
4344
});
@@ -97,8 +98,13 @@ impl ScalePage {
9798
let mut entries = vec![];
9899
let duration = Duration::_1_4;
99100
let mut add_note = |syllable: &Syllable, semitones: Option<Semitones>| {
101+
let octave = if self.scale.calc_do_offset() > 0 {
102+
Octave::P3
103+
} else {
104+
Octave::P4
105+
};
100106
let note = Note::from(
101-
Semitones::from(Octave::CENTER)
107+
Semitones::from(octave)
102108
+ Semitones::from(self.key.clone())
103109
+ Semitones::from(self.scale.calc_syllable_for_sort(syllable))
104110
+ semitones.unwrap_or(Semitones(0))

crates/notation_core/src/pitch.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::ops::{Add, Sub};
33

44
use serde::{Deserialize, Serialize};
55

6+
use crate::prelude::Key;
7+
68
// https://hellomusictheory.com/learn/
79
// http://openmusictheory.com/pitches.html
810
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug)]
@@ -310,6 +312,16 @@ impl From<Semitones> for Pitch {
310312
}
311313
}
312314

315+
impl From<Key> for Pitch {
316+
fn from(v: Key) -> Self {
317+
match v {
318+
Key::Natural(name) => Self::new(name, PitchSign::Natural),
319+
Key::Sharp(name) => Self::new(name, PitchSign::Sharp),
320+
Key::Flat(name) => Self::new(name, PitchSign::Flat),
321+
}
322+
}
323+
}
324+
313325
impl Pitch {
314326
pub fn to_text(&self) -> String {
315327
format!("{}", self)

crates/notation_core/src/scale.rs

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,29 @@ impl Scale {
118118
],
119119
}
120120
}
121+
pub fn calc_key_index(&self, key: Key) -> usize {
122+
let offset = Semitones::from(key) - Semitones::from(self.get_keys()[0]);
123+
let offset_val = if offset.0 >= 0 { offset.0 % 12 } else { offset.0 % 12 + 12 };
124+
match offset_val {
125+
0 => 0,
126+
1 => 7,
127+
2 => 2,
128+
3 => 9,
129+
4 => 4,
130+
5 => 11,
131+
6 => 6,
132+
7 => 1,
133+
8 => 8,
134+
9 => 3,
135+
10 => 10,
136+
11 => 5,
137+
_ => 0,
138+
}
139+
}
121140
//https://www.hooktheory.com/cheat-sheet
122-
pub fn get_keys(&self) -> Vec<Key> {
141+
pub fn get_keys(&self) -> [Key; 12] {
123142
match self {
124-
Scale::Ionian => vec![
143+
Scale::Ionian => [
125144
Key::C,
126145
Key::G,
127146
Key::D,
@@ -135,7 +154,7 @@ impl Scale {
135154
Key::B_FLAT,
136155
Key::F,
137156
],
138-
Scale::Dorian => vec![
157+
Scale::Dorian => [
139158
Key::D,
140159
Key::A,
141160
Key::E,
@@ -149,7 +168,7 @@ impl Scale {
149168
Key::C,
150169
Key::G,
151170
],
152-
Scale::Phrygian => vec![
171+
Scale::Phrygian => [
153172
Key::E,
154173
Key::B,
155174
Key::F_SHARP,
@@ -163,7 +182,7 @@ impl Scale {
163182
Key::D,
164183
Key::A,
165184
],
166-
Scale::Lydian => vec![
185+
Scale::Lydian => [
167186
Key::F,
168187
Key::C,
169188
Key::G,
@@ -177,7 +196,7 @@ impl Scale {
177196
Key::E_FLAT,
178197
Key::B_FLAT,
179198
],
180-
Scale::Mixolydian => vec![
199+
Scale::Mixolydian => [
181200
Key::G,
182201
Key::D,
183202
Key::A,
@@ -191,7 +210,7 @@ impl Scale {
191210
Key::F,
192211
Key::C,
193212
],
194-
Scale::Aeolian => vec![
213+
Scale::Aeolian => [
195214
Key::A,
196215
Key::E,
197216
Key::B,
@@ -205,7 +224,7 @@ impl Scale {
205224
Key::G,
206225
Key::D,
207226
],
208-
Scale::Locrian => vec![
227+
Scale::Locrian => [
209228
Key::B,
210229
Key::F_SHARP,
211230
Key::C_SHARP,
@@ -261,7 +280,21 @@ impl Scale {
261280
(Semitones::from(*pitch) - self.calc_do_semitones(key)).into()
262281
}
263282
pub fn calc_pitch(&self, key: &Key, syllable: &Syllable) -> Pitch {
264-
(Semitones::from(*syllable) + self.calc_do_semitones(key)).into()
283+
let key_index = self.calc_key_index(key.clone());
284+
if let Some(keys) = match syllable {
285+
Syllable::Do => Some(Scale::Ionian.get_keys()),
286+
Syllable::Re => Some(Scale::Dorian.get_keys()),
287+
Syllable::Mi => Some(Scale::Phrygian.get_keys()),
288+
Syllable::Fa => Some(Scale::Lydian.get_keys()),
289+
Syllable::So => Some(Scale::Mixolydian.get_keys()),
290+
Syllable::La => Some(Scale::Aeolian.get_keys()),
291+
Syllable::Ti => Some(Scale::Locrian.get_keys()),
292+
_ => None,
293+
} {
294+
keys[key_index].into()
295+
} else {
296+
(Semitones::from(*syllable) + self.calc_do_semitones(key)).into()
297+
}
265298
}
266299
pub fn calc_syllable_note(&self, key: &Key, note: &Note) -> SyllableNote {
267300
(Semitones::from(*note) - self.calc_do_semitones(key)).into()

0 commit comments

Comments
 (0)