Skip to main content

rustysynth_ext/
preset_region.rs

1use crate::error::SoundFontError;
2use crate::generator::Generator;
3use crate::generator_type::GeneratorType;
4use crate::instrument::Instrument;
5use crate::soundfont_math::SoundFontMath;
6use crate::zone::Zone;
7
8fn set_parameter(gs: &mut [i16; GeneratorType::COUNT], generator: &Generator) {
9    let index = generator.generator_type as usize;
10
11    // Unknown generators should be ignored.
12    if index < gs.len() {
13        gs[index] = generator.value as i16;
14    }
15}
16
17/// Represents a preset region.
18/// A preset region indicates how the parameters of the instrument should be modified in the preset.
19#[derive(Debug)]
20#[non_exhaustive]
21pub struct PresetRegion {
22    pub(crate) gs: [i16; GeneratorType::COUNT],
23    pub(crate) instrument: usize,
24}
25
26impl PresetRegion {
27    fn new(
28        preset_id: usize,
29        global: &Zone,
30        local: &Zone,
31        samples: &[Instrument],
32    ) -> Result<Self, SoundFontError> {
33        let mut gs: [i16; GeneratorType::COUNT] = [0; GeneratorType::COUNT];
34        gs[GeneratorType::KEY_RANGE as usize] = 0x7F00;
35        gs[GeneratorType::VELOCITY_RANGE as usize] = 0x7F00;
36
37        for generator in global.generators.iter() {
38            set_parameter(&mut gs, generator);
39        }
40
41        for generator in local.generators.iter() {
42            set_parameter(&mut gs, generator);
43        }
44
45        let instrument_id = gs[GeneratorType::INSTRUMENT as usize] as usize;
46        if instrument_id >= samples.len() {
47            return Err(SoundFontError::InvalidInstrumentId {
48                preset_id,
49                instrument_id,
50            });
51        }
52
53        Ok(Self {
54            gs,
55            instrument: instrument_id,
56        })
57    }
58
59    pub(crate) fn create(
60        preset_id: usize,
61        zones: &[Zone],
62        instruments: &[Instrument],
63    ) -> Result<Vec<PresetRegion>, SoundFontError> {
64        // Is the first one the global zone?
65        if zones[0].generators.is_empty()
66            || zones[0].generators.last().unwrap().generator_type != GeneratorType::INSTRUMENT
67        {
68            // The first one is the global zone.
69            let global = &zones[0];
70
71            // The global zone is regarded as the base setting of subsequent zones.
72            let count = zones.len() - 1;
73            let mut regions: Vec<PresetRegion> = Vec::with_capacity(count);
74            for i in 0..count {
75                regions.push(PresetRegion::new(
76                    preset_id,
77                    global,
78                    &zones[i + 1],
79                    instruments,
80                )?);
81            }
82
83            Ok(regions)
84        } else {
85            // No global zone.
86            let count = zones.len();
87            let mut regions: Vec<PresetRegion> = Vec::with_capacity(count);
88            for zone in zones.iter().take(count) {
89                regions.push(PresetRegion::new(
90                    preset_id,
91                    &Zone::empty(),
92                    zone,
93                    instruments,
94                )?);
95            }
96
97            Ok(regions)
98        }
99    }
100
101    /// Checks if the region covers the given key and velocity.
102    /// Returns `true` if the region covers the given key and velocity.
103    ///
104    /// # Arguments
105    ///
106    /// * `key` - The key of a note.
107    /// * `velocity` - The velocity of a note.
108    pub fn contains(&self, key: i32, velocity: i32) -> bool {
109        let contains_key = self.get_key_range_start() <= key && key <= self.get_key_range_end();
110        let contains_velocity = self.get_velocity_range_start() <= velocity
111            && velocity <= self.get_velocity_range_end();
112        contains_key && contains_velocity
113    }
114
115    pub fn get_modulation_lfo_to_pitch(&self) -> i32 {
116        self.gs[GeneratorType::MODULATION_LFO_TO_PITCH as usize] as i32
117    }
118
119    pub fn get_vibrato_lfo_to_pitch(&self) -> i32 {
120        self.gs[GeneratorType::VIBRATO_LFO_TO_PITCH as usize] as i32
121    }
122
123    pub fn get_modulation_envelope_to_pitch(&self) -> i32 {
124        self.gs[GeneratorType::MODULATION_ENVELOPE_TO_PITCH as usize] as i32
125    }
126
127    pub fn get_initial_filter_cutoff_frequency(&self) -> f32 {
128        SoundFontMath::cents_to_multiplying_factor(
129            self.gs[GeneratorType::INITIAL_FILTER_CUTOFF_FREQUENCY as usize] as f32,
130        )
131    }
132
133    pub fn get_initial_filter_q(&self) -> f32 {
134        0.1_f32 * self.gs[GeneratorType::INITIAL_FILTER_Q as usize] as f32
135    }
136
137    pub fn get_modulation_lfo_to_filter_cutoff_frequency(&self) -> i32 {
138        self.gs[GeneratorType::MODULATION_LFO_TO_FILTER_CUTOFF_FREQUENCY as usize] as i32
139    }
140
141    pub fn get_modulation_envelope_to_filter_cutoff_frequency(&self) -> i32 {
142        self.gs[GeneratorType::MODULATION_ENVELOPE_TO_FILTER_CUTOFF_FREQUENCY as usize] as i32
143    }
144
145    pub fn get_modulation_lfo_to_volume(&self) -> f32 {
146        0.1_f32 * self.gs[GeneratorType::MODULATION_LFO_TO_VOLUME as usize] as f32
147    }
148
149    pub fn get_chorus_effects_send(&self) -> f32 {
150        0.1_f32 * self.gs[GeneratorType::CHORUS_EFFECTS_SEND as usize] as f32
151    }
152
153    pub fn get_reverb_effects_send(&self) -> f32 {
154        0.1_f32 * self.gs[GeneratorType::REVERB_EFFECTS_SEND as usize] as f32
155    }
156
157    pub fn get_pan(&self) -> f32 {
158        0.1_f32 * self.gs[GeneratorType::PAN as usize] as f32
159    }
160
161    pub fn get_delay_modulation_lfo(&self) -> f32 {
162        SoundFontMath::cents_to_multiplying_factor(
163            self.gs[GeneratorType::DELAY_MODULATION_LFO as usize] as f32,
164        )
165    }
166
167    pub fn get_frequency_modulation_lfo(&self) -> f32 {
168        SoundFontMath::cents_to_multiplying_factor(
169            self.gs[GeneratorType::FREQUENCY_MODULATION_LFO as usize] as f32,
170        )
171    }
172
173    pub fn get_delay_vibrato_lfo(&self) -> f32 {
174        SoundFontMath::cents_to_multiplying_factor(
175            self.gs[GeneratorType::DELAY_VIBRATO_LFO as usize] as f32,
176        )
177    }
178
179    pub fn get_frequency_vibrato_lfo(&self) -> f32 {
180        SoundFontMath::cents_to_multiplying_factor(
181            self.gs[GeneratorType::FREQUENCY_VIBRATO_LFO as usize] as f32,
182        )
183    }
184
185    pub fn get_delay_modulation_envelope(&self) -> f32 {
186        SoundFontMath::cents_to_multiplying_factor(
187            self.gs[GeneratorType::DELAY_MODULATION_ENVELOPE as usize] as f32,
188        )
189    }
190
191    pub fn get_attack_modulation_envelope(&self) -> f32 {
192        SoundFontMath::cents_to_multiplying_factor(
193            self.gs[GeneratorType::ATTACK_MODULATION_ENVELOPE as usize] as f32,
194        )
195    }
196
197    pub fn get_hold_modulation_envelope(&self) -> f32 {
198        SoundFontMath::cents_to_multiplying_factor(
199            self.gs[GeneratorType::HOLD_MODULATION_ENVELOPE as usize] as f32,
200        )
201    }
202
203    pub fn get_decay_modulation_envelope(&self) -> f32 {
204        SoundFontMath::cents_to_multiplying_factor(
205            self.gs[GeneratorType::DECAY_MODULATION_ENVELOPE as usize] as f32,
206        )
207    }
208
209    pub fn get_sustain_modulation_envelope(&self) -> f32 {
210        0.1_f32 * self.gs[GeneratorType::SUSTAIN_MODULATION_ENVELOPE as usize] as f32
211    }
212
213    pub fn get_release_modulation_envelope(&self) -> f32 {
214        SoundFontMath::cents_to_multiplying_factor(
215            self.gs[GeneratorType::RELEASE_MODULATION_ENVELOPE as usize] as f32,
216        )
217    }
218
219    pub fn get_key_number_to_modulation_envelope_hold(&self) -> i32 {
220        self.gs[GeneratorType::KEY_NUMBER_TO_MODULATION_ENVELOPE_HOLD as usize] as i32
221    }
222
223    pub fn get_key_number_to_modulation_envelope_decay(&self) -> i32 {
224        self.gs[GeneratorType::KEY_NUMBER_TO_MODULATION_ENVELOPE_DECAY as usize] as i32
225    }
226
227    pub fn get_delay_volume_envelope(&self) -> f32 {
228        SoundFontMath::cents_to_multiplying_factor(
229            self.gs[GeneratorType::DELAY_VOLUME_ENVELOPE as usize] as f32,
230        )
231    }
232
233    pub fn get_attack_volume_envelope(&self) -> f32 {
234        SoundFontMath::cents_to_multiplying_factor(
235            self.gs[GeneratorType::ATTACK_VOLUME_ENVELOPE as usize] as f32,
236        )
237    }
238
239    pub fn get_hold_volume_envelope(&self) -> f32 {
240        SoundFontMath::cents_to_multiplying_factor(
241            self.gs[GeneratorType::HOLD_VOLUME_ENVELOPE as usize] as f32,
242        )
243    }
244
245    pub fn get_decay_volume_envelope(&self) -> f32 {
246        SoundFontMath::cents_to_multiplying_factor(
247            self.gs[GeneratorType::DECAY_VOLUME_ENVELOPE as usize] as f32,
248        )
249    }
250
251    pub fn get_sustain_volume_envelope(&self) -> f32 {
252        0.1_f32 * self.gs[GeneratorType::SUSTAIN_VOLUME_ENVELOPE as usize] as f32
253    }
254
255    pub fn get_release_volume_envelope(&self) -> f32 {
256        SoundFontMath::cents_to_multiplying_factor(
257            self.gs[GeneratorType::RELEASE_VOLUME_ENVELOPE as usize] as f32,
258        )
259    }
260
261    pub fn get_key_number_to_volume_envelope_hold(&self) -> i32 {
262        self.gs[GeneratorType::KEY_NUMBER_TO_VOLUME_ENVELOPE_HOLD as usize] as i32
263    }
264
265    pub fn get_key_number_to_volume_envelope_decay(&self) -> i32 {
266        self.gs[GeneratorType::KEY_NUMBER_TO_VOLUME_ENVELOPE_DECAY as usize] as i32
267    }
268
269    pub fn get_key_range_start(&self) -> i32 {
270        self.gs[GeneratorType::KEY_RANGE as usize] as i32 & 0xFF
271    }
272
273    pub fn get_key_range_end(&self) -> i32 {
274        (self.gs[GeneratorType::KEY_RANGE as usize] as i32 >> 8) & 0xFF
275    }
276
277    pub fn get_velocity_range_start(&self) -> i32 {
278        self.gs[GeneratorType::VELOCITY_RANGE as usize] as i32 & 0xFF
279    }
280
281    pub fn get_velocity_range_end(&self) -> i32 {
282        (self.gs[GeneratorType::VELOCITY_RANGE as usize] as i32 >> 8) & 0xFF
283    }
284
285    pub fn get_initial_attenuation(&self) -> f32 {
286        0.1_f32 * self.gs[GeneratorType::INITIAL_ATTENUATION as usize] as f32
287    }
288
289    pub fn get_coarse_tune(&self) -> i32 {
290        self.gs[GeneratorType::COARSE_TUNE as usize] as i32
291    }
292
293    pub fn get_fine_tune(&self) -> i32 {
294        self.gs[GeneratorType::FINE_TUNE as usize] as i32
295    }
296
297    pub fn get_scale_tuning(&self) -> i32 {
298        self.gs[GeneratorType::SCALE_TUNING as usize] as i32
299    }
300
301    pub fn get_instrument_id(&self) -> usize {
302        self.instrument
303    }
304}