We will make a player .mid files on Javascript and Web Audio API.
The end result might look
like this .
For what
Making your player makes sense for interactive music applications. full control over reproduction will be possible (change of instruments, editing of notes in rltime, precise positioning, etc.).
For normal background music, regular mp3 is more suitable.
')
Components
The file with notes must somehow be read, the instruments used are loaded, the sound is synthesized and sent to the audio output.
It's 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 gives an array of events from the change of the program, noteOn / noteOff, etc.
For convenience, you will have to modify it a bit to immediately get notes with time and duration:
Download musical instruments
For sound, the
WebAudioFont library is
used , the loading of tools in it is literally done in a couple of lines, 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 the notes to the queue at once. But there are thousands of them even in small musical fragments and such a size will “hang” the audio subsystem. Output - send in small chunks through the usual 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);
The parameters of the function of sending sounds to the playback queue can be found on the
WebAudioFont project
page .
Interactive
At any time, you can determine where the file is now 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) + '%'; }
Tool change looks 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 loads itself.
Source
Sample player is available
by reference.All code takes just under 300 lines.