Прием MIDI-данных

В этом разделе мы узнаем, как подключить MIDI-контроллер для отправки событий в Sonic Pi для управления нашими синтезаторами и звуками. Хватай свою MIDI-клавиатуру или контроллер, и начнем работать физически!

Подсоединение MIDI контроллера

Чтобы получить информацию с внешнего MIDI-устройства в Sonic Pi, нам сначала нужно подключить ее к нашему компьютеру. Как правило, это происходит через USB порт, хотя старое оборудование будет иметь 5-контактный разъем DIN, для которого вам потребуется аппаратная поддержка вашего компьютера (например, некоторые звуковые карты имеют разъемы MIDI DIN). После подключения устройства запустите Sonic Pi и загляните в раздел IO на панели «Настройки». Вы должны увидеть там в списке ваше устройство. Если его нет, попробуйте нажать кнопку «Reset MIDI» и посмотреть, появится ли оно. Если вы по-прежнему ничего не видите, то попробуйте обратиться к конфигурации MIDI в вашей операционной системы, чтобы уточнить, доступно ли она ваше устройство там. В противном случае, не стесняйтесь задавать вопросы в публичном чате: http://gitter.im/samaaron/sonic-pi

Прием событий MIDI

Как только ваше устройство подключено, Sonic Pi будет автоматически получать от него события. Вы можете убедиться в этом сами, манипулируя вашим MIDI-устройством и поглядывая в регистратор сигналов в правом нижнем углу, под журналом (если его не видно, перейдите в «Настройки» -> «Редактор» -> «Показать/Скрыть» и включите «Показать журнал сигналов»). Вы увидите поток событий, таких как:

/midi:nanokey2_keyboard:0:1/note_off  [55, 64]
/midi:nanokey2_keyboard:0:1/note_on   [53, 102]
/midi:nanokey2_keyboard:0:1/note_off  [57, 64]
/midi:nanokey2_keyboard:0:1/note_off  [53, 64]
/midi:nanokey2_keyboard:0:1/note_on   [57, 87]
/midi:nanokey2_keyboard:0:1/note_on   [55, 81]
/midi:nanokey2_keyboard:0:1/note_on   [53, 96]
/midi:nanokey2_keyboard:0:1/note_off  [55, 64]

Как только вы увидите поток таких сообщений, вы успешно подключили ваше MIDI-устройство. Поздравляем! Давайте посмотрим, что мы можем с этим сделать!

Временные состояние MIDI

Эти события разбиты на два раздела. Во-первых, есть имя события, например /midi:nanokey2_keyboard:0:1/note_on, а во-вторых, есть значения события, такие как [18, 62] . Интересно, что это две вещи, которые нам нужны для хранения информации в Time State. * Sonic Pi автоматически вставляет входящие события MIDI в Time State *. Это означает, что вы можете использовать get, чтобы получить последнее значение MIDI, а также использоватьsync для ожидания следующего MIDI значения, применяя все, что мы узнали в разделе 10 этого руководства.

Контролируя код

Теперь мы подключили MIDI-устройство, увидели его события в журнале и обнаружили, что наше знание Time State - это все, что нам нужно для работы с этими событиями, теперь мы можем начать веселиться. Давайте создадим простое MIDI-пианино:

live_loop :midi_piano do
  note, velocity = sync "/midi:nanokey2_keyboard:0:1/note_on"
  synth :piano, note: note
end

В приведенном выше коде происходит несколько вещей, включая некоторые проблемы. Во-первых, у нас есть простой live_loop, который будет постоянно повторять код, выполняемый в блоке внутри ` do / end. Это было дано разъяснение в Разделе 9.2. Во-вторых, мы применяем sync для ожидания следующего подходящего для сопоставления события Time State. Мы используем строку, определяющую MIDI-сообщение, которое мы ждем (и которое совпадает с отображением в журнале событий). Обратите внимание, что эта длинная строка пдставояется вам системой автозаполнения Sonic Pi, так что вам не нужно печатать все вручную. В журнале мы увидели, что для каждого MIDI note on события было два значения, поэтому мы присваиваем результат двум отдельным переменным note и velocity. Наконец, мы запускаем синтезатор : piano`, передавая ему нашу ноту.

