defmodule ExMidi do
@moduledoc """
Batteries-included Elixir MIDI.
`ExMidi` provides a unified API for MIDI message construction, binary
encode/decode, Standard MIDI File read/write, SYX file support, and a
streaming MIDI parser.
## Message terms
All MIDI messages are represented as `{:midi, payload}` tuples:
{:midi, {:note_on, [channel: 1, pitch: 60, velocity: 100]}}
## Modules
- `ExMidi.MidiMsg` — lightweight message constructors (tuple-based)
- `ExMidi.MidiMessage` — frozen message struct with rich API (copy, hex, dict, etc.)
- `ExMidi.MidiBin` — binary encode/decode of MIDI messages
- `ExMidi.MidiParser` — streaming byte-by-byte MIDI parser
- `ExMidi.MidiFile` — Standard MIDI File read/write (Format 0/1/2)
- `ExMidi.MidiSyx` — SYX file read/write
- `ExMidi.MidiUtil` — utility functions
- `ExMidi.MidiLib` — version information
## Quick start
# Message constructors
ExMidi.MidiMsg.note_on(60, 100)
# => {:midi, {:note_on, [pitch: 60, velocity: 100]}}
# Binary encode/decode
ExMidi.MidiBin.encode(ExMidi.MidiMsg.note_on(1, 60, 100))
# => <<144, 60, 100>>
ExMidi.MidiBin.decode(<<144, 60, 100>>)
# => {:midi, {:note_on, [channel: 1, pitch: 60, velocity: 100]}}
# Frozen message struct
msg = ExMidi.MidiMessage.new(:note_on, channel: 1, pitch: 60, velocity: 100)
ExMidi.MidiMessage.to_hex(msg)
# => "90 3C 64"
# Streaming parser
parser = ExMidi.MidiParser.new()
parser = ExMidi.MidiParser.feed_bytes(parser, [144, 60, 100])
{msg, _} = ExMidi.MidiParser.parse(parser)
# MIDI file
midi = ExMidi.MidiFile.read("song.mid")
for msg <- ExMidi.MidiFile.play(midi), do: IO.inspect(msg)
"""
@doc "Returns the current library version."
def version, do: ExMidi.MidiLib.version()
@doc "Returns all version information."
def versions, do: ExMidi.MidiLib.versions()
end