rustysynth_ext/
instrument.rs1use crate::error::SoundFontError;
2use crate::instrument_info::InstrumentInfo;
3use crate::instrument_region::InstrumentRegion;
4use crate::sample_header::SampleHeader;
5use crate::zone::Zone;
6
7#[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 Some(span_end) = span_start.checked_add(zone_count as usize) else {
31 return Err(SoundFontError::InvalidInstrument(instrument_id));
32 };
33 let Some(zone_span) = zones.get(span_start..span_end) else {
34 return Err(SoundFontError::InvalidInstrument(instrument_id));
35 };
36 let regions = InstrumentRegion::create(instrument_id, zone_span, samples)?;
37
38 Ok(Self { name, regions })
39 }
40
41 pub(crate) fn create(
42 infos: &[InstrumentInfo],
43 zones: &[Zone],
44 samples: &[SampleHeader],
45 ) -> Result<Vec<Instrument>, SoundFontError> {
46 if infos.len() <= 1 {
47 return Err(SoundFontError::InstrumentNotFound);
48 }
49
50 let count = infos.len() - 1;
52
53 let mut instruments: Vec<Instrument> = Vec::with_capacity(count);
54 for (instrument_id, info) in infos.iter().take(count).enumerate() {
55 instruments.push(Instrument::new(info, instrument_id, zones, samples)?);
56 }
57
58 Ok(instruments)
59 }
60
61 pub fn get_name(&self) -> &str {
63 &self.name
64 }
65
66 pub fn get_regions(&self) -> &[InstrumentRegion] {
68 &self.regions[..]
69 }
70}