ClojureでLEDチカチカ

現在，Clojure歴6時間ぐらいの@aster_ismです．
@athos0220 に騙されて，「Clojure = JVM上で動くLisp系のやつでしょ」ぐらいの知識しかもってないClojure初心者が，Clojure Advent Calender 駆動勉強することになりました．
（一応，Schemeっぽい何かは少し触ったことがあります）
色々と文法とかよく分からないところあるし，用語とか間違えてそうだけど，サンプルコード探して，それをベースに実行していくだけなら何とかなるよね！


## はじめに

普段はVerilog HDLとかSystemCでデジタル回路設計やハードウェアのシステム設計を主にやっているので，どうせ初っぱなにやるなら何かハードウェアを制御したいなーということで，ハードウェア制御のHello, worldであるLEDチカチカをやることにしました．
今回は簡単にデバイスにアクセスしたいので，Switch Scienceで見つけた [Pepper(もなかファーム入り)](http://www.switch-science.com/catalog/521/) 使います．
こいつは，あらかじめ入っているファームウェアでUSB接続のMIDIデバイスとして認識されます．
JavaでMIDIデバイス制御であれば簡単に情報が手に入りそうだったので選択しました．

（「clojure midi」でGoole検索したら数日前のClojure Advent Calender記事が出てきたけど，他にネタが思いつかなかったので，MIDIで被ってしまいますが，ご勘弁を）


## 環境構築

### Clojure

@athos0220 氏にClojureやりたいんだけど，まず何すればいい？と聞いたら「雷人間」で検索しろ．
と言われたので，検索するとことからスタート．
「 [Leiningen](http://leiningen.org/)  」だったのね．
インストール等は他のサイト，ユーザの記事を見れば詳しく乗っていますが，そんなの見なくてもインストールページに従えば，特に苦労せずにClojureの環境が整いました．すげー．


### Pepper

[Pepper自体はUSBで給電されますし，入出力ポート4つとVCC，GND](http://morecatlab.akiba.coocan.jp/morecat_lab/PepperMonaka.html) が出てます．
今回のデバイスはモード１で動作させて，ポート2番とGND間にLEDと適当な抵抗を挿入します．
後は60番の音つまりC3(ド)を鳴らすと，ポート2番に電圧が掛かり，LEDが光るという仕組みです．

## midi-cljを参考にお勉強開始

「midi clojure」で検索すると，一番上にGithub上のそれっぽいコードが見つかったので，参考にさせてもらいます．
https://github.com/rosejn/midi-clj

まずは，repl立ち上げて，必要なそうなJavaのクラスをインポートします．
`midi-clj/src/midi.clj` の8行目を参考に `MidiSystem` `ShortMessage` をインポートしておきます．

```clj
(import '(javax.sound.midi MidiSystem ShortMessage))
```

`midi-clj/src/midi.clj` の29行目にMIDIデバイスを取ってきそうな，関数があるので使ってみます．

```clj
(defn midi-devices []
  "Get all of the currently available midi devices."
  (for [info (MidiSystem/getMidiDeviceInfo)]
    (let [device (MidiSystem/getMidiDevice info)]
      (with-meta
        {:name         (.getName info)
         :description  (.getDescription info)
         :vendor       (.getVendor info)
         :version      (.getVersion info)
         :sources      (.getMaxTransmitters device)
         :sinks        (.getMaxReceivers device)
         :info         info
         :device       device}
        {:type :midi-device}))))
```

私の環境で実行した結果は次のようになりました．

```clj
({:name "Gervill", :description "Software MIDI Synthesizer", :vendor "OpenJDK", :version "1.0", :sources 0, :sinks -1, :info #<Info Gervill>, :device #<SoftSynthesizer com.sun.media.sound.SoftSynthesizer@ba4af76>} {:name "PEPPERMonaka [hw:1,0,0]", :description "PEPPER-Monaka, USB MIDI, PEPPER-Monaka", :vendor "ALSA (http://www.alsa-project.org)", :version "3.7.10-1.1-desktop", :sources -1, :sinks 0, :info #<MidiInDeviceInfo PEPPERMonaka [hw:1,0,0]>, :device #<MidiInDevice com.sun.media.sound.MidiInDevice@8b14a51>} {:name "PEPPERMonaka [hw:1,0,0]", :description "PEPPER-Monaka, USB MIDI, PEPPER-Monaka", :vendor "ALSA (http://www.alsa-project.org)", :version "3.7.10-1.1-desktop", :sources 0, :sinks -1, :info #<MidiOutDeviceInfo PEPPERMonaka [hw:1,0,0]>, :device #<MidiOutDevice com.sun.media.sound.MidiOutDevice@758fd559>} {:name "Real Time Sequencer", :description "Software sequencer", :vendor "Oracle Corporation", :version "Version 1.0", :sources -1, :sinks -1, :info #<RealTimeSequencerInfo Real Time Sequencer>, :device #<RealTimeSequencer com.sun.media.sound.RealTimeSequencer@13b5ab7>})
```

ちゃんとMIDIデバイス一覧が取得できました．

この中で使うデバイスは `PEPPERMonaka` なので，これの`device` を取り出してみます．
2つ目の要素のキー`device`を取ってくればいいのでこんな感じでしょうか．

```clj
(def devMonaka (:device (nth (midi-devices) 2)))
```

`midi-clj/src/midi.clj` の117行目でデバイスのオープンをしているので，先ほどのデバイスをオープンします．
`isOpen`とか，とりあえず無視しておきます．

```clj
(.open devMonaka)
```

あと，`.getReceiver` の結果は使いそうなので取っときます．

```clj
(def recvMonaka (.getReceiver devMonaka))
```

一応，`recvMonaka`を確認しておきます．

```clj
#<MidiOutReceiver com.sun.media.sound.MidiOutDevice$MidiOutReceiver@23c855d>
```

レシーバが取れてるみたいなので大丈夫でしょう．

`midi-clj/src/midi.clj` の211行目付近からノートのON，OFF制御が書かれているので，参考にします．
環境構築で説明しましたが，今回のデバイスは出力ポート2番が60番の音に対応していていますので，それを鳴らします．
あとは，LEDの点灯，消灯用に2つメッセージを作っておきます．

```clj
(def on-msg (ShortMessage.))
(.setMessage on-msg ShortMessage/NOTE_ON 0 60 100)
(def off-msg (ShortMessage.))
(.setMessage off-msg ShortMessage/NOTE_OFF 0 60 0)
```

準備は終わったので，レシーバに対してメッセージを投げてみます．

```clj
(.send recvMonaka on-msg -1)
```

ちゃんと赤いLEDが点灯しているのが確認できました．
（脇の青いLEDはパイロットランプです．こっちの方が明るい）
![LED点灯](https://qiita-image-store.s3.amazonaws.com/0/29299/6869bf3a-a34b-3a4e-239b-cd0477d319e5.png)

ついでに，消灯も試してみます．

```clj
(.send recvMonaka off-msg -1)
```

無事，LEDチカチカができました．

## まとめ

LED光りました！
と言っても，何かClojureぽいコード？を書いてない気がするし，javax.sound.midiを触ってただけのような気もしますが，Clojureよく分からなくても簡単なコードであれば，必要な部分だけ取ってきてやりたいことができたので，本とかで１から文法を学ぶ前に，とりあえず何か作ってみてClojureってこんなこと簡単にできるんだ！と興味を持ってから勉強スタートするのもありかなーと思いました．
ということで，皆さんおすすめの参考書とかサイトとか教えてください．