Кодуємо музику в браузері

Регулярно з'являються статті про створення коду Javascript який видає звуки в браузері. В них пояснюється ніж частота ноти До відрізняється від частоти ноти Ля, приклади коду справно видають «біп-біп».

Зробимо щось подібне, але з результатом більше схожим на музику. І щодо наочної нотацією в дусі ABCприблизно ось так:

image

Запустити код і прослухати можна тут:
https://jsbin.com/nosojaz/edit?html,output

Як це працює
Для відтворення використовується технологія WebAudioFont.
Скрипти иснструментов беруться безпосередньо з проекту на GitHub

Ноти з тривалістю забиваються в масив, кожен елемент якого це функція виду
function bass(pitch, duration) {
return {
preset : _tone_Rubber_32Bass000079_461_460_45127,
pitch : pitch,
duration : duration
};
}

тобто просто повернення об'єкта містить пресет (інструмент, якщо у термінах WebAudioFont), висоту і тривалість ноти.

Для наочності висоту будемо задавати в заздалегідь заданих константах (var C = 0; var Cs= 1; var D = 2; і т. д.), а тривалість — у частках від повної ноти.
Природно, для ударних висота з тривалістю не мають сенсу і тому задаються однаковими значеннями.

Для виводу звуку перебираємо масив в циклі і ставимо кожен пресет в чергу відтворення:
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);
}
}
}
}

Відправляємо масив в плеєр нескінченно з певним інтервалом:
setInterval(function () {
if (audioContext.currentTime > startTime - 1 / 4 * N) {
nextPiece();
startTime = startTime + pieceLen;
}
}, 20);

Після кожної відправки збільшуємо змінну startTime, в якій зберігається час початку поточного шматка.

Попередження: в сучасних браузерах при перекладі фокуса в інше вікно функції setTimeout і setInterval примусово сповільнюються і мелодія буде «заїдати».
Ще приклад для JSFiddle
Все приблизно те ж саме, але побільше нот і інструменти відтворюються кожен через власний GainNode для коригування рівня гучності:

image

Запустити і прослухати приклад можна тут: https://jsfiddle.net/sss1024/c53Lwete/2/

У JSFiddle, на відміну від JSBin, можна обмежитися чистим JS-кодом без HTML, а скрипти інструментів і плеєра WebAudioFont вказати в лівій частині редактора в розділі External Resources.
Попередження для початківців гітаристів: якщо в музичному магазині перевіряєте гітару перед купівлею і машинально починаєте награвати «Дим над водою» — відразу стягується штраф 150 руб.
Приклади работаеют і в мобільних браузерах, але редагувати код на маленьких екранах телефонів не дуже зручно.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.