Кодируем музыку в браузере
Сделаем что-то подобное, но с результатом больше похожим на музыку. И относительно наглядной нотацией в духе ABC, примерно вот так:
Запустить код и прослушать можно здесь:
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 для корректировки уровня громкости:
Запустить и прослушать пример можно тут: https://jsfiddle.net/sss1024/c53Lwete/2/
В JSFiddle, в отличии от JSBin, можно ограничиться чистым JS-кодом без HTML, а скрипты инструментов и плеера WebAudioFont указать в левой части редактора в разделе External Resources.
Предупреждение для начинающих гитаристов: если в музыкальном магазине проверяете гитару перед покупкой и машинально начинаете наигрывать «Дым над водой» — сразу взимается штраф 150 руб.
Примеры работаеют и в мобильных браузерах, но редактировать код на маленьких экранах телефонов не очень удобно.