Jazz-Soft.net

We make it sound!

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

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

Usage

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

Construction

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

dump()

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.

Chunk

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

MTrk

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

add()

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.

Example

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

tick()

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

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

send()

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

Helpers

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

MIDI messages:

noteOn noteOff aftertouch program pressure pitchBend control bankMSB bankLSB modMSB modLSB breathMSB breathLSB footMSB footLSB portamentoMSB portamentoLSB volumeMSB volumeLSB balanceMSB balanceLSB panMSB panLSB expressionMSB expressionLSB damper portamento sostenuto soft allSoundOff allNotesOff mtc songPosition songSelect tune clock start continue stop active sxIdRequest sxFullFrame

SMF meta events:

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

note()

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.

ch()

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

Example

// 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)
      .tick(96).noteOff('C6').noteOff('Eb6').noteOff('G6')
      .tick(96).smfEndOfTrack();
// or
smf[0].smfBPM(120).ch(0)
      .tick(96).note('C6', 127, 96).note('Eb6', 127, 96).note('G6', 127, 96)
      .tick(192).smfEndOfTrack();

player()

smf.player() - create the Player object.

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

play()

player.play() - start playback.

stop()

player.stop() - stop playback.

pause()

player.pause() - pause playback.

resume()

player.resume() - resume playback.

loop()

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.

type()

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

tracks()

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

duration()

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

durationMS()

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

position()

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

positionMS()

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

jump()

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

pos - position in MIDI ticks.

jumpMS()

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

pos - position in milliseconds.

tick2ms()

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

t - position in MIDI ticks.

ms2tick()

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

t - position in milliseconds.

Example

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

var player = smf.player();
JZZ().or('Cannot start MIDI engine!').openMidiOut().or('Cannot open MIDI Out!').and(function() {
  player.connect(this);
  player.play();
});

See also