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 () {
			
			if (stream.end()) {
				return null;
			}
			
			event = {
				
				index: stream.pos(),
				
				delta: stream.readVarInt(),
			};
			
			eventTypeByte = stream.readUint8();
			if (0xF0 === (eventTypeByte & 0xF0)) {
				
				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;
					}
					
				} 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;
					
				} 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;
				}
				
			} else {
				
				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 (!event.param2) {
						event.subtype = MIDIEvents.EVENT_MIDI_NOTE_OFF;
						event.param2 = 127; 
					}
					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
Read the next event