Теперь попробуйте сами. Введите приведенный выше код, замените ключ синхронизации строкой, соответствующей вашему конкретному MIDI-устройству, и нажмите Выполнить. Вуаля, у вас есть пианино! Однако вы, вероятно, заметите пару проблем: во-первых, все ноты имеют одинаковую громкость независимо от того, как сильно вы нажимаете на клавиатуру. Это можно легко исправить преобразовав значение MIDI velocity в амплитуду звукового сигнала. Учитывая, что MIDI имеет диапазон 0-> 127, чтобы преобразовать это число в значение между 0-> 1, нам просто нужно разделить его на 127:

live_loop :midi_piano do
  note, velocity = sync "/midi:nanokey2_keyboard:0:1/note_on"
  synth :piano, note: note, amp: velocity / 127.0
end

Обновите код и снова нажмите «Выполнить». Теперь зависимость громкости от скорости нажатия клавиш на клавиатуре соблюдается. Далее, давайте избавимся от этой досадной паузы.

Устранение задержки

Прежде чем мы сможем убрать эту паузу, нам нужно знать, почему она возникает. Чтобы обеспечить своевременную синхронизацию всех синтезаторов и эффектов на различных процессорах с различными возможностями, Sonic Pi по умолчанию планирует запуск аудио *заранее * на 0,5 секунды. (Обратите внимание, что эта дополнительная задержка может быть настроена через fns set_sched_ahead_time! и use_sched_ahead_time). Эта задержка 0,5 секунды добавляется и к нашим триггерам синтезатора : piano, поскольку она добавляется ко всем синтезаторам, запускаемым Sonic Pi. Как правило, мы действительно хотим добавить дополнительную задержку, поскольку это означает, что все синтезаторы будут рассчитаны вовремя. Однако это имеет смысл только для синтезаторов, запускаемых кодом с использованием play и sleep. В нашем случае мы фактически запускаем синтезатор : piano с помощью внешнего MIDI-устройства и поэтому не хотим, чтобы Sonic Pi контролировал время за нас. Мы можем отключить эту задержку с помощью команды use_real_time, которая отключает задержку для текущего потока. Это означает, что вы можете использовать режим реального времени для живых циклов, чье время контролируется путем синхронизации с внешними устройствами, и сохранять задержку по умолчанию для всех других живых циклов. Давайте взглянем на это:

live_loop :midi_piano do
  use_real_time
  note, velocity = sync "/midi:nanokey2_keyboard:0:1/note_on"
  synth :piano, note: note, amp: velocity / 127.0
end

Обновите код, чтобы он соответствовал приведенному выше, и снова нажмите «Выполнить». Теперь у нас есть пианино с низкой задержкой и переменной скоростью, кодируемое всего за 5 строк. Это было не так уж и просто!

Получение значений

Наконец, поскольку наши MIDI-события идут прямо в Time State, мы также можем использовать функцию get для получения последнего значения. Это не блокирует текущий поток и не возвращает nil, если не найдено никакого значения (которое вы можете переопределить, передав значение по умолчанию - смотрите документацию по get). Помните, что вы можете вызвать get в любом потоке в любое время, чтобы увидеть последнее соответствующее значение Time State. Вы даже можете использовать time_warp, чтобы вернуться назад во времени, вызвать get и увидеть прошедшие события …

Теперь контролируете Вы

Самое захватывающее то, что теперь вы можете использовать одни и те же структуры кода для вызова функций sync и get в отношении MIDI-информации с любого MIDI-устройства и выполнения в дальнейшем любых действий с полученными значениями. Теперь вы можете выбирать, что будет делать ваше MIDI-устройство!