M5StackでBLE MIDIコントローラーを作ってみよう(2)

#概要
M5stackのBLE MIDIでNote On/Note Offを行うデモです。

#有線のMIDI
##MIDIのNote On/Note Offデモ
M5stackのBLE MIDIのデモの前に、有線MIDIのNote On/Note Offのデモです。

[Arduino Uno x GarageBand](https://youtu.be/uawe6uRiEsw)
(YouTube)

##構成
- Arduino UNOに[MIDIシールド](https://www.switch-science.com/catalog/2492/)を載せたもの
- iPhone用 MIDI I/F(デモでは、諸々、昔の製品の組み合わせで動かしていますが、今なら[iRig MIDI 2](https://www.ikmultimedia.com/products/irigmidi2/)などが利用できると思います。
- GarageBand for iPhone

##ソース
Arduino IDEの「ファイル > スケッチ例 > 04.Communication >Midi」そのものです。(一部、コメント削除)

```c:Midi,ino
void setup() {
  // Set MIDI baud rate:
  Serial.begin(31250);
}

void loop() {
  // play notes from F#-0 (0x1E) to F#-5 (0x5A):
  for (int note = 0x1E; note < 0x5A; note ++) {
    //Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
    noteOn(0x90, note, 0x45);
    delay(100);
    //Note on channel 1 (0x90), some note value (note), silent velocity (0x00):
    noteOn(0x90, note, 0x00);
    delay(100);
  }
}

// plays a MIDI note. Doesn't check to see that cmd is greater than 127, or that
// data values are less than 127:
void noteOn(int cmd, int pitch, int velocity) {
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
}
```

##簡単な解説
MIDI信号は、実はFlow制御なし、BaudRate=31250bpsのUART信号そのものです。
そして、中身の多くは、UARTで3バイトの信号を送るだけになります。

**1バイト目: 信号の内容**
今回の0x90は、Note Onを示します。(正確には、Channel1へのNote On)

**2バイト目: 音程**
1バイト目にNote Onを設定すると、2バイト目は、音程を示します。

**3バイト目: べロシティ**
1バイト目にNote Onを設定すると、3バイト目は、ベロシティ(音の強さ)を示します。
多くの機器は、ベロシティの値を0x00にしてNoteOnを送信すると、NoteOffの信号として扱われます。

###MIDI信号の詳細
[MIDI1.0規格書](http://amei.or.jp/midistandardcommittee/MIDI1.0.pdf)のp2-9~p2-11を参考にしてみてください。

---

#BLE MIDI
##BLE MIDIのNote On/Note Offデモ
[M5Stack x GarageBand](https://youtu.be/rr0-JwD6YNk)
(YouTube)

##構成
- M5Stack(デモではM5stack Grayですが、M5stack Basicでも動くと思います。)
- GarageBand for iPhone

##ソース
```c:wirelessMidi.ino
#define LOAD_FONT4
#include <M5Stack.h>
#include <BLEDevice.h>
#include <BLEServer.h>

//BLE関連
//デバイス名
const char *DEVICE_NAME = "m5-stack-ble-midi";

//BLE MIDIのサービスとキャラクタラスティック
const char *SERVICE_UUID = "03B80E5A-EDE8-4B33-A751-6CE34EC4C700";
const char *CHAR_UUID = "7772E5DB-3868-4112-A1A9-F2669D106BF3";

//BLEデータ
BLEServer *pServer;
BLECharacteristic *pCharacteristic;
bool isConnected = false;

//BLE MIDIデータ
unsigned char buff[] = {0x80, 0x80, 0xB0, 0x01, 0x64};

//BLE関連関数
// サーバーのコールバック関数
class cbServer: public BLEServerCallbacks {
  void onConnect(BLEServer *pServer) {
    isConnected = true;
    M5.Lcd.clear(); 
    M5.Lcd.drawCentreString(" BLE Connected  ", 160, 120, 4);
  };

  void onDisconnect(BLEServer *pServer) {
    isConnected = false;
    M5.Lcd.clear(); 
    M5.Lcd.drawCentreString(DEVICE_NAME, 160, 120, 4);
  }
};

void setup(){
  int i;
  
  // M5Stackの初期化
  M5.begin();

  // BLE初期化
  BLEDevice::init(DEVICE_NAME);

  // サーバーの作成
  BLEServer *pServer = BLEDevice::createServer();
  // コールバック関数の設定
  pServer->setCallbacks(new cbServer());

  // サービスの作成
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // キャラクタリスティックの作成
  pCharacteristic = pService->createCharacteristic(
    CHAR_UUID,
    BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY
  );
  
  // サービスの開始
  pService->start();

  //アドバタイジングの開始    
  pServer->getAdvertising()->addServiceUUID(SERVICE_UUID);
  pServer->getAdvertising()->start();

  //ディスプレイにデバイスネームを表示
  M5.Lcd.drawCentreString("m5-stack-ble-midi", 160, 120, 4);
}

void loop() {
  if (isConnected)
  {
    for (int note = 0x1E; note < 0x5A; note ++)
    {
      notifyNote(note, 0x45);
      delay(100);
      notifyNote(note, 0x00);
      delay(100);      
    }
  }
}

//MIDI関連関数
//BLE Noteを送信
void notifyNote(int note, int velocity)
{    
  //noteをvelcityの強さで送信
  buff[2] = 0x90;
  buff[3] = note;      
  buff[4] = velocity;

  //MIDIデータをNotify
  pCharacteristic->setValue(buff, 5);
  pCharacteristic->notify();    
}
```

##簡単な解説
細かいBLEの仕組みの話をすっ飛ばすと、BLE MIDI対応機器に5バイトの信号を送るだけになります。

**1バイト目、2バイト目: タイムスタンプ**
正直、よく分かっていません...。とりあえず、今のデモでは、0で問題なさそうなので、0のままにしてあります。タイムスタンプを0に設定するには、1バイト目、2バイト目、共に0x80にしておきます。

**3バイト目~5バイト目: MIDI信号の1バイト目~3バイト目**
今回のNote Onのデモでは、

- 3バイト目: Note On("0x90")
- 4バイト目: 音程
- 5バイト目: ベロシティ

を設定しています。

---

#最後に...
MIDI信号は、非常にシンプルな規格で、BLE MIDIもそれに準じた非常にシンプルな規格です。いろんなセンサの出力をBLE MIDI信号に乗せて、新たな音を探してみてはいかがでしょうか?