We make it sound!
Home » Documentation » JZZ.js » MIDI-Out


Opening MIDI-Out port

engine.openMidiOut(arg) - try to open MIDI-Out port.


port = JZZ().openMidiOut(0);
port = JZZ().openMidiOut('Microsoft GS Wavetable Synth');
port = JZZ().openMidiOut(['Microsoft GS Wavetable Synth', 'Apple DLS Synth', 0]);
port = JZZ().openMidiOut(function(){ return [2, 1, 0]; });
port = JZZ().openMidiOut(/Yamaha/);
port = JZZ().openMidiOut();


port.info() - get an info object with the following keys:


port.name() - a shortcut for the port.info().name.


JZZ().or('Cannot start MIDI engine!')
     .openMidiOut().or('MIDI-Out: Cannot open!')
     .and(function(){ console.log('MIDI-Out:', this.name()); });

MIDI2(), MIDI1()

Initially, all MIDI-Out nodes are created in MIDI 1.0 mode. Use MIDI2() to switch the mode to MIDI 2.0, and MIDI1() to switch it back to MIDI 1.0.

port.MIDI2() - set MIDI 2.0 mode for all subsequent chained calls.

port.MIDI1() - set MIDI 1.0 mode for all subsequent chained calls.

Additionally, MIDI1() and MIDI2() clear off the default group, channel, sxId and MPE status (see below), and can be used for this purpose.


port.send(msg) - send MIDI message to the port.

msg can be an array, a comma-separated list, or an object of type JZZ.MIDI or JZZ.MIDI2, depending on MIDI 1.0 or MIDI 2.0 mode of operation.

It is subject of the same rules applied to the JZZ.MIDI/JZZ.MIDI2 constructors.


port.send(0x90, 0x3c, 0x7f)         // 90 3c 7f -- Note On, MIDI 1.0
    .MIDI2()                        // enable MIDI 2.0
    .send(0x20, 0x90, 0x3c, 0x7f)   // 20903c7f -- Note On, MIDI 2.0
    .send(0x90, 0x3c, 0x7f);        // error!

MIDI 1.0 helpers

MIDI-Out port has a complete set of helpers corresponding to the ones defined in JZZ.MIDI.

Roughly speaking, for each helper name, port.helper(...) is equivalent to port.send(JZZ.MIDI.helper(...)).

noteOn noteOff aftertouch program pressure pitchBend pitchBendF control bankMSB bankLSB bank modMSB modLSB mod modF breathMSB breathLSB breath breathF footMSB footLSB foot footF portamentoMSB portamentoLSB portamentoTime portamentoTimeF volumeMSB volumeLSB volume volumeF balanceMSB balanceLSB balance balanceF panMSB panLSB pan panF expressionMSB expressionLSB expression expressionF damper portamento sostenuto soft legato hold2 soundVariation filterResonance releaseTime attackTime brightness decayTime vibratoRate vibratoDepth vibratoDelay ptc dataMSB dataLSB data dataF dataIncr dataDecr nrpnMSB nrpnLSB nrpn rpnMSB rpnLSB rpn allSoundOff allNotesOff resetAllControllers localControl omni mono poly mode1 mode2 mode3 mode4 mtc songPosition songSelect tune clock start continue stop active reset rpnPitchBendRange rpnPitchBendRangeF rpnFineTuning rpnFineTuningF rpnCoarseTuning rpnCoarseTuningF rpnTuning rpnTuningF rpnTuningA rpnSelectTuningProgram rpnSelectTuningBank rpnSelectTuning rpnModulationDepthRange rpnModulationDepthRangeF rpnNull sxIdRequest sxFullFrame sxMasterVolume sxMasterVolumeF sxMasterFineTuning sxMasterFineTuningF sxMasterCoarseTuning sxMasterCoarseTuningF sxMasterTranspose sxMasterTransposeF sxMasterTuning sxMasterTuningF sxMasterTuningA sxTuningDumpRequest sxNoteTuning sxNoteTuningF sxNoteTuningHZ sxScaleTuning1 sxScaleTuning1F sxScaleTuning2 sxScaleTuning2F sxScaleTuning sxScaleTuningF sxGM sxGS sxXG sxMidiSoft gsMasterVolume gsMasterVolumeF gsMasterFineTuning gsMasterFineTuningF gsMasterCoarseTuning gsMasterCoarseTuningF gsMasterTranspose gsMasterTransposeF gsMasterTuningF gsMasterTuningA gsOctaveTuning gsOctaveTuningF gsScaleTuning gsScaleTuningF xgMasterVolume xgMasterVolumeF xgMasterFineTuning xgMasterFineTuningF xgMasterCoarseTuning xgMasterCoarseTuningF xgMasterTranspose xgMasterTransposeF xgMasterTuningF xgMasterTuningA xgOctaveTuning xgOctaveTuningF xgScaleTuning xgScaleTuningF

