Сделаем что-то подобное, но с результатом больше похожим на музыку. И относительно наглядной нотацией в духе ABC, примерно вот так:
Запустить код и прослушать можно здесь.
Как это работает
Для воспроизведения используется технология WebAudioFont. Скрипты иснструментов берутся непосредственно из проекта на GitHub
Ноты с длительностью забиваются в массив, каждый элемент которого это функция вида:
function bass(pitch, duration) {
return {
preset : _tone_Rubber_32Bass000079_461_460_45127,
pitch : pitch,
duration : duration
};
}
T.е. просто возврат объекта содержащего пресет (инструмент, если в терминах 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 для корректировки уровня громкости:
Запустить и прослушать пример можно тут.
В JSFiddle, в отличии от JSBin, можно ограничиться чистым JS-кодом без HTML, а скрипты инструментов и плеера WebAudioFont указать в левой части редактора в разделе External Resources.
Предупреждение для начинающих гитаристов: если в музыкальном магазине проверяете гитару перед покупкой и машинально начинаете наигрывать «Дым над водой» — сразу взимается штраф 150 руб.
Примеры работаеют и в мобильных браузерах, но редактировать код на маленьких экранах телефонов не очень удобно.
Комментарии (15)
vintage
05.11.2016 18:47А почему бы просто не генерировать midi файл налету?
musicriffstudio
05.11.2016 19:30+1зачем?
vintage
05.11.2016 19:44Чтобы воспроизводить?
musicriffstudio
05.11.2016 20:00+1он и так воспроизводится.
vintage
05.11.2016 20:37Только загружает 130Кб в течении полторы секунды.
vintage
05.11.2016 20:52Мда, Audio API не поддерживает MIDI. 21 век :-(
musicriffstudio
05.11.2016 22:44+6Стандарт General MIDI появился очень давно. Он описывает формат обмена сообщениями между устройствами, см. https://ru.wikipedia.org/wiki/MIDI.
MIDI не имеет абсолютно никакого отношения непосредственно к воспроизведению звука. Воспроизведением занимается синтезатор, который получает команды в формате MIDI-сообщений. Сообщения могут быть как указанием начать проигрывать определённую ноту, так и чем-то непривычным, типа «сменить банк» или «повернуть колёсико частоты».
Файлы с расширением .mid являются списком MIDI-команд которые может воспроизвести почти любое музыкальное ПО.
К сожалению, укоренилось мнение что звук дешёвых аудиокарт с саундбанками размером в жалкий мегабайт, который слышен при воспроизведении в виндовом плеере, это и есть нечто называемое «MIDI».
Это ошибка, см. объяснение выше.
Таким образом, заявление вида «Audio API не поддерживает MIDI» не имеет смысла.
Для браузера поддержка GM описывается стандартом Web MIDI API, в нём говорится именно о передаче сообщений между музыкальными устройствами и браузером. Web Audio API отвечает за синтез звука, читать файлы с расширением .mid в его задачи не входит.
Автор, вероятно, хотел сказать что-то типа «в современных браузерах не возможности воспроизвести файл .mid». Это действительно так. Стандарт оказался слишком сложен для неспециализированных разработчиков, очень много путаницы и сования не туда куда надо.
Для большинства есть тэг <audio> который прекрасно подходит для задач воспроизведения файлов mp3, которые звучат одинаково вне зависимости от стоимости и настроек оборудования.
Итого:
описываемый в статье способ кодирования музыки не имеет никакого отношения к MIDI или файлам с расширением .mid, не нуждается в них и прекрасно работает сам по себе, при минимальном для таких вещей объёме кода.vintage
06.11.2016 08:24-7Боюсь тест Тьюринга вы бы не прошли.
igor_suhorukov
Респект!!! А есть трекеры в браузере как Scream Tracker, OpenMPT
DeXPeriX
А меня больше волнуют не трекеры, а то, насколько сложно будет сделать конвертер из какого-нибудь распространённого трекерного формата в вот такое вот веб-аудио.
igor_suhorukov
Зачем? Трекер файл достаточно сложный по формату, эффектам и т.п. Если можно просто встроить воспроизведение трекер файла в страницу?
Сам спросил — сам нашел https://github.com/deskjet/chiptune2.js — исходники кросскомпилированного libopenmpt из C/C++ в javascript
http://deskjet.github.io/chiptune2.js — онлайн демо
Даже отлично играет
Hybrid song
Heaven Seven by Exceed
UnreaL ][ / PM из демки second reality by future crew
GreyCat
Есть готовый парсер MIDI :)
Даже много, на самом деле…
POPSuL
В статье про WebAudioFont проскакивала ссылка на вот этот ресурс http://mod.haxor.fi/Manwe/mod.song_of_peace
Вроде-бы не плохо звучит. Только вот возможности загрузить свой трек не нашёл.