Доступ к midi устройствам в браузере что это
Введение в Web MIDI
“Статья о MIDI в вебе? В 2016? Смешно, да.”
Нет. Это не то, что вы думаете. Для тех, кто помнит интернет 90х, одной фразы “MIDI в вебе” достаточно, чтобы вспомнить унылое лофайное проигрывание “The Final Countdown” при посещении гостевых книг особо одаренных веб-мастеров. Однако в 2016 году MIDI в вебе, а точнее Web MIDI API имеет большой потенциал.
MIDI стандарт отвечает за цифровой интерфейс музыкальных инструментов. Это протокол, который позволяет электронным музыкальным инструментам, компьютерам и прочим устройствам общаться друг с другом. Он работает посылая небольшие сообщения от устройства к устройству, передавая сообщения типа “нажата клавиша с нотой 12” или “клавишу с нотой 62 отпустили” в коротком цифровом формате.
Web MIDI API использует этот протокол и позволяет вам взять инструмент с MIDI, например, MIDI-клавиатуру, подсоединить к компьютеру и пересылать информацию с нее в браузер.
Но зачем подключать MIDI-клавиатуру к браузеру? Начнем с того, что для большинства музыкантов QWERTY-клавиатура не является полноценной заменой. А в реальности спектр музыкального оборудования, поддерживающего MIDI очень широк. Подключая MIDI-инструменты к браузеру и используя Web Audio API, мы можем создавать музыкальные инструменты прямо в вебе.
Хотите пианино? Просто подсоедините MIDI-клавиатуру и перейдите на страницу, использующую эти технологии для воспроизведения звука пианино. Нужен другой звук? Просто перейдите на другой сайт.
Итак, мы поняли, зачем нужен этот API, теперь будем разбираться, как он работает.
Доступ к MIDI-устройству
Теперь, когда мы убедились, что метод существует, вызовем его для доступа к любому MIDI-входу в браузере.
navigator.requestMIDIAccess() возвращает промис, это означает, что мы можем вызвать нужную функцию как в случае успешного соединения, так и в случае неудачи. Пока мы напишем две простые функции, просто выводящие в консоль результат подключения.
Краткое содержание цикла:
Декодирование MIDI-данных
Из всего содержимого MIDI-сообщения нам прежде всего интересны его данные — какой тип MIDI-событий передается, какая клавиша нажата?
Второй элемент массива это данные о нажатой/отпущенной клавиши. Всего для нот есть 128 номеров, этого достаточно для всех октав. В нашем случае нажата клавиша 61, по таблице номеров нот мы видим, что это C#.
Третий и последний элемент это скорость нажатия клавиш (velocity). Он может использоваться, например, для имитации пианино, клавиши которого могут нажиматься мягко или с силой.
Теперь, когда мы знаем, какая клавиша нажата или отпущена, попробуем эти сведения конвертировать во что-то полезное. Привяжем Web MIDI API к Web Audio API. Если вы не знакомы с Web Audio API, вам стоит прочитать несколько статей о нем.
Создание инструмента в браузере
Сделаем из нашего браузера небольшой синтезатор. Мы создадим осциллятор, генерирующий частоту нажатой клавиши, для этого нам надо конвертировать номер ноты в частоту. Алгоритм для этого нашелся в Википедии, вот как выглядит его реализация в JavaScript;
Просто отдаем ноту и получаем частоту. Используем это в функции onMIDIMessage :
Теперь мы хотим, чтобы нота с этой частотой проигрывалась при поступлении MIDI-сообщения с событием noteOn :
Но что у нас во второй части? Некоторые устройства вместо отправки сообщения noteOff передают noteOn со скоростью нажатия 0, поэтому мы проверяем, что значение скорости нажатия больше нуля.
Если нет, еще раз советую прочитать серию статей о Web Audio API, включая статью о создании синтезатора. Код в этой статье похож на то, что получилось у нас сейчас.
Что дальше?
Запомните, что noteOn и noteOff это лишь два из доступных типов сообщений и MIDI-клавиатура это лишь одно из очень разнообразных MIDI-устройств. И вы не обязаны использовать их для музыки. Может, мы еще дождемся HTML5 игр с управлением от MIDI-трубы.
Лабаем на MIDI-клавиатуре в Angular
Web MIDI API — интересный зверь. Хоть он и существует уже почти пять лет, его все еще поддерживает только Chromium. Но это не помешает нам создать полноценный синтезатор в Angular. Пора поднять Web Audio API на новый уровень!
Программировать музыку, конечно, весело, но что если мы хотим ее играть? В 80-е годы появился стандарт обмена сообщениями между электронными инструментами — MIDI. Он активно используется и по сей день, и Chrome поддерживает его на нативном уровне. Это значит, что, если у вас есть синтезатор или MIDI-клавиатура, вы можете подключить их к компьютеру и считывать то, что вы играете. Можно даже управлять устройствами с компьютера, посылая исходящие сообщения. Давайте разберемся, как это сделать по-хорошему в Angular.
Web MIDI API
Dependency Injection
Теперь мы можем подписаться на все MIDI-события. Можно создать Observable одним из двух способов:
Поскольку в этот раз нам понадобится совсем немного преобразований, токен вполне подойдет. С обработкой отказа код подписки на все события выглядит так:
Если вам интересны подобные практичные мелочи про Angular — приглашаю почитать нашу серию твитов с полезными советами.
Аналогичным образом можно добывать и входные порты, а также запрашивать их по имени.
Операторы
Для работы с потоком событий нам потребуется создать свои операторы. В конце концов, мы же не хотим каждый раз ковыряться в исходном массиве данных.
Операторы можно условно разделить на две группы:
Вот так мы можем слушать события с определенного канала:
Status byte организован группами по 16: 128—143 отвечают за нажатые клавиши ( noteOn ) на каждом из 16 каналов. 144—159 — за отпускание зажатых клавиш ( noteOff ). Таким образом, если мы возьмем остаток от деления этого байта на 16 — получим номер канала.
Если нас интересуют только сыгранные ноты, поможет такой оператор:
Теперь можно строить цепочки операторов, чтобы получить стрим, который нам нужен:
Пора применить все это на практике!
Создаем синтезатор
С небольшой помощью библиотеки для Web Audio API, которую мы обсуждали ранеесоздадим приятно звучащий синтезатор всего за пару директив. Затем мы скормим ему ноты, которые играем через описанный выше стрим.
В качестве отправной точки используем последний кусок кода. Чтобы синтезатор был полифоническим, нужно отслеживать все сыгранные ноты. Для этого воспользуемся оператором scan:
Чтобы звук не прерывался резко и не звучал всегда на одной громкости, создадим полноценный ADSR-пайп. В прошлой статье была его упрощенная версия. Напомню, идея ADSR — менять громкость звука следующим образом:
Чтобы нота начиналась не резко, удерживалась на определенной громкости, пока клавиша нажата, а потом плавно затухала.
Теперь, когда мы нажимаем клавишу, громкость будет линейно нарастать за время attack. Затем она убавится до уровня sustain за время decay. А когда мы отпустим клавишу, громкость упадет до нуля за время release.
С таким пайпом мы можем набросать синтезатор в шаблоне:
Если у вас нет MIDI-клавиатуры — можете понажимать на ноты мышкой.
Живое демо доступно тут, однако браузер не позволит получить доступ к MIDI в iframe: https://stackblitz.com/edit/angular-midi
Заключение
В Angular мы привыкли работать с событиями с помощью RxJs. И Web MIDI API не сильно отличается от привычных DOM-событий. С помощью пары токенов и архитектурных решений мы смогли с легкостью добавить поддержку MIDI в наше Angular приложение. Описанное решение доступно в виде open-source библиотеки @ng-web-apis/midi. Она является частью большого проекта, под названием Web APIs for Angular. Наша цель — создание легковесных качественных оберток для использования нативного API в Angular приложениях. Так что если вам нужен, к примеру, Payment Request API или Intersection Observer — посмотрите все наши релизы.
Введение в Web MIDI
Russian (Pусский) translation by Marat Amerov (you can also view the original English article)
“Статья о MIDI в вебе? В 2016? Смешно, да.”
Нет. Это не то, что вы думаете. Для тех, кто помнит интернет 90х, одной фразы “MIDI в вебе” достаточно, чтобы вспомнить унылое лофайное проигрывание “The Final Countdown” при посещении гостевых книг особо одаренных веб-мастеров. Однако в 2016 году MIDI в вебе, а точнее Web MIDI API имеет большой потенциал.
MIDI стандарт отвечает за цифровой интерфейс музыкальных инструментов. Это протокол, который позволяет электронным музыкальным инструментам, компьютерам и прочим устройствам общаться друг с другом. Он работает посылая небольшие сообщения от устройства к устройству, передавая сообщения типа “нажата клавиша с нотой 12” или “клавишу с нотой 62 отпустили” в коротком цифровом формате.
Web MIDI API использует этот протокол и позволяет вам взять инструмент с MIDI, например, MIDI-клавиатуру, подсоединить к компьютеру и пересылать информацию с нее в браузер.
На данный момент Web MIDI API поддерживается только в Chrome и Opera, но вы можете наблюдать за продвижением работы по добавлению его в Firefox в соответствующем треде на сайте.
Но зачем подключать MIDI-клавиатуру к браузеру? Начнем с того, что для большинства музыкантов QWERTY-клавиатура не является полноценной заменой. А в реальности спектр музыкального оборудования, поддерживающего MIDI очень широк. Подключая MIDI-инструменты к браузеру и используя Web Audio API, мы можем создавать музыкальные инструменты прямо в вебе.
Хотите пианино? Просто подсоедините MIDI-клавиатуру и перейдите на страницу, использующую эти технологии для воспроизведения звука пианино. Нужен другой звук? Просто перейдите на другой сайт.
Итак, мы поняли, зачем нужен этот API, теперь будем разбираться, как он работает.
Доступ к MIDI-устройству
Теперь, когда мы убедились, что метод существует, вызовем его для доступа к любому MIDI-входу в браузере.
navigator.requestMIDIAccess() возвращает промис, это означает, что мы можем вызвать нужную функцию как в случае успешного соединения, так и в случае неудачи. Пока мы напишем две простые функции, просто выводящие в консоль результат подключения.
Чтобы получать MIDI-данные с нашего устройства, нам надо создать переменную и задать ей значение midi.inputs.values() примерно так:
Краткое содержание цикла:
Декодирование MIDI-данных
Второй элемент массива это данные о нажатой/отпущенной клавиши. Всего для нот есть 128 номеров, этого достаточно для всех октав. В нашем случае нажата клавиша 61, по таблице номеров нот мы видим, что это C#.
Третий и последний элемент это скорость нажатия клавиш (velocity). Он может использоваться, например, для имитации пианино, клавиши которого могут нажиматься мягко или с силой.
Теперь, когда мы знаем, какая клавиша нажата или отпущена, попробуем эти сведения конвертировать во что-то полезное. Привяжем Web MIDI API к Web Audio API. Если вы не знакомы с Web Audio API, вам стоит прочитать несколько статей о нем.
Создание инструмента в браузере
Сделаем из нашего браузера небольшой синтезатор. Мы создадим осциллятор, генерирующий частоту нажатой клавиши, для этого нам надо конвертировать номер ноты в частоту. К счастью, наш хороший друг Википедия дает нам небольшой алгоритм для этого. Вот как выглядит его реализация в JavaScript:
Но что у нас во второй части? Некоторые устройства вместо отправки сообщения noteOff передают noteOn со скоростью нажатия 0, поэтому мы проверяем, что значение скорости нажатия больше нуля.
Если нет, еще раз советую прочитать серию статей о Web Audio API, включая статью о создании синтезатора. Код в этом учебнике похож на то, что я сделал сейчас, поэтому было бы идеальным местом для применения того, что вы узнали здесь.
Что дальше?
Запомните, что noteOn и noteOff это лишь два из доступных типов сообщений и MIDI-клавиатура это лишь одно из очень разнообразных MIDI-устройств. И вы не обязаны использовать их для музыки. Может, мы еще дождемся HTML5 игр с управлением от MIDI-трубы. Похоже на мою вещь.
Разрешения
Часть доступов и разрешений, необходимых для корректной работы мобильного Яндекс.Браузера, запрашивается при его установке.
Доступ к микрофону
Требуется для голосового поиска и разговоров с Алисой.
Если при установке вы отказались предоставить браузеру доступ к микрофону, вы можете сделать это позже:
Доступ к камере
Требуется для поиска по картинке.
Если при установке вы отказались предоставить браузеру доступ к камере, вы можете сделать это позже:
Доступ к местоположению
Используется в следующих случаях:
Если при установке вы отказались предоставить браузеру доступ к местоположению, вы можете сделать это позже:
Если вы не нашли информацию в Справке или у вас возникает проблема в работе Яндекс.Браузера, опишите все свои действия по шагам. Если возможно, сделайте скриншот. Это поможет специалистам службы поддержки быстрее разобраться в ситуации.
Разрешения
Часть доступов и разрешений, необходимых для корректной работы мобильного Яндекс.Браузера, запрашивается при его установке.
Доступ к микрофону
Требуется для голосового поиска и разговоров с Алисой.
Если при установке вы отказались предоставить браузеру доступ к микрофону, вы можете сделать это позже:
Доступ к камере
Требуется для поиска по картинке.
Если при установке вы отказались предоставить браузеру доступ к камере, вы можете сделать это позже:
Доступ к местоположению
Используется в следующих случаях:
Если при установке вы отказались предоставить браузеру доступ к местоположению, вы можете сделать это позже:
Если вы не нашли информацию в Справке или у вас возникает проблема в работе Яндекс.Браузера, опишите все свои действия по шагам. Если возможно, сделайте скриншот. Это поможет специалистам службы поддержки быстрее разобраться в ситуации.