LoginSignup
2
2

More than 3 years have passed since last update.

音楽関連素人の自分が初めてMIDIで色々通信してみた

Last updated at Posted at 2020-10-17
1 / 20

皆さんこんにちは、おの/るしわんです。

Image from Gyazo

こちらの記事は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の略

大本として同じだが、端子とファイル拡張子で同じ名前を混合して使われていることは知っていました

Image from Gyazo


今回調べて勉強になった点は、

  • 端子の種類は3種類
    • inとoutが別れているので、通信は一方方向
    • thruは機能の一部のイメージだけども…
  • 両脇2ピンは使ってないらしい
    • 一番真ん中がGND
    • その両脇でデータ通信
  • USBでも同じ内容のデータを送ることもできる
    • USBでつなぐMIDIキーボードなんてのもある(これは以前から知っていた)
    • 送るデータは主に音色、音程、強さ
    • 音楽用らしく、同期信号も送っているらしい…

そもそもなぜMIDIを扱おうと思ったのか

MFTokyo2020で、necobitさんの展示を拝見しました


基板(MT-4)を購入しちゃいました。MIDIデータからソレノイドなど4つ動かせるものだそうです。

Image from Gyazo


Maker Faireの帰りにアキバへ寄りました。

目的はPCからMIDI端子に変える何かですね。
単純に、3.5mmジャックからMIDI変換を探しましたが、ありませんでした。
考えるとわかることでしたが、MIDIの送信しているデータは音程や強さですので、単純な変換ケーブルはなかったでした。
MIDIインターフェースのようなものもあり、USBで繋げるものもありますが、高価なものが多かったでした。


後日M5Stackのモジュールを再びnecobitさんから通販で購入し、PCからの音でなく、M5Stackからの音でMT-4を動かそうとしました。


M5Stackの演奏からファンを回す

こちらのサンプルコードからM5StackをArduinoで書き込んでいきます

今回はその中の「M5Stack_MIDI_T_RndSeq」から使っていきます


開発環境や利用したライブラリ

  • Arduino 1.8.13
  • Arduino MIDI
    • 自分はIDE内で検索してもなかなか見つからなかったのでZipでダウンロードしました

その他、サンプルコードによっては別途ライブラリが必要ですので、サンプルコード内のコメントを読み飛ばさないように…


動いた!

ランダムな値を通信しているものなので、演奏と一緒という感じではないですが、動かすことができました!


配線とかは特に特殊なところはないですが、M5StackのMIDIモジュールのoutからMT-4へつなぎ、各電源をつなぐ
MT-4には、モーター用の電源ソケットがあるのでモーターに合わせたACアダプタをさす
自分は今回5Vで動く小さなファンだったので、5VのUSB-Cでつないでいます

Image from Gyazo


Bluetooth MIDIの発見


MacでBluetooth MIDIを利用する

サンプルコードの「BLE-LOCAL_MIDI_Translator」を利用します。
このコードをArduinoでM5Stackに書き込みます。


次にMacで、こちらを参考にしつつ、
「Audio MIDI設定」というアプリケーションから

Image from Gyazo

サンプルコードのままだと「M5」という名前で見つかるので接続します


例えば、「Garage Band」で流した音をM5Stackへ送りたい場合は、

Image from Gyazo

すでに設定には、接続されていると出てくる

これで行ける(と思う…)


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を普段使わない人にも使ってもらえそうになる気もしました

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2