MidiWriterJS is a JavaScript library providing an API for generating expressive multi-track MIDI files.
Note that the master
branch is in active development so if you're looking for a tried and true stable version please use the latest release.
npm install midi-writer-js
var MidiWriter = require('midi-writer-js');
// Start with a new track
var track = new MidiWriter.Track();
// Define an instrument (optional):
track.addEvent(new MidiWriter.ProgramChangeEvent({instrument : 1}));
// Add some notes:
var note = new MidiWriter.NoteEvent({pitch:['C4', 'D4', 'E4'], duration: '4'});
track.addEvent(note);
// Generate a data URI
var write = new MidiWriter.Writer([track]);
console.log(write.dataUri());
addEvent({event}, mapFunction)
setTempo(tempo)
addText(text)
addCopyright(text)
addTrackName(text)
addInstrumentName(text)
addMarker(text)
addCuePoint(text)
addLyric(text)
setTimeSignature(numerator, denominator)
The NoteEvent
supports these options:
Name | Type | Description |
---|---|---|
pitch | array | An array of notes to be triggered. Can be a string or valid MIDI note code. Format for string is C#4 . Pro tip: You can use the output from tonal functions to build scales, chords, intervals, etc. in this parameter. |
duration | string or array |
How long the note should sound.
|
wait | string | How long to wait before sounding note (rest). Takes same values as duration. |
sequential | boolean | If true then array of pitches will be played sequentially as opposed to simulatanously. Default: false |
velocity | number | How loud the note should sound, values 1-100. Default: 50 |
repeat | number | How many times this event should be repeated. Default: 1 |
channel | number | MIDI channel to use. Default: 1 |
The Writer
class provides a few ways to output the file:
buildFile()
Uint8Arraybase64()
stringdataUri()
stringstdout()
file stream (cli)
Here's an example of how everyone's favorite song "Hot Cross Buns" could be written. Note use of the mapping function passed as the second argument of addEvent()
. This can be used to apply specific properties to all events. With some
street smarts you could also use it for programmatic crescendos and other property 'animation'.
var MidiWriter = require('midi-writer-js');
var track = new MidiWriter.Track();
track.addEvent([
new MidiWriter.NoteEvent({pitch: ['E4','D4'], duration: '4'}),
new MidiWriter.NoteEvent({pitch: ['C4'], duration: '2'}),
new MidiWriter.NoteEvent({pitch: ['E4','D4'], duration: '4'}),
new MidiWriter.NoteEvent({pitch: ['C4'], duration: '2'}),
new MidiWriter.NoteEvent({pitch: ['C4', 'C4', 'C4', 'C4', 'D4', 'D4', 'D4', 'D4'], duration: '8'}),
new MidiWriter.NoteEvent({pitch: ['E4','D4'], duration: '4'}),
new MidiWriter.NoteEvent({pitch: ['C4'], duration: '2'})
], function(event, index) {
return {sequential:true};
}
);
var write = new MidiWriter.Writer([track]);
console.log(write.dataUri());
MidiWriterJS can export MIDI from VexFlow voices, though this feature is still experimental. Current usage is to use MidiWriter.VexFlow.trackFromVoice(voice)
to create a MidiWriterJS Track
object:
// ...VexFlow code defining notes
var voice = create_4_4_voice().addTickables(notes);
var track = MidiWriter.VexFlow.trackFromVoice(voice);
var writer = new MidiWriter.Writer([track]);
console.log(writer.dataUri());