Skip to main content

rustysynth_ext/
preset.rs

1use crate::error::SoundFontError;
2use crate::instrument::Instrument;
3use crate::preset_info::PresetInfo;
4use crate::preset_region::PresetRegion;
5use crate::zone::Zone;
6
7/// Represents a preset in the SoundFont.
8#[derive(Debug)]
9#[non_exhaustive]
10pub struct Preset {
11    pub(crate) name: String,
12    pub(crate) patch_number: i32,
13    pub(crate) bank_number: i32,
14    pub(crate) library: i32,
15    pub(crate) genre: i32,
16    pub(crate) morphology: i32,
17    pub(crate) regions: Vec<PresetRegion>,
18}
19
20impl Preset {
21    fn new(
22        info: &PresetInfo,
23        preset_id: usize,
24        zones: &[Zone],
25        instruments: &[Instrument],
26    ) -> Result<Self, SoundFontError> {
27        let name = info.name.clone();
28
29        let zone_count = info.zone_end_index - info.zone_start_index + 1;
30        if zone_count <= 0 {
31            return Err(SoundFontError::InvalidPreset(preset_id));
32        }
33
34        let span_start = info.zone_start_index as usize;
35        let Some(span_end) = span_start.checked_add(zone_count as usize) else {
36            return Err(SoundFontError::InvalidPreset(preset_id));
37        };
38        let Some(zone_span) = zones.get(span_start..span_end) else {
39            return Err(SoundFontError::InvalidPreset(preset_id));
40        };
41        let regions = PresetRegion::create(preset_id, zone_span, instruments)?;
42
43        Ok(Self {
44            name,
45            patch_number: info.patch_number,
46            bank_number: info.bank_number,
47            library: info.library,
48            genre: info.genre,
49            morphology: info.morphology,
50            regions,
51        })
52    }
53
54    pub(crate) fn create(
55        infos: &[PresetInfo],
56        zones: &[Zone],
57        instruments: &[Instrument],
58    ) -> Result<Vec<Preset>, SoundFontError> {
59        if infos.len() <= 1 {
60            return Err(SoundFontError::PresetNotFound);
61        }
62
63        // The last one is the terminator.
64        let count = infos.len() - 1;
65
66        let mut presets: Vec<Preset> = Vec::with_capacity(count);
67        for (preset_id, info) in infos.iter().take(count).enumerate() {
68            presets.push(Preset::new(info, preset_id, zones, instruments)?);
69        }
70
71        Ok(presets)
72    }
73
74    /// Gets the name of the preset.
75    pub fn get_name(&self) -> &str {
76        &self.name
77    }
78
79    /// Gets the patch number of the preset.
80    pub fn get_patch_number(&self) -> i32 {
81        self.patch_number
82    }
83
84    /// Gets the bank number of the preset.
85    pub fn get_bank_number(&self) -> i32 {
86        self.bank_number
87    }
88
89    /// Gets the library info.
90    pub fn get_library(&self) -> i32 {
91        self.library
92    }
93
94    /// Gets the genre info.
95    pub fn get_genre(&self) -> i32 {
96        self.genre
97    }
98
99    /// Gets the morphology info.
100    pub fn get_morphology(&self) -> i32 {
101        self.morphology
102    }
103
104    /// Gets the regions of the preset.
105    pub fn get_regions(&self) -> &[PresetRegion] {
106        &self.regions[..]
107    }
108}