https://github.com/sinshu/rustysynth
A SoundFont MIDI synthesizer written in pure Rust
https://github.com/sinshu/rustysynth
audio meltysynth midi rust soundfont synthesizer
Last synced: 8 months ago
JSON representation
A SoundFont MIDI synthesizer written in pure Rust
- Host: GitHub
- URL: https://github.com/sinshu/rustysynth
- Owner: sinshu
- License: other
- Created: 2022-09-19T06:55:33.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2025-04-19T11:30:59.000Z (about 1 year ago)
- Last Synced: 2025-04-19T16:52:11.163Z (about 1 year ago)
- Topics: audio, meltysynth, midi, rust, soundfont, synthesizer
- Language: Rust
- Homepage:
- Size: 1.01 MB
- Stars: 165
- Watchers: 4
- Forks: 27
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# RustySynth
RustySynth is a SoundFont MIDI synthesizer written in pure Rust, ported from [MeltySynth](https://github.com/sinshu/meltysynth).
## 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.
## Demo
This is a demo video to show the synthesizer running on [rust-sfml](https://github.com/jeremyletang/rust-sfml) in real-time.
https://www.youtube.com/watch?v=o9rPTJIPmVk
[](https://www.youtube.com/watch?v=o9rPTJIPmVk)
## Installation
RustySynth is available on [crates.io](https://crates.io/crates/rustysynth):
```
cargo add rustysynth
```
## Examples
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:](example/src/main.rs#L15)
```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 = vec![0_f32; sample_count];
let mut right: Vec = vec![0_f32; sample_count];
// Render the waveform.
synthesizer.render(&mut left[..], &mut right[..]);
```
[Another example code to synthesize a MIDI file:](example/src/main.rs#L41)
```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 = vec![0_f32; sample_count];
let mut right: Vec = 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:](https://github.com/sinshu/rustysynth/blob/tinyaudio/workspace/src/main.rs)
```rust
// 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 = vec![0_f32; params.channel_sample_count];
let mut right: Vec = 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));
```
## 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] Performace optimization
## License
RustySynth is available under [the MIT license](LICENSE.txt).