Let’s celebrate Zelda’s 30th anniversary by generating a MIDI file of the game’s main theme.

PLAY DEMO

To generate MIDI files, we are going to use the MidiWriterJS.

Installation

1
npm install midi-writer-js

Usage

Here is how to get started with the library:

A MIDI file is a collection of tracks which are collections of notes.

Create a track

1
2
3
4
5
6
7
var MidiWriter = require('midi-writer-js');

// Create Track
var track = new MidiWriter.Track();

// Assign an instrument to a track
track.addEvent(new MidiWriter.ProgramChangeEvent({instrument : 1}));

Add a note to a track

1
track.addEvent(new MidiWriter.NoteEvent({pitch: ['Bb4'], duration: '2', velocity:100}));

pitch

pitch represents the notes you want to add.

Examples would be: 'Bb4', 'F4', 'A#2'

The letter is the note, you can alter it with b or # and the letter corresponds to the octave (I would say that 4 corresponds to your treble clef pitch)

duration

duration represents the duration of each note

duration American Name English Name
1 whole semibreve
2 half minim
d2 dotted half dotted minim
4 quarter crotchet
d4 dotted quarter dotted crotchet
8 eighth quaver
d8 dotted eighth dotted quaver
16 sixteenth semiquaver

Velocity

velocity represents the volume at which that note will play.

Generate the Midi JavaScript Object

1
2
// Generate MIDI
var write = new MidiWriter.Writer([track]);

The argument must be an Array of tracks. It is of course possible to add several tracks if you want to have several instruments playing at the same time.

Generate the MIDI file

I have chosen to go the base64 string route. Here is the code:

1
2
3
4
5
6
7
8
// Generate a base64 representation of the MIDI file
var base64String = write.base64();

// Strip off the header
var data = base64String.split("base64,").pop();

// Write the file
fs.writeFileSync("zelda.mid", data, {encoding: 'base64'});

Click here if you want to read more on how to strip off the base64 string header.

Zelda

You can check the git repo here to see the full sequence of notes.

PS: I have submitted my code to the creator of the official library and he has now merged it and added it to the examples :D