# RustySynth-ext
RustySynth-ext is a fork of [RustySynth](https://github.com/sinshu/rustysynth) — a
SoundFont MIDI synthesizer written in pure Rust, ported from
[MeltySynth](https://github.com/sinshu/meltysynth) — that adds optional
SoundFont3 (`.sf3`) support on top of the upstream SoundFont2 (`.sf2`) support.
## Features
* Suitable for both real-time and offline synthesis.
* Supports standard MIDI files with additional features including dynamic tempo changing.
* No dependencies other than the standard library by default.
* Optional SoundFont3 (.sf3) support.
SF3 SoundFonts store their samples as Ogg Vorbis streams instead of raw PCM,
roughly 10x smaller than the equivalent SF2. Loading them is opt-in because it
adds the pure-Rust [`lewton`](https://crates.io/crates/lewton) decoder:
```
cargo add rustysynth-ext --features sf3
```
With the `sf3` feature enabled, `SoundFont::new` loads `.sf3` files
transparently, decompressing every sample into the same 16-bit PCM layout used
by `.sf2` files.
## Examples
An example code to synthesize a simple chord:
```rust
// Load the SoundFont.
let mut sf2 = File::open("TimGM6mb.sf2").unwrap();
let sound_font = Arc::new(SoundFont::new(&mut sf2).unwrap());
// Create the synthesizer.
let settings = SynthesizerSettings::new(44100);
let mut synthesizer = Synthesizer::new(&sound_font, &settings).unwrap();
// Play some notes (middle C, E, G).
synthesizer.note_on(0, 60, 100);
synthesizer.note_on(0, 64, 100);
synthesizer.note_on(0, 67, 100);
// The output buffer (3 seconds).
let sample_count = (3 * settings.sample_rate) as usize;
let mut left: Vec<f32> = vec![0_f32; sample_count];
let mut right: Vec<f32> = vec![0_f32; sample_count];
// Render the waveform.
synthesizer.render(&mut left[..], &mut right[..]);
```
Another example code to synthesize a MIDI file:
```rust
// Load the SoundFont.
let mut sf2 = File::open("TimGM6mb.sf2").unwrap();
let sound_font = Arc::new(SoundFont::new(&mut sf2).unwrap());
// Load the MIDI file.
let mut mid = File::open("flourish.mid").unwrap();
let midi_file = Arc::new(MidiFile::new(&mut mid).unwrap());
// Create the MIDI file sequencer.
let settings = SynthesizerSettings::new(44100);
let synthesizer = Synthesizer::new(&sound_font, &settings).unwrap();
let mut sequencer = MidiFileSequencer::new(synthesizer);
// Play the MIDI file.
sequencer.play(&midi_file, false);
// The output buffer.
let sample_count = (settings.sample_rate as f64 * midi_file.get_length()) as usize;
let mut left: Vec<f32> = vec![0_f32; sample_count];
let mut right: Vec<f32> = vec![0_f32; sample_count];
// Render the waveform.
sequencer.render(&mut left[..], &mut right[..]);
```
## Todo
* __Wave synthesis__
- [x] SoundFont reader
- [x] Waveform generator
- [x] Envelope generator
- [x] Low-pass filter
- [x] Vibrato LFO
- [x] Modulation LFO
* __MIDI message processing__
- [x] Note on/off
- [x] Bank selection
- [x] Modulation
- [x] Volume control
- [x] Pan
- [x] Expression
- [x] Hold pedal
- [x] Program change
- [x] Pitch bend
- [x] Tuning
* __Effects__
- [x] Reverb
- [x] Chorus
* __Other things__
- [x] Standard MIDI file support
- [x] MIDI file loop extension support
- [x] Performance optimization
## License
RustySynth-ext is available under [the MIT license](LICENSE.txt). It is a fork
of [RustySynth](https://github.com/sinshu/rustysynth), whose copyright notice is
preserved in the license text.