Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 44 additions & 44 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
*/
const _atob = function(string) {
// base64 character set, plus padding character (=)
let b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
// Regular expression to check formal correctness of base64 encoded strings
let b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
// remove data type signatures at the begining of the string
// eg : "data:audio/mid;base64,"
string = string.replace( /^.*?base64,/ , '');
string = string.replace(/^.*?base64,/ , '');
// atob can work with strings with whitespaces, even inside the encoded part,
// but only \t, \n, \f, \r and ' ', which can be stripped.
string = String(string).replace(/[\t\n\f\r ]+/g, '');
Expand All @@ -50,7 +50,7 @@
* [MidiParser description]
* @type {Object}
*/
const MidiParser = {
const MidiParser = {
// debug (bool), when enabled will log in console unimplemented events
// warnings and internal handled errors.
debug: false,
Expand All @@ -77,23 +77,23 @@
if(!File || !FileReader) throw new Error('The File|FileReader APIs are not supported in this browser. Use instead MidiParser.Base64() or MidiParser.Uint8()');

// validate provided element
if( _fileElement === undefined ||
if(_fileElement === undefined ||
!(_fileElement instanceof HTMLElement) ||
_fileElement.tagName !== 'INPUT' ||
_fileElement.type.toLowerCase() !== 'file'
_fileElement.type.toLowerCase() !== 'file'
){
console.warn('MidiParser.addListener() : Provided element is not a valid FILE INPUT element');
return false;
}
_callback = _callback || function(){};

_fileElement.addEventListener('change', function(InputEvt){ // set the 'file selected' event handler
if (!InputEvt.target.files.length) return false; // return false if no elements where selected
_fileElement.addEventListener('change', function(InputEvt){ // set the 'file selected' event handler
if (!InputEvt.target.files.length) return false; // return false if no elements where selected
console.log('MidiParser.addListener() : File detected in INPUT ELEMENT processing data..');
let reader = new FileReader(); // prepare the file Reader
reader.readAsArrayBuffer(InputEvt.target.files[0]); // read the binary data
reader.onload = function(e){
_callback( MidiParser.Uint8(new Uint8Array(e.target.result))); // encode data with Uint8Array and call the parser
const reader = new FileReader(); // prepare the file Reader
reader.readAsArrayBuffer(InputEvt.target.files[0]); // read the binary data
reader.onload = function(e){
_callback(MidiParser.Uint8(new Uint8Array(e.target.result))); // encode data with Uint8Array and call the parser
};
});
},
Expand All @@ -105,12 +105,12 @@
Base64 : function(b64String){
b64String = String(b64String);

let raw = _atob(b64String);
let rawLength = raw.length;
let t_array = new Uint8Array(new ArrayBuffer(rawLength));
const raw = _atob(b64String);
const rawLength = raw.length;
const t_array = new Uint8Array(new ArrayBuffer(rawLength));

for(let i=0; i<rawLength; i++) t_array[i] = raw.charCodeAt(i);
return MidiParser.Uint8(t_array) ;
return MidiParser.Uint8(t_array) ;
},

/**
Expand All @@ -119,7 +119,7 @@
* or 'false' if any error was generated.
*/
Uint8: function(FileAsUint8Array){
let file = {
const file = {
data: null,
pointer: 0,
movePointer: function(_bytes){ // move the pointer negative and positive direction
Expand All @@ -128,7 +128,7 @@
},
readInt: function(_bytes){ // get integer from next _bytes group (big-endian)
_bytes = Math.min(_bytes, this.data.byteLength-this.pointer);
if (_bytes < 1) return -1; // EOF
if (_bytes < 1) return -1; // EOF
let value = 0;
if(_bytes > 1){
for(let i=1; i<= (_bytes-1); i++){
Expand All @@ -142,21 +142,21 @@
},
readStr: function(_bytes){ // read as ASCII chars, the followoing _bytes
let text = '';
for(let char=1; char <= _bytes; char++) text += String.fromCharCode(this.readInt(1));
for(let char=1; char <= _bytes; char++) text += String.fromCharCode(this.readInt(1));
return text;
},
readIntVLV: function(){ // read a variable length value
let value = 0;
if ( this.pointer >= this.data.byteLength ){
if (this.pointer >= this.data.byteLength){
return -1; // EOF
}else if(this.data.getUint8(this.pointer) < 128){ // ...value in a single byte
value = this.readInt(1);
}else{ // ...value in multiple bytes
let FirstBytes = [];
const FirstBytes = [];
while(this.data.getUint8(this.pointer) >= 128){
FirstBytes.push(this.readInt(1) - 128);
}
let lastByte = this.readInt(1);
const lastByte = this.readInt(1);
for(let dt = 1; dt <= FirstBytes.length; dt++){
value += FirstBytes[FirstBytes.length - dt] * Math.pow(128, dt);
}
Expand All @@ -172,13 +172,13 @@
console.warn('Header validation failed (not MIDI standard or file corrupt.)');
return false; // Header validation failed (not MIDI standard or file corrupt.)
}
let headerSize = file.readInt(4); // header size (unused var), getted just for read pointer movement
let MIDI = {}; // create new midi object
const headerSize = file.readInt(4); // header size (unused var), getted just for read pointer movement
const MIDI = {}; // create new midi object
MIDI.formatType = file.readInt(2); // get MIDI Format Type
MIDI.tracks = file.readInt(2); // get ammount of track chunks
MIDI.track = []; // create array key for track data storing
let timeDivisionByte1 = file.readInt(1); // get Time Division first byte
let timeDivisionByte2 = file.readInt(1); // get Time Division second byte
const timeDivisionByte1 = file.readInt(1); // get Time Division first byte
const timeDivisionByte2 = file.readInt(1); // get Time Division second byte
if(timeDivisionByte1 >= 128){ // discover Time Division mode (fps or tpf)
MIDI.timeDivision = [];
MIDI.timeDivision[0] = timeDivisionByte1 - 128; // frames per second MODE (1st byte)
Expand All @@ -187,9 +187,9 @@

// ** read TRACK CHUNK
for(let t=1; t <= MIDI.tracks; t++){
MIDI.track[t-1] = {event: []}; // create new Track entry in Array
let headerValidation = file.readInt(4);
if ( headerValidation === -1 ) break; // EOF
MIDI.track[t-1] = {event: []}; // create new Track entry in Array
const headerValidation = file.readInt(4);
if (headerValidation === -1) break; // EOF
if(headerValidation !== 0x4D54726B) return false; // Track chunk header validation failed.
file.readInt(4); // move pointer. get chunk size (bytes length)
let e = 0; // init event counter
Expand All @@ -200,7 +200,7 @@
while(!endOfTrack){
e++; // increase by 1 event counter
MIDI.track[t-1].event[e-1] = {}; // create new event object, in events array
MIDI.track[t-1].event[e-1].deltaTime = file.readIntVLV(); // get DELTA TIME OF MIDI event (Variable Length Value)
MIDI.track[t-1].event[e-1].deltaTime = file.readIntVLV(); // get DELTA TIME OF MIDI event (Variable Length Value)
statusByte = file.readInt(1); // read EVENT TYPE (STATUS BYTE)
if(statusByte === -1) break; // EOF
else if(statusByte >= 128) laststatusByte = statusByte; // NEW STATUS BYTE DETECTED
Expand All @@ -215,8 +215,8 @@
//
if(statusByte === 0xFF){ // Meta Event type
MIDI.track[t-1].event[e-1].type = 0xFF; // assign metaEvent code to array
MIDI.track[t-1].event[e-1].metaType = file.readInt(1); // assign metaEvent subtype
let metaEventLength = file.readIntVLV(); // get the metaEvent length
MIDI.track[t-1].event[e-1].metaType = file.readInt(1); // assign metaEvent subtype
const metaEventLength = file.readIntVLV(); // get the metaEvent length
switch(MIDI.track[t-1].event[e-1].metaType){
case 0x2F: // end of track, has no data byte
case -1: // EOF
Expand Down Expand Up @@ -254,10 +254,10 @@
default :
// if user provided a custom interpreter, call it
// and assign to event the returned data
if( this.customInterpreter !== null){
MIDI.track[t-1].event[e-1].data = this.customInterpreter( MIDI.track[t-1].event[e-1].metaType, file, metaEventLength);
if(this.customInterpreter !== null){
MIDI.track[t-1].event[e-1].data = this.customInterpreter(MIDI.track[t-1].event[e-1].metaType, file, metaEventLength);
}
// if no customInterpretr is provided, or returned
// if no customInterpreter is provided, or returned
// false (=apply default), perform default action
if(this.customInterpreter === null || MIDI.track[t-1].event[e-1].data === false){
file.readInt(metaEventLength);
Expand All @@ -280,14 +280,14 @@

// if user provided a custom interpreter, call it
// and assign to event the returned data
if( this.customInterpreter !== null){
MIDI.track[t-1].event[e-1].data = this.customInterpreter( MIDI.track[t-1].event[e-1].type, file , false);
if(this.customInterpreter !== null){
MIDI.track[t-1].event[e-1].data = this.customInterpreter(MIDI.track[t-1].event[e-1].type, file , false);
}

// if no customInterpretr is provided, or returned
// if no customInterpreter is provided, or returned
// false (=apply default), perform default action
if(this.customInterpreter === null || MIDI.track[t-1].event[e-1].data === false){
let event_length = file.readIntVLV();
const event_length = file.readIntVLV();
MIDI.track[t-1].event[e-1].data = file.readInt(event_length);
if (this.debug) console.info('Unimplemented 0xF exclusive events! data block readed as Integer');
}
Expand All @@ -312,8 +312,8 @@
default:
// if user provided a custom interpreter, call it
// and assign to event the returned data
if( this.customInterpreter !== null){
MIDI.track[t-1].event[e-1].data = this.customInterpreter( MIDI.track[t-1].event[e-1].metaType, file , false);
if(this.customInterpreter !== null){
MIDI.track[t-1].event[e-1].data = this.customInterpreter(MIDI.track[t-1].event[e-1].metaType, file , false);
}

// if no customInterpretr is provided, or returned
Expand All @@ -336,7 +336,7 @@
* to be manually increased
* If you want default action to be performed, return false
*/
customInterpreter : null // function( e_type , arrayByffer, metaEventLength){ return e_data_int }
customInterpreter : null // function(e_type , arrayByffer, metaEventLength){ return e_data_int }
};


Expand All @@ -352,5 +352,5 @@
}


})();

})();