RustySynth is a SoundFont MIDI synthesizer written in pure Rust, ported from MeltySynth.
- 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.
 
This is a demo video to show the synthesizer running on rust-sfml in real-time.
https://www.youtube.com/watch?v=o9rPTJIPmVk
RustySynth is available on crates.io:
cargo add rustysynth
Here are some example codes.
Note
Each example omits the use statements.
For full code, see the respective links.
An example code to synthesize a simple chord:
// 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:
// 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[..]);Yet another example code to synthesize a MIDI file in real-time with the TinyAudio crate:
// Setup the audio output.
let params = OutputDeviceParameters {
    channels_count: 2,
    sample_rate: 44100,
    channel_sample_count: 4410,
};
// Buffer for the audio output.
let mut left: Vec<f32> = vec![0_f32; params.channel_sample_count];
let mut right: Vec<f32> = vec![0_f32; params.channel_sample_count];
// 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(params.sample_rate as i32);
let synthesizer = Synthesizer::new(&sound_font, &settings).unwrap();
let mut sequencer = MidiFileSequencer::new(synthesizer);
// Play the MIDI file.
sequencer.play(&midi_file, false);
// Start the audio output.
let _device = run_output_device(params, {
    move |data| {
        sequencer.render(&mut left[..], &mut right[..]);
        for (i, value) in left.iter().interleave(right.iter()).enumerate() {
            data[i] = *value;
        }
    }
})
.unwrap();
// Wait for 10 seconds.
std::thread::sleep(std::time::Duration::from_secs(10));- Wave synthesis
- SoundFont reader
 - Waveform generator
 - Envelope generator
 - Low-pass filter
 - Vibrato LFO
 - Modulation LFO
 
 - MIDI message processing
- Note on/off
 - Bank selection
 - Modulation
 - Volume control
 - Pan
 - Expression
 - Hold pedal
 - Program change
 - Pitch bend
 - Tuning
 
 - Effects
- Reverb
 - Chorus
 
 - Other things
- Standard MIDI file support
 - MIDI file loop extension support
 - Performace optimization
 
 
RustySynth is available under the MIT license.
