皆さんこんにちは、おの/るしわんです。
こちらの記事はIoTLT Vol.68でLTさせていただいた内容を記事にしたものになります。
Qiitaのスライドの機能も利用しつつですが、LTでは話せない試したソースコードの内容など入れ込んでいければと思います。
プロトアウトスタジオ(#protoout)4期生の講師やってます
- 音楽関連に興味ある学生が2/6人
- Qiitaトレンドに6人全員が載ったことも!
- クラウドファンディングでサクセス目指して奮闘中!!
- 12月7日から2週間の予定
ぜひ学生の活躍をご覧いただければと思います。
目次
- MIDIに関して、初心者の自分が調べてみてわかったこと
- 買った基板を試してみた(necobitさんのMT-4)
- MIDI周りの技術を使ってみた(Bluetooth MIDI)
全体的に自分は今こんなのにワクワクしてますという内容です
MIDIとは?
Musical Instrument Digital Interfaceの略
大本として同じだが、端子とファイル拡張子で同じ名前を混合して使われていることは知っていました
今回調べて勉強になった点は、
- 端子の種類は3種類
- inとoutが別れているので、通信は一方方向
- thruは機能の一部のイメージだけども…
- 両脇2ピンは使ってないらしい
- 一番真ん中がGND
- その両脇でデータ通信
- USBでも同じ内容のデータを送ることもできる
- USBでつなぐMIDIキーボードなんてのもある(これは以前から知っていた)
- 送るデータは主に音色、音程、強さ
- 音楽用らしく、同期信号も送っているらしい…
そもそもなぜMIDIを扱おうと思ったのか
MFTokyo2020で、necobitさんの展示を拝見しました
スピーカー自作とかにもハマったけど、やっぱり行き着く先はアナログ音ですかねぇ
— るしわん (@tkyko13) October 4, 2020
necobitさんの基盤買っちゃいました!
#mft2020 pic.twitter.com/HPSZF8LEZk
基板(MT-4)を購入しちゃいました。MIDIデータからソレノイドなど4つ動かせるものだそうです。
Maker Faireの帰りにアキバへ寄りました。
目的はPCからMIDI端子に変える何かですね。
単純に、3.5mmジャックからMIDI変換を探しましたが、ありませんでした。
考えるとわかることでしたが、MIDIの送信しているデータは音程や強さですので、単純な変換ケーブルはなかったでした。
MIDIインターフェースのようなものもあり、USBで繋げるものもありますが、高価なものが多かったでした。
後日M5Stackのモジュールを再びnecobitさんから通販で購入し、PCからの音でなく、M5Stackからの音でMT-4を動かそうとしました。
かっちった…midiの端子ってまだまだ使うよなぁmidiインターフェイスも欲しくなってくるがああいうのめっちゃ高い〜
— るしわん (@tkyko13) October 9, 2020
M5Stack用MIDIモジュール 2 を購入しました! https://t.co/YBFcJfVjHt #BASEec @necobitterより
M5Stackの演奏からファンを回す
こちらのサンプルコードからM5StackをArduinoで書き込んでいきます
今回はその中の「M5Stack_MIDI_T_RndSeq」から使っていきます
開発環境や利用したライブラリ
- Arduino 1.8.13
-
Arduino MIDI
- 自分はIDE内で検索してもなかなか見つからなかったのでZipでダウンロードしました
その他、サンプルコードによっては別途ライブラリが必要ですので、サンプルコード内のコメントを読み飛ばさないように…
動いた!
ランダムな値を通信しているものなので、演奏と一緒という感じではないですが、動かすことができました!
M5StackのMIDIモジュールを使ってMT-4を介し、ちっちゃいですがファンを回しました!
— るしわん (@tkyko13) October 17, 2020
本当はソレノイドで何か叩きたかったですが、いったん手元のもので成功#necobit #電子楽器初心者 #沼入り口 pic.twitter.com/lE9IIHUe1n
配線とかは特に特殊なところはないですが、M5StackのMIDIモジュールのoutからMT-4へつなぎ、各電源をつなぐ
MT-4には、モーター用の電源ソケットがあるのでモーターに合わせたACアダプタをさす
自分は今回5Vで動く小さなファンだったので、5VのUSB-Cでつないでいます
Bluetooth MIDIの発見
- USBケーブルで同じようなデータ送るものもあるし確かにあってもおかしくない
- ちなみにWeb Bluetoothから利用することもできるみたい
MacでBluetooth MIDIを利用する
サンプルコードの「BLE-LOCAL_MIDI_Translator」を利用します。
このコードをArduinoでM5Stackに書き込みます。
次にMacで、こちらを参考にしつつ、
「Audio MIDI設定」というアプリケーションから
サンプルコードのままだと「M5」という名前で見つかるので接続します
例えば、「Garage Band」で流した音をM5Stackへ送りたい場合は、
すでに設定には、接続されていると出てくる
これで行ける(と思う…)
BLE-LOCAL_MIDI_Translatorのサンプルコードについて
BLEからLOCALに変換するコードだと思うのですが、2020年10月現在ではまだ変換されておらず、BLEで受け取ったデータをコンソール出力のみのようです
そこで自分が通信するデータを変えながらデータを観察し、どこにどのデータがあるのかを見て変換するソースコードを自作してみました(ただ音を止めるなどの処理がまだなので完璧ではないです!)
#include <Arduino.h>
// M5STACK(ESP32)向け BLE MIDI
// Programed by Kazuyuki Eguchi 2018/04/24
// BLE->LOCAL Transrate code add by necobit 2020/07/03
#include <M5Stack.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <MIDI.h>
// MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI_H);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI);
#define MIDI_SERVICE_UUID "03b80e5a-ede8-4b33-a751-6ce34ec4c700"
#define MIDI_CHARACTERISTIC_UUID "7772e5db-3868-4112-a1a9-f2669d106bf3"
#define DEVIVE_NAME "M5"
BLEServer *pServer;
BLEAdvertising *pAdvertising;
BLECharacteristic *pCharacteristic;
int pos = 0;
char midi_s[5];
char midi_send[3];
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextSize(1);
M5.Lcd.setCursor(10, 0);
M5.Lcd.printf("BLE MIDI Connected.");
};
void onDisconnect(BLEServer* pServer) {
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextSize(1);
M5.Lcd.setCursor(10, 0);
M5.Lcd.printf("BLE MIDI Disconnect.");
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
pos = 0;
if (rxValue.length() > 0) {
for (int i = 0; i < rxValue.length(); i++)
{
midi_s[pos] = rxValue[i];
// Serial.printf("%x ", midi_s[pos]);
pos++;
if (pos == 5)
{
//7bit
// char tone = midi_s[2] << 1;
// tone = tone >> 1;
char pitch = midi_s[3] << 1;
pitch = pitch >> 1;
char vel = midi_s[4] << 1;
vel = vel >> 1;
MIDI.sendNoteOn(pitch, vel, 1);
Serial.printf("%d ","%d ", pitch, vel);
pos = 0;
}
}
Serial.println();
}
}
};
void setup() {
M5.begin();
Serial.begin(115200);
Serial2.begin(31250);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextSize(1);
M5.Lcd.setCursor(10, 0);
M5.Lcd.printf("BLE MIDI Disconnect.");
BLEDevice::init(DEVIVE_NAME);
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(BLEUUID(MIDI_SERVICE_UUID));
pCharacteristic = pService->createCharacteristic(
BLEUUID(MIDI_CHARACTERISTIC_UUID),
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_WRITE_NR
);
pCharacteristic->setCallbacks(new MyCallbacks());
pService->start();
BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
oAdvertisementData.setFlags(0x04);
oAdvertisementData.setCompleteServices(BLEUUID(MIDI_SERVICE_UUID));
oAdvertisementData.setName(DEVIVE_NAME);
pAdvertising = pServer->getAdvertising();
pAdvertising->setAdvertisementData(oAdvertisementData);
pAdvertising->start();
}
void loop() {
// delay(10);
}
送られてくるバイナリ配列の
- 2番目 - tone、音色
- 3番目 - pitch、高さ
- 4番目 - vel、強さ
でした。これはMIDIで送るデータの主なものですので、これでMT-4へMIDI.sendNoteOn()
で送ることができます。
Garage Bandからファンを回せたら楽しいよね
まだコードが完成してないですが、できそうなことはわかりました
やはり何か既存のアプリケーションからファンを回したり、モーターを回したりすることは何かもっと身近に電子工作が入ってくる感じがしてすごく面白く感じますし、普段の行動をハックするようなものだったり、Arduinを普段使わない人にも使ってもらえそうになる気もしました