以下のまとめの続きです。
●Sonic Pi での音をシンプルに鳴らす方法の情報メモ(自分用まとめ その1) - Qiita
 https://qiita.com/youtoy/items/f82d2c350bc60a4e5816
ファイルを利用して音を鳴らす
PC内の wavファイルを利用することもできるようです。
以下、公式から抜粋したファイルの指定方法です。
# Raspberry Pi, Mac, Linux
sample "/Users/sam/Desktop/my-sound.wav"
# Windows
sample "C:/Users/sam/Desktop/my-sound.wav" 
また、上記のファイル利用の場合にも、オプションの指定が以下のようにできたりするようです。
# Raspberry Pi, Mac, Linux
sample "/Users/sam/Desktop/my-sound.wav", rate: 0.5, amp: 0.3
# Windows
sample "C:/Users/sam/Desktop/my-sound.wav", rate: 0.5, amp: 0.3 
乱数を使う
乱数を使う方法についてです。
以下は、50 から 95 の間でランダムな数値が得られますが、毎回同じ数値が選ばれます。
乱数を使った音の再現性を考慮して、毎回同じ乱数列が生成されるようです(以下は、その乱数列の 1つ目を毎回取得)。
play rrand(50, 95) 
以下のように、ループの中で何度も呼び出すと、乱数列の中から 1つずつ取得されるため、全て同じ音とはならない形です。
ただし、音を止めて再び再生した場合は、同じ音の組み合わせが選ばれていく形です。
loop do
  play rrand(50, 95)
  sleep 0.5
end  
生成される乱数列を変更するには、シードの値としていろいろと異なる値を指定してやれば OK です。
例えば以下の例では、 use_random_seed の後の 40 という値を、別の値に変更してやる形です。
use_random_seed 40
3.times do
  play rrand(50, 100)
  sleep 0.5
