Javascript MIDI Player
- Tutorial
We will make a .mid file player for Javascript and Web Audio API.
The end result may look like this .
Making your player makes sense for interactive music applications as full control over playback will be possible (change of instruments, editing notes in real time, precise positioning, etc.).
For ordinary background music, regular mp3 is more suitable.
The file with notes needs to be read somehow, loaded the used tools, to synthesize a sound and send it to an audio output.
Everything is simple.
A simple search on GitHub gives us a bunch of projects for reading MIDI events from files.
Choose https://github.com/nfroidure/MIDIFile . It produces an array of events from a program change, noteOn / noteOff, etc.
For convenience, you will have to modify it a bit to immediately receive notes with time and duration:
The WebAudioFont library is used for sound , loading the tools in it is done with just a couple of lines, something like this:
You can send all notes to the playback queue at once. But there are thousands of them, even in small musical fragments, and such a size will "hang" the audio subsystem. Exit - send in small pieces through the regular setInterval function:
You can read about the parameters of the function of sending sounds to the playback queue on the WebAudioFont project page .
At any time, you can determine where the file is currently playing. In the demo player it looks like this:
A tool change looks something like this:
- Just a few lines and everything is loaded by itself.
An example of a player is available at the link
All code takes a little less than 300 lines.
The end result may look like this .
For what
Making your player makes sense for interactive music applications as full control over playback will be possible (change of instruments, editing notes in real time, precise positioning, etc.).
For ordinary background music, regular mp3 is more suitable.
Components
The file with notes needs to be read somehow, loaded the used tools, to synthesize a sound and send it to an audio output.
Everything is simple.
Reading files
A simple search on GitHub gives us a bunch of projects for reading MIDI events from files.
Choose https://github.com/nfroidure/MIDIFile . It produces an array of events from a program change, noteOn / noteOff, etc.
For convenience, you will have to modify it a bit to immediately receive notes with time and duration:
Downloading musical instruments
The WebAudioFont library is used for sound , loading the tools in it is done with just a couple of lines, something like this:
for (var i = 0; i < song.tracks.length; i++) {
var nn = findFirstIns(player, song.tracks[i].program);
var info = player.loader.instrumentInfo(nn);
player.loader.startLoad(audioContext, info.url, info.variable);
}
Sound synthesis
You can send all notes to the playback queue at once. But there are thousands of them, even in small musical fragments, and such a size will "hang" the audio subsystem. Exit - send in small pieces through the regular setInterval function:
setInterval(function () {
if (audioContext.currentTime > nextStepTime - stepDuration) {
sendNotes(song, songStart, currentSongTime, currentSongTime + stepDuration, audioContext, input, player);
currentSongTime = currentSongTime + stepDuration;
nextStepTime = nextStepTime + stepDuration;
}
}, 22);
You can read about the parameters of the function of sending sounds to the playback queue on the WebAudioFont project page .
Interactive
At any time, you can determine where the file is currently playing. In the demo player it looks like this:
function showPosition(song, currentSongTime) {
var o = document.getElementById('position');
o.value = 100 * currentSongTime / song.duration;
document.getElementById('tmr').innerHTML = '' + Math.round(100 * currentSongTime / song.duration) + '%';
}
A tool change looks something like this:
var nn=selectIns.value;
var info = player.loader.instrumentInfo(nn);
player.loader.startLoad(audioContext, info.url, info.variable);
player.loader.waitLoad(function () {
console.log('loaded');
song.tracks[i].info = info;
});
- Just a few lines and everything is loaded by itself.
Source
An example of a player is available at the link
All code takes a little less than 300 lines.