MIDI-проигрыватель на Javascript

Будем делать проигрыватель файлов .mid на Javascript и Web Audio API.

image

Конечный результат может выглядеть вот так.

image

Для чего

Делать свой плеер имеет смысл для интерактивных музыкальных приложений т.к. будет возможен полный контроль за воспроизведением (смена инструментов, редактирование нот в рилтайме, точное позиционирование и т.п.).

Для обычной фоновой музыки больше подходит обычный mp3.

Составные части

Файл с нотами надо как-то прочитать, загрузить используемые инструменты, синтезировать звук и отправить его в аудиовыход.

Всё просто.

Чтение файлов

Простой поиск по GitHub даёт нам кучу проектов для чтения MIDI-событий из файлов.

Выберем https://github.com/nfroidure/MIDIFile. Он выдаёт массив событий от смены программы, noteOn/noteOff и пр.

Для удобства придётся его немного модифицировать чтоб сразу получать ноты со временем и длительностью:

image

Загрузка музыкальных инструментов

Для звука используется библиотека WebAudioFont, загрузка инструментов в ней делается буквально парой строчек, примерно так:

for (var i = 0; i < song.tracks.length; i++) { 	var nn = findFirstIns(player, song.tracks[i].program); 	var info = player.loader.instrumentInfo(nn); 	player.loader.startLoad(audioContext, info.url, info.variable); 	} 

Синтез звука

Можно отправить в очередь воспроизведения все ноты сразу. Но их тысячи даже в небольших музыкальных фрагментах и такой размер «повесит» аудио подсистему. Выход — отправлять небольшими кусками через обычную функцию setInterval:

setInterval(function () { 	if (audioContext.currentTime > nextStepTime - stepDuration) { 		sendNotes(song, songStart, currentSongTime, currentSongTime + stepDuration, audioContext, input, player); 		currentSongTime = currentSongTime + stepDuration; 		nextStepTime = nextStepTime + stepDuration; 	} }, 22); 

О параметрах функции отправки звуков в очередь воспроизведения можно прочитать на странице проекта WebAudioFont.

Интерактив

В любой момент можно определить в каком месте файла сейчас находится воспроизведения. В демо-плеере это выглядит так:

function showPosition(song, currentSongTime) { 	var o = document.getElementById('position'); 	o.value = 100 * currentSongTime / song.duration; 	document.getElementById('tmr').innerHTML = '' + Math.round(100 * currentSongTime / song.duration) + '%'; } 

Смена инструмента выглядит примерно так:

var nn=selectIns.value; var info = player.loader.instrumentInfo(nn);					 player.loader.startLoad(audioContext, info.url, info.variable); player.loader.waitLoad(function () { 	console.log('loaded'); 	song.tracks[i].info = info; }); 

— буквально несколько строчек и всё подгружается само.

Исходный код

Пример плеера доступен по ссылке

Весь код занимает чуть менее 300 строк.

FavoriteLoadingДобавить в избранное
Posted in Без рубрики

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *