Struct musical_note::Key

source ·
pub struct Key {
    pub tonic: (NoteName, Accidental),
    pub scale: Scale,
}

Fields§

§tonic: (NoteName, Accidental)§scale: Scale

Implementations§

Examples found in repository?
src/lib.rs (line 399)
398
399
400
    fn default() -> Self {
        Self::new(Default::default(), Default::default(), Default::default())
    }

[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,
        }
    }

“as” or “eis” — without octave.

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
Deserialize this value from the given Serde deserializer. Read more
Converts to this type from the input type.
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.