Skip to main content

Crate moont

Crate moont 

Source
Expand description

Roland CM-32L synthesizer emulator.

Renders 32kHz stereo PCM audio from MIDI input. 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::{CM32L, Frame, Rom, Synth};

let control = std::fs::read("CM32L_CONTROL.ROM").unwrap();
let pcm = std::fs::read("CM32L_PCM.ROM").unwrap();
let rom = Rom::new(&control, &pcm).expect("invalid ROM");
let mut synth = CM32L::new(rom);

// Note On: channel 1, middle C, 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.
synth.play_msg(0x3c81);

§Loading ROMs

The CM-32L ROMs are not distributed with this crate. Load them at runtime with Rom::new:

let control = std::fs::read("CM32L_CONTROL.ROM").unwrap();
let pcm = std::fs::read("CM32L_PCM.ROM").unwrap();
let rom = Rom::new(&control, &pcm).expect("invalid ROM");

With the bundle-rom feature, ROMs are parsed at compile time and embedded in the binary, enabling [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 = Rom::bundled();

§General MIDI translation

The CM-32L uses its own instrument map. When the input is General MIDI, use GmSynth to translate program changes, drum notes, and pan direction into CM-32L equivalents. GM defaults are automatically reapplied after any device reset:

use moont::{GmSynth, Rom, Synth};

let control = std::fs::read("CM32L_CONTROL.ROM").unwrap();
let pcm = std::fs::read("CM32L_PCM.ROM").unwrap();
let mut synth = GmSynth::new(Rom::new(&control, &pcm).unwrap());
synth.play_msg(0x7f3c91);

§Type-safe MIDI messages

The midi::Message type provides validated message construction as an alternative to raw u32 values:

use moont::midi::Message;

let msg = Message::note_on(60, 100, 0).unwrap();
let packed: u32 = msg.try_into().unwrap();

§Features

FeatureDescription
bundle-romEmbed pre-parsed ROMs in the binary (enables Rom::bundled())
tracingEmit tracing spans and events
CrateDescription
moont-renderRender .mid files to .wav
moont-liveReal-time ALSA MIDI sink
moont-webWebAssembly wrapper with Web Audio API

Re-exports§

pub use gm::GmSynth;
pub use rom::Rom;

Modules§

gm
General MIDI to CM-32L translation.
midi
MIDI message types, instrument enums, and conversions.
param
Shared parameter types for instrument timbres, patches, and rhythm keys.
rom
ROM parsing, structures, and PCM sample processing.
smf
Minimal Standard MIDI File (SMF) parser.

Structs§

CM32L
CM-32L synthesizer state.
Frame
Stereo PCM audio frame of two (left, right) 16-bit little-endian samples.

Enums§

ControlCommand
High-level runtime control commands for a synth instance.
ControlError
Error applying ControlCommand.

Constants§

SAMPLE_RATE
Audio frames (stereo samples) per second.

Traits§

Synth
Interface for MIDI synthesizers.