Haematite is port of MeltySynth by Sinshu to Crystal. It is a library that provides MIDI music playback using SoundFonts for Crystal projects wity almost no dependencies.

It is effectively the same thing as my CL-MeltySynth library for Common Lisp, except that it's written in pure Crystal. I try to keep the two projects in sync and as similar as possible. In general CL-MeltySynth receives updates first, and then Haematite follows.

Wanna support me? Buy me a coffee on Ko-Fi
Buy Me a Coffee at ko-fi.com

Example videos

These were played using midi123, a command-line MIDI player that uses Haematite.


How do I get set up?

Add this to your shard.yml:

    fossil: https://chiselapp.com/user/MistressRemilia/repository/Haematite

This has mostly been tested with Crystal 1.4.x and 1.5.0. You will need Fossil installed to clone this repo and the dependency. If you use Crystal versions before 1.5.0, you will need to build the latest version of Shards by hand to get Fossil support.


There is an included program, simple-player, that acts as an example of how to use the library together with CrSFML, as well as how to dump rendered audio to a WAV file. Study that to see how to use it in a non-trivial way.

The important parts are:

# The SynthesizerSettings class is used to hold the setup parameters.
settings = Haematite::SynthesizerSettings.new(sampleRate: 44100)

# Create a Synthesizer using the settings, and a path to a SoundFont.
synth = Haematite::Synthesizer.new("/path/to/soundfont.sf2", settings)

# Create a MidiFileSequencer for the synth.
seq = Haematite::MidiFileSequencer.new(synth)

# Create a Slice to render into.  Here we're rendering to Signed 16-bit
# Little-Endian.
batch = Slice(Int16).new(2 * (0.05 * 44100).round.to_i32!, 0i16)

# Start playing a MIDI file.  The False is to disable looping.
seq.play("/path/to/midi.mid", false)

# Repeatedly render to batch within a loop of some sort.  The rendering methods
# will return false when looping is disabled and the MIDI has finished playing.
while seq.renderInterleavedInt16LE(block)
  # batch now holds a block of rendered audio
  # Maybe write it to a WAV or an audio device?

Example Programs


Running Tests

You will need to place the following SoundFonts into the specs directory with these exact filenames:

Style info

I use a somewhat non-standard style for my code.

How do I contribute?

  1. Go to https://chiselapp.com/user/MistressRemilia/repository/Haematite/ and clone the Fossil repository.
  2. Create a new branch for your feature.
  3. Push locally to the new branch.
  4. Create a bundle with Fossil that contains your changes.
  5. Get in contact with me.


Links and Licenses

Haematite itself is mostly under the GNU Affero General Public License version 3, except for the port of Zita-Rev1, which is under the GNU General Public License version 3, and the port of YK Chorus, which is under the GNU General Public License version 2