zmidi-core-0.2.0: Read and write MIDI files.

PortabilityAs per dependencies.
MaintainerStephen Tetley <>




Concrete syntax tree for MIDI files.

Values are sometimes not interpreted. This means that the the data types do not fully represent the sematics of the data, but all the data is either stored in the tree or synthesizeable.

readFile >>= writeFile will produce an identical binary [1].

[1] Or it should, failure indicates a bug...


MidiFile representation.

data MidiFile Source

MidiFile : header * tracks




mf_header :: Header
mf_tracks :: [Track]


data Header Source

Header : format * num_tracks * time_division

TimeDivision is often 384 or 480 ticks per beat.

The header is the start of a MIDI file, it is indicated by the 4 character marker MThd.


newtype Track Source

Track : [message]

In MIDI files, the start of a track is indicated by the 4 character marker MTrk.




getMessages :: [Message]


data Format Source

The file format - in a MIDI file this is a big-endian word16 with 0,1 or 2 being the only valid values.



Format 0 file - single multi-channel track.


Format 1 file - 1 or more tracks, played simultaneously.


Format 2 file - 1 or more independent tracks.

type DeltaTime = Word32Source

All time values in a MIDI track are represented as a delta from the previous event rather than an absolute time.

Although DeltaTime is a type synonym for Word32, in MIDI files it is represented as a varlen to save space.

type Message = (DeltaTime, Event)Source

MIDI messages are pairs of DeltaTime and Event wrapped in a newtype.

Sequential messages with delta time 0 are played simultaneously.

data Event Source

Recognised event types - some types (DataEvent and SysEx) are not interpreted.


DataEvent DataEvent

Data event - just initial tag byte, uninterpreted

VoiceEvent VoiceEvent

Voice event (e.g note-on, note-off) are relayed to specific channels.

SysExEvent SysExEvent

SysEx - system exclusive event. Usually synthesizer specific, not interpreted.

SysCommonEvent SysCommonEvent

SysCommon - system common event.

SysRealTimeEvent SysRealTimeEvent

SysRealTime - system realtime event.

MetaEvent MetaEvent

Meta event - interpreted (e.g. end-of-track, set-tempo).


data DataEvent Source

Data events are events with tags from 0x00 to 0x7F.

Data events have no payload - they are represented only by the tag byte.


Data1 TagByte 

data VoiceEvent Source

Voice events control the output of the synthesizer.

Note - the constructors are not in the the same order as their byte values. Controller and ProgramChange are higher than they naturally occur so the will come first after a comparison or sort.

When generating MIDI, Controller and ProgramChange events should be signalled before NoteOn or NoteOff events at the same delta-time. Changing the order of the constructors helps to sort for this.


Controller Word8 Word8 Word8
 channel * controller_number * value

Controller change, e.g. by a footswitch.

ProgramChange Word8 Word8

channel * program_number - change the instrument playing on the specified channel. For playback on computers (rather than synthesizers) the program numbers will correspond to the General MIDI instrument numbers.

NoteOff Word8 Word8 Word8
 channel * note * velocity

Turn off a sounding note.

NoteOn Word8 Word8 Word8
 channel * note * velocity

Start playing a note.

NoteAftertouch Word8 Word8 Word8
 channel * note * pressure_value

Change of pressure applied to the synthesizer key.

ChanAftertouch Word8 Word8
 channel * pressure_value
PitchBend Word8 Word16
 channel * value

Change the pitch of a sounding note. Often used to approximate microtonal tunings.

NOTE - currently value is uninterpreted.

data SysExEvent Source

SysEx - system exclusive event.


SysEx Word32 [Word8]
 length * data

An uninterpreted sys-ex event.

data SysCommonEvent Source

System common event.

Common information for all channels in a system.

These events may not be pertinent to MIDI files generated on a computer (as opposed to MIDI generated by a synthesizer or sequencer).


QuarterFrame SplitByte

Time code quarter frame.

SongPosPointer Word8 Word8

Song position pointer.

SongSelect Word8

Song number should be in the range 0..127.

Common_undefined TagByte

Tag should be limited to 0xF4 or 0xF5.

Other values would indicate either a badly formed MIDI file or a failure with the parser.


Tune request message for analogue synthesizers.


End-of-system-exclusive message.

data SysRealTimeEvent Source

System real-time event.

These events may not be pertinent to MIDI files generated on a computer (as opposed to MIDI generated by a synthesizer or sequencer).



Timing signal.

RT_undefined TagByte

Tag should be limited to either 0xF9 or 0xFD.

Other values would indicate either a badly formed MIDI file or a failure with the parser.


Start playing a sequence.


Continue playing a stopped sequence.


Stop playing a sequence.


Synchronization pulse...


Reset to power-up status.

data MetaEvent Source

Meta event

In Format 1 files general events (e.g. text events) should only appear in track 1. Certain events (e.g. end-of-track) can appear in any track where necessary.


TextEvent TextType String
 text_type * contents

Free text field (e.g. copyright statement). The contents can notionally be any length.

SequenceNumber Word16

Format 1 files - only track 1 should have a sequence number.

Format 2 files - a sequence number should identify each track.

The sequence number event should occur at the start of a track, before any non-zero time events.

ChannelPrefix Word8 Word8
 1 * channel

Relay all meta and sys-ex events to the given channel.

The first byte should always be 1.


End-of-track event.

SetTempo Word32
SMPTEOffset Word8 Word8 Word8 Word8 Word8
 hour * minute * second * frac * subfrac

The SMPTE time when a track should start. This event should occur at the start of a track, before any non-zero time events.

TimeSignature Word8 Word8 Word8 Word8
 numerator * denominator * metro * num_32nd_notes
KeySignature Int8 ScaleType
 key_type * scale_type

key_type is the number of sharps (postive numbers) or flats (negative numbers), e.g. (-1) is 1 flat.

scale_type indicates major or minor.

SSME Word32 [Word8]
 length * data

Sequencer specific meta-event - uninterpreted.

data TimeDivision Source

Default unit of time in the MIDI file.


FPS Word16


TPB Word16

Ticks-per-beat, i.e. the number of units for a quater note.

data TextType Source

Enumeration of the text meta event types.

data ScaleType Source

Scale type - major or minor.



Interim types.


data SplitByte Source

SplitByte - divide a byte into the upper four and lower 4 bits.




upper4 :: Word8
lower4 :: Word8


data Varlen Source

Space efficient representation of length fields.

This data type is not used directly in the syntax tree where it would be cumbersome. But it is used as an intermediate type in the parser and emitter.


V1 !Word8 
V2 !Word8 !Word8 
V3 !Word8 !Word8 !Word8 
V4 !Word8 !Word8 !Word8 !Word8