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}