overtoneを使ってドミソを鳴らす

<!---


--->

MML(Music Macro Language)を触って見たいなとおもっていたところovertoneを見つけました。clojureでプログラミングすることで音を鳴らせるようだ。気になったのでインストールしてドミソを鳴らすまでやります。

## overtoneとは


## 実行環境

- macOS Sierra 10.12.1（16B2657）
- REPL-y 0.3.7, nREPL 0.2.7
- Clojure 1.7.0
- Leiningen 2.5.2 on Java 1.8.0_45 Java HotSpot(TM) 64-Bit Server VM


## プロジェクトの作成

leinコマンドでプロジェクトを作成します。今回はtutorialという名前にします。

```
$ lein new tutorial
Generating a project called tutorial based on the 'default' template.
The default template is intended for library projects, not applications.
To see other templates (app, plugin, etc), try `lein help new`.

```

プロジェクトが作成されるとtutorialディレクトリができているので、そこに移動します。

```
$ cd tutorial

```

## overtoneのインストール

overtoneをインストールできるようにproject.cljを書き換えます。

```clojure:project.clj
(defproject tutorial "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [
                 [org.clojure/clojure "1.7.0"]
                 [overtone "0.10.1"]
                 ])

```

変更箇所はここです。`[overtone "0.10.1"]` を追加しました。

```:差分
$ git diff project.clj
diff --git a/overtone/tutorial/project.clj b/overtone/tutorial/project.clj
index 5ae6fc4..75c418d 100644
--- a/overtone/tutorial/project.clj
+++ b/overtone/tutorial/project.clj
@@ -3,4 +3,7 @@
   :url "http://example.com/FIXME"
   :license {:name "Eclipse Public License"
             :url "http://www.eclipse.org/legal/epl-v10.html"}
-  :dependencies [[org.clojure/clojure "1.7.0"]])
+  :dependencies [
+                 [org.clojure/clojure "1.7.0"]
+                 [overtone "0.10.1"]
+                 ])
```

依存パッケージをインストールします。

```
$ lein deps
Retrieving overtone/overtone/0.10.1/overtone-0.10.1.pom from clojars
Retrieving org/clojure/clojure/1.5.1/clojure-1.5.1.pom from central
Retrieving org/clojure/data.json/0.2.3/data.json-0.2.3.pom from central
Retrieving clj-native/clj-native/0.9.3/clj-native-0.9.3.pom from clojars
Retrieving net/java/dev/jna/jna/3.4.0/jna-3.4.0.pom from central
Retrieving overtone/at-at/1.2.0/at-at-1.2.0.pom from clojars
Retrieving org/clojure/clojure/1.3.0/clojure-1.3.0.pom from central
Retrieving overtone/osc-clj/0.9.0/osc-clj-0.9.0.pom from clojars
Retrieving javax/jmdns/jmdns/3.4.1/jmdns-3.4.1.pom from central
Retrieving commons-net/commons-net/3.0.1/commons-net-3.0.1.pom from central
Retrieving org/apache/commons/commons-parent/21/commons-parent-21.pom from central
Retrieving org/apache/apache/9/apache-9.pom from central
Retrieving overtone/at-at/1.1.1/at-at-1.1.1.pom from clojars
Retrieving overtone/byte-spec/0.3.1/byte-spec-0.3.1.pom from clojars
Retrieving overtone/midi-clj/0.5.0/midi-clj-0.5.0.pom from clojars
Retrieving overtone/at-at/1.0.0/at-at-1.0.0.pom from clojars
Retrieving overtone/libs.handlers/0.2.0/libs.handlers-0.2.0.pom from clojars
Retrieving overtone/scsynth/3.5.7.0/scsynth-3.5.7.0.pom from clojars
Retrieving overtone/scsynth-extras/3.5.7.0/scsynth-extras-3.5.7.0.pom from clojars
Retrieving clj-glob/clj-glob/1.0.0/clj-glob-1.0.0.pom from clojars
Retrieving net/java/dev/jna/jna/3.4.0/jna-3.4.0.jar from central
Retrieving org/clojure/data.json/0.2.3/data.json-0.2.3.jar from central
Retrieving javax/jmdns/jmdns/3.4.1/jmdns-3.4.1.jar from central
Retrieving commons-net/commons-net/3.0.1/commons-net-3.0.1.jar from central
Retrieving clj-native/clj-native/0.9.3/clj-native-0.9.3.jar from clojars
Retrieving overtone/at-at/1.2.0/at-at-1.2.0.jar from clojars
Retrieving overtone/byte-spec/0.3.1/byte-spec-0.3.1.jar from clojars
Retrieving overtone/overtone/0.10.1/overtone-0.10.1.jar from clojars
Retrieving overtone/midi-clj/0.5.0/midi-clj-0.5.0.jar from clojars
Retrieving overtone/osc-clj/0.9.0/osc-clj-0.9.0.jar from clojars
Retrieving overtone/libs.handlers/0.2.0/libs.handlers-0.2.0.jar from clojars
Retrieving overtone/scsynth-extras/3.5.7.0/scsynth-extras-3.5.7.0.jar from clojars
Retrieving clj-glob/clj-glob/1.0.0/clj-glob-1.0.0.jar from clojars
Retrieving overtone/scsynth/3.5.7.0/scsynth-3.5.7.0.jar from clojars
$
```

