moont 0.8.2

Roland CM-32L synthesizer emulator
Documentation

moont

Roland CM-32L synth emulator, based on Munt, written in Rust with no code 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.

moont aims to be sample-accurate with Munt. It accomplishes this across a variety of input comparison tests with no known incompatibilities. Inputs for which moont output does not match Munt should be reported as a bug.

Usage

Add the moont crate as dependency in Cargo.toml:

[dependencies]
moont = "0.8.2"

Loading ROMs

This repository does not distribute the Roland CM-32L ROMs. In the default build configuration, the only option is to load them at runtime:

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

let rom = Rom::new(&control_rom, &pcm_rom)?;
let mut synth = CM32L::new(rom);

For situations where redistribution of the ROMs is not a concern, the bundle-rom feature flag avoids runtime loading:

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

let mut synth = CM32L::new(Rom::bundled());

This feature goes beyond bundling ROM data as binary blobs: at build time, the ROMs are validated, parsed, PCM-unscrambled and converted to Rust values. Rust literals are generated, compiled into the library, and Rom::bundled() returns a handle to this static generated data.

General MIDI Translation

When the input is General MIDI, use GmSynth to translate program changes, drum notes, and bank selects into CM-32L equivalents:

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

let mut synth = GmSynth::new(Rom::new(&control_rom, &pcm_rom)?);

Rendering Audio

Use play_msg() or play_msg_at() to enqueue MIDI events, and render() to advance the time and output 32kHz stereo samples to a buffer.

use moont::{Frame, Synth};

// 0x90: Note On, Channel 1
// 0x3c: Note C-3 (Middle C)
// 0x7f: Velocity 127 (Max)
synth.play_msg(0x7f3c91);

// 1 second of output.
let mut buf = vec![Frame(0, 0); 32000];
synth.render(&mut buf);

// 0x81: Note Off, Channel 1
// 0x3c: Note C-3 (Middle C)
synth.play_msg(0x3c81);

Munt Feature Comparison

moont emulates mt32emu configured with these device settings:

  • CM-32L hardware model.
    • Compared to MT-32: features 33 extra rhythm sounds.
    • None of the MT-32 "quirks".
  • 32kHz output sample rate without resampling: same as the hardware.
  • 4096 MIDI queue size.
  • "Nice" DAC input mode.
  • "Nice" amplitude ramp mode.
  • "Nice" panning mode.
  • "Nice" partial mixing mode.
  • "Coarse" output mode.

moont makes major scope limitations compared to mt32emu:

  • No support for alternate configuration, or other hardware models.
  • No C/C++ API, just available as Rust library crate.
  • No display functionality.
  • Limited state introspection.

Testing

Since the ROMs are not distributed, most tests are excluded from the published crate. When built from source, the sample accurate comparison tests require a patched version of libmt32emu to make its behavior deterministic.

License

moont is a derivative work of Munt. Both are distributed under LGPL 2.1+.

Copyright (C) 2021-2026 Geoff Hill geoff@geoffhill.org

Copyright (C) 2003-2026 Dean Beeler, Jerome Fisher, Sergey V. Mikayev

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.