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()); });


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.

It is subject of the same rules applied to the JZZ.MIDI constructor.


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

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 ptc dataMSB dataLSB data dataIncr dataDecr nrpnMSB nrpnLSB nrpn rpnMSB rpnLSB rpn allSoundOff allNotesOff resetAllControllers localControl omni mono poly 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() sxMasterTuning() sxMasterTuningF() sxMasterTuningA() sxTuningDumpRequest sxNoteTuning sxNoteTuningF sxNoteTuningHZ sxScaleTuning1 sxScaleTuning1F sxScaleTuning2 sxScaleTuning2F sxScaleTuning sxScaleTuningF

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.

Standard MIDI File Meta Events 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


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

chan - channel number (from 0 to 15), or nothing. If called without parameter, the channel information is no longer set for subsequent calls.

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.ch(0).note('C#5', 127, 500);


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) - 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