Bozeで始めるSonicPi

この記事は[Boze Advent Calendar](
https://qiita.com/advent-calendar/2020/boze2020)21日目に登録されています。

初めまして。Niko_14といいます。
普段はSonicPiで音を書いている様子をTwitterに投稿したり、
ライブコーディングしている様子を配信していたりします。

この記事では、自分が配信などでよく使用しているSonicPiの簡単な始め方に関して、このアドカレの主催である三日坊主さんに絡めて解説していきたいと思います。

#1.インストール
　まずはSonicPiをインストールしましょう。以下の公式サイトのURLから使用しているOSに対応したインストーラーをダウンロードして実行してください。

　公式サイト：https://sonic-pi.net/

　インストールが完了したらSonicPiを起動してください。ロゴがしばらく表示された後に、エディタが立ち上がるはずです。
　万が一起動時に重大なエラーが～というダイアログが表示された場合は、一度ダイアログを閉じた後にもう一度SonicPiを起動してください。誤って多重起動してしまったなどの問題で起動に失敗するときがたまにあります。

#音を同期させる
　SonicPi上で演奏を行う場合、複数のループをいくつも作成してそれぞれで音を抜き差ししていく、という構成が非常に多いです。
　この構成上、複数のループを同期させる必要があるわけですが、普通に以下のような書き方をしただけでは同期はできません。

```title:ruby
live_loop :kick do
  tick
  sample :drum_heavy_kick if(spread,1,4).look
  sleep 0.25
end

live_loop :bass do
  tick
  synth :tb303,release:0,decay:2.75,note: :c2,cutoff:rrand(60,70)
  sleep 4
end
```
　上記コードを書く際に、一度Ctrl+sで演奏を止めてから再度演奏する場合には開始タイミングが同一になるのですが、例えば下の:bassを先に実行し、音が切れる前に上の:kickを書き加えて実行すると、なんだかタイミングがずれることがわかるかと思います。
　このズレを回避するために、自分などがよく使用する同期方法のコードが以下になります。

```title:ruby
live_loop :metro do
  sleep 4
end

live_loop :kick,sync: :metro do
  tick
  sample :drum_heavy_kick if(spread,1,4).look
  sleep 0.25
end

live_loop :bass,sync: :metro do
  tick
  synth :tb303,release:0,decay:2.75,note: :c2,cutoff:rrand(60,70)
  sleep 4
end
```
　この書き方をすることによって、:bassも:kickも:metroが実行されると同時に実行されるようになり、リズムが常に同期するようになります。

　では、上記の書き方である程度同期ができるようになったところで、坊主さん要素を追加していきたいと思います。
#hannya.wav
　2019年末から2020年頭にかけて、三日坊主さんがある音源を配布しています。それがこのhannya.wavです。これは、三日坊主さんが実際に般若心経を唱えているものが録音された音源となります。今回、坊主さんに再配布の許可をいただきましたため、この場にて配布させていただきたいと思います。
　[hannya.wav](https://drive.google.com/file/d/1sRlXNq06GwKZyS5TTSXZvJyVYG0x5nQC/view?usp=sharing)
　この音源を元に、色々と加工してみましょう。
　まず、この音源はSonicPi上でどのぐらいの長さの音源になるのか計測します。SonicPiには、内蔵の機能として以下のように書くと指定したサンプルの長さを取得することができます。

```title:ruby
live_loop :tes do
  long = sample_duration :loop_amen
  sample :loop_amen
  sleep long
end
```
　上記のようなコードを書いて、お手元のSonicPiで再生してみてください。おそらく、sampleが1周流れ終わった瞬間に次のsampleが流れ始めると思います。これは、sample_durationで取得したサンプルの長さをlong変数に代入し、これをsleepで使用することでサンプルが流れ終わるまでの時間と次のループが起動するまでの時間を統一しているためです。
　このような形で、サンプルの長さを使うことで自然に次のループにつなげることができます。
　では、これをhannya.wavでもやってみましょう。
　（なお、外部サンプルの追加方法に関しては自分が以前出しました[こちらの資料](https://niko14.booth.pm/items/1834278)内で解説しておりますので、割愛させていただきます。）

```title:ruby
live_loop :hannya do
  long = sample_duration hannya
  sample hannya
  sleep long
end
```
　上記コードで演奏すると、坊主さんの般若心境が流れていきます。
　ただ、このまま演奏しても4つ打ちなどを入れた場合に中途半端な位置でループが終わって次に行ってしまいます。
　これを解消するために、以下のようにコードを改変してみましょう。

```title:ruby
live_loop :hannya do
  sample hannya,beat_streach:256
  sleep 256
end
```
　これで、4/4拍子として256拍=64小節で1ループが回るようになります。beat_streachを使用する場合、サンプルの再生時間に手を加える結果音が変わってしまうのですが、元のhannya.wavの長さが約213であるため、多少低くなる程度で十分実用に耐えるレベルです。
　次に、せっかくなのでこの上にさらに般若心境をかぶせてみましょう。ただし、そのまま同じものをかぶせてもつまらないので、手を入れてみることにします。

```title:ruby
live_loop :metro do
  sleep 4
end

live_loop :hannya,sync: :metro do
  sample hannya,beat_streach:256
  sleep 256
end

live_loop :hannyabreak,sync: :metro do
  tick
  sample hannya,onset:pick
  sleep 1
end
```
　一番下の:hannyabreakが今回追加したループになります。ここで、新しくonsetというオプションを使用しています。これは、サンプル内で音量差の大きい部分を分割し、数値を指定することで分割したうちの特定の個所を鳴らすことができるオプションです。ここで、pick(ランダムで配列の要素を指定する）を使用することで分割したサンプルがランダムで鳴るようにしています。
　このオプションを追加したことで、低音の般若心境が延々流れる中に、通常の音程の般若心境のランダムな部分がかぶっていくような構成を作ることができました。
　では、ここにキックなどの要素をさらに継ぎ足していきましょう。このあたりに関しても、自分が以前出しました資料内に書き方の解説などを書いてありますので、参考にしてみてください。

#演奏例

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/sonicpi?src=hash&amp;ref_src=twsrc%5Etfw">#sonicpi</a> 例の記事用も兼ねて <a href="https://t.co/fFytg9qHxs">pic.twitter.com/fFytg9qHxs</a></p>&mdash; Niko_14 (@himazin917) <a href="https://twitter.com/himazin917/status/1340654350620758016?ref_src=twsrc%5Etfw">December 20, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>