Expand description
Roland CM-32L synthesizer emulator.
Renders 32kHz stereo PCM audio from MIDI input. no_std compatible
(requires alloc). Based on Munt,
with no external dependencies.
The CM-32L is in the MT-32 family of synthesizers. This hardware predates General MIDI, but many early 1990s PC games directly support these synths.
§Quick start
use moont::{Frame, Synth, cm32l};
let control = std::fs::read("CM32L_CONTROL.ROM").unwrap();
let pcm = std::fs::read("CM32L_PCM.ROM").unwrap();
let rom = cm32l::Rom::new(&control, &pcm).expect("invalid ROM");
let mut synth = cm32l::Device::new(rom);
// Note On: MIDI channel 2, note C4, max velocity.
synth.play_msg(0x7f3c91);
// Render 1 second of audio at 32 kHz.
let mut buf = vec![Frame(0, 0); 32000];
synth.render(&mut buf);
// Note Off: MIDI channel 2.
synth.play_msg(0x3c81);§Loading ROMs
The CM-32L ROMs are not distributed with this crate. Load them at
runtime with cm32l::Rom::new:
let control = std::fs::read("CM32L_CONTROL.ROM").unwrap();
let pcm = std::fs::read("CM32L_PCM.ROM").unwrap();
let rom = cm32l::Rom::new(&control, &pcm).expect("invalid ROM");With the bundle-rom feature, ROMs are parsed at compile time and
embedded in the binary, enabling cm32l::Rom::bundled(). Place
CM32L_CONTROL.ROM and CM32L_PCM.ROM in rom/ inside the crate
directory, or set the MOONT_ROM_DIR environment variable:
let rom = cm32l::Rom::bundled();§General MIDI translation
The CM-32L uses its own instrument map. When the input is General MIDI,
use cm32l::GmDevice to translate program changes, drum notes, and pan
direction into CM-32L equivalents. GM defaults are automatically
reapplied after any device reset:
use moont::{Synth, cm32l};
let control = std::fs::read("CM32L_CONTROL.ROM").unwrap();
let pcm = std::fs::read("CM32L_PCM.ROM").unwrap();
let mut synth =
cm32l::GmDevice::new(cm32l::Rom::new(&control, &pcm).unwrap());
synth.play_msg(0x7f3c90);§Type-safe MIDI messages
The Message type provides validated message construction as
an alternative to raw u32 values:
use moont::Message;
let msg = Message::note_on(60, 100, 0).unwrap();
let packed: u32 = msg.try_into().unwrap();§Features
| Feature | Description |
|---|---|
bundle-rom | Embed pre-parsed ROMs in the binary (enables cm32l::Rom::bundled()) |
tracing | Emit tracing spans and events |
§Related crates
| Crate | Description |
|---|---|
moont-render | Render .mid files to .wav |
moont-live | Real-time ALSA MIDI sink |
moont-web | WebAssembly wrapper with Web Audio API |
Modules§
- cm32l
- CM-32L-specific API surface.
- gm
- General MIDI to CM-32L translation.
- param
- Shared parameter types for instrument timbres, patches, and rhythm keys.
- smf
- Minimal Standard MIDI File (SMF) parser.
Structs§
- CM32L
- CM-32L synthesizer state.
- Frame
- Stereo PCM audio frame of two native-endian signed 16-bit samples.
- Message
- Validated MIDI message.
Enums§
- Control
Command - High-level runtime control commands for a synth instance.
- Control
Error - Error applying
ControlCommand. - Midi
Error - Error returned when constructing or converting a
Messagemessage.
Constants§
- SAMPLE_
RATE - Audio frames (stereo samples) per second.
Traits§
- Synth
- Interface for MIDI synthesizers.