JZZ: MIDI library for Node.js and web-browsers
JZZ.js allows sending, receiving and playing MIDI messages
in Node.js and all major browsers
in Linux, MacOS and Windows.
Some features are available on iOS and Android devices.
JZZ.js enables Web MIDI API
in Node.js and those browsers that don't support it,
and provides additional functionality to make developer's life easier.
For the best user experience, it's highly RECOMMENDED (though not required)
to install the latest version of Jazz-Plugin
and browser extensions from Chrome Web Store
or Mozilla Add-ons
or Apple App Store.
Features
- MIDI In/Out
- User-defined MIDI nodes
- MIDI files
- MPE
- SMPTE
- UMP (MIDI 2.0)
- Additional modules
Install
npm install jzz --save
or yarn add jzz
or get the full development version and minified scripts from Github
Note: in the (unlikely) case you get into trouble installing the
midi-test module,
that requires special system configuration,
you can safely remove it from the devDependencies
by running npm remove midi-test --save-dev
.
Usage
Plain HTML
<script src="JZZ.js"></script>
//...
CDN (jsdelivr)
<script src="https://cdn.jsdelivr.net/npm/jzz"></script> // the latest version, or
<script src="https://cdn.jsdelivr.net/npm/jzz@1.8.4"></script> // any particular version
//...
CDN (unpkg)
<script src="https://unpkg.com/jzz"></script> // the latest version, or
<script src="https://unpkg.com/jzz@1.8.4"></script> // any particular version
//...
CommonJS
var JZZ = require('jzz');
TypeScript / ES6
import { JZZ } from 'jzz';
AMD
require(['JZZ'], function(JZZ) {
});
Web MIDI API
(Node.js example)
var navigator = require('jzz');
navigator.requestMIDIAccess().then(onSuccess, onFail);
navigator.close();
JZZ API
MIDI Output/Input
JZZ().or('Cannot start MIDI engine!')
.openMidiOut().or('Cannot open MIDI Out port!')
.wait(500).send([0x90,60,127])
.wait(500).send([0x80,60,0]);
JZZ().openMidiIn().or('Cannot open MIDI In port!')
.and(function() { console.log('MIDI-In: ', this.name()); })
.connect(function(msg) { console.log(msg.toString()); })
.wait(10000).close();
Connecting MIDI nodes
var input = JZZ().openMidiIn();
var output = JZZ().openMidiOut();
var delay = JZZ.Widget({ _receive: function(msg) { this.wait(500).emit(msg); }});
input.connect(delay);
delay.connect(output);
Helpers and shortcuts
port.send([0x90, 61, 127]).wait(500).send([0x80, 61, 0]);
port.send(0x90, 61, 127).wait(500).send(0x80, 61, 0);
port.send(0x90, 'C#5', 127).wait(500).send(0x80, 'Db5', 0);
port.noteOn(0, 'C#5', 127).wait(500).noteOff(0, 'B##4');
port.note(0, 'C#5', 127, 500);
port.ch(0).noteOn('C#5').wait(500).noteOff('C#5');
port.ch(0).note('C#5', 127, 500);
Asynchronous calls
async function playNote() {
var midi = await JZZ();
var port = await midi.openMidiOut();
await port.noteOn(0, 'C5', 127);
await port.wait(500);
await port.noteOff(0, 'C5');
await port.close();
console.log('done!');
}
async function playAnotherNote() {
var port = await JZZ().openMidiOut();
await port.noteOn(0, 'C5', 127).wait(500).noteOff(0, 'C5').close();
console.log('done!');
}
Virtual MIDI ports
var logger = JZZ.Widget({ _receive: function(msg) { console.log(msg.toString()); }});
JZZ.addMidiOut('Console Logger', logger);
var port = JZZ().openMidiOut('Console Logger');
navigator.requestMIDIAccess = JZZ.requestMIDIAccess;
Frequency / MIDI conversion
JZZ.MIDI.freq('A5');
JZZ.MIDI.freq(69);
JZZ.MIDI.freq(69.5);
JZZ.MIDI.midi(440);
JZZ.MIDI.midi(450);
JZZ.MIDI.midi('A5');
MIDI 2.0
MIDI2()
is an adapter that enables MIDI 2.0 in all subsequent chained calls.
MIDI1()
returns the operation back to MIDI 1.0.
Note that the downstream MIDI nodes don't require any special actions to receive and transfer MIDI 2.0 messages:
var first = JZZ.Widget();
var second = JZZ.Widget();
var third = JZZ.Widget();
first.connect(second);
second.connect(third);
third.connect(function (msg) { console.log(msg.toString()); });
first
.send([0x90, 0x3c, 0x7f])
.MIDI2()
.send([0x20, 0x90, 0x3c, 0x7f])
.MIDI1()
.send([0x90, 0x3c, 0x7f])
When used with MIDI 2.0, most of MIDI 1.0 helpers require group
as an additional first parameter
and produce MIDI 1.0 messages wrapped into UMP packages.
Most of the new MIDI 2.0 helpers don't have corresponding MIDI 1.0 messages.
Use gr()
, ch()
and sxId()
calls to set default group
, channel
and SysEx ID
for the subsequent calls.
MIDI2()
and MIDI1()
clear off default group
, channel
, SysEx ID
and MPE
settings:
first
.noteOn(5, 'C5', 127)
.ch(5).noteOn('C5', 127)
.MIDI2()
.noteOn(2, 5, 'C5', 127)
.gr(2).noteOn(5, 'C5', 127)
.ch(5).noteOn('C5', 127)
.MIDI2()
.noteOn(2, 5, 'C5', 127)
.ch(5).noteOn(2, 'C5', 127)
.MIDI2()
.umpNoteOn(2, 5, 'C5', 127)
.gr(2).umpNoteOn(5, 'C5', 127)
.ch(5).umpNoteOn('C5', 127)
More on MIDI 2.0 support...
Additional modules
Testing your MIDI application
Check the Getting Started page
and the API reference
for more information...
Thanks for your support!