npm install @tonejs/midi
Midi makes it straightforward to read and write MIDI files with Javascript. It uses midi-file for parsing and writing.
Node.js:
const { Midi } = require('@tonejs/midi')
Typescript / ES6
import { Midi } from '@tonejs/midi'
Browser
<script src="https://unpkg.com/@tonejs/midi"></script>
const midi = new Midi()
// load a midi file in the browser const midi = await Midi.fromUrl("path/to/midi.mid") //the file name decoded from the first track const name = midi.name //get the tracks midi.tracks.forEach(track => { //tracks have notes and controlChanges //notes are an array const notes = track.notes notes.forEach(note => { //note.midi, note.time, note.duration, note.name }) //the control changes are an object //the keys are the CC number track.controlChanges[64] //they are also aliased to the CC number's common name (if it has one) track.controlChanges.sustain.forEach(cc => { // cc.ticks, cc.value, cc.time }) //the track also has a channel and instrument //track.instrument.name })
The data parsed from the midi file looks like this:
{ // the transport and timing data header: { name: String, // the name of the first empty track, // which is usually the song name tempos: TempoEvent[], // the tempo, e.g. 120 timeSignatures: TimeSignatureEvent[], // the time signature, e.g. [4, 4], PPQ: Number // the Pulses Per Quarter of the midi file // this is read only }, duration: Number, // the time until the last note finishes // an array of midi tracks tracks: [ { name: String, // the track name if one was given channel: Number, // channel // the ID for this channel; 9 and 10 are // reserved for percussion notes: [ { midi: Number, // midi number, e.g. 60 time: Number, // time in seconds ticks: Number, // time in ticks name: String, // note name, e.g. "C4", pitch: String, // the pitch class, e.g. "C", octave : Number, // the octave, e.g. 4 velocity: Number, // normalized 0-1 velocity duration: Number, // duration in seconds between noteOn and noteOff } ], // midi control changes controlChanges: { // if there are control changes in the midi file '91': [ { number: Number, // the cc number ticks: Number, // time in ticks time: Number, // time in seconds value: Number, // normalized 0-1 } ], }, instrument: { // and object representing the program change events number : Number, // the instrument number 0-127 family: String, // the family of instruments, read only. name : String, // the name of the instrument percussion: Boolean, // if the instrument is a percussion instrument }, } ] }
If you are using Node.js or have the raw binary string from the midi file, just use the parse method:
const midiData = fs.readFileSync("test.mid") const midi = new Midi(midiData)
You can also create midi files from scratch or by modifying an existing file.
// create a new midi file var midi = new Midi() // add a track const track = midi.addTrack() track.addNote({ midi : 60, time : 0, duration: 0.2 }) .addNote({ name : 'C5', time : 0.3, duration: 0.1 }) .addCC({ number : 64, value : 127, time : 0.2 }) // write the output fs.writeFileSync("output.mid", new Buffer(midi.toArray()))
Thank you midi-file!