Skip to main content

rustysynth_ext/
synthesizer.rs

1use std::cmp;
2use std::collections::HashMap;
3use std::sync::Arc;
4
5use crate::array_math::ArrayMath;
6use crate::channel::Channel;
7use crate::chorus::Chorus;
8use crate::error::SynthesizerError;
9use crate::region_pair::RegionPair;
10use crate::reverb::Reverb;
11use crate::soundfont::SoundFont;
12use crate::soundfont_math::SoundFontMath;
13use crate::synthesizer_settings::SynthesizerSettings;
14use crate::voice_collection::VoiceCollection;
15
16/// An instance of the SoundFont synthesizer.
17#[derive(Debug)]
18#[non_exhaustive]
19pub struct Synthesizer {
20    pub(crate) sound_font: Arc<SoundFont>,
21    pub(crate) sample_rate: i32,
22    pub(crate) block_size: usize,
23    pub(crate) maximum_polyphony: usize,
24
25    preset_lookup: HashMap<i32, usize>,
26    default_preset: usize,
27
28    channels: Vec<Channel>,
29
30    voices: VoiceCollection,
31
32    block_left: Vec<f32>,
33    block_right: Vec<f32>,
34
35    inverse_block_size: f32,
36
37    block_read: usize,
38
39    master_volume: f32,
40
41    effects: Option<Effects>,
42}
43
44impl Synthesizer {
45    /// The number of channels.
46    pub const CHANNEL_COUNT: usize = 16;
47    /// The percussion channel.
48    pub const PERCUSSION_CHANNEL: usize = 9;
49
50    /// Initializes a new synthesizer using a specified SoundFont and settings.
51    ///
52    /// # Arguments
53    ///
54    /// * `sound_font` - The SoundFont instance.
55    /// * `settings` - The settings for synthesis.
56    pub fn new(
57        sound_font: &Arc<SoundFont>,
58        settings: &SynthesizerSettings,
59    ) -> Result<Self, SynthesizerError> {
60        settings.validate()?;
61
62        let mut preset_lookup: HashMap<i32, usize> = HashMap::new();
63
64        let mut min_preset_id = i32::MAX;
65        let mut default_preset: usize = 0;
66        for i in 0..sound_font.presets.len() {
67            let preset = &sound_font.presets[i];
68
69            // The preset ID is Int32, where the upper 16 bits represent the bank number
70            // and the lower 16 bits represent the patch number.
71            // This ID is used to search for presets by the combination of bank number
72            // and patch number.
73            let preset_id = (preset.bank_number << 16) | preset.patch_number;
74            preset_lookup.insert(preset_id, i);
75
76            // The preset with the minimum ID number will be default.
77            // If the SoundFont is GM compatible, the piano will be chosen.
78            if preset_id < min_preset_id {
79                default_preset = i;
80                min_preset_id = preset_id;
81            }
82        }
83
84        let mut channels: Vec<Channel> = Vec::with_capacity(Synthesizer::CHANNEL_COUNT);
85        for i in 0..Synthesizer::CHANNEL_COUNT {
86            channels.push(Channel::new(i == Synthesizer::PERCUSSION_CHANNEL));
87        }
88
89        let voices = VoiceCollection::new(settings);
90
91        let block_left: Vec<f32> = vec![0_f32; settings.block_size];
92        let block_right: Vec<f32> = vec![0_f32; settings.block_size];
93
94        let inverse_block_size = 1_f32 / settings.block_size as f32;
95
96        let block_read = settings.block_size;
97
98        let master_volume = 0.5_f32;
99
100        let effects = if settings.enable_reverb_and_chorus {
101            Some(Effects::new(settings))
102        } else {
103            None
104        };
105
106        Ok(Self {
107            sound_font: Arc::clone(sound_font),
108            sample_rate: settings.sample_rate,
109            block_size: settings.block_size,
110            maximum_polyphony: settings.maximum_polyphony,
111            preset_lookup,
112            default_preset,
113            channels,
114            voices,
115            block_left,
116            block_right,
117            inverse_block_size,
118            block_read,
119            master_volume,
120            effects,
121        })
122    }
123
124    /// Processes a MIDI message.
125    ///
126    /// # Arguments
127    ///
128    /// * `channel` - The channel to which the message will be sent.
129    /// * `command` - The type of the message.
130    /// * `data1` - The first data part of the message.
131    /// * `data2` - The second data part of the message.
132    pub fn process_midi_message(&mut self, channel: i32, command: i32, data1: i32, data2: i32) {
133        if !(0 <= channel && channel < self.channels.len() as i32) {
134            return;
135        }
136
137        let channel_info = &mut self.channels[channel as usize];
138
139        match command {
140            0x80 => self.note_off(channel, data1),       // Note Off
141            0x90 => self.note_on(channel, data1, data2), // Note On
142            0xB0 => match data1 // Controller
143            {
144                0x00 => channel_info.set_bank(data2), // Bank Selection
145                0x01 => channel_info.set_modulation_coarse(data2), // Modulation Coarse
146                0x21 => channel_info.set_modulation_fine(data2), // Modulation Fine
147                0x06 => channel_info.data_entry_coarse(data2), // Data Entry Coarse
148                0x26 => channel_info.data_entry_fine(data2), // Data Entry Fine
149                0x07 => channel_info.set_volume_coarse(data2), // Channel Volume Coarse
150                0x27 => channel_info.set_volume_fine(data2), // Channel Volume Fine
151                0x0A => channel_info.set_pan_coarse(data2), // Pan Coarse
152                0x2A => channel_info.set_pan_fine(data2), // Pan Fine
153                0x0B => channel_info.set_expression_coarse(data2), // Expression Coarse
154                0x2B => channel_info.set_expression_fine(data2), // Expression Fine
155                0x40 => channel_info.set_hold_pedal(data2), // Hold Pedal
156                0x5B => channel_info.set_reverb_send(data2), // Reverb Send
157                0x5D => channel_info.set_chorus_send(data2), // Chorus Send
158                0x63 => channel_info.set_nrpn_coarse(data2), // NRPN Coarse
159                0x62 => channel_info.set_nrpn_fine(data2), // NRPN Fine
160                0x65 => channel_info.set_rpn_coarse(data2), // RPN Coarse
161                0x64 => channel_info.set_rpn_fine(data2), // RPN Fine
162                0x78 => self.note_off_all_channel(channel, true), // All Sound Off
163                0x79 => self.reset_all_controllers_channel(channel), // Reset All Controllers
164                0x7B => self.note_off_all_channel(channel, false), // All Note Off
165                _ => (),
166            },
167            0xC0 => channel_info.set_patch(data1), // Program Change
168            0xE0 => channel_info.set_pitch_bend(data1, data2), // Pitch Bend
169            _ => (),
170        }
171    }
172
173    /// Stops a note.
174    ///
175    /// # Arguments
176    ///
177    /// * `channel` - The channel of the note.
178    /// * `key` - The key of the note.
179    pub fn note_off(&mut self, channel: i32, key: i32) {
180        if !(0 <= channel && channel < self.channels.len() as i32) {
181            return;
182        }
183
184        for voice in self.voices.get_active_voices().iter_mut() {
185            if voice.channel() == channel && voice.key() == key {
186                voice.end();
187            }
188        }
189    }
190
191    /// Starts a note.
192    ///
193    /// # Arguments
194    ///
195    /// * `channel` - The channel of the note.
196    /// * `key` - The key of the note.
197    /// * `velocity` - The velocity of the note.
198    pub fn note_on(&mut self, channel: i32, key: i32, velocity: i32) {
199        if velocity == 0 {
200            self.note_off(channel, key);
201            return;
202        }
203
204        if !(0 <= channel && channel < self.channels.len() as i32) {
205            return;
206        }
207
208        let channel_info = &self.channels[channel as usize];
209
210        let preset_id = (channel_info.get_bank_number() << 16) | channel_info.get_patch_number();
211
212        let mut preset = self.default_preset;
213        match self.preset_lookup.get(&preset_id) {
214            Some(value) => preset = *value,
215            None => {
216                // Try fallback to the GM sound set.
217                // Normally, the given patch number + the bank number 0 will work.
218                // For drums (bank number >= 128), it seems to be better to select the standard set (128:0).
219                let gm_preset_id = if channel_info.get_bank_number() < 128 {
220                    channel_info.get_patch_number()
221                } else {
222                    128 << 16
223                };
224
225                // If no corresponding preset was found. Use the default one...
226                if let Some(value) = self.preset_lookup.get(&gm_preset_id) {
227                    preset = *value
228                }
229            }
230        }
231
232        let preset = &self.sound_font.presets[preset];
233        for preset_region in preset.regions.iter() {
234            if preset_region.contains(key, velocity) {
235                let instrument = &self.sound_font.instruments[preset_region.instrument];
236                for instrument_region in instrument.regions.iter() {
237                    if instrument_region.contains(key, velocity) {
238                        let region_pair = RegionPair::new(preset_region, instrument_region);
239
240                        if let Some(value) = self.voices.request_new(instrument_region, channel) {
241                            value.start(&region_pair, channel, key, velocity)
242                        }
243                    }
244                }
245            }
246        }
247    }
248
249    /// Stops all the notes in the specified channel.
250    ///
251    /// # Arguments
252    ///
253    /// * `immediate` - If `true`, notes will stop immediately without the release sound.
254    pub fn note_off_all(&mut self, immediate: bool) {
255        if immediate {
256            self.voices.clear();
257        } else {
258            for voice in self.voices.get_active_voices().iter_mut() {
259                voice.end();
260            }
261        }
262    }
263
264    /// Stops all the notes in the specified channel.
265    ///
266    /// # Arguments
267    ///
268    /// * `channel` - The channel in which the notes will be stopped.
269    /// * `immediate` - If `true`, notes will stop immediately without the release sound.
270    pub fn note_off_all_channel(&mut self, channel: i32, immediate: bool) {
271        if immediate {
272            for voice in self.voices.get_active_voices().iter_mut() {
273                if voice.channel() == channel {
274                    voice.kill();
275                }
276            }
277        } else {
278            for voice in self.voices.get_active_voices().iter_mut() {
279                if voice.channel() == channel {
280                    voice.end();
281                }
282            }
283        }
284    }
285
286    /// Resets all the controllers.
287    pub fn reset_all_controllers(&mut self) {
288        for channel in &mut self.channels {
289            channel.reset_all_controllers();
290        }
291    }
292
293    /// Resets all the controllers of the specified channel.
294    ///
295    /// # Arguments
296    ///
297    /// * `channel` - The channel to be reset.
298    pub fn reset_all_controllers_channel(&mut self, channel: i32) {
299        if !(0 <= channel && channel < self.channels.len() as i32) {
300            return;
301        }
302
303        self.channels[channel as usize].reset_all_controllers();
304    }
305
306    /// Resets the synthesizer.
307    pub fn reset(&mut self) {
308        self.voices.clear();
309
310        for channel in &mut self.channels {
311            channel.reset();
312        }
313
314        if let Some(effects) = self.effects.as_mut() {
315            effects.reverb.mute();
316            effects.chorus.mute();
317        }
318
319        self.block_read = self.block_size;
320    }
321
322    /// Renders the waveform.
323    ///
324    /// # Arguments
325    ///
326    /// * `left` - The buffer of the left channel to store the rendered waveform.
327    /// * `right` - The buffer of the right channel to store the rendered waveform.
328    ///
329    /// # Remarks
330    ///
331    /// The output buffers for the left and right must be the same length.
332    pub fn render(&mut self, left: &mut [f32], right: &mut [f32]) {
333        if left.len() != right.len() {
334            panic!("The output buffers for the left and right must be the same length.");
335        }
336
337        let left_length = left.len();
338
339        let mut wrote = 0;
340        while wrote < left_length {
341            if self.block_read == self.block_size {
342                self.render_block();
343                self.block_read = 0;
344            }
345
346            let src_rem = self.block_size - self.block_read;
347            let dst_rem = left_length - wrote;
348            let rem = cmp::min(src_rem, dst_rem);
349
350            for t in 0..rem {
351                left[wrote + t] = self.block_left[self.block_read + t];
352                right[wrote + t] = self.block_right[self.block_read + t];
353            }
354
355            self.block_read += rem;
356            wrote += rem;
357        }
358    }
359
360    fn render_block(&mut self) {
361        self.voices
362            .process(&self.sound_font.wave_data, &self.channels);
363
364        self.block_left.fill(0_f32);
365        self.block_right.fill(0_f32);
366        for voice in self.voices.get_active_voices().iter_mut() {
367            let previous_gain_left = self.master_volume * voice.previous_mix_gain_left;
368            let current_gain_left = self.master_volume * voice.current_mix_gain_left;
369            Synthesizer::write_block(
370                previous_gain_left,
371                current_gain_left,
372                voice.block(),
373                &mut self.block_left[..],
374                self.inverse_block_size,
375            );
376            let previous_gain_right = self.master_volume * voice.previous_mix_gain_right;
377            let current_gain_right = self.master_volume * voice.current_mix_gain_right;
378            Synthesizer::write_block(
379                previous_gain_right,
380                current_gain_right,
381                voice.block(),
382                &mut self.block_right[..],
383                self.inverse_block_size,
384            );
385        }
386
387        if let Some(effects) = self.effects.as_mut() {
388            let chorus = &mut effects.chorus;
389            let chorus_input_left = &mut effects.chorus_input_left[..];
390            let chorus_input_right = &mut effects.chorus_input_right[..];
391            let chorus_output_left = &mut effects.chorus_output_left[..];
392            let chorus_output_right = &mut effects.chorus_output_right[..];
393            chorus_input_left.fill(0_f32);
394            chorus_input_right.fill(0_f32);
395            for voice in self.voices.get_active_voices().iter_mut() {
396                let previous_gain_left = voice.previous_chorus_send * voice.previous_mix_gain_left;
397                let current_gain_left = voice.current_chorus_send * voice.current_mix_gain_left;
398                Synthesizer::write_block(
399                    previous_gain_left,
400                    current_gain_left,
401                    voice.block(),
402                    chorus_input_left,
403                    self.inverse_block_size,
404                );
405                let previous_gain_right =
406                    voice.previous_chorus_send * voice.previous_mix_gain_right;
407                let current_gain_right = voice.current_chorus_send * voice.current_mix_gain_right;
408                Synthesizer::write_block(
409                    previous_gain_right,
410                    current_gain_right,
411                    voice.block(),
412                    chorus_input_right,
413                    self.inverse_block_size,
414                );
415            }
416            chorus.process(
417                chorus_input_left,
418                chorus_input_right,
419                chorus_output_left,
420                chorus_output_right,
421            );
422            ArrayMath::multiply_add(
423                self.master_volume,
424                chorus_output_left,
425                &mut self.block_left[..],
426            );
427            ArrayMath::multiply_add(
428                self.master_volume,
429                chorus_output_right,
430                &mut self.block_right[..],
431            );
432
433            let reverb = &mut effects.reverb;
434            let reverb_input = &mut effects.reverb_input[..];
435            let reverb_output_left = &mut effects.reverb_output_left[..];
436            let reverb_output_right = &mut effects.reverb_output_right[..];
437            reverb_input.fill(0_f32);
438            for voice in self.voices.get_active_voices().iter_mut() {
439                let previous_gain = reverb.get_input_gain()
440                    * voice.previous_reverb_send
441                    * (voice.previous_mix_gain_left + voice.previous_mix_gain_right);
442                let current_gain = reverb.get_input_gain()
443                    * voice.current_reverb_send
444                    * (voice.current_mix_gain_left + voice.current_mix_gain_right);
445                Synthesizer::write_block(
446                    previous_gain,
447                    current_gain,
448                    voice.block(),
449                    &mut reverb_input[..],
450                    self.inverse_block_size,
451                );
452            }
453
454            reverb.process(reverb_input, reverb_output_left, reverb_output_right);
455            ArrayMath::multiply_add(
456                self.master_volume,
457                reverb_output_left,
458                &mut self.block_left[..],
459            );
460            ArrayMath::multiply_add(
461                self.master_volume,
462                reverb_output_right,
463                &mut self.block_right[..],
464            );
465        }
466    }
467
468    fn write_block(
469        previous_gain: f32,
470        current_gain: f32,
471        source: &[f32],
472        destination: &mut [f32],
473        inverse_block_size: f32,
474    ) {
475        if SoundFontMath::max(previous_gain, current_gain) < SoundFontMath::NON_AUDIBLE {
476            return;
477        }
478
479        if (current_gain - previous_gain).abs() < 1.0E-3_f32 {
480            ArrayMath::multiply_add(current_gain, source, destination);
481        } else {
482            let step = inverse_block_size * (current_gain - previous_gain);
483            ArrayMath::multiply_add_slope(previous_gain, step, source, destination);
484        }
485    }
486
487    /// Gets the SoundFont used as the audio source.
488    pub fn get_sound_font(&self) -> &SoundFont {
489        &self.sound_font
490    }
491
492    /// Gets the sample rate for synthesis.
493    pub fn get_sample_rate(&self) -> i32 {
494        self.sample_rate
495    }
496
497    /// Gets the block size for rendering waveform.
498    pub fn get_block_size(&self) -> usize {
499        self.block_size
500    }
501
502    /// Gets the number of maximum polyphony.
503    pub fn get_maximum_polyphony(&self) -> usize {
504        self.maximum_polyphony
505    }
506
507    /// Gets the value indicating whether reverb and chorus are enabled.
508    pub fn get_enable_reverb_and_chorus(&self) -> bool {
509        self.effects.is_some()
510    }
511
512    /// Gets the master volume.
513    pub fn get_master_volume(&self) -> f32 {
514        self.master_volume
515    }
516
517    /// Sets the master volume.
518    ///
519    /// # Arguments
520    ///
521    /// * `value` - The new value of the master volume.
522    pub fn set_master_volume(&mut self, value: f32) {
523        self.master_volume = value;
524    }
525}
526
527#[derive(Debug)]
528struct Effects {
529    reverb: Reverb,
530    reverb_input: Vec<f32>,
531    reverb_output_left: Vec<f32>,
532    reverb_output_right: Vec<f32>,
533
534    chorus: Chorus,
535    chorus_input_left: Vec<f32>,
536    chorus_input_right: Vec<f32>,
537    chorus_output_left: Vec<f32>,
538    chorus_output_right: Vec<f32>,
539}
540
541impl Effects {
542    fn new(settings: &SynthesizerSettings) -> Effects {
543        Self {
544            reverb: Reverb::new(settings.sample_rate),
545            reverb_input: vec![0_f32; settings.block_size],
546            reverb_output_left: vec![0_f32; settings.block_size],
547            reverb_output_right: vec![0_f32; settings.block_size],
548            chorus: Chorus::new(settings.sample_rate, 0.002, 0.0019, 0.4),
549            chorus_input_left: vec![0_f32; settings.block_size],
550            chorus_input_right: vec![0_f32; settings.block_size],
551            chorus_output_left: vec![0_f32; settings.block_size],
552            chorus_output_right: vec![0_f32; settings.block_size],
553        }
554    }
555}