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

  • Tutorial
Регулярно появляются статьи о создании кода Javascript который издаёт звуки в браузере. В них объясняется чем частота ноты До отличается от частоты ноты Ля, примеры кода исправно издают «бип-бип».

Сделаем что-то подобное, но с результатом больше похожим на музыку. И относительно наглядной нотацией в духе ABC, примерно вот так:

image

Запустить код и прослушать можно здесь.

Как это работает


Для воспроизведения используется технология 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 для корректировки уровня громкости:

image

Запустить и прослушать пример можно тут.

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

Примеры работаеют и в мобильных браузерах, но редактировать код на маленьких экранах телефонов не очень удобно.
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 15

    0
    Респект!!! А есть трекеры в браузере как Scream Tracker, OpenMPT
      0
      А меня больше волнуют не трекеры, а то, насколько сложно будет сделать конвертер из какого-нибудь распространённого трекерного формата в вот такое вот веб-аудио.
        +1
        Зачем? Трекер файл достаточно сложный по формату, эффектам и т.п. Если можно просто встроить воспроизведение трекер файла в страницу?

        Сам спросил — сам нашел 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
          0
          Есть готовый парсер MIDI :)
          Даже много, на самом деле…
          0

          В статье про WebAudioFont проскакивала ссылка на вот этот ресурс http://mod.haxor.fi/Manwe/mod.song_of_peace
          Вроде-бы не плохо звучит. Только вот возможности загрузить свой трек не нашёл.

          0

          А почему бы просто не генерировать midi файл налету?

            +1
            зачем?
              0

              Чтобы воспроизводить?

                +1
                он и так воспроизводится.
                  0

                  Только загружает 130Кб в течении полторы секунды.

                    0

                    Мда, Audio API не поддерживает MIDI. 21 век :-(

                      +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, не нуждается в них и прекрасно работает сам по себе, при минимальном для таких вещей объёме кода.
                        –7

                        Боюсь тест Тьюринга вы бы не прошли.

                          +1
                          Прямое оскорбление? Вы, чай, паблосом ошиблись, м?
                            0

                            А вот вы бы прошли.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое