ZOOM G1onをPythonからMIDI制御する

# ZOOM G1on
**G1on**とは、言わずと知れたZOOMの超高コスパなギター用マルチエフェクタ(アンプシミュレータ)です。
ZOOMは昔から空間系のクオリティの高さに定評がありますが、アンプシミュレータとしてもなかなか高クオリティな上に、リズムマシンとルーパーまでついて実売価格が五千円台という恐るべきデバイスです。アンプに突っ込んで大きな音で鳴らしてやると気持ちいいですね。
ZOOMの製品には、９０年代半ばの**ZOOM 4040**や**ZOOM 9050**の時代からお世話になっていますが、歪み系に難があると言われていた当時のチープな歪みとは隔世の感があります。軽く小さく持ち運びも便利でPCからのUSB給電でもしっかり動くG1onは、後継機が出たとしても長く付き合っていきたい逸品といえます。

## MIDIインプリメンテーションチャートが非公開
性能的には優秀なG1onですが、何故か説明書のどこにも(WEBサイトのどこにも)MIDIインプリメンテーションチャートが掲載されていません。
PCに接続すると、MIDI入出力ともに**ZOOM 1 Series**という名前のポートが現れます。しかし、このポートに対して色々信号を送ってみても、意図通りに動くのはプログラムチェンジくらいのもので、コントロールチェンジ信号を送ってエフェクトのパラメタを変化させられるわけでもなく、なんともモヤモヤしてしまいます。
昔のZOOM製品の説明書には事細かにMIDIインプリメンテーションチャートが載っていたのに、今になってなぜ非公開にするのかまるで解せません。理解不能です。(USB)MIDIで自在に制御できれば、もっともっと活用され、より多くのギタリストに愛されるデバイスになるのではないでしょうか。

## システムエクスクルーシブメッセージで制御可能
とはいえ悲観することはありません。
G1onは、次の特別なSysExを受け取ると、MIDIによってパッチやパラメタを編集可能なモードに遷移します。
**F052006350F7**
そして、次のメッセージを受け取ると、編集可能なモードを終了します。
**F052006351F7**

編集可能なモードに移行すると、ツマミをいじってパラメタを変えたり、エフェクトの種類を変えたりする度に、G1onからSysExが送られてきます。この信号を読み解けば、おおよそは解析できようというものです。

## パラメタの制御やエフェクトのON/OFFは簡単
パラメタ制御は次のSysExによって可能です。
F052006331 **01**(エフェクトの位置) **02**(パラメタの位置) **0000**(値) F7
注意すべきは、エフェクトの位置は０から、パラメタの位置は２から始まることです。たとえば、３番目にアンプがあるとすると、そのアンプのゲインを１００にしたければ、F05200633102026400F7を送ってやればいいことになります。
この**F052006331**で始まるSysExは、エフェクトのON/OFFにも関わっています。
F052006331 **01**(エフェクトの位置) 00 **00**(state) 00 F7
stateが00ならOFF、01ならONになります。


## パッチデータは固定長１３４バイト
次のSysExは５つのエフェクトがすべてバイパスで、名前は空白、パッチ全体の音量(Level)が100の状態のパッチデータです。

**F0520063280001000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000100000000000020006401000000200300000000202020200020202020202000F7**
このデータを基準として音量やパッチ名を変えてみると、自明な構造がすぐに２つ見つかります。
１つ目は**110バイト目が音量**を示していること、２つ目は**121バイト目から最後までがパッチ名**となっていることです。
ただし、パッチ名は若干複雑な構造で、最初の４文字と後続する６文字が２つのヌル終端アスキー文字列として別れています。例えば、HelloWorldというパッチ名の場合、パッチデータの名前の部分をCの文字列で表せば`"Hell\0oWorld"`という形式になっているわけです。

肝心のエフェクトデータの部分は、メッセージの先頭から第１エフェクト・第２エフェクトの順に第５エフェクトまで順序だって格納されているようです。
こまかな解析は時間がないため諦め、ただ一つのエフェクトを除き全てバイパスにしておき、エフェクトの種類を順次変えながらパッチデータで変化した部分を収集するという力技で全てのパタンを抽出しました。

# pymidiate

パッチデータを収集し、おおよそのデータが揃ったところで、いよいよ制御ライブラリの開発です。
MIDI制御ライブラリとしては、弊社開発の[pymidiate(ベータ版)](https://github.com/PGkids/pymidiate)を使用し、このライブラリにG1on制御ライブラリをバンドルする形にしました。
https://github.com/PGkids/pymidiate
上記リポジトリからソースツリーを引っ張ってきて、`python setup.py install`でOKです。
現在はWindowsでしか動きませんが、MIDIバックエンドの[interMidiator](https://github.com/PGkids/interMidiator)をALSA対応などに書き換えれば他OSでも動くと思います。

**(2019.3.3 23:37) 正しくインストールできない問題をFIXしてリポジトリに反映しました**

今夜は時間がないので、とりあえず使い方だけをまとめます。

## 使い方

```python
from midiate.zoom.g1on import G1on

## G1on制御オブジェクトを生成
g1on = G1on()
## MIDIバックエンドのinterMidiatorを起動し、G1onに接続
g1on.connect()

## パッチデータを生成し、送信。
## 各エフェクト用のコントローラが５つ組で返される
znr,comp,amp,delay,reverb = g1on.make_patch('ZNR','Comp','MS1959','Delay','Hall')

## コントローラを使ってパラメタを変更
comp['Sense'] = 6

## 同一エフェクトなら複数パラメタを一気に変更することも可能
amp['Gain','Level','OUT'] = 40, 120, 'ComboFront'
delay['Time','Mix'] = 1000,40

## エフェクトのOFF
delay.off()
## エフェクトのON
delay.on()

## G1onと接続解除し、MIDIバックエンドのinterMidiatorを終了
g1on.disconnect()
```

パッチ名やパッチの音量(Level)を指定してパッチデータを送信する場合には、
`g1on.make_patch('ZNR','MS1959',name='my patch',level=80)`
のようにすればOKです。

パッチデータを生成して送信するのではなく、G1onに保存されている既存のパッチに対してPythonで制御したい場合には、次のようにすればいいでしょう。
例えば、**バンクB**の**4番**のパッチに、**ZNR**,**TScream**,**MSDRIVE**,**ModReverb**の順でエフェクトが入っているとするなら、

```python

# パッチの選択
g1on.select_patch('B',4) # 小文字'b'でもOK

# コントローラは５つ組で返されることに注意
znr,stomp,amp,reverb,_ = g1on.make_controllers('ZNR','TScream','MSDRIVE','ModReverb')

# コントローラを使って制御
amp['Trebl','Middl','Bass','Prese'] = 60,45,60,55
```
のような感じになると思います。

急ごしらえで書きましたので設計面で雑な部分もありバグも取り切れてはいませんが、なかなか直感的に使用できるライブラリになったのではないでしょうか。
コンパクトで持ち運びもラクチン、しかもノートPCのUSB給電でも駆動するG1onを自在にリアルタイム制御できれば、ギター演奏の可能性は飛躍的に高まるものと思います。