Skip to main content

rustysynth_ext/
instrument.rs

1use crate::error::SoundFontError;
2use crate::instrument_info::InstrumentInfo;
3use crate::instrument_region::InstrumentRegion;
4use crate::sample_header::SampleHeader;
5use crate::zone::Zone;
6
7/// Represents an instrument in the SoundFont.
8#[derive(Debug)]
9#[non_exhaustive]
10pub struct Instrument {
11    pub(crate) name: String,
12    pub(crate) regions: Vec<InstrumentRegion>,
13}
14
15impl Instrument {
16    fn new(
17        info: &InstrumentInfo,
18        instrument_id: usize,
19        zones: &[Zone],
20        samples: &[SampleHeader],
21    ) -> Result<Self, SoundFontError> {
22        let name = info.name.clone();
23
24        let zone_count = info.zone_end_index - info.zone_start_index + 1;
25        if zone_count <= 0 {
26            return Err(SoundFontError::InvalidInstrument(instrument_id));
27        }
28
29        let span_start = info.zone_start_index as usize;
30        let span_end = span_start + zone_count as usize;
31        let zone_span = &zones[span_start..span_end];
32        let regions = InstrumentRegion::create(instrument_id, zone_span, samples)?;
33
34        Ok(Self { name, regions })
35    }
36
37    pub(crate) fn create(
38        infos: &[InstrumentInfo],
39        zones: &[Zone],
40        samples: &[SampleHeader],
41    ) -> Result<Vec<Instrument>, SoundFontError> {
42        if infos.len() <= 1 {
43            return Err(SoundFontError::InstrumentNotFound);
44        }
45
46        // The last one is the terminator.
47        let count = infos.len() - 1;
48
49        let mut instruments: Vec<Instrument> = Vec::with_capacity(count);
50        for (instrument_id, info) in infos.iter().take(count).enumerate() {
51            instruments.push(Instrument::new(info, instrument_id, zones, samples)?);
52        }
53
54        Ok(instruments)
55    }
56
57    /// Gets the name of the instrument.
58    pub fn get_name(&self) -> &str {
59        &self.name
60    }
61
62    /// Gets the regions of the instrument.
63    pub fn get_regions(&self) -> &[InstrumentRegion] {
64        &self.regions[..]
65    }
66}