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 96 97 98 99 100 101 102 103 104
use crate::Chord;
use crate::Note;
/// Describes the entries contains in a `Phrase`
#[derive(Clone)]
pub enum PhraseEntry {
/// Silent Rest that has a rhythm value (see `constants::rhythm`)
Rest(f64),
/// A regular single `Note`
Note(Note),
/// A list of Notes played simultaneously
Chord(Chord),
}
impl PhraseEntry {
/// Returns the rhythm value of the entry.
/// In case of a Chord, this is the rhythm value specified in Chord::new(),
/// not the value of the notes of the Chord.
pub fn rhythm(&self) -> f64 {
match self {
PhraseEntry::Chord(c) => c.rhythm(),
PhraseEntry::Note(n) => n.rhythm(),
PhraseEntry::Rest(r) => *r,
}
}
}
/// Describes a single musical phrase. Multiple Phrases can be stored in a Part.
/// Phrases can be played in parallel too
#[derive(Default, Clone)]
pub struct Phrase {
/// list of entries in the phrase
entries: Vec<PhraseEntry>,
/// duration of the `Phrase`
duration: f64,
/// title of the phrase
name: String,
}
impl Phrase {
/// Returns a new `Phrase`
/// A `Phrase` contains entries that can be either a single `Note`, a `Chord` or a `Rest`
/// Entries in a Phrase are played sequentially.
pub fn new() -> Phrase {
Phrase::default()
}
/// Sets a name for the `Phrase`. The name does not have to be unique.
pub fn set_name<S: ToString>(&mut self, name: S) {
self.name = name.to_string();
}
/// Adds a note to the phrase. It starts after the previous
/// entry.
pub fn add_note(&mut self, note: Note) {
self.duration += note.rhythm();
self.entries.push(PhraseEntry::Note(note));
}
/// Adds multiple sequential notes to the phrase
/// Each note will be played after the previous one.
/// This function will clone the notes into the Phrase's entry Vec
pub fn add_sequential_notes<N: IntoIterator<Item = Note>>(&mut self, notes: N) {
for n in notes.into_iter() {
self.add_note(n);
}
}
/// Adds a chord to the phrase.
/// All notes of the Chord will start simultaneously
/// but can end at different times depending on their respective
/// rhythm values.
/// The following `Entry` of the `Phrase` will start at the end
/// of this `Chord`'s `rhythm` value, regardless of its inner notes'
/// duration.
/// Therefore, a `Chord` with a single `Note` (or several) allows to play the next
/// notes/chords while the current is still playing, by setting a `rhythm` shorter
/// than the notes it contains.
pub fn add_chord(&mut self, c: Chord) {
self.duration += c.rhythm();
self.entries.push(PhraseEntry::Chord(c));
}
/// Adds a rest to the phrase. It starts after the previous entry
pub fn add_rest(&mut self, rhythm: f64) {
self.duration += rhythm;
self.entries.push(PhraseEntry::Rest(rhythm));
}
/// Returns the Phrase's Vec of notes
pub fn entries(&self) -> &[PhraseEntry] {
self.entries.as_slice()
}
/// Returns the Phrase's name
pub fn name(&self) -> &str {
self.name.as_str()
}
// Returns the total duration (in beats, i.e. the "rhythm" unit) of the `Phrase`
pub fn duration(&self) -> f64 {
self.duration
}
}