1use crate::error::SoundFontError;
2use crate::instrument::Instrument;
3use crate::preset_info::PresetInfo;
4use crate::preset_region::PresetRegion;
5use crate::zone::Zone;
6
7#[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 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 pub fn get_name(&self) -> &str {
76 &self.name
77 }
78
79 pub fn get_patch_number(&self) -> i32 {
81 self.patch_number
82 }
83
84 pub fn get_bank_number(&self) -> i32 {
86 self.bank_number
87 }
88
89 pub fn get_library(&self) -> i32 {
91 self.library
92 }
93
94 pub fn get_genre(&self) -> i32 {
96 self.genre
97 }
98
99 pub fn get_morphology(&self) -> i32 {
101 self.morphology
102 }
103
104 pub fn get_regions(&self) -> &[PresetRegion] {
106 &self.regions[..]
107 }
108}