├── .eslintrc ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── bower.json ├── demo-es5.js ├── demo.js ├── demobundle.js ├── dist ├── index.js ├── index.js.map └── index.min.js ├── index.html ├── package.json └── src └── index.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": "eslint:recommended", 4 | "env": { 5 | "browser": true, 6 | "es6": true 7 | }, 8 | "rules": { 9 | "no-console": 0 10 | }, 11 | "parserOptions": { 12 | "sourceType": "module" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | test/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Chinmay Pendharkar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # midimessage 2 | 3 | [![npm version](https://badge.fury.io/js/midimessage.svg)](http://badge.fury.io/js/midimessage) 4 | 5 | Simple MIDI Message Parser for JavaScript. This parser takes in a [MIDIMessageEvent](http://webaudio.github.io/web-midi-api/#MIDIMessageEvent) and returns a plain Javascript Object with propties indicating the data in the MIDI message. 6 | 7 | ## Installation 8 | 9 | `npm install midimessage` 10 | 11 | ## Usage 12 | 13 | ```js 14 | var MIDIMessage = require('midimessage'); 15 | 16 | midiInput.onmidimessage = function(event){ 17 | var midiMessage = MIDIMessage(event); 18 | console.log("Parsed", midiMessage); 19 | } 20 | ``` 21 | 22 | ## API 23 | 24 | `MIDIMessage` : _Function_ - Takes a MIDIMessageEvent as the only argument and decodes the data in the MIDIMessageEvent. Returns a MIDIMessage Object which has various properties set to values based on the MIDIMessage. 25 | 26 | These properties are based off the [MIDI Message Standard](http://www.midi.org/techspecs/midimessages.php) as defined in the [MIDI Spec](http://www.midi.org/techspecs/) 27 | 28 | These are some of the properties that may be exposed (based on the incoming MIDI message) : 29 | 30 | - `channel`: __Number__ (0-127) - MIDI Channel Number. 31 | - `messageType`: __String__ - Type of message. Possible values defined below. 32 | - `key`: __Number__ (0-127) - The key (note) number. Defined on -`noteon`,`noteoff`,`keypressure` messages. 33 | - `velocity`: __Number__ (0-127) - Velocity. Defined on `noteon`,`noteoff` messages. 34 | - `controllerNumber`: __Number__ (0-127) - Controller Number. Controller numbers 120-127 are reserved as "Channel Mode Messages". 35 | - `controllerValue`: __Number__ (0-127) Controller Value. Has various meanings based on `controllerNumber`. 36 | - `channelModeMessage`: __String__ - Channel Mode Message. Specific messages for Channel Modes based on `controllerNumber`. Possible values defined below. 37 | - `pressure`: __Number__ (0-127) - Pressure value. 38 | - `pitchBend`: __Number__ (0-16383) - Pitch Bend value. Center (no pitch change) is 8192. 39 | 40 | 41 | Possible values of `messageType` property. 42 | 43 | ```js 44 | [ 45 | 'noteon', // Note On event. 46 | 'noteoff', // Note Off event. 47 | 'keypressure', // Polyphonic Key Pressure (Aftertouch). 48 | 'controlchange', // Control Change. 49 | 'programchange', // Program Change. 50 | 'channelpressure', // Channel Pressure (After-touch). 51 | 'pitchbendchange', // Pitch Bend Change. 52 | ] 53 | ``` 54 | 55 | 56 | Possible values of `channelModeMessage` property. 57 | 58 | ```js 59 | [ 60 | 'allsoundoff', // All Sound Off. 61 | 'resetallcontrollers', // Reset All Controllers. 62 | 'localcontroloff', // Local Control Off. 63 | 'localcontrolon', // Local Control On. 64 | 'allnotesoff', // All Notes Off. 65 | 'omnimodeoff', // Omni Mode Off. 66 | 'omnimodeon', // Omni Mode On. 67 | 'monomodeon', // Mono Mode On (Poly Off). 68 | 'polymodeon' // Poly Mode On (Mono Off) 69 | ] 70 | ``` 71 | 72 | # License 73 | 74 | MIT 75 | 76 | See License file 77 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "midimessage", 3 | "version": "1.0.6", 4 | "authors": [ 5 | "Chinmay Pendharkar " 6 | ], 7 | "description": "Web-MIDI Message Parser", 8 | "main": "dist/index.js", 9 | "keywords": [ 10 | "midi", 11 | "parse", 12 | "message", 13 | "webmidi" 14 | ], 15 | "license": "MIT", 16 | "homepage": "https://github.com/notthetup/midimessage", 17 | "ignore": [ 18 | "**/.*", 19 | "node_modules", 20 | "bower_components", 21 | "test", 22 | "tests", 23 | "src", 24 | "bower.json", 25 | "demo.js", 26 | "demobundle.js", 27 | "demo-es5.js", 28 | "index.html", 29 | "LICENSE", 30 | "package.json", 31 | "README.md" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /demo-es5.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var MIDIMessage = require('./dist/index.js'); //eslint-disable-line 4 | 5 | if (navigator.requestMIDIAccess){ 6 | navigator.requestMIDIAccess().then( onMIDIInit, onMIDIReject ); 7 | } 8 | else{ 9 | console.error("DOH! No MIDI support present in your browser."); 10 | } 11 | 12 | function onMIDIInit (midi){ 13 | // midi.inputs 14 | // midi.onstatechange 15 | // midi.outputs 16 | // midi.sysexEnabled 17 | console.log("Successfully Initialized MIDI"); 18 | var foundString = "Found " + midi.inputs.size + " inputs and " + midi.outputs.size + " outputs."; 19 | console.log(foundString); 20 | console.log("Sysex is", midi.sysexEnabled ? "enabled" : "disabled"); 21 | onMIDIConect(midi); 22 | 23 | 24 | midi.onstatechange = function(event){ 25 | console.log("MIDIConnectionEvent on port", event.port); 26 | if (event.port.type === "input" && event.port.connection === "open"){ 27 | onMIDIConect(midi); 28 | } 29 | } 30 | } 31 | 32 | function onMIDIConect(midi){ 33 | 34 | midi.inputs.forEach(function(input){ 35 | console.log("Input id:", input.id, input); 36 | input.onmidimessage = function(event){ 37 | var midiMessage = MIDIMessage(event); 38 | console.log("Parsed", midiMessage); 39 | } 40 | }); 41 | } 42 | 43 | function onMIDIReject (error){ 44 | console.error(error); 45 | return; 46 | } 47 | -------------------------------------------------------------------------------- /demo.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import MIDIMessage from './dist/index.js'; 4 | 5 | if (navigator.requestMIDIAccess){ 6 | navigator.requestMIDIAccess().then( onMIDIInit, onMIDIReject ); 7 | } 8 | else{ 9 | console.error("DOH! No MIDI support present in your browser."); 10 | } 11 | 12 | function onMIDIInit (midi){ 13 | // midi.inputs 14 | // midi.onstatechange 15 | // midi.outputs 16 | // midi.sysexEnabled 17 | console.log("Successfully Initialized MIDI"); 18 | var foundString = "Found " + midi.inputs.size + " inputs and " + midi.outputs.size + " outputs."; 19 | console.log(foundString); 20 | console.log("Sysex is", midi.sysexEnabled ? "enabled" : "disabled"); 21 | onMIDIConect(midi); 22 | 23 | 24 | midi.onstatechange = function(event){ 25 | console.log("MIDIConnectionEvent on port", event.port); 26 | if (event.port.type === "input" && event.port.connection === "open"){ 27 | onMIDIConect(midi); 28 | } 29 | } 30 | } 31 | 32 | function onMIDIConect(midi){ 33 | 34 | for (let input of midi.inputs.values()) { 35 | console.log("Input id:", input.id, input); 36 | input.onmidimessage = function(event){ 37 | var midiMessage = MIDIMessage(event); 38 | console.log("Parsed", midiMessage); 39 | } 40 | } 41 | 42 | for (let output of midi.outputs.values()) { 43 | console.log("Output id:", output.id, output); 44 | } 45 | } 46 | 47 | function onMIDIReject (error){ 48 | console.error(error); 49 | return; 50 | } 51 | -------------------------------------------------------------------------------- /demobundle.js: -------------------------------------------------------------------------------- 1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 2 | 3 | 4 | MIDI Message Test 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "midimessage", 3 | "version": "1.0.7", 4 | "description": "Web-MIDI Message Parser", 5 | "main": "dist/index.min.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "browserify demo.js -t babelify -o demobundle.js && http-server", 11 | "test-es5": "browserify demo-es5.js -o demobundle.js && http-server", 12 | "build": "eslint src/*.js && browserify src/index.js --standalone midimessage -t babelify -o dist/index.js && uglifyjs dist/index.js --mangle --source-map dist/index.js.map --output dist/index.min.js" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/notthetup/midimessage.git" 17 | }, 18 | "keywords": [ 19 | "midi", 20 | "parse", 21 | "message" 22 | ], 23 | "author": "Chinmay Pendharkar", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/notthetup/midimessage/issues" 27 | }, 28 | "homepage": "https://github.com/notthetup/midimessage#readme", 29 | "devDependencies": { 30 | "@babel/core": "^7.2.2", 31 | "babel-preset-es2015": "^6.24.1", 32 | "babelify": "^10.0.0", 33 | "browserify": "^16.2.3", 34 | "npm-check-updates": "^2.15.0", 35 | "uglifyjs": "^2.4.10" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | export default function(event){ 4 | function MIDIMessage (event){ 5 | this._event = event; 6 | this._data = event.data; 7 | this.receivedTime = event.receivedTime; 8 | 9 | if (this._data && this._data.length < 2){ 10 | console.warn("Illegal MIDI message of length", this._data.length); 11 | return; 12 | } 13 | 14 | this._messageCode = event.data[0] & 0xf0; 15 | this.channel = (event.data[0] & 0x0f)+1; 16 | 17 | switch(this._messageCode){ 18 | 19 | // Note Off 20 | case 0x80: 21 | this.messageType = "noteoff"; 22 | this.key = event.data[1] & 0x7F; 23 | this.velocity = event.data[2] & 0x7F; 24 | break; 25 | 26 | // Note On 27 | case 0x90: 28 | this.messageType = "noteon"; 29 | this.key = event.data[1] & 0x7F; 30 | this.velocity = event.data[2] & 0x7F; 31 | break; 32 | 33 | // Polyphonic Key Pressure 34 | case 0xA0: 35 | this.messageType = "keypressure"; 36 | this.key = event.data[1] & 0x7F; 37 | this.pressure = event.data[2] & 0x7F; 38 | break; 39 | 40 | // Control Change 41 | case 0xB0: 42 | this.messageType = "controlchange"; 43 | this.controllerNumber = event.data[1] & 0x7F; 44 | this.controllerValue = event.data[2] & 0x7F; 45 | 46 | if (this.controllerNumber === 120 && this.controllerValue === 0){ 47 | this.channelModeMessage = "allsoundoff"; 48 | } 49 | else if (this.controllerNumber === 121){ 50 | this.channelModeMessage = "resetallcontrollers"; 51 | } 52 | else if (this.controllerNumber === 122){ 53 | if (this.controllerValue === 0){ 54 | this.channelModeMessage = "localcontroloff"; 55 | }else{ 56 | this.channelModeMessage = "localcontrolon"; 57 | } 58 | } 59 | else if (this.controllerNumber === 123 && this.controllerValue === 0){ 60 | this.channelModeMessage = "allnotesoff"; 61 | } 62 | else if (this.controllerNumber === 124 && this.controllerValue === 0){ 63 | this.channelModeMessage = "omnimodeoff"; 64 | } 65 | else if (this.controllerNumber === 125 && this.controllerValue === 0){ 66 | this.channelModeMessage = "omnimodeon"; 67 | } 68 | else if (this.controllerNumber === 126){ 69 | this.channelModeMessage = "monomodeon"; 70 | } 71 | else if (this.controllerNumber === 127){ 72 | this.channelModeMessage = "polymodeon"; 73 | } 74 | break; 75 | 76 | // Program Change 77 | case 0xC0: 78 | this.messageType = "programchange"; 79 | this.program = event.data[1]; 80 | break; 81 | 82 | // Channel Pressure 83 | case 0xD0: 84 | this.messageType = "channelpressure"; 85 | this.pressure = event.data[1] & 0x7F; 86 | break; 87 | 88 | // Pitch Bend Change 89 | case 0xE0: 90 | this.messageType = "pitchbendchange"; 91 | var msb = event.data[2] & 0x7F; 92 | var lsb = event.data[1] & 0x7F; 93 | this.pitchBend = (msb << 7) + lsb; 94 | break; 95 | } 96 | } 97 | 98 | return new MIDIMessage(event); 99 | } 100 | --------------------------------------------------------------------------------