No description
Find a file
Johann Queuniet b9366ab969
All checks were successful
CI / stable (push) Successful in 14s
CI / audit (push) Successful in 9s
CI / msrv (1.90) (push) Successful in 18s
CI / stable (pull_request) Successful in 15s
CI / msrv (1.90) (pull_request) Successful in 19s
CI / audit (pull_request) Successful in 9s
chore: exclude .idea from package, drop stale -p flag in gen_golden
Keep IntelliJ config in git but out of the published crate via
Cargo.toml exclude. Update the gen_golden usage comment now that the
crate is standalone (no workspace -p needed).
2026-07-23 09:20:22 +02:00
.forgejo/workflows chore: standalone-ize after monorepo split 2026-07-23 09:06:17 +02:00
.idea chore: add IDEA configuration files 2026-07-23 09:13:53 +02:00
examples chore: exclude .idea from package, drop stale -p flag in gen_golden 2026-07-23 09:20:22 +02:00
src fix(audio): robustness fixes across sms-audio/opl-audio/dm2-wav (#243) 2026-07-16 15:46:17 +02:00
.gitignore chore: standalone-ize after monorepo split 2026-07-23 09:06:17 +02:00
Cargo.lock chore: standalone-ize after monorepo split 2026-07-23 09:06:17 +02:00
Cargo.toml chore: exclude .idea from package, drop stale -p flag in gen_golden 2026-07-23 09:20:22 +02:00
deny.toml chore: standalone-ize after monorepo split 2026-07-23 09:06:17 +02:00
LICENSE-APACHE chore: standalone-ize after monorepo split 2026-07-23 09:06:17 +02:00
LICENSE-MIT chore: standalone-ize after monorepo split 2026-07-23 09:06:17 +02:00
README.md chore: standalone-ize after monorepo split 2026-07-23 09:06:17 +02:00

sms-audio

Pure-Rust SoundMusicSys (SMS / Halestorm) song renderer.

Renders a Standard MIDI File against a bank of decoded Sound Manager samples to mono PCM. The crate is engine-agnostic: it knows MIDI and sampled-instrument synthesis — not resource forks or any specific game. Callers decode their 'SONG' / 'INST' / 'snd ' resources themselves and hand in an [InstrumentBank] of ready-to-play samples.

  • #![forbid(unsafe_code)]
  • Single dependency: thiserror
  • Synthesis follows the documented SoundMusicSys behaviour; original code, not derived from any GPL source — cleanly licensable under MIT OR Apache-2.0.

What it does

  • Parses a Standard MIDI File and drives a sampled-instrument voice pool.
  • Per-instrument sustain loops, one-shots, velocity/CC7 amplitude scaling (opt-in per instrument), and linear or nearest-neighbour interpolation (preserving the original non-interpolated aliasing when asked).
  • SMS 'SONG' playback parameters are exposed on [RenderOpts] — post-note-off release ticks, voice-count-to-full-scale mapping, music voice cap, and releasing-voice stealing — all with engine-neutral defaults for callers that have no SONG record.
  • A [diag] module and a [fingerprint] module for render diagnostics and audio-similarity checks.

Usage

use sms_audio::{Instrument, InstrumentBank, RenderOpts};

let mut bank = InstrumentBank::new();
bank.insert(0, my_instrument); // an Instrument you decoded from a 'snd ' resource

// `smf` is raw Standard MIDI File bytes.
let pcm = sms_audio::render(&smf, &bank, RenderOpts::default())?;
// pcm.samples: Vec<f32> in [-1.0, 1.0] at pcm.sample_rate (22254 Hz by default)

See examples/render_song.rs for a complete, data-free example that builds a minimal SMF and a synthesized instrument in code:

cargo run --example render_song

Provenance

Extracted from the dm2-tools Dungeon Master II toolchain, where it renders the game's Macintosh soundtrack. The per-crate commit history is preserved from that monorepo.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.