ArduinoとMIDIキーボードを組み合わせて楽器をつくる方法

今日は```楽器の日```！

ということで、MIDIキーボードからArduinoを制御して、簡単な楽器を作ってみます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/7132/e522d6be-b11e-4d06-4b91-2d287b7dd880.jpeg" height="500" />

作り方は簡単
```Arduono```と```Arduino USB Host Shield```をガッチャンコして、
USBケーブルで```MIDIキーボード```を繋げるだけ

## 使ったもの
- [Arduono Uno](https://amzn.to/2RFOnQF)
- [Arduino USB Host Shield](https://amzn.to/3elfTN3)
- [KORG NANOKEY2](https://amzn.to/3clTPzT)
- [圧電スピーカー（SPT15）](http://akizukidenshi.com/catalog/g/gP-04228/)

## ライブラリ
- [USB Host Library Rev.2.0（1.2.1）](https://github.com/felis/USB_Host_Shield_2.0)
- [USBH_MIDI（0.3.1）](https://github.com/YuuichiAkagawa/USBH_MIDI)

バージョンは両方とも最新の使っています。
わかりにくいですが、```USB Host Library Rev.2.0```という名前のライブラリーのバージョン```1.2.1```です。


## とりあえず動かしてみる

試しにUSBH_MIDIのサンプルにあるコードを動かしてみます。
https://github.com/YuuichiAkagawa/USBH_MIDI/blob/master/examples/USBH_MIDI_dump/USBH_MIDI_dump.ino

PCからコードを書き込んで、シリアルモニタで確認できます。
鍵盤を押すとこんな感じのログが表示されます。

```
0002310D: 64: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00027C13: 64: 09 90 48 76 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00027CA7: 64: 08 80 48 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00027D80: 64: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00027D80: 64: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0002CA5C: 64: 09 90 48 5A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0002CAF0: 64: 08 80 48 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0002CBC7: 64: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
```

bufMidiに16進数で１バイトずつMIDIの信号が入っているのですが、細かい仕様は[こちら](https://ja.wikipedia.org/wiki/MIDI#MIDI.E3.83.87.E3.83.BC.E3.82.BF.E3.83.95.E3.82.A9.E3.83.BC.E3.83.9E.E3.83.83.E3.83.88)

このログでいうと
xxxxxxxx: xx: ```00 00 00 00 00 ~```の２桁毎に表示されている数字の部分がそれです。

例えば１バイト目が、
09だったら鍵盤を押したタイミング（Note On）、
08だったら鍵盤を離したタイミング（Note Off）になります。


音程は３バイト目が取得できるので、

```
00027C13: 64: 09 90 48 76 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
```

これは```48番目の鍵盤を押した```ということが分かります。

音程はピアノの中央の```ド```を```60```として半音毎に1変化します。

ド - 60
ド# - 61
レ - 62
レ# - 63
ミ - 64
ファ - 65
ソ - 67

といった具合です。
使われるのは7ビットで0（とても低いド）~127（とても高いソ）までの128音対応してます。

<img src="https://upload.wikimedia.org/wikipedia/commons/7/7a/NoteNamesFrequenciesAndMidiNumbers.svg" height="700" />

## Arduinoを楽器にしてみる

そんなわけで、鍵盤に対応した音を圧電スピーカーから鳴らしてみます。

使い方はBuilt-In Examplesの[toneMelody](https://www.arduino.cc/en/Tutorial/toneMelody)とほぼいっしょ

![image](https://qiita-image-store.s3.amazonaws.com/0/7132/46f15cce-130d-0695-5266-dab33d8e4bbf.png)


Note Numberは丁度0から始まるので配列にしてしまいます。
対応した周波数の配列、60番目が基準の440Hzです。

```c
double tones[128] = {8.2, 8.7, 9.2, 9.7, 10.3, 10.9, 11.6, 12.2, 13, 13.8, 14.6, 15.4, 16.4, 17.3, 18.4, 19.4, 20.6, 21.8, 23.1, 24.5, 26, 27.5, 29.1, 30.9, 32.7, 34.6, 36.7, 38.9, 41.2, 43.7, 46.2, 49, 51.9, 55, 58.3, 61.7, 65.4, 69.3, 73.4, 77.8, 82.4, 87.3, 92.5, 98, 103.8, 110, 116.5, 123.5, 130.8, 138.6, 146.8, 155.6, 164.8, 174.6, 185, 196, 207.7, 220, 233.1, 246.9, 261.6, 277.2, 293.7, 311.1, 329.6, 349.2, 370, 392, 415.3, 440, 466.2, 493.9, 523.3, 554.4, 587.3, 622.3, 659.3, 698.5, 740, 784, 830.6, 880, 932.3, 987.8, 1046.5, 1108.7, 1174.7, 1244.5, 1318.5, 1396.9, 1480, 1568, 1661.2, 1760, 1864.7, 1975.5, 2093, 2217.5, 2349.3, 2489, 2637, 2793.8, 2960, 3136, 3322.4, 3520, 3729.3, 3951.1, 4186, 4434.9, 4698.6, 4978, 5274, 5587.7, 5919.9, 6271.9, 6644.9, 7040, 7458.6, 7902.1, 8372, 8869.8, 9397.3, 9956.1, 10548.1, 11175.3, 11839.8, 12543.9};
```


上の２つのサンプルを組み合わせて、鍵盤を押した時に対応する音が鳴るようにしてみました。

```c:miditone.ino
#include <usbh_midi.h>
#include <usbhub.h>
#include <SPI.h>

USB Usb;
USBH_MIDI Midi(&Usb);

int pin = 8;
int melo = 200;
double tones[128] = {8.2, 8.7, 9.2, 9.7, 10.3, 10.9, 11.6, 12.2, 13, 13.8, 14.6, 15.4, 16.4, 17.3, 18.4, 19.4, 20.6, 21.8, 23.1, 24.5, 26, 27.5, 29.1, 30.9, 32.7, 34.6, 36.7, 38.9, 41.2, 43.7, 46.2, 49, 51.9, 55, 58.3, 61.7, 65.4, 69.3, 73.4, 77.8, 82.4, 87.3, 92.5, 98, 103.8, 110, 116.5, 123.5, 130.8, 138.6, 146.8, 155.6, 164.8, 174.6, 185, 196, 207.7, 220, 233.1, 246.9, 261.6, 277.2, 293.7, 311.1, 329.6, 349.2, 370, 392, 415.3, 440, 466.2, 493.9, 523.3, 554.4, 587.3, 622.3, 659.3, 698.5, 740, 784, 830.6, 880, 932.3, 987.8, 1046.5, 1108.7, 1174.7, 1244.5, 1318.5, 1396.9, 1480, 1568, 1661.2, 1760, 1864.7, 1975.5, 2093, 2217.5, 2349.3, 2489, 2637, 2793.8, 2960, 3136, 3322.4, 3520, 3729.3, 3951.1, 4186, 4434.9, 4698.6, 4978, 5274, 5587.7, 5919.9, 6271.9, 6644.9, 7040, 7458.6, 7902.1, 8372, 8869.8, 9397.3, 9956.1, 10548.1, 11175.3, 11839.8, 12543.9};


void setup() {
  Serial.begin(9600);
  pinMode(pin, OUTPUT);

  if (Usb.Init() == -1) {
    while(1);
  }
  delay(200);
}

void loop() {
  Usb.Task();

  if (Usb.getUsbTaskState() == USB_STATE_RUNNING) {
    getTone();
  }
  delay(2);
}

void getTone() {
  char buf[20];
  uint8_t bufMidi[64];
  uint16_t rcvd;
  
  if (Midi.RecvData(&rcvd, bufMidi) == 0 ) {
    if (bufMidi[0] == 9) {
      int note = bufMidi[2];
      tone(pin, tones[note], 200);
    }
  }
}
```

[![image](https://qiita-image-store.s3.amazonaws.com/0/7132/653c5620-043b-7aa3-af06-344ec5a14342.png)
実際に弾いてみた](https://www.instagram.com/p/BGRzlptRhFz/)


## おわり
今回使ってないですが、ベロシティとかピッチベンドとか他のパラメーターも取れるし、
キーボードにオクターブシフトがついていれば128個のボタンが手に入ります。
MIDI機器なら結構安いものもあるし、楽器以外にもいろいろ活用できそうです。