We make it sound!

Home » Documentation » JZZ.js » JZZ.MIDI.SMF

JZZ.MIDI.SMF - Standard MIDI Files
( reading / writing / playing )


// in Node.js:
var JZZ = require('jzz');
// or in HTML:
<script src="JZZ.js"></script>
<script src="JZZ.midi.SMF.js"></script>


(works with or without the new keyword)

JZZ.MIDI.SMF() - create a new SMF (MIDI File) object with the default settings: type = 1, ppqn = 96.

JZZ.MIDI.SMF(type) - create MIDI File of requested type; valid values for type are 0, 1, or 2; default timing: ppqn = 96.

JZZ.MIDI.SMF(type, ppqn) - create MIDI File with PPQN timing; ppqn - number of pulses (ticks) per quarter note.

JZZ.MIDI.SMF(type, fps, ppf) - create MIDI File with SMPTE timing; fps - number of frames per second; ppf - number of pulses (ticks) per frame.

JZZ.MIDI.SMF(smf) - copy-constructor, where smf is another SMF object.

JZZ.MIDI.SMF(data) - create from binary data; data - the contents of MIDI or RMI file as a String of bytes.


smf.dump(rmi) - export MIDI File in .MID(.KAR) format if rmi evaluates to false, or in .RMI format otherwie; returns a String of bytes.

Array attributes

SMF object is subclassed from JavaScript Array and inherits all its functions and attributes like push(), length, operator [], etc...

It contains data chunks and MIDI tracks.


(works with or without the new keyword)

JZZ.MIDI.SMF.Chunk(type, data) - create an arbitrary Chunk object; type - chunk name, a 4-byte String; data - chunk contents, a String of bytes.

Chunks of non-MTrk types are ignored by most MIDI software.


(works with or without the new keyword)

JZZ.MIDI.SMF.MTrk() - create a new MIDI Track.

As well as SMF, MTrk object is also subclassed from JavaScript Array and inherits all its functions and attributes. It contains MIDI events.


mtrk.add(time, midi) - add MIDI event to the track; time - the event time in MIDI ticks; midi - a MIDI message or a Standard MIDI File Meta Event.


var smf = new JZZ.MIDI.SMF(0, 96);
smf.push(new JZZ.MIDI.SMF.MTrk());

smf[0].add(0, JZZ.MIDI.smfBPM(120)) // tempo 120 bpm
      .add(96, JZZ.MIDI.noteOn(0, 'C6', 127))
      .add(96, JZZ.MIDI.noteOn(0, 'Eb6', 127))
      .add(96, JZZ.MIDI.noteOn(0, 'G6', 127))
      .add(192, JZZ.MIDI.noteOff(0, 'C6'))
      .add(192, JZZ.MIDI.noteOff(0, 'Eb6'))
      .add(192, JZZ.MIDI.noteOff(0, 'G6'))
      .add(288, JZZ.MIDI.smfEndOfTrack());

require('fs').writeFileSync('out.mid', smf.dump(), 'binary');


mtrk.tick(time) - return a "timed reference" to the track;

unlike in the MIDI-Out's wait(), the time is set in MIDI ticks.


mtrk.send(midi) - add MIDI event at the "current" tick; similar to the MIDI-Out's send(),


For each helper name, mtrk.helper(...) is equivalent to mtrk.send(JZZ.MIDI.helper(...)).

MIDI messages:

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

SMF meta events:

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


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


mtrk.ch(chan) - set channel information for the subsequent chained calls; same as the MIDI-Out's ch(),


mtrk.sxId(id) - set default SysEx ID for the subsequent chained calls; same as the MIDI-Out's sxId(),


// the calls from the example above can be rewritten shorter:
smf[0].smfBPM(120).ch(0) // subsequent calls will apply to channel 0
      .tick(96).noteOn('C6', 127).noteOn('Eb6', 127).noteOn('G6', 127)
// or
      .tick(96).note('C6', 127, 96).note('Eb6', 127, 96).note('G6', 127, 96)


smf.player() - create the Player object.

Player is subclassed from MIDI-In and inherits all its methods, in particular, connect() and disconnect().

Messages (including the SMF Meta Events) sent to the Player via send() or helper functions, will be redirected to the output;

SMF Tempo Meta Events (smfTempo, smfBPM) will also affect the playback tempo if MIDI file is PPQN-timed (most common case).


player.play() - start playback.


player.stop() - stop playback.


player.pause() - pause playback.


player.resume() - resume playback.


player.loop(value) - set / unset the loop.

value - if integer - set the loop counter to value; otherwise if true - set the loop to infinity; if false - unset the loop.


player.speed(x) - slow down (0.0 < x < 1.0) or speed up (x > 1.0) playback.

x - ratio to the default playback speed;

If called without paramener, returns the current payback speed.


player.type() - return the type of the MIDI file (0, 1 or 0).


player.tracks() - return the number of MIDI tracks in the file.


player.duration() - return the MIDI file duration in MIDI ticks.


player.durationMS() - return the MIDI file duration in milliseconds.


player.position() - return the current MIDI file position in MIDI ticks.


player.positionMS() - return the current MIDI file position in milliseconds.


player.jump(pos) - jump to the specified position in MIDI ticks.

pos - position in MIDI ticks.


player.jumpMS(pos) - jump to the specified position in milliseconds.

pos - position in milliseconds.


player.tick2ms(t) - convert the position in MIDI ticks into milliseconds.

t - position in MIDI ticks.


player.ms2tick(t) - convert the position in milliseconds into MIDI ticks.

t - position in milliseconds.

User hook

player.onEnd() - called when the end of the MIDI file is reached.


var data = require('fs').readFileSync('test.mid', 'binary');
var smf = new JZZ.MIDI.SMF(data);

var player = smf.player();
player.onEnd = function() { console.log('Done!'); };

JZZ().or('Cannot start MIDI engine!').openMidiOut().or('Cannot open MIDI Out!').and(function() {

See also