Struct musical_note::Key
source · pub struct Key {
pub tonic: (NoteName, Accidental),
pub scale: Scale,
}Fields§
§tonic: (NoteName, Accidental)§scale: ScaleImplementations§
source§impl Key
impl Key
sourcepub fn new(note: NoteName, accidental: Accidental, scale: Scale) -> Self
pub fn new(note: NoteName, accidental: Accidental, scale: Scale) -> Self
sourcepub fn get_root(&self) -> [u8; 2]
pub fn get_root(&self) -> [u8; 2]
[root_midi, root_index]
root_midi is u8 in rage 0..12, based on note name and accidental.
root_index is u8 in rage 0..7, based only on note name.
Examples found in repository?
src/lib.rs (line 529)
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619
pub fn resolve_pitch(
&self,
notes_map: &NotesMap,
midi_note: u8,
octave: Octave,
) -> ResolvedNote {
let note: (NoteName, Accidental);
let key_root_midi = self.key.get_root()[0];
match self.degree_midi.binary_search(&midi_note) {
Ok(note_index) => {
note = self.degree_notes[note_index];
// println!("found note from scale {:?} at index {:?}", note, note_index);
}
Err(_err) => {
if midi_note == key_root_midi + 1 && self.key.scale == Scale::Minor {
// println!("that is minor II♭");
note = notes_map
.resolve_note_for_midi(self.degree_notes[1 as usize], midi_note)
.unwrap();
} else if midi_note == (key_root_midi + 8) % 12 && self.key.scale == Scale::Major {
// println!("that is major VI♭");
let candidate_note = self.degree_notes[5 as usize];
note = notes_map
.resolve_note_for_midi(candidate_note, midi_note)
.unwrap();
} else {
// println!("just search for anything for midi: {:?}", midi_note);
note = notes_map
.resolve_enharmonic(self.used_accidentals.last().copied(), midi_note);
}
}
}
ResolvedNote::new(note.0, note.1, octave, octave.apply_to_midi_note(midi_note))
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Serialize, Deserialize)]
pub enum Scale {
Major,
Minor,
Dorian,
Phrygian,
Lydian,
Mixolidyan,
Locrian,
}
impl Scale {
/// Get interval structure of the scale.
pub fn structure(&self) -> [u8; 6] {
match self {
Self::Major => [2, 2, 1, 2, 2, 2],
Self::Minor => [2, 1, 2, 2, 1, 2],
Self::Dorian => [2, 1, 2, 2, 2, 1],
Self::Phrygian => [1, 2, 2, 2, 1, 2],
Self::Lydian => [2, 2, 2, 1, 2, 2],
Self::Mixolidyan => [2, 2, 1, 2, 2, 1],
Self::Locrian => [1, 2, 2, 1, 2, 2],
}
}
/// Make concrete representation, based on given Key.
fn resolve_for_key(&self, notes_map: &NotesMap, key: &Key) -> ResolvedScale {
let root = key.get_root();
let (root_midi, _root_idx) = (root[0], root[1]);
let mut degree_midi = [root_midi; 7];
let mut degree_notes = [key.tonic; 7];
let mut used_accidentals = Vec::with_capacity(10);
for (idx, interval) in self.structure().iter().enumerate() {
let mut next_midi = degree_midi[idx];
next_midi += interval;
if next_midi > 11 {
next_midi %= 12;
}
let index = degree_notes[idx].0.index() + 1;
let candidate_note = NoteName::by_index(index);
// println!(
// "candidate_note: {:?}, next_midi: {:?}",
// candidate_note, next_midi
// );
let next_note = notes_map
.resolve_note_for_midi((candidate_note, Accidental::White), next_midi)
.unwrap();
degree_notes[idx + 1] = next_note;
degree_midi[idx + 1] = next_midi;
if next_note.1 != Accidental::White {
used_accidentals.push(next_note.1);
}
// println!(
// "next_note: {:?}, degree_notes: {:?}, degree_midi: {:?}, used_accidentals: {:?}",
// next_note, degree_notes, degree_midi, used_accidentals
// )
}
ResolvedScale {
key: *key,
degree_midi,
degree_notes,
used_accidentals,
}
}Trait Implementations§
source§impl<'de> Deserialize<'de> for Key
impl<'de> Deserialize<'de> for Key
source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Deserialize this value from the given Serde deserializer. Read more
source§impl PartialOrd<Key> for Key
impl PartialOrd<Key> for Key
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
This method tests less than or equal to (for
self and other) and is used by the <=
operator. Read more