Reads a chunk from the input (meaning, it can either read a header chunk or a track chunk).
Reads the entire input and returns the data in a MIDI object.
Reads a complete file with a single track of a single event
import mididi.def : MetaEventType, TrackFormat; auto reader = MIDIReader!(ubyte[])([ 'M', 'T', 'h', 'd', // header chunk 0x00, 0x00, 0x00, 0x06, // length 0x00, 0x01, // format 1 0x00, 0x02, // 2 tracks 0b0_0000000, 0x60, // time division: 0, 0, 0x60 'M', 'T', 'r', 'k', // track chunk 1 0, 0, 0, 4, // length = 4 0x00, 0xFF, 0x2F, 0x00, // end of track 'M', 'T', 'r', 'k', // track chunk 2 0, 0, 0, 4, // length = 4 0x00, 0xFF, 0x2F, 0x00, // end of track ]); auto midi = reader.readMIDI(); assert(midi.headerChunk.trackFormat == TrackFormat.simultaneous); assert(midi.headerChunk.nTracks == 2); assert(midi.headerChunk.division.getFormat() == 0); assert(midi.headerChunk.division.getTicksPerQuarterNote() == 0x0060); assert(midi.trackChunks.length == 2); assert(midi.trackChunks[0].events.length == 1); const event = midi.trackChunks[0].events[0]; assert(event.asMetaEvent().type == MetaEventType.endOfTrack);
Reads a file that has bytes past the last chunk, which is disallowed.
auto reader = MIDIReader!(ubyte[])([ 'M', 'T', 'h', 'd', 0x00, 0x00, 0x00, 0x06, // length 0x00, 0x00, // format: 0 0x00, 0x01, // nTracks: 1 0b0_0000000, 0x60, // time division: 0, 0, 0x60 'M', 'T', 'r', 'k', 0, 0, 0, 4, 0x00, 0xFF, 0x2F, 0x00, 'M', 'T', 'r', 'k', // too many chunks 0, 0, 0, 4, 0x00, 0xFF, 0x2F, 0x00, ]); try { const _ = reader.readMIDI(); assert(false, "File is invalid, but no exception was thrown"); } catch (Exception e) {}
MIDIReader is the raw MIDI reader object.
This can be used to read the standard MIDI chunk-by-chunk or event-by-event.
Constraints: T must be an input range of ubyte