examples/MIDIFile.js
function () {
			// Check available datas
			if (stream.end()) {
				return null;
			}
			// Creating the event
			event = {
				// Memoize the event index
				index: stream.pos(),
				// Read the delta time
				delta: stream.readVarInt(),
			};
			// Read the eventTypeByte
			eventTypeByte = stream.readUint8();
			if (0xF0 === (eventTypeByte & 0xF0)) {
				// Meta events
				if (eventTypeByte === MIDIEvents.EVENT_META) {
					event.type = MIDIEvents.EVENT_META;
					event.subtype = stream.readUint8();
					event.length = stream.readVarInt();
					switch (event.subtype) {
					case MIDIEvents.EVENT_META_SEQUENCE_NUMBER:
						if (strictMode && 2 !== event.length) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						event.msb = stream.readUint8();
						event.lsb = stream.readUint8();
						return event;
					case MIDIEvents.EVENT_META_TEXT:
					case MIDIEvents.EVENT_META_COPYRIGHT_NOTICE:
					case MIDIEvents.EVENT_META_TRACK_NAME:
					case MIDIEvents.EVENT_META_INSTRUMENT_NAME:
					case MIDIEvents.EVENT_META_LYRICS:
					case MIDIEvents.EVENT_META_MARKER:
					case MIDIEvents.EVENT_META_CUE_POINT:
						event.data = stream.readBytes(event.length);
						return event;
					case MIDIEvents.EVENT_META_MIDI_CHANNEL_PREFIX:
						if (strictMode && 1 !== event.length) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						event.prefix = stream.readUint8();
						return event;
					case MIDIEvents.EVENT_META_END_OF_TRACK:
						if (strictMode && 0 !== event.length) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						return event;
					case MIDIEvents.EVENT_META_SET_TEMPO:
						if (strictMode && 3 !== event.length) {
							throw new Error(stream.pos() + ' Tempo meta event length must be 3.');
						}
						event.tempo = (
							(stream.readUint8() << 16) +
							(stream.readUint8() << 8) +
							stream.readUint8());
						event.tempoBPM = 60000000 / event.tempo;
						return event;
					case MIDIEvents.EVENT_META_SMTPE_OFFSET:
						if (strictMode && 5 !== event.length) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						event.hour = stream.readUint8();
						if (strictMode && 23 < event.hour) {
							throw new Error(stream.pos() + ' SMTPE offset hour value must' +
								' be part of 0-23.');
						}
						event.minutes = stream.readUint8();
						if (strictMode && 59 < event.minutes) {
							throw new Error(stream.pos() + ' SMTPE offset minutes value' +
								' must be part of 0-59.');
						}
						event.seconds = stream.readUint8();
						if (strictMode && 59 < event.seconds) {
							throw new Error(stream.pos() + ' SMTPE offset seconds value' +
								' must be part of 0-59.');
						}
						event.frames = stream.readUint8();
						if (strictMode && 30 < event.frames) {
							throw new Error(stream.pos() + ' SMTPE offset frames value must' +
								' be part of 0-30.');
						}
						event.subframes = stream.readUint8();
						if (strictMode && 99 < event.subframes) {
							throw new Error(stream.pos() + ' SMTPE offset subframes value' +
								' must be part of 0-99.');
						}
						return event;
					case MIDIEvents.EVENT_META_KEY_SIGNATURE:
						if (strictMode && 2 !== event.length) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						event.key = stream.readUint8();
						if (strictMode && (-7 > event.key || 7 < event.key)) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						event.scale = stream.readUint8();
						if (strictMode && 0 !== event.scale && 1 !== event.scale) {
							throw new Error(stream.pos() + ' Key signature scale value must' +
								' be 0 or 1.');
						}
						return event;
					case MIDIEvents.EVENT_META_TIME_SIGNATURE:
						if (strictMode && 4 !== event.length) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						event.data = stream.readBytes(event.length);
						event.param1 = event.data[0];
						event.param2 = event.data[1];
						event.param3 = event.data[2];
						event.param4 = event.data[3];
						return event;
					case MIDIEvents.EVENT_META_SEQUENCER_SPECIFIC:
						event.data = stream.readBytes(event.length);
						return event;
					default:
						if (strictMode) {
							throw new Error(stream.pos() + ' Unknown meta event type ' +
								'(' + event.subtype.toString(16) + ').');
						}
						event.data = stream.readBytes(event.length);
						return event;
					}
					// System events
				} else if (eventTypeByte === MIDIEvents.EVENT_SYSEX ||
					eventTypeByte === MIDIEvents.EVENT_DIVSYSEX) {
					event.type = eventTypeByte;
					event.length = stream.readVarInt();
					event.data = stream.readBytes(event.length);
					return event;
					// Unknown event, assuming it's system like event
				} else {
					if (strictMode) {
						throw new Error(stream.pos() + ' Unknown event type ' +
							eventTypeByte.toString(16) + ', Delta: ' + event.delta + '.');
					}
					event.type = eventTypeByte;
					event.badsubtype = stream.readVarInt();
					event.length = stream.readUint8();
					event.data = stream.readBytes(event.length);
					return event;
				}
				// MIDI eventsdestination[index++]
			} else {
				// running status
				if (0 === (eventTypeByte & 0x80)) {
					if (!(MIDIEventType)) {
						throw new Error(stream.pos() + ' Running status without previous event');
					}
					MIDIEventParam1 = eventTypeByte;
				} else {
					MIDIEventType = eventTypeByte >> 4;
					MIDIEventChannel = eventTypeByte & 0x0F;
					MIDIEventParam1 = stream.readUint8();
				}
				event.type = MIDIEvents.EVENT_MIDI;
				event.subtype = MIDIEventType;
				event.channel = MIDIEventChannel;
				event.param1 = MIDIEventParam1;
				switch (MIDIEventType) {
				case MIDIEvents.EVENT_MIDI_NOTE_OFF:
					event.param2 = stream.readUint8();
					return event;
				case MIDIEvents.EVENT_MIDI_NOTE_ON:
					event.param2 = stream.readUint8();

					// If velocity is 0, it's a note off event in fact
					if (!event.param2) {
						event.subtype = MIDIEvents.EVENT_MIDI_NOTE_OFF;
						event.param2 = 127; // Find a standard telling what to do here
					}
					return event;
				case MIDIEvents.EVENT_MIDI_NOTE_AFTERTOUCH:
					event.param2 = stream.readUint8();
					return event;
				case MIDIEvents.EVENT_MIDI_CONTROLLER:
					event.param2 = stream.readUint8();
					return event;
				case MIDIEvents.EVENT_MIDI_PROGRAM_CHANGE:
					return event;
				case MIDIEvents.EVENT_MIDI_CHANNEL_AFTERTOUCH:
					return event;
				case MIDIEvents.EVENT_MIDI_PITCH_BEND:
					event.param2 = stream.readUint8();
					return event;
				default:
					if (strictMode) {
						throw new Error(stream.pos() + ' Unknown MIDI event type ' +
							'(' + MIDIEventType.toString(16) + ').');
					}
					return event;
				}
			}
		}
