Expand description
A pure-Rust General MIDI synthesizer. Its DSP code has no third-party Rust
dependencies. Default builds embed separately licensed recorded material
from first-party asset crates, so no external SoundFont or runtime sound-bank
lookup is required. Input is a Standard MIDI File; output is interleaved
stereo f32.
Two surfaces:
offline— load or parse an SMF, then render, normalize, and atomically write a WAV with bounded audio memory. The path shown below.live—live::RealtimeSynth: raw MIDI bytes in viawrite_byte, stereo blocks summed into your output buffer viarender_add.
use ferrosintesis::offline::{self, Normalization, Options};
// A one-note Standard MIDI File, assembled in memory: format 0, one
// track, 480 ticks per quarter; a harp plays middle C for one beat.
let mut smf: Vec<u8> = Vec::new();
smf.extend(b"MThd");
smf.extend(6u32.to_be_bytes()); // header length
smf.extend(0u16.to_be_bytes()); // format 0
smf.extend(1u16.to_be_bytes()); // one track
smf.extend(480u16.to_be_bytes()); // ticks per quarter note
let track = [
0x00, 0xC0, 46, // program change: harp
0x00, 0x90, 60, 100, // note on: middle C, velocity 100
0x83, 0x60, 0x80, 60, 0, // 480 ticks later: note off
0x00, 0xFF, 0x2F, 0x00, // end of track
];
smf.extend(b"MTrk");
smf.extend((track.len() as u32).to_be_bytes());
smf.extend(track);
let song = offline::parse(&smf)?;
let opt = Options::default().with_tail(1.0); // short reverb tail
let stats = offline::render_to_wav(
&song,
&opt,
std::path::Path::new("output.wav"),
Normalization::loudness(-18.0, -1.0),
)?;
assert!(stats.voices_spawned >= 1 && stats.peak > 0.0);Rendering is deterministic for a fixed executable, MIDI file, and options.
The default embedded-samples feature compiles
roughly 111 MiB of recorded audio — 1156 WAVs across twenty-five
first-party asset crates — into the binary; default-features = false
builds the fully modeled synth instead, a far smaller artifact with
synthetic note onsets in place of the recorded ones.
embedded_samples_available reports which build this is. No unsafe
code, no build scripts.
Most of that audio is CC0; ten of the twenty-five crates carry an
attribution obligation that travels with a distributed binary. The
NOTICE file at the repository root is the index of what you must
reproduce, and each asset crate packages the exact required text.
All 128 GM melodic program numbers route to a synthesized voice family, but programs within a family may share an engine and support varies by program. The GM sound-effects block 120–127 also has explicit voice paths. This is not a claim of GM conformance or reference-module timbre. The README carries the program-by-program table; DESIGN.md in the repository carries the full design essay.
Modules§
- live
- Realtime raw-MIDI byte input and block-render API.
- offline
- Offline rendering: a Standard MIDI File in, an atomically completed WAV out.
Enums§
- Midi
Error - Why a Standard MIDI File could not be read.
Functions§
- embedded_
samples_ available - Whether this build contains the optional compile-time attack-sample bank.