Передача MIDI данных от Arduino в компьютер

Передача MIDI данных от Arduino в компьютер

Передача одиночного потока данных

От одного сенсора передать данные от Arduino в Max/MSP очень просто. Для примера возьмем потенциометр и подключим его к pin 0 контроллера Arduino. Контроллер будет считывать состояние потенциометра и передавать данные последовательным потоком в компьютер в ПО Max/MSP. Диапазон чисел от потенциометра будет лежать в пределах 0-127, что как раз подходит для MIDI.

Как только данные приняты Max/MSP, они сразу же будут перенаправлены на объект ctlout, что дает возможность контроля над любым параметром в любом приложении, которые принимают MIDI данные.

Скетч для Arduino очень прост:

byte val; void setup() { Serial.begin(57600); // Открываем последовательный вывод данных } void loop() { val = analogRead(0) / 8; // считываем значение потенциометра и преобразовываем к диапазону 0 – 127 Serial.print(val, BYTE); // отдаем значение в послед. порт delay(5); // задержка } }

Патч для Max/MSP:

Но что делать, если необходимо передавать данные от 2-х, 3-х, или сразу от 4-х потенциометров? Вот тут сразу начнутся проблемы. Дело в том, что в один промежуток времени может передаваться/приниматься только один байт. И будут возникать неизбежные задержки в передаче данных.

В данном варианте в первом байте будет содержаться информация от первого потенциометра, во втором байте – от второго. На стороне ПК, в MIDI-секвенсоре будет трудно разделять эти данные, да и неэффективно.

Передача многопоточных данных

Одним из решением данной проблемы является преобразование всех данных от потенциометров в MIDI-формат в контроллере Arduino, а затем уже передача MIDI-данных от Arduino в Max/MSP.

MIDI структура

Структура MIDI кажется сложной только на первый взгляд, на самом деле вы в ней быстро освоитесь. Каждое действие (взятие ноты, снятие ноты, питч-бенд и др.) передается в виде MIDI-событий. Мы будем работать с MIDI-событиями состоящими из трех байт. Соответственно в каждом байте хранится 8 бит и мы охватываем диапазон от 0 до 255.

Первый байт – статус, за ним идут 2 байта с данными. В статусном байте содержится информация о типе события, который мы передаем (взятие ноты, снятие ноты, пауза и т.п.) и номер канала от 1 до 16. Байты с данными содержат информацию о действии, к примеру если бы нажали клавишу какой-либо ноты, то данные будут содержать тон ноты и как резко вы ее нажали (velocity): Status Byte; Data Byte #1; Data Byte #2;

Байт статуса

Статусный байт разделен на два полубайта. Первый полубайт содержит биты 4-7 байта, а второй полубайт биты 0-3. Для удобства, принято использовать шестнадцатеричную систему счисления, т.о. первый полубайт может содержать значение от 0 до F, то же самое и второй 0-F.

Первый полубайт указывает на тип события:

8 = Note Off

9 = Note On

A = After Touch

B = Control Change

C = Patch Change

D = Channel Pressure

E = Pitch Bend

F = System Message

Второй полубайт указывает на номер канала:

0 = Канал 1

1 = Канал 2

2 = Канал 3

3 = Канал 4

4 = Канал 5

5 = Канал 6

6 = Канал 7

7 = Канал 8

8 = Канал 9

9 = Канал 10

A = Канал 11

B = Канал 12

C = Канал 13

D = Канал 14

E = Канал 15

F = Канал 16

Если совместить два полубайта, то мы получим всю необходимую информацию статусного байта о MIDI-действии. К примеру, если необходимо передать информацию о взятии ноты на 1-м канале, то значение статусного байта будет 0x90. Префикс 0x указывает на то, что используется шестнадцатеричная система счисления, 9 – взятие ноты, 0 – 1 канал. Или, если необходимо передать питч-бенд на 3-канале, то значение статус-байта будет 0xE2.

Байты данных

После того, как передан статусный байт, нужно передать два байта с данными. Для того, чтобы стало более понятно, приведу два примера:в первом будет взятие ноты (note-on), во втором сообщение контроллера (control change).

При взятии ноты в байте #1 содержится значение тона (pitch) в диапазоне 0-127. В байте #2 содержится значение velocity также в диапазоне 0-127. К примеру, если необходимо передать взятие ноты на 3 канале с pitch 60 и velocity 123, то последовательность байтов для передачи будет следующая:

0x92

60

123

В статусном байте 9 указывает на взятие ноты, 2 – третий канал. В следующем байте #1 цифра 60 указывает на тон, в байте #2 цифра 123 – значение velocity. Если передается взятие ноты (note-on), но с значением velocity – 0, то это равносильно снятию ноты (note-off).

Если статусный байт передает сообщение контроллера, то в 1-ом байте содержится номер контроллера 0-127, а во втором его значение 0-127. К примеру:

0xB4

1

82

Здесь значение B в статусном байте указывает, что это сообщение контроллера (control change), 4 – пятный канал. Первый байт данных содержит цифру 1, это контроллер Modulation. Второй байт содержит величину 82 контроллера.

Основные контроллеры MIDI

Modulation (CC #1)

Breath (CC #2)

Foot Pedal (CC #4)

Portamento Time (CC #5)

Volume (CC #7)

Pan (CC #10)

Expression (CC #11)

Soft Pedal (CC #68)

Передача данных с Arduino

Итак, после всего вышеописанного мы сможем легко посылать MIDI-данные с Arduino. Затем эти данные поступают в Max/MSP и дальше передаются в virtual MIDI path (IAC Driver Bus 1 под OS X или LooBe1 под Windows), а затем уже в музыкальное ПО или DAW (Live, Logic, ProTools, Reason).

Приведу примеры с взятием ноты и с передачей сообщения контроллера.

Пример 1. Отсылаем событие взятия ноты, пауза 1 сек, снятие ноты, пауза 1 сек.

Скетч Arduino:

void setup() { Serial.begin(57600); } void loop() { // посылаем note-on Serial.print(0x90, BYTE); // MIDI Note-on; канал 1 Serial.print(60, BYTE); // MIDI note pitch 60 Serial.print(127, BYTE); // MIDI note velocity 127 delay(1000); // пауза 1 сек // посылаем note-off Serial.print(0x90, BYTE); // MIDI Note-on; канал 1 Serial.print(60, BYTE); // MIDI note pitch 60 Serial.print(0, BYTE); // MIDI note velocity 0 (т.е. note off) delay(1000); // пауза 1 сек }

Патч для Max/MSP:

Пример 2. Отсылаем событие контроллера каждую секунду

Скетч Arduino:

void setup() { Serial.begin(57600); } void loop() { // посылаем сообщение контроллера Serial.print(0xB2, BYTE); // MIDI control change; канал 3 Serial.print(1, BYTE); // MIDI controller #1 Serial.print(127, BYTE); // MIDI controller value of 127 delay(1000); // пауза 1 сек }

Патч для Max/MSP:

Соединяем все воедино

Теперь, мы легко можем считает состояние нескольких потенциометров, сформировать и послать MIDI-данные в Max/MSP. Рассмотрим пару примеров.

Пример 1. Считываем значение потенциометров, подключенных к аналоговым входам 0 и 1. Эти значения будут посылаться в MIDI канал 1, контроллер 1 и канал 2, контроллер 1.

Скетч Arduino:

byte val = 0; void setup() { Serial.begin(57600); } void loop() { val = analogRead(0) / 8; // считываем значение потенциометра 1 // let’s send a control change message Serial.print(0xB0, BYTE); // MIDI control change; канал 1 Serial.print(1, BYTE); // MIDI controller #1 Serial.print(val, BYTE); // MIDI controller значение потенциометра 1 val = analogRead(1) / 8; // считываем значение потенциометра 2 // let’s send a control change message Serial.print(0xB1, BYTE); // MIDI control change; канал 2 Serial.print(1, BYTE); // MIDI controller #1 Serial.print(val, BYTE); // MIDI controller значение потенциометра 2 delay(5); }

Патч для Max/MSP:

Пример 2. Считываем значение с 6 потенциометров и передаем данные контроллера 1 в канал 1, 2, 3, 4, 5 и 6.

Скетч Arduino:

byte val = 0; void setup() { Serial.begin(57600); } void loop() { for(int i = 0; i < 6; i ++) { val = analogRead(i) / 8; // считываем значения потенциометров // (на аналоговых входах 0 - 5) // посылаем сообщение контроллера Serial.print(0xB0 + i, BYTE); // MIDI control change; номер канала Serial.print(1, BYTE); // MIDI controller #1 Serial.print(val, BYTE); // MIDI controller значение от потенциометра delay(1); // пауза } }

Патч для Max/MSP:

Оригинал статьи на английском языке (перевод Колтыков А.В. для сайта cxem.net)


Категория: Arduino
Метки:

Написать коментарий

*
= 5 + 2

Добавить изображение

Последние статьи