A MIDI file parser and writer in MoonBit
moon add CAIMEOX/midiMidiFile { format: UInt16, division: UInt16, tracks: Array[Track] }
Track { events: Array[Event] }
Event =>
NoteOn(delta, channel, note, velocity)
| NoteOff(delta, channel, note, velocity)
| ControlChange(delta, channel, controller, value)
| ProgramChange(delta, channel, program)
| Aftertouch(delta, channel, value)
| PolyTouch(delta, channel, note, value)
| PitchWheel(delta, channel, pitch) // signed 14-bit centered at 0
| Tempo(delta~ : UInt, microseconds~ : UInt) // 0x51, in microseconds
| TimeSignature(delta~ : UInt, numerator~ : Byte, denominator~ : Byte, clocks_per_beat~ : Byte, thirty_seconds_per_quarter~ : Byte) // 0x58, denominator is log(2)D
| KeySignature(delta~ : UInt, sf~ : Byte, mi~ : Byte) // 0x59, sharp/flat and major/minor
| Meta(delta, meta_type, data[]) // raw meta payload
| SysEx(delta, data[]) // payload (without trailing F7)
| Clock | Start | Continue | Stop | ActiveSensing | Resetpub fn parse(bytes: Bytes) -> MidiFile raise ParseErrorpub fn serialize(file: MidiFile) -> Bytesfn demo(bytes: Bytes) raise @midi.ParseError {
let mf = @midi.parse(bytes)
println(mf.to_string()) // Uses Show impl to pretty print
}pub suberror ParseError {
InvalidHeader
InvalidTrack
UnexpectedEOF
UnknownEventType
InvalidData(String)
}pub(all) enum Event {
NoteOn(UInt, Byte, Byte, Byte)
NoteOff(UInt, Byte, Byte, Byte)
ControlChange(UInt, Byte, Byte, Byte)
ProgramChange(UInt, Byte, Byte)
Aftertouch(UInt, Byte, Byte)
PolyTouch(UInt, Byte, Byte, Byte)
PitchWheel(UInt, Byte, Int)
Tempo(UInt, UInt)
TimeSignature(UInt, Byte, Byte, Byte, Byte)
KeySignature(UInt, Byte, Byte)
Meta(UInt, Byte, Array[Byte])
SysEx(UInt, Array[Byte])
Clock(UInt)
Start(UInt)
Continue(UInt)
Stop(UInt)
ActiveSensing(UInt)
Reset(UInt)
}A MIDI file parser and writer in MoonBit