Additional helpers can send multiple messages:

port.note(c, n, v, t) is equivalent to port.noteOn(c, n, v).wait(t).noteOff(c, n) if t > 0, and to port.noteOn(c, n, v) otherwise.

In MIDI 2.0, all above helpers require an additional first parameter group and produce MIDI 1.0 messages wrapped into Universal MIDI Packages (UMP).

Standard MIDI File Meta Events (MIDI 1.0 only) can also be sent down the pipeline:

smf smfSeqNumber smfText smfCopyright smfSeqName smfInstrName smfLyric smfMarker smfCuePoint smfProgName smfDevName smfChannelPrefix smfEndOfTrack smfTempo smfBPM smfSMPTE smfTimeSignature smfKeySignature smfMetaEvent


All statements below do the same job:

port.send([0x90, 61, 127]).wait(500).send([0x80, 61, 0]);   // arrays
port.send(0x90, 61, 127).wait(500).send(0x80, 61, 0);       // comma-separated
port.send(0x90, 'C#5' ,127).wait(500).send(0x80, 'Db5' ,0); // note names
port.noteOn(0, 'C#5', 127).wait(500).noteOff(0, 'B##4');    // helpers
port.note(0, 'C#5', 127, 500);                              // another helper

MIDI 2.0 helpers

Similarly to MIDI 1.0 helpers, these are defined in JZZ.MIDI2.

noop umpClock umpTimestamp umpTicksPQN umpDelta umpNoteOn umpNoteOff umpProgram umpPressure umpPressureF umpPnPressure umpPnPressureF umpAftertouch umpAftertouchF umpPitchBend umpPitchBendF umpPnPitchBend umpPnPitchBendF umpRPN umpPnRPN umpNRPN umpPnNRPN umpControl umpTempo umpBPM umpTimeSignature umpCustomText umpMetadata umpCMetadata umpProjectName umpCProjectName umpCompositionName umpCCompositionName umpClipName umpCClipName umpCopyright umpCCopyright umpComposerName umpCComposerName umpLyricistName umpCLyricistName umpArrangerName umpCArrangerName umpPublisherName umpCPublisherName umpPerformerName umpCPerformerName umpAccPerformerName umpCAccPerformerName umpRecordingDate umpCRecordingDate umpRecordingLocation umpCRecordingLocation umpText umpCText umpLyrics umpCLyrics umpLyricsLanguage umpLyricsLanguage umpRuby umpCRuby umpRubyLanguage umpCRubyLanguage


port.gr(group) - (MIDI 2.0 only) - set default group for all subsequent chained calls.

group - group number (from 0 to 15), or nothing. If called without parameter, removes the default group.


port.ch(chan) - set default channel for all subsequent chained calls.

chan - channel number (from 0 to 15), or nothing. If called without parameter, removes the default channel.

Can save some typing if multiple messages are sent to the same MIDI channel.


These statements are equivalent to the ones in the previous example:

port.ch(0).noteOn('C#5').wait(500).noteOff('C#5');          // default velocity 127 can be omitted


port.sxId(id) - set the default SysEx ID for all subsequent chained calls.

id - 7 bit SysEx ID, or nothing (default: 0x7F).


// sends:
//   f0 7f 08 04 04 00 34 f7
//   f0 7f 08 04 03 55 2b f7


port.mpe(m, n) - (MIDI 1.0 only) - start MPE mode for all subsequent chained calls.

m - master channel (from 0 to 14).

n - number of note channels (MPE zone size).

If called without parameters, returns to regular operation.

In MPE mode each note will be assigned to its own channel while there are enough channels.

Each channel can be separately controlled with its own pitchBend() and other messages.

Certain messages like program() are common for all notes and must be sent to the master channel.

Some messages like pitchBend() can be sent both to the master channel and to the note channels.

To send message to the master channel, omit the channel number in the corresponding helper call.

To send message to a note channel, substitute the channel number by the note when calling the helper.

NOTE: some calls may be ambigious if the function accepts variable number of arguments. This can be fixed by adding undefined in the end of the argumant list.
e.g. port.mpe(0, 4).bank(1, 1) - goes to the master channel;
port.mpe(0, 4).bank(1, 1, undefined) - goes to the note channel.


port.mpe(0, 6).program(25)                                  // program change on master channel (0)
    .noteOn('E4').noteOn('A4').noteOn('E5')                 // channels 1, 2, 3
    .noteOn('A5').noteOn('C#6').noteOn('E6')                // channels 4, 5, 6
    .wait(500).pitchBend('C#6', 64)                         // pitch bend on channel 5
    .wait(500).pitchBend(10)                                // pitch bend on master channel


port.close() - close the port.

No other calls except the common calls can be chained to the closed port.

This call is optional, since all ports automatically close on exit.

Other calls

port.or(), port.and(), port.wait()

See also