📜 ⬆️ ⬇️

We encode music in the browser

There are regular articles about creating Javascript code that makes sounds in the browser. They explain how the frequency of the note C differs from the frequency of the note A, code samples regularly publish a “beep-bleep”.

Let's do something similar, but with the result more like music. And a relatively visual ABC- like notation, like this:

image
')
Run the code and listen here .

How it works


To play using technology WebAudioFont . Tools are taken directly from the project on GitHub.

Notes with duration are clogged in an array, each element of which is a function of the form:

function bass(pitch, duration) { return { preset : _tone_Rubber_32Bass000079_461_460_45127, pitch : pitch, duration : duration }; } 

T.e. simply returning the object containing the preset (the instrument, if in terms of WebAudioFont ), the pitch and duration of the note.

For clarity, the height will be given in the predetermined constants (var C = 0; var Cs = 1; var D = 2; etc.), and the duration - in fractions of the full note.

Naturally, for drums, heights with durations do not make sense and therefore are given the same values.

To output audio, loop through the array in a loop and set each preset in the play queue:

 function beats(notes) { for (var n = 0; n < notes.length; n++) { var beat = notes[n]; for (var i = 0; i < beat.length; i++) { if (beat[i]) { player.queueWaveTable(audioContext , audioContext.destination , beat[i].preset , startTime + n * beatLen , beat[i].pitch , beat[i].duration); } } } } 

We send an array to the player infinitely at a certain interval:

 setInterval(function () { if (audioContext.currentTime > startTime - 1 / 4 * N) { nextPiece(); startTime = startTime + pieceLen; } }, 20); 

After each sending, we increase the startTime variable, which stores the start time of the current piece.

Warning: in modern browsers, when moving the focus to another window, the setTimeout and setInterval functions are forced to slow down and the melody will “stick”.

Another example for JSFiddle


Everything is about the same, but more notes and instruments are played each through its own GainNode to adjust the volume level:

image

Run and listen to the example here .

In JSFiddle, unlike JSBin, you can restrict yourself to pure JS code without HTML, and specify the scripts of tools and the WebAudioFont player in the left side of the editor in the External Resources section.
Warning for novice guitarists: if you check a guitar in a record store before you buy it and automatically start playing “Smoke over water”, a penalty of 150 rubles will be charged immediately.

The examples also work in mobile browsers, but editing the code on the small screens of the phones is not very convenient.

Source: https://habr.com/ru/post/314472/


All Articles