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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
use crate::Chord;
use crate::Note;
use crate::Result;
/// Describes the entries contains in a `Phrase`
#[derive(Debug, 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(Debug, 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 {
Self::default()
}
/// Returns a new `Phrase` made of the sequential notes from the iterator
///
/// # Arguments
///
/// * `sequence`: iterator over the sequence of notes. Can be produced with `Note::new_sequence` for example
///
/// # Errors
///
/// This returns any error that can be found in the iterator entries
pub fn from_notes_sequence<N: IntoIterator<Item = Result<Note>>>(sequence: N) -> Result<Self> {
let mut duration = 0.;
let entries = sequence
.into_iter()
.map(|r| {
r.map(|n| {
duration += n.rhythm();
PhraseEntry::Note(n)
})
})
.collect::<Result<Vec<_>>>()?;
Ok(Self {
entries,
duration,
..Self::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 = Result<Note>>>(
&mut self,
notes: N,
) -> Result<()> {
for n in notes.into_iter() {
self.add_note(n?);
}
Ok(())
}
/// 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
}
}