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#[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 pub const CHANNEL_COUNT: usize = 16;
47 pub const PERCUSSION_CHANNEL: usize = 9;
49
50 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 let preset_id = (preset.bank_number << 16) | preset.patch_number;
74 preset_lookup.insert(preset_id, i);
75
76 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 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), 0x90 => self.note_on(channel, data1, data2), 0xB0 => match data1 {
144 0x00 => channel_info.set_bank(data2), 0x01 => channel_info.set_modulation_coarse(data2), 0x21 => channel_info.set_modulation_fine(data2), 0x06 => channel_info.data_entry_coarse(data2), 0x26 => channel_info.data_entry_fine(data2), 0x07 => channel_info.set_volume_coarse(data2), 0x27 => channel_info.set_volume_fine(data2), 0x0A => channel_info.set_pan_coarse(data2), 0x2A => channel_info.set_pan_fine(data2), 0x0B => channel_info.set_expression_coarse(data2), 0x2B => channel_info.set_expression_fine(data2), 0x40 => channel_info.set_hold_pedal(data2), 0x5B => channel_info.set_reverb_send(data2), 0x5D => channel_info.set_chorus_send(data2), 0x63 => channel_info.set_nrpn_coarse(data2), 0x62 => channel_info.set_nrpn_fine(data2), 0x65 => channel_info.set_rpn_coarse(data2), 0x64 => channel_info.set_rpn_fine(data2), 0x78 => self.note_off_all_channel(channel, true), 0x79 => self.reset_all_controllers_channel(channel), 0x7B => self.note_off_all_channel(channel, false), _ => (),
166 },
167 0xC0 => channel_info.set_patch(data1), 0xE0 => channel_info.set_pitch_bend(data1, data2), _ => (),
170 }
171 }
172
173 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 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 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 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(®ion_pair, channel, key, velocity)
242 }
243 }
244 }
245 }
246 }
247 }
248
249 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 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 pub fn reset_all_controllers(&mut self) {
288 for channel in &mut self.channels {
289 channel.reset_all_controllers();
290 }
291 }
292
293 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 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 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 left[wrote..wrote + rem]
351 .copy_from_slice(&self.block_left[self.block_read..self.block_read + rem]);
352 right[wrote..wrote + rem]
353 .copy_from_slice(&self.block_right[self.block_read..self.block_read + rem]);
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 Synthesizer::write_block_stereo(
368 self.master_volume * voice.previous_mix_gain_left,
369 self.master_volume * voice.current_mix_gain_left,
370 self.master_volume * voice.previous_mix_gain_right,
371 self.master_volume * voice.current_mix_gain_right,
372 voice.block(),
373 &mut self.block_left[..],
374 &mut self.block_right[..],
375 self.inverse_block_size,
376 );
377 }
378
379 if let Some(effects) = self.effects.as_mut() {
380 let chorus = &mut effects.chorus;
381 let chorus_input_left = &mut effects.chorus_input_left[..];
382 let chorus_input_right = &mut effects.chorus_input_right[..];
383 let chorus_output_left = &mut effects.chorus_output_left[..];
384 let chorus_output_right = &mut effects.chorus_output_right[..];
385 chorus_input_left.fill(0_f32);
386 chorus_input_right.fill(0_f32);
387 for voice in self.voices.get_active_voices().iter_mut() {
388 Synthesizer::write_block_stereo(
389 voice.previous_chorus_send * voice.previous_mix_gain_left,
390 voice.current_chorus_send * voice.current_mix_gain_left,
391 voice.previous_chorus_send * voice.previous_mix_gain_right,
392 voice.current_chorus_send * voice.current_mix_gain_right,
393 voice.block(),
394 chorus_input_left,
395 chorus_input_right,
396 self.inverse_block_size,
397 );
398 }
399 chorus.process(
400 chorus_input_left,
401 chorus_input_right,
402 chorus_output_left,
403 chorus_output_right,
404 );
405 ArrayMath::multiply_add(
406 self.master_volume,
407 chorus_output_left,
408 &mut self.block_left[..],
409 );
410 ArrayMath::multiply_add(
411 self.master_volume,
412 chorus_output_right,
413 &mut self.block_right[..],
414 );
415
416 let reverb = &mut effects.reverb;
417 let reverb_input = &mut effects.reverb_input[..];
418 let reverb_output_left = &mut effects.reverb_output_left[..];
419 let reverb_output_right = &mut effects.reverb_output_right[..];
420 reverb_input.fill(0_f32);
421 for voice in self.voices.get_active_voices().iter_mut() {
422 let previous_gain = reverb.get_input_gain()
423 * voice.previous_reverb_send
424 * (voice.previous_mix_gain_left + voice.previous_mix_gain_right);
425 let current_gain = reverb.get_input_gain()
426 * voice.current_reverb_send
427 * (voice.current_mix_gain_left + voice.current_mix_gain_right);
428 Synthesizer::write_block(
429 previous_gain,
430 current_gain,
431 voice.block(),
432 &mut reverb_input[..],
433 self.inverse_block_size,
434 );
435 }
436
437 reverb.process(reverb_input, reverb_output_left, reverb_output_right);
438 ArrayMath::multiply_add(
439 self.master_volume,
440 reverb_output_left,
441 &mut self.block_left[..],
442 );
443 ArrayMath::multiply_add(
444 self.master_volume,
445 reverb_output_right,
446 &mut self.block_right[..],
447 );
448 }
449 }
450
451 fn write_block(
452 previous_gain: f32,
453 current_gain: f32,
454 source: &[f32],
455 destination: &mut [f32],
456 inverse_block_size: f32,
457 ) {
458 if SoundFontMath::max(previous_gain, current_gain) < SoundFontMath::NON_AUDIBLE {
459 return;
460 }
461
462 if (current_gain - previous_gain).abs() < 1.0E-3_f32 {
463 ArrayMath::multiply_add(current_gain, source, destination);
464 } else {
465 let step = inverse_block_size * (current_gain - previous_gain);
466 ArrayMath::multiply_add_slope(previous_gain, step, source, destination);
467 }
468 }
469
470 #[expect(
475 clippy::too_many_arguments,
476 reason = "the two channels read naturally side by side"
477 )]
478 fn write_block_stereo(
479 previous_gain_left: f32,
480 current_gain_left: f32,
481 previous_gain_right: f32,
482 current_gain_right: f32,
483 source: &[f32],
484 destination_left: &mut [f32],
485 destination_right: &mut [f32],
486 inverse_block_size: f32,
487 ) {
488 let left_is_audible =
489 SoundFontMath::max(previous_gain_left, current_gain_left) >= SoundFontMath::NON_AUDIBLE;
490 let right_is_audible = SoundFontMath::max(previous_gain_right, current_gain_right)
491 >= SoundFontMath::NON_AUDIBLE;
492
493 match (left_is_audible, right_is_audible) {
494 (false, false) => {}
495 (true, false) => Synthesizer::write_block(
496 previous_gain_left,
497 current_gain_left,
498 source,
499 destination_left,
500 inverse_block_size,
501 ),
502 (false, true) => Synthesizer::write_block(
503 previous_gain_right,
504 current_gain_right,
505 source,
506 destination_right,
507 inverse_block_size,
508 ),
509 (true, true) => {
510 let left_step = Synthesizer::gain_step(
511 previous_gain_left,
512 current_gain_left,
513 inverse_block_size,
514 );
515 let right_step = Synthesizer::gain_step(
516 previous_gain_right,
517 current_gain_right,
518 inverse_block_size,
519 );
520
521 match (left_step, right_step) {
522 (Some(left_step), Some(right_step)) => ArrayMath::multiply_add_slope_stereo(
523 previous_gain_left,
524 left_step,
525 previous_gain_right,
526 right_step,
527 source,
528 destination_left,
529 destination_right,
530 ),
531 (None, None) => ArrayMath::multiply_add_stereo(
532 current_gain_left,
533 current_gain_right,
534 source,
535 destination_left,
536 destination_right,
537 ),
538 (Some(left_step), None) => ArrayMath::multiply_add_slope_stereo(
539 previous_gain_left,
540 left_step,
541 current_gain_right,
542 0_f32,
543 source,
544 destination_left,
545 destination_right,
546 ),
547 (None, Some(right_step)) => ArrayMath::multiply_add_slope_stereo(
548 current_gain_left,
549 0_f32,
550 previous_gain_right,
551 right_step,
552 source,
553 destination_left,
554 destination_right,
555 ),
556 }
557 }
558 }
559 }
560
561 fn gain_step(previous_gain: f32, current_gain: f32, inverse_block_size: f32) -> Option<f32> {
563 if (current_gain - previous_gain).abs() < 1.0E-3_f32 {
564 None
565 } else {
566 Some(inverse_block_size * (current_gain - previous_gain))
567 }
568 }
569
570 pub fn get_sound_font(&self) -> &SoundFont {
572 &self.sound_font
573 }
574
575 pub fn get_sample_rate(&self) -> i32 {
577 self.sample_rate
578 }
579
580 pub fn get_block_size(&self) -> usize {
582 self.block_size
583 }
584
585 pub fn get_maximum_polyphony(&self) -> usize {
587 self.maximum_polyphony
588 }
589
590 pub fn get_enable_reverb_and_chorus(&self) -> bool {
592 self.effects.is_some()
593 }
594
595 pub fn get_master_volume(&self) -> f32 {
597 self.master_volume
598 }
599
600 pub fn set_master_volume(&mut self, value: f32) {
606 self.master_volume = value;
607 }
608}
609
610#[derive(Debug)]
611struct Effects {
612 reverb: Reverb,
613 reverb_input: Vec<f32>,
614 reverb_output_left: Vec<f32>,
615 reverb_output_right: Vec<f32>,
616
617 chorus: Chorus,
618 chorus_input_left: Vec<f32>,
619 chorus_input_right: Vec<f32>,
620 chorus_output_left: Vec<f32>,
621 chorus_output_right: Vec<f32>,
622}
623
624impl Effects {
625 fn new(settings: &SynthesizerSettings) -> Effects {
626 Self {
627 reverb: Reverb::new(settings.sample_rate),
628 reverb_input: vec![0_f32; settings.block_size],
629 reverb_output_left: vec![0_f32; settings.block_size],
630 reverb_output_right: vec![0_f32; settings.block_size],
631 chorus: Chorus::new(settings.sample_rate, 0.002, 0.0019, 0.4),
632 chorus_input_left: vec![0_f32; settings.block_size],
633 chorus_input_right: vec![0_f32; settings.block_size],
634 chorus_output_left: vec![0_f32; settings.block_size],
635 chorus_output_right: vec![0_f32; settings.block_size],
636 }
637 }
638}