function () {
			// Check available datas
			if (stream.end()) {
				return null;
			}
			// Creating the event
			event = {
				// Memoize the event index
				index: stream.pos(),
				// Read the delta time
				delta: stream.readVarInt(),
			};
			// Read the eventTypeByte
			eventTypeByte = stream.readUint8();
			if (0xF0 === (eventTypeByte & 0xF0)) {
				// Meta events
				if (eventTypeByte === MIDIEvents.EVENT_META) {
					event.type = MIDIEvents.EVENT_META;
					event.subtype = stream.readUint8();
					event.length = stream.readVarInt();
					switch (event.subtype) {
					case MIDIEvents.EVENT_META_SEQUENCE_NUMBER:
						if (strictMode && 2 !== event.length) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						event.msb = stream.readUint8();
						event.lsb = stream.readUint8();
						return event;
					case MIDIEvents.EVENT_META_TEXT:
					case MIDIEvents.EVENT_META_COPYRIGHT_NOTICE:
					case MIDIEvents.EVENT_META_TRACK_NAME:
					case MIDIEvents.EVENT_META_INSTRUMENT_NAME:
					case MIDIEvents.EVENT_META_LYRICS:
					case MIDIEvents.EVENT_META_MARKER:
					case MIDIEvents.EVENT_META_CUE_POINT:
						event.data = stream.readBytes(event.length);
						return event;
					case MIDIEvents.EVENT_META_MIDI_CHANNEL_PREFIX:
						if (strictMode && 1 !== event.length) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						event.prefix = stream.readUint8();
						return event;
					case MIDIEvents.EVENT_META_END_OF_TRACK:
						if (strictMode && 0 !== event.length) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						return event;
					case MIDIEvents.EVENT_META_SET_TEMPO:
						if (strictMode && 3 !== event.length) {
							throw new Error(stream.pos() + ' Tempo meta event length must be 3.');
						}
						event.tempo = (
							(stream.readUint8() << 16) +
							(stream.readUint8() << 8) +
							stream.readUint8());
						event.tempoBPM = 60000000 / event.tempo;
						return event;
					case MIDIEvents.EVENT_META_SMTPE_OFFSET:
						if (strictMode && 5 !== event.length) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						event.hour = stream.readUint8();
						if (strictMode && 23 < event.hour) {
							throw new Error(stream.pos() + ' SMTPE offset hour value must' +
								' be part of 0-23.');
						}
						event.minutes = stream.readUint8();
						if (strictMode && 59 < event.minutes) {
							throw new Error(stream.pos() + ' SMTPE offset minutes value' +
								' must be part of 0-59.');
						}
						event.seconds = stream.readUint8();
						if (strictMode && 59 < event.seconds) {
							throw new Error(stream.pos() + ' SMTPE offset seconds value' +
								' must be part of 0-59.');
						}
						event.frames = stream.readUint8();
						if (strictMode && 30 < event.frames) {
							throw new Error(stream.pos() + ' SMTPE offset frames value must' +
								' be part of 0-30.');
						}
						event.subframes = stream.readUint8();
						if (strictMode && 99 < event.subframes) {
							throw new Error(stream.pos() + ' SMTPE offset subframes value' +
								' must be part of 0-99.');
						}
						return event;
					case MIDIEvents.EVENT_META_KEY_SIGNATURE:
						if (strictMode && 2 !== event.length) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						event.key = stream.readUint8();
						if (strictMode && (-7 > event.key || 7 < event.key)) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						event.scale = stream.readUint8();
						if (strictMode && 0 !== event.scale && 1 !== event.scale) {
							throw new Error(stream.pos() + ' Key signature scale value must' +
								' be 0 or 1.');
						}
						return event;
					case MIDIEvents.EVENT_META_TIME_SIGNATURE:
						if (strictMode && 4 !== event.length) {
							throw new Error(stream.pos() + ' Bad metaevent length.');
						}
						event.data = stream.readBytes(event.length);
						event.param1 = event.data[0];
						event.param2 = event.data[1];
						event.param3 = event.data[2];
						event.param4 = event.data[3];
						return event;
					case MIDIEvents.EVENT_META_SEQUENCER_SPECIFIC:
						event.data = stream.readBytes(event.length);
						return event;
					default:
						if (strictMode) {
							throw new Error(stream.pos() + ' Unknown meta event type ' +
								'(' + event.subtype.toString(16) + ').');
						}
						event.data = stream.readBytes(event.length);
						return event;
					}
					// System events
				} else if (eventTypeByte === MIDIEvents.EVENT_SYSEX ||
					eventTypeByte === MIDIEvents.EVENT_DIVSYSEX) {
					event.type = eventTypeByte;
					event.length = stream.readVarInt();
					event.data = stream.readBytes(event.length);
					return event;
					// Unknown event, assuming it's system like event
				} else {
					if (strictMode) {
						throw new Error(stream.pos() + ' Unknown event type ' +
							eventTypeByte.toString(16) + ', Delta: ' + event.delta + '.');
					}
					event.type = eventTypeByte;
					event.badsubtype = stream.readVarInt();
					event.length = stream.readUint8();
					event.data = stream.readBytes(event.length);
					return event;
				}
				// MIDI eventsdestination[index++]
			} else {
				// running status
				if (0 === (eventTypeByte & 0x80)) {
					if (!(MIDIEventType)) {
						throw new Error(stream.pos() + ' Running status without previous event');
					}
					MIDIEventParam1 = eventTypeByte;
				} else {
					MIDIEventType = eventTypeByte >> 4;
					MIDIEventChannel = eventTypeByte & 0x0F;
					MIDIEventParam1 = stream.readUint8();
				}
				event.type = MIDIEvents.EVENT_MIDI;
				event.subtype = MIDIEventType;
				event.channel = MIDIEventChannel;
				event.param1 = MIDIEventParam1;
				switch (MIDIEventType) {
				case MIDIEvents.EVENT_MIDI_NOTE_OFF:
					event.param2 = stream.readUint8();
					return event;
				case MIDIEvents.EVENT_MIDI_NOTE_ON:
					event.param2 = stream.readUint8();

					// If velocity is 0, it's a note off event in fact
					if (!event.param2) {
						event.subtype = MIDIEvents.EVENT_MIDI_NOTE_OFF;
						event.param2 = 127; // Find a standard telling what to do here
					}
					return event;
				case MIDIEvents.EVENT_MIDI_NOTE_AFTERTOUCH:
					event.param2 = stream.readUint8();
					return event;
				case MIDIEvents.EVENT_MIDI_CONTROLLER:
					event.param2 = stream.readUint8();
					return event;
				case MIDIEvents.EVENT_MIDI_PROGRAM_CHANGE:
					return event;
				case MIDIEvents.EVENT_MIDI_CHANNEL_AFTERTOUCH:
					return event;
				case MIDIEvents.EVENT_MIDI_PITCH_BEND:
					event.param2 = stream.readUint8();
					return event;
				default:
					if (strictMode) {
						throw new Error(stream.pos() + ' Unknown MIDI event type ' +
							'(' + MIDIEventType.toString(16) + ').');
					}
					return event;
				}
			}
		}
Read the next event