rust_music/part.rs
1use crate::{Instrument, Phrase};
2
3/// Describes a score's part. A `Part` is played by a single
4/// instrument and can contain multiple phrases, played sequentially
5/// or simultaneously
6#[derive(Debug, Default, Clone, PartialEq)]
7pub struct Part {
8 /// The phrases of the `Part`, indexed by the beat at which they start
9 phrases: Vec<(f64, Phrase)>,
10 /// The instrument playing the `Part`
11 instrument: Instrument,
12 /// The length in beats of the `Part`
13 duration: f64,
14 /// The end time in beat of the last added `Phrase`
15 previous_phrase_end: f64,
16 /// The title of the `Part`
17 name: String,
18}
19
20impl Part {
21 /// Returns a new empty `Part` with the given `name` and `instrument`
22 ///
23 /// # Arguments
24 ///
25 /// * `name` - title of the `Part`
26 /// * `instrument` - instrument playing the `Part`
27 pub fn new(instrument: Instrument) -> Part {
28 Part {
29 phrases: Vec::new(),
30 instrument,
31 duration: 0.,
32 previous_phrase_end: 0.,
33 name: String::default(),
34 }
35 }
36
37 /// Sets a name for the `Part`. The name does not have to be unique.
38 pub fn set_name<S: ToString>(&mut self, name: S) {
39 self.name = name.to_string();
40 }
41
42 /// Inserts a `Phrase` in the `Part`. The phrase will start at beat `start_beat`.
43 /// Each beat corresponds to `1.0` in rhythm value.
44 /// The `Phrase` can be played in parallel with other phrases if `start_beat` is
45 /// smaller then their length.
46 pub fn add_phrase(&mut self, phrase: Phrase, start_beat: f64) {
47 let phrase_end = start_beat + phrase.duration();
48 self.duration = self.duration.max(phrase_end);
49 self.previous_phrase_end = phrase_end;
50 self.phrases.push((start_beat, phrase))
51 }
52
53 /// Appends a `Phrase` immediately at the end of the last added `Phrase`.
54 /// If phrases added before the last one were longer, they can be played
55 /// in parallel with the new `Phrase`.
56 pub fn append_phrase_to_previous(&mut self, phrase: Phrase) {
57 self.add_phrase(phrase, self.previous_phrase_end)
58 }
59
60 /// Appends a `Phrase` immediately at the end of the entire `Part`, i.e. the end
61 /// of the `Phrase` that ends the latest
62 pub fn append_phrase_to_part_end(&mut self, phrase: Phrase) {
63 self.add_phrase(phrase, self.duration)
64 }
65
66 /// Returns the title of the `Part`
67 pub fn name(&self) -> &str {
68 self.name.as_str()
69 }
70
71 /// Returns the map of phrases of the `Part`
72 pub fn phrases(&self) -> &[(f64, Phrase)] {
73 &self.phrases
74 }
75
76 /// Returns the instrument playing the `Part`
77 pub fn instrument(&self) -> Instrument {
78 self.instrument
79 }
80
81 // Returns the total duration (in beats, i.e. the "rhythm" unit) of the `Part`.
82 // This corresponds to the end of the `Phrase` that finishes the latest.
83 pub fn duration(&self) -> f64 {
84 self.duration
85 }
86}