midi-player-js
Version:
Midi parser & player engine for browser or Node. Works well with single or multitrack MIDI files.
149 lines (133 loc) • 8.98 kB
JavaScript
var assert = require('assert');
var sinon = require('sinon');
var MidiPlayer = require('..');
var zelda = 'data:audio/midi;base64,TVRoZAAAAAYAAQACAIBNVHJrAAADoQDAAQCQRn+CAIBGfwCQRn9AgEZ/AJBBf0CAQX8AkEF/QIBBfwCQRn9AgEZ/AJBEfyCARH8AkEJ/IIBCfwCQRH+DAIBEf0CQRn+CAIBGfwCQRn9AgEZ/AJBBf0CAQX8AkEF/QIBBfwCQRn9AgEZ/AJBFfyCARX8AkEN/IIBDfwCQRX+BQIBFf4IAkEUBhACARQGEAJBGf4EAgEZ/AJBBf4FAgEF/AJBGf0CARn8AkEZ/IIBGfwCQSH8ggEh/AJBKfyCASn8AkEt/IIBLfwCQTX+CAIBNf0CQTX9AgE1/AJBNf0CATX8AkE5/IIBOfwCQUH8ggFB/AJBSf4IAgFJ/QJBSf0CAUn8AkFJ/QIBSfwCQUH8ggFB/AJBOfyCATn8AkFB/YIBQfwCQTn8ggE5/AJBNf4IAgE1/AJBNf4EAgE1/AJBLf2CAS38AkE1/IIBNfwCQTn+CAIBOfwCQTX9AgE1/AJBLf0CAS38AkEl/YIBJfwCQS38ggEt/AJBNf4IAgE1/AJBLf0CAS38AkEl/QIBJfwCQSH9ggEh/AJBKfyCASn8AkEx/ggCATH8AkE9/gQCAT38AkE1/QIBNfwCQQX8ggEF/AJBBfyCAQX8AkEF/QIBBfwCQQX8ggEF/AJBBfyCAQX8AkEF/QIBBfwCQQX8ggEF/AJBBfyCAQX8AkEF/QIBBfwCQQX9AgEF/AJBGf4EAgEZ/AJBBf4FAgEF/AJBGf0CARn8AkEZ/IIBGfwCQSH8ggEh/AJBKfyCASn8AkEt/IIBLfwCQTX+CAIBNf0CQTX9AgE1/AJBNf0CATX8AkE5/IIBOfwCQUH8ggFB/AJBSf4MAgFJ/AJBVf4EAgFV/AJBUf4EAgFR/AJBRf4IAgFF/AJBNf4EAgE1/AJBOf4MAgE5/AJBSf4EAgFJ/AJBRf4EAgFF/AJBNf4IAgE1/AJBNf4EAgE1/AJBOf4MAgE5/AJBSf4EAgFJ/AJBRf4EAgFF/AJBNf4IAgE1/AJBKf4EAgEp/AJBLf4MAgEt/AJBOf4EAgE5/AJBNf4EAgE1/AJBJf4IAgEl/AJBGf4EAgEZ/AJBIf2CASH8AkEp/IIBKfwCQTH+CAIBMfwCQT3+BAIBPfwCQTX9AgE1/AJBBfyCAQX8AkEF/IIBBfwCQQX9AgEF/AJBBfyCAQX8AkEF/IIBBfwCQQX9AgEF/AJBBfyCAQX8AkEF/IIBBfwCQQX9AgEF/AJBBf0CAQX8A/y8ATVRyawAACUMAwAEAkCpAgQCAKkAAkDVAgQCANUAAkDpAggCAOkAAkClAgQCAKUAAkDNAgQCAM0AAkDhAggCAOEAAkCdAgQCAJ0AAkDFAgQCAMUAAkDpAggCAOkAAkCpAgQCAKkAAkDVAgQCANUAAkDpAggCAOkAAkC5AQIAuQACQLkAggC5AAJApQCCAKUAAkC5AQIAuQACQLkAggC5AAJApQCCAKUAAkC5AQIAuQACQLkAggC5AAJApQCCAKUAAkC5AIIAuQACQKUAggClAAJAuQCCALkAAkClAIIApQACQLkBAgC5AAJAuQCCALkAAkClAIIApQACQLkBAgC5AAJAuQCCALkAAkClAIIApQACQLkBAgC5AAJAuQCCALkAAkClAIIApQACQLkAggC5AAJApQCCAKUAAkC5AIIAuQACQKUAggClAAJAuQECALkAAkC5AIIAuQACQKUAggClAAJAuQECALkAAkC5AIIAuQACQKUAggClAAJAuQECALkAAkC5AIIAuQACQKUAggClAAJAuQCCALkAAkClAIIApQACQLkAggC5AAJApQCCAKUAAkCxAQIAsQACQLEAggCxAAJAnQCCAJ0AAkCxAQIAsQACQLEAggCxAAJAnQCCAJ0AAkCxAQIAsQACQLEAggCxAAJAnQCCAJ0AAkCxAIIAsQACQJ0AggCdAAJAsQCCALEAAkCdAIIAnQACQKkBAgCpAAJAqQCCAKkAAkCVAIIAlQACQKkBAgCpAAJAqQCCAKkAAkCVAIIAlQACQKkBAgCpAAJAqQCCAKkAAkCVAIIAlQACQKkAggCpAAJAlQCCAJUAAkCpAIIAqQACQJUAggCVAAJAxQECAMUAAkDFAIIAxQACQLEAggCxAAJAxQECAMUAAkDFAIIAxQACQLEAggCxAAJAxQECAMUAAkDFAIIAxQACQLEAggCxAAJAxQCCAMUAAkCxAIIAsQACQMUAggDFAAJAsQCCALEAAkC9AQIAvQACQL0AggC9AAJAqQCCAKkAAkC9AQIAvQACQL0AggC9AAJAqQCCAKkAAkC9AQIAvQACQL0AggC9AAJAqQCCAKkAAkC9AIIAvQACQKkAggCpAAJAvQCCAL0AAkCpAIIAqQACQLkBAgC5AAJAuQCCALkAAkClAIIApQACQLkBAgC5AAJAuQCCALkAAkClAIIApQACQLkBAgC5AAJAuQCCALkAAkClAIIApQACQLkAggC5AAJApQCCAKUAAkC5AIIAuQACQKUAggClAAJAwQECAMEAAkDBAIIAwQACQK0AggCtAAJAwQECAMEAAkDBAIIAwQACQK0AggCtAAJAwQECAMEAAkDBAIIAwQACQK0AggCtAAJAwQCCAMEAAkCtAIIArQACQMEAggDBAAJArQCCAK0AAkClAQIApQACQOUAggDlAAJA5QCCAOUAAkDhAQIA4QACQOEAggDhAAJA4QCCAOEAAkDdAQIA3QACQN0AggDdAAJA3QCCAN0AAkDZAQIA2QACQKUBAgClAAJAuQECALkAAkC5AIIAuQACQKUAggClAAJAuQECALkAAkC5AIIAuQACQKUAggClAAJAuQECALkAAkC5AIIAuQACQKUAggClAAJAuQCCALkAAkClAIIApQACQLkAggC5AAJApQCCAKUAAkCxAQIAsQACQLEAggCxAAJAnQCCAJ0AAkCxAQIAsQACQLEAggCxAAJAnQCCAJ0AAkCxAQIAsQACQLEAggCxAAJAnQCCAJ0AAkCxAIIAsQACQJ0AggCdAAJAsQCCALEAAkCdAIIAnQACQKkBAgCpAAJAqQCCAKkAAkCpAIIAqQACQKkBAgCpAAJAqQCCAKkAAkCpAIIAqQACQKkBAgCpAAJAqQCCAKkAAkCpAIIAqQACQKkAggCpAAJAqQCCAKkAAkCpAIIAqQACQKkAggCpAAJApQECAKUAAkClAIIApQACQKUAggClAAJApQECAKUAAkClAIIApQACQKUAggClAAJApQECAKUAAkClAIIApQACQKUAggClAAJApQCCAKUAAkClAIIApQACQKUAggClAAJApQCCAKUAAkChAQIAoQACQKEAggChAAJAoQCCAKEAAkChAQIAoQACQKEAggChAAJAoQCCAKEAAkChAQIAoQACQKEAggChAAJAoQCCAKEAAkChAIIAoQACQKEAggChAAJAoQCCAKEAAkChAIIAoQACQKUBAgClAAJApQCCAKUAAkClAIIApQACQKUBAgClAAJApQCCAKUAAkClAIIApQACQKUBAgClAAJApQCCAKUAAkClAIIApQACQKUAggClAAJApQCCAKUAAkClAIIApQACQKUAggClAAJAoQECAKEAAkChAIIAoQACQKEAggChAAJAoQECAKEAAkChAIIAoQACQKEAggChAAJAoQECAKEAAkChAIIAoQACQKEAggChAAJAoQCCAKEAAkChAIIAoQACQKEAggChAAJAoQCCAKEAAkClAQIApQACQKUAggClAAJApQCCAKUAAkClAQIApQACQKUAggClAAJApQCCAKUAAkClAQIApQACQKUAggClAAJApQCCAKUAAkClAIIApQACQKUAggClAAJApQCCAKUAAkClAIIApQACQL0BAgC9AAJAvQCCAL0AAkC9AIIAvQACQL0BAgC9AAJAvQCCAL0AAkC9AIIAvQACQL0BAgC9AAJAvQCCAL0AAkC9AIIAvQACQL0AggC9AAJAvQCCAL0AAkC9AIIAvQACQL0AggC9AAJAuQECALkAAkC5AIIAuQACQLkAggC5AAJAuQECALkAAkC5AIIAuQACQLkAggC5AAJAuQECALkAAkC5AIIAuQACQLkAggC5AAJAuQCCALkAAkC5AIIAuQACQLkAggC5AAJAuQCCALkAAkDBAQIAwQACQMEAggDBAAJAwQCCAMEAAkDBAQIAwQACQMEAggDBAAJAwQCCAMEAAkDBAQIAwQACQMEAggDBAAJAwQCCAMEAAkDBAIIAwQACQMEAggDBAAJAwQCCAMEAAkDBAIIAwQACQKUBAgClAAJA5QCCAOUAAkDlAIIA5QACQOEBAgDhAAJA4QCCAOEAAkDhAIIA4QACQN0BAgDdAAJA3QCCAN0AAkDdAIIA3QACQNkBAgDZAAJApQECAKUAA/y8A';
describe('MidiPlayerJS', function() {
describe('#Utils', function () {
describe('#byteToHex()', function () {
it('should return hex value from byte.', function () {
assert.equal('7f', MidiPlayer.Utils.byteToHex(127));
});
});
describe('#bytesToHex()', function () {
it('should return hex value from array of bytes.', function () {
assert.equal('7f3a', MidiPlayer.Utils.bytesToHex([127, 58]));
});
});
describe('#hexToNumber()', function () {
it('should return base 10 value from hex string.', function () {
assert.equal(254, MidiPlayer.Utils.hexToNumber('fe'));
});
});
describe('#bytesToNumber()', function () {
it('should return base 10 value from array of bytes.', function () {
assert.equal(923139, MidiPlayer.Utils.bytesToNumber([14, 22, 3]));
});
});
describe('#bytesToLetters()', function () {
it('should return string from array of bytes.', function () {
assert.equal('Mthd', MidiPlayer.Utils.bytesToLetters([77, 116, 104, 100]));
});
});
describe('#decToBinary()', function () {
it('should return binary value from decimal.', function () {
assert.equal('10110', MidiPlayer.Utils.decToBinary(22));
});
});
describe('#readVarInt()', function () {
it('should return binary value from decimal.', function () {
assert.equal(42, MidiPlayer.Utils.readVarInt([128, 42]));
});
});
});
describe('#Player', function () {
describe('#loadFile()', function () {
it('should load file correctly.', function () {
var Player = new MidiPlayer.Player();
Player.loadFile('demo/midi/zelda.mid');
assert.equal(3330, Player.buffer.length);
assert.equal(2, Player.tracks.length);
});
it('should load 500_Miles.mid file correctly.', function () {
var Player = new MidiPlayer.Player();
Player.loadFile('demo/midi/500_Miles.mid');
//assert.equal(3330, Player.buffer.length);
//assert.equal(2, Player.tracks.length);
});
it('should load O-Zone_-_Dragostea_Din_Tei.mid file correctly.', function () {
var Player = new MidiPlayer.Player();
Player.loadFile('demo/midi/O-Zone_-_Dragostea_Din_Tei.mid');
//assert.equal(3330, Player.buffer.length);
//assert.equal(2, Player.tracks.length);
});
});
describe('#loadDataUri()', function () {
it('should load data correctly from data uri.', function () {
var Player = new MidiPlayer.Player();
Player.loadDataUri(zelda);
assert.equal(3330, Player.buffer.length);
assert.equal(2, Player.tracks.length);
});
});
describe('#getCurrentTime', function () {
let Player;
beforeEach(function() {
this.clock = sinon.useFakeTimers();
this.clock.tick(5000); //set start time
Player = new MidiPlayer.Player();
Player.loadDataUri(zelda);
});
afterEach(function() {
this.clock = sinon.restore();
});
it('should return 0 after init', function () {
assert.equal(Player.getCurrentTick(), 0);
});
it('should return last known tick after pause', function () {
const skipTicks = 123456;
Player.skipToTick(skipTicks);
Player.play();
this.clock.tick(6); //run 1 tick
Player.pause();
assert.equal(Player.getCurrentTick(), skipTicks + 1);
});
it('should return 0 after stop', function () {
const skipTicks = 123456;
Player.skipToTick(skipTicks);
Player.play();
this.clock.tick(6); //run 1 tick
Player.stop();
assert.equal(Player.getCurrentTick(), 0);
})
});
describe('#getCurrentTick', function () {
it('should return correct tick when skipping without playing.', function () {
const skipTicks = 500;
const Player = new MidiPlayer.Player();
Player.loadDataUri(zelda);
Player.skipToTick(skipTicks);
assert.equal(Player.getCurrentTick(), skipTicks);
})
});
describe('#getSongTimeRemaining', function () {
let Player;
beforeEach(function () {
this.clock = sinon.useFakeTimers();
this.clock.tick(5000); //set start time
Player = new MidiPlayer.Player();
Player.loadDataUri(zelda);
});
afterEach(function () {
this.clock = sinon.restore();
});
it('should return totalTime after stop', function () {
const skipTicks = 123456;
Player.skipToTick(skipTicks);
Player.play();
this.clock.tick(6); //run 1 tick
Player.stop();
assert.equal(Player.getSongTimeRemaining(), Player.getSongTime());
})
});
});
});