end 
なお、上記の rrand(50, 100) は 50 と 100 を含まない、その間の浮動小数点数の値が得られるようです。
これを整数にしたい場合は、以下のような指定をすれば良いようです。なお rrand_i(20, 110) の場合は、20 と 110 を含んだ整数が得られるようです。
rrand_i(20, 110)
その他に ``randやrand_i` などもあるようです。
# 0以上、10未満の浮動小数点数
rand(10)
# 0以上、1未満の浮動小数点数
rand
# 0以上、10未満の整数
rand_i(10)
乱数のさらなる活用
上記の乱数を活用した例を、以下に記載します。
以下は、ベルの音にオプションで指定した rate の部分と、sleep で指定する時間の部分で乱数が使われています。
loop do
  sample :perc_bell, rate: (rrand 0.125, 1.5)
  sleep rrand(0.2, 2)
end 
また、以下のような活用事例も掲載されていました。
use_synth :tb303
loop do
  play 50, release: 0.1, cutoff: rrand(60, 120)
  sleep 0.125
end
以下の聞き比べてみると、 cutoff: rrand(60, 120) の部分との違いが良く分かります。
use_synth :tb303
loop do
  play 50, release: 0.1
  sleep 0.125
end
cutoff
ここで突如登場した cutoff については、以下のブログ記事などをご参照ください。
●[音楽をプログラミングしよう] #06 - 音色変化であそぼう | なるーらぼ
 https://nalu-labo.amebaownd.com/posts/638054/
その他のランダムな選択
リスト内からランダムに選ぶ
また、 choose([60, 65, 72])  といった書き方で、あらかじめリストで用意した複数の値の中から、何れかをランダムに選択する、という処理もできるようです。
loop do
  play choose([60, 65, 72])
  sleep 1
end 
こちらも、上記の乱数と同様に use_random_seed 【数値】 を一緒に使うことで、ランダムな選ばれ方の規則が変わるようです。
サイコロ的なもの
1 から 6 までの目のサイコロを振る、というのに相当するものが、以下で実行できるようです。
dice(6)
この数字を変えると、20面のサイコロといったようになり、得られる最大の値を変えることができるようです。
一定確率で true/false を返す
以下のような書き方で、6分1の確率で true、それ以外の場合は false を返す、といった処理もできるようです(if文で非常に有用です、と紹介されています)。
one_in(6)
繰り返しや条件文
繰り返し
以下は 特定の処理の集まりを 3回繰り返す例です。
3.times do
  play 50
  sleep 0.5
  sample :elec_blup
  sleep 0.5
  play 62
  sleep 0.25
end 
if文
上で出てきた one_in を使った条件分岐の例です。
loop do
  if one_in(2)
    sample :drum_heavy_kick
    sleep 0.5
  else
    sample :drum_cymbal_closed
    sleep 0.25
  end
  
end 
また、以下のような if文の書き方もあるようです。
以下は、最大で 4つの音が同時に鳴りますが、そのうち 3つはそれぞれ異なる確率で鳴るか鳴らないかが決まる、という動作をするようです。
use_synth :dsaw
loop do
  play 50, amp: 0.3, release: 2
  play 53, amp: 0.3, release: 2 if one_in(2)
  play 57, amp: 0.3, release: 2 if one_in(3)
  play 60, amp: 0.3, release: 2 if one_in(4)
  sleep 1.5
end
ループの同時実行(スレッド)
ループ処理の固まりを 2つ作成し、それらを同時並行で処理させる場合はスレッドを使うというやり方になるようです。
以下が、2つのループを同時並行で処理させる例です。
in_thread do
  loop do
    sample :drum_heavy_kick
    sleep 1
  end
end
loop do
  use_synth :fm
  play 40, release: 0.2
  sleep 0.5
end 
以下のようにすれば、3つ同時というのもできるようです。
in_thread do
  loop do
    sample :drum_heavy_kick
    sleep 1
  end
end
in_thread do
  loop do
    use_synth :fm
    play 40, release: 0.2
    sleep 0.5
  end
end
loop do
  use_synth :zawa
  play 52, release: 2.5, phase: 2, amp: 0.5
  sleep 2
end 
スレッドの同期
2つのスレッドの同期、ということもできるようです。
以下の例では、 cue :tick と sync :tick があることで、1つ目のスレッドの処理(音は鳴らさず、メトロノームのような機能として 1秒ごとに :tick というビートメッセージを送信)が、2つ目の処理タイミングを決めるような動作をしています。
in_thread do
  loop do
    cue :tick
    sleep 1
  end
end
in_thread do
  loop do
    sync :tick
    sample :drum_heavy_kick
  end
end 
データ構造
リング
配列を以下のようにリングという形にすることができるようです。
# リングの作成1
(ring 52, 55, 59) 
# リングの作成2: 通常のリストから作成
[52, 55, 59].ring 
具体的には、以下のように扱える形になるようです。
(ring 52, 55, 59)[0] #=> 52
(ring 52, 55, 59)[1] #=> 55
(ring 52, 55, 59)[2] #=> 59
(ring 52, 55, 59)[3] #=> 52
(ring 52, 55, 59)[-1] #=> 59
リングの活用
以下のように、リングを反転させたり、一部のみを取り出したり等もできるようです。
次のような単純なリングを作成します。
(ring 10, 20, 30, 40, 50)
リングを逆にしたいときにはどうしたらよいでしょう? リングを反転させるには、チェインコマンドの.reverseを使います。
(ring 10, 20, 30, 40, 50).reverse #=> (ring 50, 40, 30, 20, 10)
では次に、リングから最初の3つの値を取得するにはどうしたらよいでしょう?
(ring 10, 20, 30, 40, 50).take(3) #=> (ring 10, 20, 30)
最後に、リングをシャッフルするにはどうしたらよいでしょう?
(ring 10, 20, 30, 40, 50).shuffle #=> (ring 40, 30, 10, 50, 20)
おわりに
今回、まとめ1 に続き記事を作りました。
そして、Sonic Pi の機能をまだまとめきれてなく、その3 の記事とか特定の機能を扱う別記事が何らかできそうな予感がします。
