Sonic PiにSuperColliderで作ったエフェクトを追加してみる

# はじめに
現在、大学の授業でSonic Piを学んでいます。
その授業中に自作Synthの作り方を教わりましたが、エフェクトは同じように追加することはできませんでした。
先生に尋ねたところ、「自作エフェクトの追加はやったことがない」という返答をいただきました。
そこで、頑張って成し遂げた自作エフェクト追加の方法を以下に書き連ねようと思います。
[参考にしたgist](https://gist.github.com/xavriley/0907002649d6b6b2ac2bcbe739d96761)とほぼほぼ同じ内容になりますが、ご了承ください。

# 前提
自作Synthの作り方は理解していることを前提とします。
まだ試したことのない方は、[「Sonic Piで、自作Synthをつくる - Qiita」](https://qiita.com/yoppa/items/829d25addf499824d2f9)の記事などを参考にしてください。
とてもわかりやすく書かれているので、是非自分の手で改造することを推奨します。

## 環境
- Windows 10 Pro
- Sonic Pi 3.1.0
- SuperCollider 3.10.0


# SuperCollider でエフェクトを作る

今回は、ボコーダーのエフェクトを作ります。
`with_fx` 時にノート番号を指定したら、 `do` と `end` の内側の音がノート番号の音に変換されて聞こえるようにします。
ついでなので `attack` と `release` と `amp` も引数に入れて、良い感じに変換していただくようなエフェクトにしました。

まずはデスクトップに`my-synths`フォルダを作り、SuperColliderで作ったscsyndefファイルを保存しましょう。
ここまでは自作Synthの作り方と同じです。

ここで重要な点が二つあります。

一つは、引数には `out_bus = 0` と `in_bus = 0` を必ず入れるようにしてください。
流れとしては、

1. `In.ar(in_bus, 1)` で入力を受け取る
- エフェクトをかけてから変数 `mix` に代入する
- `Out.ar(out_bus,mix)` に渡す

という感じになります。

もう一つは、ファイル名です。
初めからSonic Piに保存されているエフェクトのファイル名に合わせたいと思います。
Sonic Piで `myVocoder` という名前のエフェクトにしたい場合は、
SuperColliderのSynthDefには `sonic-pi-fx_myVocoder` という名前で登録しておきましょう。
（もしかしたら他のファイル名でも上手くいくかもしれませんが、こうしておいた方が無難かなと思います。

以下はソースコードです。
実行すると `sonic-pi-fx_myVocoder.scsyndef` というファイルがデスクトップの `my-synths` ディレクトリに保存されていると思います。

```clojure
(
SynthDef("sonic-pi-fx_myVocoder",{
	arg out_bus = 0, in_bus = 0, note = 60, amp = 1.0, attack = 0.01, release = 1.0;
	var source = In.ar(in_bus, 1);
	var career = LFSaw.ar(note.midicps, 0, 0.2);
	var fft1 = FFT(LocalBuf(1024, 1), career, wintype: 1);
    var fft2 = FFT(LocalBuf(1024, 1), source, wintype: 1);
	var chain = PV_MagMul(fft1, fft2);
	var mix = IFFT(chain);
	var env = EnvGen.ar(Env.perc(attack, release, amp), doneAction: 2);
	mix = mix * env;
    Out.ar(out_bus,mix);
}).writeDefFile("C:\\Users\\{myname}\\Desktop\\my-synths");
)
```



# Sonic Pi にエフェクトの詳細を設定する

ここからはSonic Piの内部のコードを編集することになります。
Sonic Pi自体が壊れる可能性もなきにしもあらずかと思われますので、十分注意してください。

Sonic PiのSynthとFxを管理しているファイルを編集していきます。
まずは `C:\Program Files (x86)\Sonic Pi\app\server\ruby\lib\sonicpi\synths` にある `synthinfo.rb` ファイルを、デスクトップなどの任意の場所にコピーしてください。
いざというときに元に戻せるように、このファイルをもう一つ別名で保存しておくことをオススメします。

編集する箇所は二つです。

まずは、自らのエフェクトのクラスを作りましょう。
他の `FXhogehoge` みたいなクラスの間くらい（大体4900行目とかその辺）に書き加えると良いと思います。
僕はRubyを書いたり読んだりした経験が皆無なので、詳しくは分かりません。

以下のソースコードを元に、必要な部分を変更してください。
クラス名はなんでも良いです。
`name` と `synth_name` は先ほどのscsyndefファイルの名前と対応させてください。
また、エフェクトが `arg` として受け取りたいものは、 `out_bus` と `in_bus` 以外は `arg_defaults` の中に記述しておきましょう。

```ruby
class FXVocoder < FXInfo
  def name
  	"myVocoder"
  end
  
  def introduced
    Version.new(2,10,0)
  end

  def synth_name
    "fx_myVocoder"
  end

  def doc
    ""
  end

  def arg_defaults
    super.merge({
      :note => 60,
      :amp => 1.0,
      :attack => 0.01,
      :release => 1.0
    })
  end
end
```

もう一カ所は、`@@synth_infos` の部分です（7630行目付近です）。
先ほどの `synth_name` とクラス名に対応させて、以下のような行を書き加えてください。

```ruby
:fx_myVocoder => FXVocoder.new,
```

二カ所とも書き加えましたら、 `C:\Program Files (x86)\Sonic Pi\app\server\ruby\lib\sonicpi\synths` にある `synthinfo.rb` を管理者権限で置き換えてください。

また、先ほどデスクトップの `my-synths` ディレクトリに保存していた `sonic-pi-fx_myVocoder.scsyndef` ファイルを、管理者権限で `C:\Program Files (x86)\Sonic Pi\etc\synthdefs\compiled` の中に置いてください。

ここまでで一通り手順は終了です。

# 試す

こんな感じで使ってみましょう。

```ruby
live_loop :live do
  with_fx :myVocoder ,note: choose(chord(:C3,:M7)) do
    sample :misc_crow
  end
  sleep 0.5
end
```
カラスが歌い出したら成功です。
おつかれさまでした！