このシリーズでは先月、Sonic Piを支えるランダム化のシステムについて技術的に詳しく見ました。そして、コードを動的に制御する新しい基準を、どのように決定論的に追加できるか探索しました。今月は、引続きSonic Piのユニークなチック(tick)システムに焦点を当て、技術的に詳しく見てみたいと思います。この記事の終わりまでに、あなた自身のやり方で、ライブコーディングDJに必要なリズムやリフのチックができるようになるでしょう。
音楽を作るときに、何ビート目であるかによって何か異なることをしたいことがよくあるでしょう。Sonic Piには、tick
と呼ばれるビートをカウントする特別なシステムがあって、ビートが実際にいつ起こるかを正確に制御でき、またそれぞれ独自のテンポを持った複数のビートにも対応しています。
早速遊んでみましょう。ビートを進めるのに必要なことは、単にtick
を呼ぶだけです。新しいBufferを開いて、次のコードを入力してRun
を叩いてみてください:
puts tick #=> 0
これは現在のビートの0
を返すでしょう。Run
ボタンを数回押しているにも関わらず、これが常に0
を返すことに注意してください。これは、それぞれの実行で新しいビートのカウントが0から開始するためです。しかし、実行がアクティブのままであれば、ビートを好きなだけ進めることができます:
puts tick #=> 0
puts tick #=> 1
puts tick #=> 2
コードの行の末尾に#=>
シンボルがあるときは、そのコードが右側のテキストをログ出力することを意味しています。例えば、puts foo #=> 0
はputs foo
がプログラムのその場所で0
をログ出力することを意味します。
ここまでで、tick
が2つのことをしているのを見てきました。それは、ビートを増やし(1を加算し)、ビートの値を返しています。場合によっては、ビートを増やさずにただ値を見たいことがあるかもしれませんが、それはlook
で実現できます:
puts tick #=> 0
puts tick #=> 1
puts look #=> 1
puts look #=> 1
このコードではtick
でビートを2回増加させ、その後look
を2回呼んでいます。実行すると、ログに0
, 1
, 1
, 1
の値が表示されるでしょう。最初の2つのtick
で0
と1
を返し、次の2つのlook
はビートの最新の値である1
を単純に返しています。
tick
でビートを進め、look
でビートを確認できるようになりました。次は何でしょう? tick
で何かを進める必要がありそうですね。Sonic Piはリフやメロディーやリズムを表すのにリングを使っていて、tick
システムはこれと密接に連携するよう設計されています。実際に、リングは.
の付いたtick
の独自のバージョンを持っていて、それは2つのことをします。最初に、それは通常のtick
と同じようにビートを増加させます。次に、ビートをインデックスとして使用して、リングの値にアクセスします。次を見てみましょう:
puts (ring :a, :b, :c).tick #=> :a
.tick
はtick
の.
付きの特別なバージョンで、これはリングの最初の値である:a
を返します。次のように、.tick
を複数回呼ぶことで、リングの値をそれぞれ掴むことができます:
puts (ring :a, :b, :c).tick #=> :a
puts (ring :a, :b, :c).tick #=> :b
puts (ring :a, :b, :c).tick #=> :c
puts (ring :a, :b, :c).tick #=> :a
puts look #=> 3
ログを見ると、:a
, :b
, :c
が表示され、その後再び:a
が表示されているでしょう。look
が3
を返しているのに注目してください。.tick
の呼び出しは、tick
の通常の呼び出しとちょうど似た振る舞いをしていますが、それは独自のビートを増加させているのです。
‘tick’は、リングとlive_loop
と組み合わせることによって、本当の力が発揮されます。それらを組み合せると、シンプルなアルペジエーターを構築して理解するために必要な全ての道具を手に入れたことになります。必要なものは、次の4つです:
これらの概念のすべてを、次のコードで見つけることができます:
notes = (ring 57, 62, 55, 59, 64)
live_loop :arp do
use_synth :dpulse
play notes.tick, release: 0.2
sleep 0.125
end
各行を順に見ていきましょう。最初に、繰り返し演奏される音符のリングを定義しています。次に、:arp
と名付けられたlive_loop
を作ってループさせています。live_loop
を繰り返す度に、シンセを:dpulse
に設定し、.tick
と使ってリング内の次の音符を演奏しています。これにより、ビートのカウンタを増加させ、最新のビートの値を音符のリングのインデックスとして使っている点に注意してください。最後に、1/8拍待ってループしています。
本当に知っておいて欲しい大切なことは、tick
はlive_loop
でローカルなことです。これは、それぞれのlive_loop
がそれ自身の独立したビートのカウンタを持っていることを意味します。これは、グローバルなメトロノームとビートよりもはるかに強力です。実際に動いているところを見てみましょう:
notes = (ring 57, 62, 55, 59, 64)
with_fx :reverb do
live_loop :arp do
use_synth :dpulse
play notes.tick + 12, release: 0.1
sleep 0.125
end
end
live_loop :arp2 do
use_synth :dsaw
play notes.tick - 12, release: 0.2
sleep 0.75
end
Sonic Piのtick
システムに関する混乱の大きな原因は、live_loop
に複数のリングでtick
をしようとする際に生じるものです:
use_bpm 300
use_synth :blade
live_loop :foo do
play (ring :e1, :e2, :e3).tick
play (scale :e3, :minor_pentatonic).tick
sleep 1
end
live_loop
には独自のビートのカウンタがありますが、ここでは同じlive_loop
内で.tick
を2回呼び出しています。これは、ループする毎にビートが2回増加されることを意味しています。これは何か面白いポリリズムを生み出すことができるかもしれませんが、多くの場合あなたが望むものではないでしょう。この問題には2つの解決策があります。1つめは、live_loop
の開始時に手動でtick
を呼び出し、.look
を使って各live_loop
の現在のビートを確認することです。2つめは、.tick(:foo)
のように、.tick
の呼び出しにユニークな名前を渡すことです。Sonic Piは、名前付きチック毎に別々のビートのカウンタを作成し、追跡します。そうすれば、必要なだけ多くのビートで作業できます! 詳細については、チュートリアルの9.4の名前付きチックに関するセクションを参照してください。
tick
, ring
, live_loop
の知識を使って、最後に楽しい例を紹介しましょう。いつものように、これを完成された曲として扱わないようにしてください。これで遊びながら色々と変更して、どこまで変えることができるか見てみてください。ではまた次回お会いしましょう…
use_bpm 240
notes = (scale :e3, :minor_pentatonic).shuffle
live_loop :foo do
use_synth :blade
with_fx :reverb, reps: 8, room: 1 do
tick
co = (line 70, 130, steps: 32).tick(:cutoff)
play (octs :e3, 3).look, cutoff: co, amp: 2
play notes.look, amp: 4
sleep 1
end
end
live_loop :bar do
tick
sample :bd_ada if (spread 1, 4).look
use_synth :tb303
co = (line 70, 130, steps: 16).look
r = (line 0.1, 0.5, steps: 64).mirror.look
play notes.look, release: r, cutoff: co
sleep 0.5
end