## RELPモードの起動

ちょっとした処理を試行錯誤する場合はREPLモードを使うと便利です。leinコマンドでpeplモードを起動します。

```
$ lein repl
nREPL server started on port 59082 on host 127.0.0.1 - nrepl://127.0.0.1:59082
REPL-y 0.3.7, nREPL 0.2.7
Clojure 1.7.0
Java HotSpot(TM) 64-Bit Server VM 1.8.0_45-b14
    Docs: (doc function-name-here)
          (find-doc "part-of-name-here")
  Source: (source function-name-here)
 Javadoc: (javadoc java-object-or-class-here)
    Exit: Control+D or (exit) or (quit)
 Results: Stored in vars *1, *2, *3, an exception in *e
```

ちょっとだけ試しに足し算します。

```
user=> (+ 1 3)
4
```

良さそうですね。

## overtoneのuse

overtoneを使うのでuseします。

```
user=> (use 'overtone.live)
--> Loading Overtone...
--> Booting internal SuperCollider server...
Found 0 LADSPA plugins
*** ERROR: open directory failed '/Users/sximada/Library/Application Support/SuperCollider/synthdefs'
Number of Devices: 2
   0 : "Built-in Microph"
   1 : "Built-in Output"

"Built-in Microph" Input Device
   Streams: 1
      0  channels 2

"Built-in Output" Output Device
   Streams: 1
      0  channels 2

SC_AudioDriver: sample rate = 44100.000000, driver's block size = 512
--> Connecting to internal SuperCollider server...
--> Connection established

    _____                 __
   / __  /_  _____  _____/ /_____  ____  ___
  / / / / | / / _ \/ ___/ __/ __ \/ __ \/ _  / /_/ /| |/ /  __/ /  / /_/ /_/ / / / /  __/
 \____/ |___/\___/_/   \__/\____/_/ /_/\___/

   Collaborative Programmable Music. v0.10.1


Cometh the hour, cometh Sximada, the overtone hacker.

nil
user=>
```

useできました。

```
user=> (use 'overtone.core)

IllegalStateException ->ShellStringList already refers to: #'overtone.live/->ShellStringList in namespace: user  clojure.lang.Namespace.warnOrFailOnReplace (Namespace.java:88)

```

こちらは失敗してしまいます(なんでだ?)。

## 鳴らす

実際に音を鳴らします。

```
user=> (definst foo [] (saw 220))
#<instrument: foo>
user=> (odoc saw)
-------------------------
overtone.live/saw
([freq])

  band limited sawtooth wave generator

  [freq 440.0]

  freq - Frequency in Hertz (control rate).

  The sawtooth wave produces even and odd harmonics in
  series and therefore produces a bright sound that is an
  excellent starting point for brassy, raspy sounds. It's
  also suitable for creating the gritty, bright sounds
  needed for leads and raspy basses. Due to its harmonic
  richness it's extremely suitable for use with sounds that
  will be filter swept.

  Categories: Generators -> Deterministic
  Rates: [ :ar ]
  Default rate: :ar

nil
user=> (definst bar [freq 220] (saw freq))
#<instrument: bar>
user=> (bar 110)
#<synth-node[loading]: user/bar 41>
```

鳴りましたか？成功したら鳴り続けているはずです。

## 止める

鳴り続けているとうるさいので止めます。

```
user=> (kill bar)
nil
```

## 同時に音を鳴らす

複数の音を同時に鳴らします。

```
user=> (bar 123)
#<synth-node[loading]: user/bar 42>
user=> (bar 124)
#<synth-node[loading]: user/bar 43>
user=> (bar 125)
#<synth-node[loading]: user/bar 44>
```

停止の場合は一括で停止します。

```
user=> (kill bar)
nil
user=>
```

## ドミソ

ド/ミ/ソを同時に鳴らして和音にしてみます。

```
user=> (bar 261.626)
#<synth-node[loading]: user/bar 66>
user=> (bar 329.628)
#<synth-node[loading]: user/bar 67>
user=> (bar 391.995)
#<synth-node[loading]: user/bar 68>
user=>
```

停止は先ほどと同様 `(kill bar)` です。

```
user=> (kill bar)
nil
user=>
```