moont 0.8.3

Roland CM-32L synthesizer emulator
Documentation
# moont

Roland CM-32L synth emulator, based on [Munt](https://github.com/munt/munt/),
written in Rust with no code dependencies.

The CM-32L is in the [MT-32 family](https://en.wikipedia.org/wiki/Roland_MT-32)
of synthesizers. This hardware predates [General
MIDI](https://en.wikipedia.org/wiki/General_MIDI), but [many early 1990s PC
games](https://www.vogonswiki.com/index.php/List_of_MT-32-compatible_computer_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](https://gitlab.gnome.org/geoffhill/moont/-/issues).


## Usage

Add the `moont` crate as dependency in Cargo.toml:

    [dependencies]
    moont = "0.8.3"


## 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 makes major scope limitations compared to mt32emu:

- No support for alternate configurations or other hardware models.
- No C/C++ API, just Rust library crate.
- No display functionality.
- Very limited runtime state introspection.

moont behaves like this libmt32emu configuration:

- CM-32L hardware model.
  + Compared to MT-32: 33 extra rhythm sounds.
  + None of the MT-32 "quirks".
- 32kHz output sample rate (matching CM-32L).
- 4096 MIDI queue size.
- "Coarse" output mode (no upsampling).
- "Nice" DAC input mode.
- "Nice" amplitude ramp mode.
- "Nice" panning mode.
- "Nice" partial mixing mode.


## 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 Munt fork](https://gitlab.gnome.org/geoffhill/munt) at `./munt` in
the workspace root to make its behavior deterministic. It is built and linked
as a static library automatically.


## 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](COPYING.LESSER.txt),
or (at your option) any later version.