Sonic Pi(ソニックパイ)へようこそ。これから説明するクレイジーな音作りに、あなたも夢中になることを願っています。音楽、シンセ、プログラミング、作曲、演奏など、これから学ぶことは、本当に刺激的なものになるでしょう。
でも、ちょっと待ってください。まずは自己紹介が必要でしたね。失礼いたしました! 私は、Sonic Piを作成したSam Aaronといいます。Twitter上の@samaaronで見つけることができますので、連絡くれるとうれしいです。もしかすると、僕がSonic Piを使って観客の前で演奏しているライブコーディングのパフォーマンスにも興味を持ってもらえるかもしれません。
Sonic Piを改善するために、気づいたことや、アイデアを持っていたら、是非、知らせてください。フィードバックはとても役立ちます。あなたのアイデアが次の重要な機能になるかもしれません!
最後に、このチュートリアル(使いかた)は、カテゴリ別にグループ化されたセクションに分かれています。始まりから終わりまで、簡単に学べるように手引きを書いたので、自由に、色々なセクションを覗いてみてください。何か、不足している点に気がついたら、将来のバージョンのために検討したいので、知らせてください。
最後に、他の人がライブコーディングするのを見るのはとても良い学習方法です。私は定期的にhttp://youtube.com/samaaronでライブをストリーミングしているので、ぜひ立ち寄って、たくさんの質問をしてみてください :-)
では、早速はじめましょう!
Sonic Piの最もエキサイティングな側面のひとつは、まるでギターをライブで演奏するかのように、ライブでコードを書いて音楽を作ることができることです。つまり、ステージやコンサートでSonic Piが使えるということです!
これからチュートリアルで、実際のSonic Piの詳しい使い方に入る前に、まず、ライブコーディングがどんなものか体験してみましょう。あまり(もしくは全然)わからなくても、心配ご無用! そのまま席についたまま、楽しんでいきましょう。
さぁ、はじめましょう! 下のコードを上の空欄のBuffer(バッファ)にコピーしてみましょう。
live_loop :flibble do
sample :bd_haus, rate: 1
sleep 0.5
end
左上のRun
(再生)ボタンを押すと、いい感じの速さでバスドラムの音が聞こえてきます。Stop
(停止)ボタンを押せば、いつでも音を止めることができます。ですが、まだStop
(停止)ボタンを押さずに、次のステップを実行しましょう。
バスドラムがまだ鳴っていることを確認します。
sleep
の値を、0.5
から、1
のような、より大きい値に書き換えてみましょう。
Run
(再生)ボタンをもう一度押します。
ドラムの速さがどのように変わったかを確認してみましょう。
この瞬間を忘れないでください。これが、あなたが初めてSonic Piでライブコーディングをした瞬間です。そしてこれが最後にはならないはず…
これは簡単でした。では他の要素を加えてみましょう。sample :bd_haus
の上に、sample :ambi_choir, rate: 0.3
を追加してみます。コードはこのようになるはずです。
live_loop :flibble do
sample :ambi_choir, rate: 0.3
sample :bd_haus, rate: 1
sleep 1
end
では、ちょっと遊んでみましょう。値を変えてみてください。大きな値、小さな値、もしくはマイナスの値にしたとき、何が起こるでしょうか? では、:ambi_choir
のrate:
の値をほんの少し(0.29などに)変えた時、どうなるでしょう? sleep
の値をすごく小さくすると、どうでしょう? 速くしすぎると、エラーが出てコンピュータが止まってしまいます。これはコンピュータがついていけないからです(そんな時は、より大きい値をsleep
に設定してRun
ボタンをもう一度押しましょう)。
では、sample
の行に#
をつけることで、「コメント」してみてください。
live_loop :flibble do
sample :ambi_choir, rate: 0.3
# sample :bd_haus, rate: 1
sleep 1
end
コンピュータに#をつけた行を無視するよう命令したので、聞こえませんね。これはコメントと呼ばれます。Sonic Piでは、要素を削除したり追加したりするのにコメントを使います。
最後に、遊んでみると面白いのことをみなさんにお伝えしましょう。下のほうにあるコードを空いたBufferにコピーします。次に、2つのループがある(つまり2つのことが同時進行している)ということ以外は深く考えないようにして、遊びながら実験してみましょう。その際、以下のようなヒントがあります:
rate:
の青い値を変更し、sample
の音が変わることを聞いてみましょう。
sleep
の時間を変更し、それぞれのループを異なる速度で繰り返すのを聞いてみましょう。
sample
の行のコメントを解除して(#
を削除)、ギターの逆再生を楽しみましょう。
いくつかのmix:
の値を0
(最小値)から1
(最大値)の間で変えてみましょう。
Run
ボタンを押すのを忘れないでください。次のループで音が変化するのを聞くことができるでしょう。うまくいかなくても気にしないでください。Stop
ボタンを押して、Buffer内のコードを削除して、新しいコードをコピー&ペーストして、再び演奏の準備をすれば良いです。失敗することがどんなことよりも学習の近道になるのですから。
live_loop :guit do
with_fx :echo, mix: 0.3, phase: 0.25 do
sample :guit_em9, rate: 0.5
end
# sample :guit_em9, rate: -0.5
sleep 8
end
live_loop :boom do
with_fx :reverb, room: 1 do
sample :bd_boom, amp: 10, rate: 1
end
sleep 8
end
さあ、これらが実際にどう動くか好奇心が動き出すまで、そしてあなたが次に何をしたらいいかを知りたくなるまで、演奏と実験を続けましょう。さあ、残りのチュートリアルを読む準備ができました。
次にあなたを待っているものは…
Sonic Piは、音楽をコーディング(記述)するためのとてもシンプルなインタフェース(操作画面)を持っています。ちょっと見てみましょう。
A - 演奏の操作 B - 編集の操作 C - 情報とヘルプ D - コードエディタ E - 設定画面 F - ログビューア G - ヘルプシステム H - スコープビューア I - Cue Viewer
ここにあるピンクのボタンで、音を再生したり停止するための主要な操作ができます。Runボタンは編集画面内のコードを実行します。Stopボタンですべてのコードの動作を停止します。Saveボタンは外部ファイルにコードを保存し、Recordボタンは演奏中の音を(WAVファイルに)録音します。
These orange buttons allow you to manipulate the code editor. The Size + and Size - buttons allow you to make the text bigger and smaller.
これらの青いボタンで、情報、ヘルプや設定にアクセスします。Infoボタンは、概要、コア、協力者、コミュニティ、ライセンス、ヒストリーといったSonic Pi自体についての情報を画面に表示します。HelpボタンはGのヘルプシステム表示を切り替えます。またPrefsボタンは基本的なシステムを操作するための設定画面の表示を切り替えます。
ここは音楽を作曲/演奏したりするためのコードを書く領域です。コードを書いたり、消したり、切り取り、貼り付けなどを行うためのシンプルな編集画面です。Google DocsやWordの基本版だと思ってください。編集画面ではコードの意味合いに応じて自動で色つけします。はじめは変わっていると思うかもしれませんが、とても使いやすくなるはずです。例えば、数値は青色で示されます。
Sonic Piには多くの変更可能な設定があり、Prefsボタンを切り替えることでアクセスできます。このボタンにより、多くの変更可能なオプションを含む環境設定パネルの表示/非表示を切り替えることができます。オプションの例としては、モノラルモードへの強制変更や、ステレオ反転、ログ出力の切り替え、さらにRaspberry Piのボリュームスライダーやオーディオセレクターなどがあります。
コードを実行させた時、ログ画面にはプログラムがどうなっているかについての情報が表示されます。デフォルトでは、正確な再生時間を毎音ごとにメッセージとして見ることができます。コードのデバッグ(欠陥を取り除く作業)に利用でき、コードが何をしているかを理解することにも役立ちます。
最後は、Sonic Piインタフェースのもっとも重要な部分の1つである、画面の下にあるヘルプシステムです。青いHelpボタンによって表示/非表示を切り替えることができます。ヘルプシステムは、ヘルプと情報を含んでいます。このチュートリアル、入手できるシンセのリスト、サンプルや実例、エフェクトのリスト、そして音楽をコーディングするために備えているSonic Piの全機能のリストといった、Sonic Piの全てについてのヘルプと情報があります。
スコープビューアは、あなたの聞いている音を見ることを可能にします。ノコギリ波がのこぎりのようだったり、単純なビープ音が正弦波であることを簡単に見ることが出来ます。また、うるさい音と静かな音の違いを線の大きさで見ることも可能です。Sonic Piには、3つのスコープがあります。デフォルトは左右のチャネルを混ぜあわせたモノラルスコープです。左右のチャネルを別々のスコープで描画するステレオスコープがあります。最後に、左右のチャネルの位相の関係を描画するリサジュースコープがあります。(https://ja.wikipedia.org/wiki/%E3%83%AA%E3%82%B5%E3%82%B8%E3%83%A5%E3%83%BC%E5%9B%B3%E5%BD%A2)
All internal and external events (called cues in Sonic Pi) are automatically logged in the Cue Viewer. For example, if you have a MIDI controller connected and press one of its buttons, you’ll see a new cue event in the Cue Viewer telling you the name of the controller and which button you pressed. Once you’ve mastered the basics of making and producing sounds, you’ll start to want to cue sounds or whole sections of sounds based on events such as these. A cue event is just an indication that something happened. For example, every time a live loop spins round, it sends a cue event out which is logged in the Cue Viewer. Also, external events such as MIDI messages from connected MIDI equipment and OSC messages from other programs or computers are also displayed in the Cue Viewer. It is also possible to directly generate cue events using the cue
function. Anything that appears in the Cue Viewer can be used to trigger something happening. This is covered in more detail in Sections 10 to 12 of this tutorial.
Sonic Piは、遊びと実験を通して、コンピューティングと音楽の両方を学ぶ手助けをしてくれます。もっとも大切なことは、楽しむこと。そうすれば、コードや作曲、演奏を、学ぶ前に自然と身につけられるでしょう。
このチュートリアルの内容に取り組むにあたって、私が何年もライブコーディングしてきて得られたアドバイスを紹介しましょう。「間違いはない、あるのはただ可能性だけ」これは、しばしばジャズについて言われることですが、ライブコーディングにも同様に言えることです。経験に関係なく、あなたが全くの初心者でも、熟練のライブコーダーでも、コードを実行してまったく予期せぬ結果になることがあります。めちゃくちゃクールに聞こえる場合は、そのコードを実行すればいいのですが、すごく耳障りで場違いに聞こえる場合もあります。そうなっても問題ではありません。重要なのは、あなたが次にすべきことです。音を取り除き、それを操作し、素晴らしいものに変化させるのです。観衆は熱狂するでしょう。
学習していると、今すぐすごいことをしたい気持ちに駆られます。しかし、今はその気持ちをこらえ、それは後に到達する遠い目標として持ってください。その代わり、今のところは、あなたが楽しくやりがいをもって書くことができる最も単純な事を考えていきましょう。それが、あなたの頭の中のすごいことへの小さな一歩になるのです。一度その単純な一歩についてアイデアを思いついたら、それを作って遊んでみてください。そして、そこからどのような新しいアイデアを得られるか見てみましょう。すぐに、あなたは楽しみながら確実に上達することに大忙しになっているでしょう。
でも、みんなと作品をシェア(共有)することは忘れないでください!
Sonic Piの紹介はこれくらいにして、さっそく音を試してみましょう。
この章では、基本的なシンセ(synth)の出し方と操作方法を紹介します。シンセは、音を作り出すシンセサイザーという響きのよい言葉を短縮したものです。典型的なシンセは、非常に使うのが複雑です。特にアナログのシンセは、沢山のパッチワイヤーとモジュールがついています。ですが、Sonic Piでは、とても簡単で親しみやすい方法で、このシンセの力を手に入れることが出来ます。
Sonic Piの分かりやすくシンプルな操作画面に騙されないでください。もし使いこなせたら、洗練されたサウンド操作を可能にします。きっと驚くはずです。
次のコードを見てください。
play 70
ここからすべてが始まります。アプリケーションの上部のコードウィンドウ(Run
ボタンの下の大きな空白)にコピーして貼り付けます。そして、Run
ボタンを押してみましょう。
ビックリした? もう1回、押してみましょう。そしてもう1回…
わお! すごい! 一日中楽しんで居られそうだけど、でも待って。ビープ音の無限の流れに夢中になる前に、数値を変えてみましょう。
play 75
違いが分かりますか? より低い値も試してみましょう。
play 60
So, lower numbers make lower pitched beeps and higher numbers make higher pitched beeps. Just like on a piano, the keys at the lower part of the piano (the left hand side) play lower notes and the keys on the higher part of the piano (the right hand side) play higher notes.
play 60
もし、これがあなたにとって何の意味か分からなくても心配しないでください。私も始めた時は同じでした。いま重要なことは、低い数値は低い音を、高い数値は高い音を生み出す、ということを知っておくことです。
音符を奏でることはとても楽しいですが、同時にたくさんの音符を鳴らすとさらに楽しくなります。これを試してみましょう。
play 72
play 75
play 79
華やかです! 複数のplay
を書くと、全て同時に演奏されます。自分で試してみましょう。どの数値がいい組み合わせでしょうか? どれがひどい音? 実験、探求しながら、自分自身で見つけていきましょう。
音符と和音を演奏するのは楽しいですね。でも、メロディーの演奏はどうすればよいでしょうか? 一音ずつ、同時ではなく演奏したい場合は? それは簡単です。音符の間にsleep
を入れば可能です。
play 72
sleep 1
play 75
sleep 1
play 79
なんて素敵なアルペジオ(和音を続けて弾くこと)! では、sleep 1
の1
は何を意味するのでしょうか? これは1拍休む、という意味ですが、とりあえず今は、1秒休む、と考えましょう。では、アルペジオをもう少し早くしたいと思ったら? それは、短い値を使えばよいのです。例えば半分の値0.5
ではどうでしょう?
play 72
sleep 0.5
play 75
sleep 0.5
play 79
早くなりましたね。では、自分で時間を変えてみましょう。違う時間と音符を使ってみましょう。
たとえばplay 52.3
やplay 52.63
のような中間的な値でも演奏してみてください。通常の音符にこだわる必要は全くありません。遊んで、楽しんでみてください。
みなさんの中で、すでにいくつかの音楽記号を知っている人は、たとえばCとかF#などの音名を使ってメロディーを書きたいかも知れません(もし知らなくても心配無用です。それが必要というわけではありません)。Sonic Piはそれをカバーしてくれます。以下のことをやってみましょう。
play :C
sleep 0.5
play :D
sleep 0.5
play :E
演奏する音階の前にコロン’:’を入れることを忘れないでください。コロンを置くと、Cが:C
のように色が変わります。また、音名のあとに数値を追加してオクターヴを指定することもできます。
play :C3
sleep 0.5
play :D3
sleep 0.5
play :E4
半音♯(シャープ)にしたい場合は、’play :Fs3’のように音名の後に’s’を追加します。半音♭(フラット)にしたい場合は、’play :Eb3’のように’b’を追加します。
夢中になって、自分の曲を作って楽しみましょう。
Sonic Piは、演奏した音符や再生したサンプルを制御可能なだけでなく、音の作成や制御のための様々なオプションを提供しています。このチュートリアルではこれらの多くを紹介していく予定です。また、ヘルプシステムにはそれぞれについての詳細なドキュメントがあります。ここでは、その中でも最も有用なものの2つ、amplitude(音量)とpan(パン)を紹介します。では最初に、オプションが実際にどのようなものか見てみましょう。
Sonic Piはシンセのためにオプションという概念を備えています。オプションは、サウンドの特徴をコントロールしたり変更するための手段で、play
に渡されます。シンセはそれぞれ独自に細かく音をチューニングするためのオプションを持っています。その一方で、amp:
(音量)やエンベロープ(他の章で紹介します)のような、多くのサウンドに共通するオプションもあります。
オプションは2つの主要な部分からなり、1つはその名前(制御の名前)で、もう1つはその値(制御に設定したい値)です。例えば、cheese:
というオプションがあったとして、1
の値にセットしたいとします。
オプションは、play
の後にカンマ,
を入れて、その後、amp:
(コロン:
を忘れずに)のようなオプションの名前、スペース、そしてオプションの値、というように渡していきます。例えば、
play 50, cheese: 1
(cheese:
は無効なオプションです。例として使っています)
カンマを使って区切り、複数のオプションを使用することができます。
play 50, cheese: 1, beans: 0.5
オプションの順番は問題ではないので、以下は同じものです。
play 50, beans: 0.5, cheese: 1
シンセで認識されないオプションは無視されます(cheese
(チーズ)とbeans
(豆)などは明らかに馬鹿げた名前でしょう!)
もし偶然同じオプションを2回、違う値で使った場合は、最後のものが有効になります。例えば、ここでのbeans:
は、0.5ではなく2の値が採用されます。
play 50, beans: 0.5, cheese: 3, eggs: 0.1, beans: 2
Sonic Piの多くの命令にはオプションが用意されているので、ちょっとだけ時間を使って、その使い方を習得しましょう! それでは最初のオプションamp:
で演奏してみましょう。
アンプは音の大きさをコンピュータで表したものです。アンプが大きいと大きな音を出し、アンプが小さいと静かな音を出します。Sonic Piは時間と音符を数字を使って表現するので、アンプにも数字を使用します。1の値が通常の音量であるのに対して、0はサイレント(無音)です(何も聞こえませんよ)。2、10、100 というふうに、アンプを上げることができます。ただし、全体の音を増幅しすぎると、大きな音になりすぎないように、Sonic Piはコンプレッサー(圧縮)と呼ばれるエフェクトを使用して確実な音量に抑えることを覚えておいてください。これは多くの場合、音がこもって奇妙に聞こえます。ですから、圧縮を防ぐために0から0.5のような値で使用してみてください。
音の大きさを変えるために、amp:
オプションを使います。例として、半分の音量で演奏するために、0.5にしてみます。
play 60, amp: 0.5
倍の音量で演奏するために、2にしてみます。
play 60, amp: 2
amp:
オプションは、関連付けられているplay
への命令だけを変更します。ですから、この例では、最初の命令は半分の音量になり、次はデフォルトの値(1)に戻ります。
play 60, amp: 0.5
sleep 0.5
play 65
もちろん、それぞれの命令で異なったamp:
の値を設定して演奏することもできます。
play 50, amp: 0.1
sleep 0.25
play 55, amp: 0.2
sleep 0.25
play 57, amp: 0.4
sleep 0.25
play 62, amp: 1
もうひとつの面白いオプションはpan:
です。ステレオで音の位置を制御します。左に音をパンすることは左のスピーカーから音が聞こえることを意味し、右にパンすれば右のスピーカーから聞こえます。値としては、-1は最も左、0は中心、1は最も右、というようにステレオの領域で表現することができます。もちろん、音の正確な位置をコントロールするために、-1から1の間のどの値でも使用することができます。
左のスピーカーから音を鳴らしてみましょう。
play 60, pan: -1
では、右のスピーカーから鳴らします。
play 60, pan: 1
最後に元の通り、中心から鳴らしてみます(デフォルトの位置です)。
play 60, pan: 0
では、続けてあなたの音のアンプやパンを変えて楽しんでみましょう!
これまで、ビープ音を鳴らして楽しんできました。けれども、もしかするとあなたはこのベーシックなビープ音に退屈し始めているかも知れません。これがSonic Piが提供してくれるサウンドの全てなのでしょうか? もちろん、ビープ音だけではなくて、もっと他にもたくさんのライブコーディングがありますよね? はい、あります。この章ではSonic Piが作り出すエキサイティングな音の領域へと探検していきましょう。
Sonic Piは、シンセサイザーの略であるシンセと呼ばれる楽器の機能を持っています。サンプルがすでに録音された音であるのに対して、シンセはあなたがそれをコントロールすることに応じて新しいサウンドを生み出すことができます(このチュートリアルの後半でみていきます)。Sonic Piのシンセは、パワフルで表現力に富んでいて、探索しながら演奏したり、楽しめるはずです。最初に、ひとまずここでシンセを使うために、選び方を学んでみましょう。
面白い音は、ノコギリ(saw)波です。試してみましょう。
use_synth :saw
play 38
sleep 0.25
play 50
sleep 0.25
play 62
sleep 0.25
他の音prophetを試してみましょう。
use_synth :prophet
play 38
sleep 0.25
play 50
sleep 0.25
play 62
sleep 0.25
2つを一緒にしたらどうでしょう。一方のあとに、もう一方を。
use_synth :saw
play 38
sleep 0.25
play 50
sleep 0.25
use_synth :prophet
play 57
sleep 0.25
Now multiple sounds at the same time (by not sleeping between successive calls to play
):
use_synth :tb303
play 38
sleep 0.25
use_synth :dsaw
play 50
sleep 0.25
use_synth :prophet
play 57
sleep 0.25
use_synth
コマンドは、下のplay
にだけ影響していることに注意してください。大きなスイッチのようなものだと考えてください。指定したどんなシンセでも、新しいplay
へ命令として演奏されます。use_synth
で新しいシンセにスイッチすることができます。
Sonic Piにどのようなシンセがあるのか見るには、左端のメニュー(エフェクトの上)にあるシンセ・オプションを見てください。20以上が用意されています。私のお気に入りを以下に紹介します:
:prophet
:dsaw
:fm
:tb303
:pulse
では、音楽の中でシンセを切り替えて遊んでみてください。音楽の異なるセクションに違うシンセを使うように、シンセを組み合わせて新しい音を作って楽しんでください。
前のほうのセクションで、音をいつ再生するか制御するのに、どのようにsleep
コマンドを使用可能か見てきました。しかし、まだ我々は音のデュレーション(長さ)を制御できていないですね。
音のデュレーションを制御するための、パワフルでシンプルな手段として、Sonic PiにはADSR amplitude envelope(ADSR・アンプ・エンベロープ)という概念があります(ADSRが何を意味するかはこのセクションの後半で紹介します)。アンプ・エンベロープは制御のための便利な2つの側面を持っています。
音のデュレーション(長さ)を制御する 音のアンプ(音量)を制御する
デュレーションは音の持続する長さのことです。長いデュレーションは、より長く音が鳴ることを意味します。Sonic Piの全てのサウンドは、アンプ・エンベロープで制御でき、ひとつのエンベロープ(音量や音色の時間的な変化)の長さは、音の長さでもあります。
ADSRエンベロープは、デュレーションの制御だけでなく、アンプ(音量)の緻密な制御も可能にします。全てのサウンドは、サイレント(無音)で始まり、間に音があり、またサイレントで終了します。エンベロープを使用すると、サウンドの音がある部分の音量をスライドさせたり、保持したりすることができます。これは、音楽の音量を上げたり下げたりするのを、誰かに指示するような感じです。例えば、あなたは誰かに「無音で始めて、ゆっくりとフル・ボリュームにして、少しそのままで、そして一気に無音に戻る」と頼むとします。Sonic Piはエンベロープでこれをプログラムできるようにしてくれます。
前のセクションで見てきたように、アンプの0
は無音、1
は通常の音量です。
では、エンベロープのそれぞれの部分を順番に見ていきましょう。
エンベロープのうちデフォルトで使われている唯一の部分はリリース・フェーズです。通常、全てのシンセのリリース・フェーズ(終わるまでの時間)は1で、これは終了するまでに1拍(デフォルトBPMの60の場合には1秒)のデュレーションを持っているということです。
play 70
この音は1秒間だけ聞こえます。続いて時間を指定しよう。上の記述は、次の明示的で長い記述を簡略化したものです。
play 70, release: 1
これも全く同じように(1秒間持続する)音が出たと思います。しかし、release:
のオプションを変更することでとても簡単に持続時間を変更することができるようになりました。
play 60, release: 2
また、非常に小さなリリース・フェーズの値を使って、シンセのサウンドをとても短くすることができます。
play 60, release: 0.2
音がリリースされるまでの持続時間はリリース・フェーズと呼ばれていて、デフォルトではリニア・トランジション(直線的な移行、つまり真っ直ぐ)です。以下の図は、この移行を表したものです。
図の左端の縦の線は、サウンドが0
の音量(ゼロ・アンプ)からスタートしていることを示しています。しかし、すぐにフル・アンプに上がります(これは私たちが後で学ぶ、アタック・フェーズというものです)。いったんフル・アンプになり、それからrelease:
で指定した値を取りながら、直線的にゼロに下がります。長いリリース・タイムは長いシンセ・フェード・アウト(徐々に消えること)を生成します。
これにより、リリース・フェーズを変更して、あなたのサウンドのデュレーションを変えることができます。自分の音楽にリリース・タイムを追加して演奏してみましょう。
通常、アタック・フェーズは全てのシンセにおいて0
です。つまり、0
アンプから1
にただちに移動することを意味します。シンセは最初から音が打たれます。けれども、あなたは音をフェード・イン(徐々に大きく)したいかも知れません。これは、attack:
のオプションで実現することができます。いくつかの音をフェード・インしてみましょう。
play 60, attack: 2
sleep 3
play 65, attack: 0.5
複数のオプションを使うこともできます。例えば、短いアタック、長いリリースに、変更してみましょう。
play 60, attack: 0.7, release: 4
この、短いアタックに長いリリースのエンベロープは、以下の図のように表します。
もちろん、ほかに変更することもできます。長いアタックに短いリリースを試してみましょう。
play 60, attack: 4, release: 0.7
そして、アタックとリリース両方短くして、短いサウンドにもできます。
play 60, attack: 0.5, release: 0.5
アタック・フェーズとリリース・フェーズの設定に付け加えて、サステイン・フェーズ(持続時間)を指定することができます。サステイン・フェーズとは、アタックとリリースの間でフル・アンプの音が鳴り続ける時間のことです。
play 60, attack: 0.3, sustain: 1, release: 1
サステイン・フェーズは、オプションのリリース・フェーズに入る前に、ミックスの中で主となる存在感を与えたい重要なサウンドにとって有効です。もちろん、attack:
とrelease:
両方のオプションを0に設定することもとても有効ですし、サウンドに対して、完全にフェード・インなし、フェード・アウトなしにするためにサステインを使えば良いのです。けれど、注意してください、0のリリースはオーディオの中にクリック音を生成します。たいていの場合、0.2のようなごく小さい値を使う方が良いです。
そして、今あなたがさらなる制御のレベルを必要としているならば、ディケイ・タイムというものを設定することもできます。これは、アタックとサステインの間にくるエンベロープのフェーズで、音量がattack_level:
からdecay_level:
(もしこれを明示的に指定しなければ、この値はsustain_level:
と同じ値に設定されます)に落ちる時間を指定します。通常では、decay:
のオプションは0で、アタックとサステインのレベルは両方とも1です。ですから、ディケイ・フェーズで効果を得るには、アタック、サステインのレベルも指定しなくてはなりません。
play 60, attack: 0.1, attack_level: 1, decay: 0.2, sustain_level: 0.4, sustain: 1, release: 0.5
最後の仕掛けは、decay_level:
オプションがデフォルトではsustain_level:
と同じ値に設定されていて、エンベロープを完全に制御したい場合に明示的に別な値に設定できることです。これにより次のようなエンベロープを作ることができるでしょう。
play 60, attack: 0.1, attack_level: 1, decay: 0.2, decay_level: 0.3, sustain: 1, sustain_level: 0.4, release: 0.5
またdecay_level:
をsustain_level:
より大きく設定することもできます。
play 60, attack: 0.1, attack_level: 0.1, decay: 0.2, decay_level: 1, sustain: 0.5, sustain_level: 0.8, release: 1.5
つまり要約すると、Sonic PiのADSRエンベロープには、以下のフェーズがあります。
attack(アタック)- 音量を0からattack_level
まで移行させる時間
decay(ディケイ)- 音量をattack_level
からdecay_level
まで移行させる時間
sustain(サステイン)- 音量をdecay_level
からsustain_level
まで移行させる時間
release(リリース)- 音量をsustain_level
から0に移行させる時間
サウンドのデュレーションは、これらのフェーズの合計であることに注意することが大切です。したがって、以下のサウンドは、0.5 + 1 + 2 + 0.5 = 4 で、4秒のデュレーションになります。
play 60, attack: 0.5, attack_level: 1, decay: 1, sustain_level: 0.4, sustain: 2, release: 0.5
ではあなたのサウンドにエンベロープを追加して演奏してみましょう。
あなたの音楽を発展させる方法は他にもあります。すでに録音された音を使うことです。偉大なヒップホップの伝統では、これらのあらかじめ録音された音のことを、サンプルと呼びます。つまり、マイクを持って外に出て、雨が優しくキャンバスを打つ音を録音しに行けば、それだけでサンプルを作ることができます。
Sonic Piは、サンプルで楽しいことがたくさんできるようになっています。130以上のパブリック・ドメイン(著作権がない)サンプルが、ジャム(即興演奏)するために同梱されているだけでなく、あなたが持っているサンプルを操作して演奏することも可能です。さっそく見てみましょう…
ビープ音を演奏するのは最初だけです。もっと面白いのは、録音済みのサンプルを使うことです。やってみましょう。
sample :ambi_lunar_land
Sonic Piは演奏のためにたくさんのサンプルを持っています。play
コマンドを使うようにサンプルを使えばよいのです。複数のサンプルや音符を演奏するには、それらをひとつひとつ順番に書いていきます。
play 36
play 48
sample :ambi_lunar_land
sample :ambi_drone
もし間を空けたいなら、sleep
を使います。
sample :ambi_lunar_land
sleep 1
play 48
sleep 0.5
play 36
sample :ambi_drone
sleep 1
play 36
最初のサウンドが終わる前に、次のサウンドが始まることに注意してください。sleep
コマンドは、サウンドの開始の間隔だけを記述しています。これによって、簡単にサウンドを重ね合わせて、おもしろいオーバー・ラップ(重複)のエフェクト(効果)を生み出すことができるのです。このチュートリアルの後半で、エンベロープでサウンドのduration
(長さ)を制御する方法についてみていきます。
Sonic Piが収録しているサンプルの種類を知るには、2つの方法があります。1つ目は、このヘルプシステムを使うことです。下のメニューの中のサンプル
をクリックし、カテゴリを選ぶと、使用できるサウンドのリストが表示されます。
あるいは、オート・コンプリーション(自動補完)システムを使うこともできます。sample :ambi_
のような複数のサンプルを束ねるグループ名をタイプし始めると、同じグループ内から選択できるサンプルの名前がドロップ・ダウンして表れます。以下のサンプル・グループの接頭語を入力してみましょう。
:ambi_
:bass_
:elec_
:perc_
:guit_
:drum_
:misc_
:bd_
さあ、あなたの曲でサンプルのミックスを始めてみましょう!
シンセの項目で見てきたように、パラメータで簡単にサウンドを制御することができます。サンプルは全く同じパラメータの仕組みを備えています。何度も登場する、amp:
とpan:
をもう一度見てみましょう。
シンセで使った書き方と全く同じ方法で、サンプルのアンプ(音量)を変えることができます。
sample :ambi_lunar_land, amp: 0.5
サンプルでpan:
のパラメータを使うこともできます。例えば、次のコードは、定番のドラムフレーズのアーメン・ブレイクを左耳で再生し、半分まで来たところで再度右耳で再生する方法です。
sample :loop_amen, pan: -1
sleep 0.877
sample :loop_amen, pan: 1
0.877は、:loop_amen
サンプルの半分の再生時間であることに注意してください。
そして、use_synth_defaults
(あとで説明します)をシンセに設定している場合、サンプルはこれを無視して再生します。
すでに私たちは、音楽を作るために様々なシンセやサンプルを演奏することができます。そろそろ、音楽をもっとユニークで面白くするために、シンセとサンプルを編集する方法を学ぶ時間です。まずは、サンプルを引き延ばしたり圧縮する方法をみてみましょう。
サンプルとは、あらかじめ録音されたサウンドで、サウンドを再生するためにスピーカーのコーン(振動板)をどう動かすかを表す数値が格納されています。スピーカーのコーンは行ったり来たり(振動)するため、数値は、その時々でコーンがどれくらいの距離を行ったり来たりすべきかをその時々で表す必要があります。録音された音を忠実に再生するために、サンプルは概して1秒間に何千もの数値を格納しておく必要があるのです! Sonic Piはこの数値のリストを使って、適切なスピードでサウンドを再生するための正しい方法をあなたのコンピュータのスピーカーに伝え、振動させるのです。けれども、サウンドを変えるためにスピーカーに与えられる数値のスピードを変えるのも楽しいですよ。
アンビエント・サウンドのひとつ、:ambi_choir
で演奏してみましょう。デフォルトのレートで演奏するには、sample
にrate:
のオプションを渡します。
sample :ambi_choir, rate: 1
これはデフォルトのレート(1)で演奏するので、まだ何も変わったところはありません。ですが、数値を何か他の値に変えてもよいのです。0.5
はどうでしょう。
sample :ambi_choir, rate: 0.5
ワオ! 何が起きたのでしょう? そう、2つのことが起こりました。1つ目は、サンプルは再生に2倍の時間をかけていました。2つ目は、サウンドは1オクターブ低くなっていました。もう少し詳しく、これらのことを探ってみましょう。
引き延ばしたり圧縮したりして楽しいサンプルは、定番のアーメン・ブレイクです。通常のレートでは、ドラムン・ベース(音楽ジャンルのひとつ)のトラックを思わせます。
sample :loop_amen
:loop_amenですが、レート(速度)を変えると、音楽のジャンルが切り替わったように聞こえます。半分のスピードにすると、オールドスクールのヒップホップに。
sample :loop_amen, rate: 0.5
スピードを上げると、ジャングルのジャンルになりますね。
sample :loop_amen, rate: 1.5
では、パーティーの最後の仕掛けに、マイナスのレートを使うと何が起きるでしょうか。
sample :loop_amen, rate: -1
ワオ! 逆再生! いろいろな異なったサンプルで、異なったレートで演奏してみましょう。ものすごく速い数値や、おかしなくらいゆっくりになる数値を使って、どんなおもしろいサウンドを作れるか、試してみましょう。
サンプルは、バネのように考えると便利です。再生速度(プレイバック)は、バネを縮めたり伸ばしたりするようなものです。もしサンプルをレート 2 で再生した場合、通常の長さの半分に、バネを縮めることになります。ですので、サンプルは半分の時間で演奏するので、より短くなります。もしサンプルを半分のレートで再生した場合、2倍の長さにバネを伸ばすことになります。そのため、サンプルは再生に2倍の時間をかけるため、より長くなるのです。もっと縮める(レートを上げる)と、短く再生され、さらに伸ばす(レートを下げる)と、さらに長く再生されます。
バネを縮めることは、その密度(1cmあたりのコイルの数)を増やすことです。これは高いピッチ(音程)のサンプルに近づくことになります。バネを伸ばすことは、密度を減らすことで、低いピッチ(音程)のサウンドに近づいていきます。
(このセクションはさらに細かい部分に興味がある人向けです。飛ばしても構いませんよ…)
上記で見てきたように、サンプルは、スピーカーが一定の時間でどのように振動すべきかを表現した長大な数値のリストによって表されています。この数値のリストで、これと同じようなグラフを描いてみます。
あなたはこれと同じような図を、以前に見たことがあるかも知れません。これはサンプルの波形と呼ばれるものです。これは数値のグラフです。このような波形はだいたい、1秒間に44100ポイントのデータを有しています(これはナイキスト・シャノンのサンプリング定理によるものです)。サンプルが2秒間続くなら、スピーカーに1秒間に44100ポイントのレート(長さ)を与えることで88200の数値で表現されます。もちろん、1秒間に88200ポイントで、2倍のレートとすることもできます。ですので、これは1秒間で再生されます。1秒間に22050ポイントで、半分のレートで再生することも可能です。この場合、4秒で再生されます。
サンプルのデュレーションは、再生するレートの影響を受けます:
2倍の再生レートは、再生時間を半分にする 半分の再生レートは、再生時間を2倍にする 4分の1の再生レートは、再生時間を4倍にする 10分の1の再生レートは、10倍長く再生させる
これを以下の数式で表します。
new_sample_duration = (1 / rate) * sample_duration
再生レートを変えることは、サンプルのピッチ(音程)にも影響します。周波数や波形のピッチがどれくらい速く上下に動くかで決定されます。我々の脳は、どういうわけか、スピーカーの速い動きを高い音階に、遅い動きを低い音階に捉えます。だからあなたは時々、大きなベース・スピーカーが超低音を吐き出すのを見ることができるのです。実際に高い音を出しているときのスピーカーよりも、ゆっくりと振動しているのです。
もし波形を取り出して圧縮したら、1秒間でさらに頻繁に上下します。これがサウンドをより高い音にするのです。上下の運動を2倍にすると、周波数が2倍になるということになります。そのため、サンプルを2倍のレートで再生すると、聞こえる周波数が2倍になるということです。また、レートを半分にすると、周波数が半分になるということでもあります。他のレートはそれに応じて周波数に影響します。
ADSRエンベロープを用いて、サンプルのデュレーション(再生時間)とアンプ(音量)を編集することもできます。しかしながら、シンセのADSRエンベロープとは少しだけ異なったように作用します。サンプルに使用するエンベロープは、サンプルのアンプとデュレーションを減らすことしかできません。決して増やすことはできないのです。サンプルは、それが再生され終わったときか、エンベロープが完了したときのいずれかで停止します。どちらが先でも停止します。非常に長いrelease:
を使ったとしても、サンプルのデュレーションは延長されません。
では、我々にはすっかりお馴染みのフレーズ、アーメン・ブレイクに戻りましょう:
sample :loop_amen
オプションが設定されていない場合、全サンプルがフル・アンプ(最大音量)で聞こえます。もし1秒間のフェード・インを使いたい場合、attack:
パラメータを使います(フェード・インとは徐々に音が大きくなることです)。
sample :loop_amen, attack: 1
もっと短いフェード・インの場合は、attack:
の値を小さくします。
sample :loop_amen, attack: 0.3
ADSR エンベロープの特徴が標準的なシンセ・エンベロープと異なる点は、サステイン(持続時間)の値です。標準的なシンセのエンベロープでは、もし手動で変更しなければ、0に設定されています。ですが、サンプルでは、サステインの値は通常、魔法のように全自動にセットされます。サステインの時間は、サンプルの残りを演奏するように調整されます。デフォルトの値を渡さないときに、サンプルがフルで流れるのはこのためです。アタック、ディケイ、サステイン、リリース(この4つの頭文字がADSR)の値が全て0のときは、何の音も聞こえません。Sonic Piはサンプルの長さがどれくらいなのか計算し、アタック、ディケイ、リリース・タイムを差し引いて、あなたのサステイン・タイムの結果を使用します。もし、アタック、ディケイ、リリースの値がサンプルのデュレーションより長く追加された場合、サステインは0にセットされます。
これまでのことを探索するために、アーメン・ブレイクをさらに詳細に見てみましょう。アーメン・ブレイクのサンプルがどれくらいの長さなのか、Sonic Piに尋ねてみてはどうでしょう:
print sample_duration :loop_amen
1秒間のサンプルの長さは1.753310657596372
と答えるでしょう。ここでは、便宜的に1.75
としますリリース・タイムを0.75
にすると、驚くべきことが起こります。
sample :loop_amen, release: 0.75
サンプルの最初の1秒をフル・アンプで再生し、最後の0.75秒はフェード・アウトします。これがオート・サステインの動きです。標準では、release:
はいつもサンプルの最後から動作します。もしサンプルの長さが10.75秒なら、最初の10秒はフル・アンプで再生し、最後の0.75秒はフェード・アウトします。
通常、release:
はサンプルの最後でフェード・アウトするということを覚えておいてください。
サンプルのデュレーションの間にフェード・アウトとインを行うにはattack:
とrelease:
の両方を使うことができます。オート・サステインの仕組みと一緒に、使用できます。
sample :loop_amen, attack: 0.75, release: 0.75
サンプルのアーメン・ブレイク全体のデュレーションは1.75秒なので、アタックとリリースの時間が1.5秒まで追加されると、サステインは自動的に0.25秒にセットされます。これで簡単にサンプルをフェード・イン、アウトすることができます。
手動でsustain:
を0などにセットして、通常のADSRシンセの挙動に簡単に戻すこともできます。
sample :loop_amen, sustain: 0, release: 0.75
いま、サンプルはトータルで0.75秒間だけ再生されました。attack:
とdecay:
のデフォルト値が0ですので、サンプルはフル・アンプ(最大音量)に直接変わり、0秒間サステイン(持続)し、リリースの0.75秒間で0アンプに戻ります。
この仕様を、長いサウンドのサンプルを短く、より打楽器的にするために、効果的に使うことができます。:drum_cymbal_open
:
sample :drum_cymbal_open
上のサンプルでは一定時間シンバルの音が鳴っているのが聞こえます。ですが、もっとパーカッシブ(打楽器的)にしてみましょう。
sample :drum_cymbal_open, attack: 0.01, sustain: 0, release: 0.1
サステイン(持続時間)を増やすことで、シンバルを叩いた後の減衰の効果も出すことができます:
sample :drum_cymbal_open, attack: 0.01, sustain: 0.3, release: 0.1
今すぐ、サンプルを楽しくさせるエンベロープをいじってみましょう。面白い結果を得るために数値を思いきり変更してみましょう。
このセクションでは、Sonic Piのサンプルの再生について私たちが探求してきたことをまとめます。簡単にまとめてみましょう。これまで、サンプルを再生する方法をみてきました。
sample :loop_amen
まず、サンプルのレート(速さ)を変更する方法を見つけて、このように半分の速度で再生してみました。
sample :loop_amen, rate: 0.5
次に、サンプルを徐々に大きくするフェードインを知りました(半分の速度でやってみましょう)。
sample :loop_amen, rate: 0.5, attack: 1
また、sustain:
に明確な値とアタックとリリースの両方の短い値を設定することで、サンプルを打楽器のように使用する方法を見つけました。
sample :loop_amen, rate: 2, attack: 0.01, sustain: 0, release: 0.35
では、いつもサンプルの先頭から開始する必要はあるのでしょうか? そして、いつもサンプルの最後まで終了する必要はあるのでしょうか?
サンプルのどこからでも、好きな場所を選んで音を再生することが可能です。0はサンプルの開始で、1は終了です。0.5はサンプルの途中です。アーメン・ブレイクの最後の半分を再生してみましょう。
sample :loop_amen, start: 0.5
どのようにすればサンプルの最後の1/4を再生できますか?
sample :loop_amen, start: 0.75
同様に、サンプルの0から1の間の値を終了点として選ぶことができます。アーメン・ブレイクの半分までで終わらせてみましょう。
sample :loop_amen, finish: 0.5
もちろん、私たちは好きな部分を再生するために、これまでの開始と終了の2つを組み合わせることができます。どのようにすれば真ん中あたりの短い場所だけを選べるのでしょうか?
sample :loop_amen, start: 0.4, finish: 0.6
もし、終了位置のあとを、開始位置として選ぶとどうなるでしょう?
sample :loop_amen, start: 0.6, finish: 0.4
かっこいい! 逆再生になりますね!
ここで紹介した部分再生の機能を、すでに学んだrate:
を組み合わせることができます。例えば、アーメン・ブレイクの真ん中のとても小さな部分をとてもゆっくりと再生することができます:
sample :loop_amen, start: 0.5, finish: 0.7, rate: 0.2
そして、面白い結果を創りだすために、ADSRエンベロープと、いままでの全てを組み合わせることができます。
sample :loop_amen, start: 0.5, finish: 0.8, rate: -0.2, attack: 0.3, release: 1
今すぐ、サンプルとこれまでに紹介した楽しい内容を組み合わせて演奏してみましょう!
内蔵のサンプルは、すぐに使用でき、再生することができる一方で、あなたは自分で録音した音を試してみたいと思うかもしれません。Sonic Piはこれに完全に対応しています。最初に、あなたの録音した音の携帯性について少し議論してみましょう。
あなたが内蔵のシンセやサンプルだけを使って作曲した場合、音楽を忠実に再現するために必要なものは、コードだけになります。でもちょっと考えてみてください。それは、実はとても凄いことなのですよね! あなたの音楽を忠実に再現する作品は、テキストによるシンプルなものなので、電子メールで周りに送ったり、Gistに埋め込んで公開することができます。コードを持っていれば友人と本当に簡単に共有することができます。
しかし、もしあなたが、自身で記録したサンプルを使ってしまうと、この携帯性が失われてしまいます。なぜならば、あなたの音楽を他の人達が再現しようとしても、あなたのコードだけでは再生することができず、記録したサンプルが必要になってしまうからです。この事は、あなたの音楽を他の人が操作したり編集したり、試してみることを制限してしまうことがあるということです。もちろん、あなた自身が録音したサンプルを使うことを止めるということではなく、方法(データを送って、正しく共有するなど)に配慮していけばよいという事です。
では、どうやって、あなたが録音したWAVファイルやAIFFファイルをコンピュータで再生するのでしょうか? sample
のファイルを置く場所を指定(パスを通す)するだけで、再生できるようになります。
# Raspberry Pi, Mac, Linux
sample "/Users/sam/Desktop/my-sound.wav"
# Windows
sample "C:/Users/sam/Desktop/my-sound.wav"
Sonic Piは自動的にサンプルを読み込んで再生します。あなたは、sample
に今まで使ってきた全てのパラメータを、あなたが録音した音に使うことができます。
# 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
注: このセクションは外部サンプルのある巨大なディレクトリを扱う際の高度なトピックを扱っています。あなたがサンプルパックをダウンロードしたり購入したりして、それをSonic Piから使いたい場合が当てはまるでしょう。
内蔵サンプルで問題なければ、このセクションは飛ばしても構いませんよ。
外部サンプルのある大きなフォルダを扱う際に、個々のサンプルを再生する度にパス全体をタイプするのは、面倒かもしれません。
例えば、次のようなフォルダがあなたのマシンにあるとします。
/path/to/my/samples/
そしてそのフォルダの中の次のようなサンプルがあるとします。
100_A#_melody1.wav
100_A#_melody2.wav
100_A#_melody3.wav
120_A#_melody4.wav
120_Bb_guit1.wav
120_Bb_piano1.wav
例えばピアノのサンプルを再生したい場合、次のようなフルパスでの指定が可能です。
sample "/path/to/my/samples/120_Bb_piano1.wav"
次にギターのサンプルを再生したい場合、また同じようにフルパスでの指定が可能です。
sample "/path/to/my/samples/120_Bb_guit.wav"
しかしながら、これらのどちらのサンプルの呼び出しでも、ディレクトリ内のファイル名を知っている必要があります。もしサンプルを順番に聴いて行きたい場合どうしたら良いでしょう?
もしディレクトリの1番目のサンプルを再生したい場合、必要なことは次のようにsample
にディレクトリ名と’0’のインデックスを渡すだけです。
sample "/path/to/my/samples/", 0
さらにディレクトリ名は変数を使ってショートカットを作ることも可能です。
samps = "/path/to/my/samples/"
sample samps, 0
次に、ディレクトリの2番目のサンプルを再生したい場合、先ほどのインデックスに1を追加すれば出来ます。
samps = "/path/to/my/samples/"
sample samps, 1
もはやディレクトリ内のサンプルの名前を知る必要がないことに注意してください。必要なのはディレクトリそのもの(もしくはそのショートカット)を知っていることです。もしディレクトリ内のサンプルの数より大きい値をインデックスに指定した場合、リングのように単純に先頭に戻ります。したがって、どのような数字もディレクトリ内のどれかのサンプルを取得することが保証されているのです。
インデックスは機能的には十分かもしれませんが、サンプルを分類するもっと強力な方法が必要になるかもしれません。幸いにして、いくつかのサンプルパックではファイル名に意味のある情報を付加してくれています。ディレクトリ内のファイル名を別な観点から見てみましょう。
100_A#_melody1.wav
100_A#_melody2.wav
100_A#_melody3.wav
120_A#_melody4.wav
120_Bb_guit1.wav
120_Bb_piano1.wav
これらのファイル名はかなりの情報を持っていることに注目してください。最初にサンプルのBPM(beats per minute)があります。ピアノのサンプルはBPMが120で最初の3つのメロディーはBPMが100であることが分かると思います。また、サンプルのファイル名はキーを含んでいます。ギターのサンプルはキーがBbでメロディーのキーはA#です。この情報は我々の他のコードと組み合わせるのにとても役立ちます。例えば、ピアノのサンプルをBPM120でBbのキーのソースコードとしか使えないことが分かると思います。
サンプルの特定の命名規則を使って、我々が必要とするファイルをフィルタできることが分かりました。例えば、BPM120で演奏している場合に、"120"
という文字列を含む全てのサンプルを次のようにフィルタできます。
samps = "/path/to/my/samples/"
sample samps, "120"
これは最初にマッチしたものを再生します。もし2番目にマッチしたものを再生したい場合には、インデックスを使用します。
samps = "/path/to/my/samples/"
sample samps, "120", 1
さらに複数のフィルタを使うこともできます。例えば、”120”と”A#”をファイル名に含むサンプルが必要な場合、次のような簡単なコードで実現できます。
samps = "/path/to/my/samples/"
sample samps, "120", "A#"
最後に、フィルタを使用した場合にもsample
で通常使用されるオプションをそのまま自由に追加できます。
samps = "/path/to/my/samples/"
sample samps, "120", "Bb", 1, lpf: 70, amp: 2
サンプルフィルタの引数前の処理システムは、ソースとフィルタという2つタイプの情報を認識します。ソースは、候補となる可能性のあるサンプルのリストを作成するのに使われる情報です。ソースは次の2つの形式を取ることができます。
“/path/to/samples” - 有効なディレクトリを表す文字列 “/path/to/samples/foo.wav” - サンプルへの有効なパスを表す文字列
sample
関数は、最初に全てのソースを集めてサンプルの候補の巨大なリストを作成します。このリストは最初に全ての有効なパスを追加した後、次にディレクトリ内にある全ての有効な.flac
, .aif
, .aiff
, .wav
, .wave
ファイルを追加します。
例として、次のコードを見てください。
samps = "/path/to/my/samples/"
samps2 = "/path/to/my/samples2/"
path = "/path/to/my/samples3/foo.wav"
sample samps, samps2, path, 0
ここでは、2つのディレクトリの内容と1つの特定のサンプルを組み合わせています。もし"/path/to/my/samples/"
に3つのサンプルがあり、"/path/to/my/samples2/"
に12個のサンプルがあるとすると、インデックスやフィルタ可能となるサンプルは16(3 + 12 + 1)になります。
デフォルトでは、ディレクトリ内のサンプルファイルのみが候補リストに集められますが、ときにはネストした数多くのフォルダ内のサンプルを検索したりフィルタしたりしたいことがあるかもしれません。その場合には、次のように**
をパスの最後に付けることで、全てのサブディレクトリ内のサンプルを再帰的に検索することができます。
samps = "/path/to/nested/samples/**"
sample samps, 0
とても大きなフォルダのセットを検索するのは、長い時間が掛かるかもしれないことに気をつけてください。しかし、フォルダーのソースの内容は全てキャッシュされるので、この遅延は一度目しか発生しません。
最後に、ソースの指定は「必ず先頭に」付けるようにしてください。もし何もソースが指定されない場合、内蔵サンプルのセットが候補リストして選択されます。
候補リストを取得した後、選択肢を減らすために次のようなフィルタのタイプを使うことができます。
"foo"
という文字列は、(ディレクトリパスと拡張子を除いた)ファイル名の部分一致を抽出します。
/fo[oO]/
という正規表現は、(ディレクトリパスと拡張子を除いた)ファイル名のパターンマッチを抽出します。
:foo
というキーワードは、(ディレクトリパスと拡張子を除いた)ファイル名の完全一致を抽出します。
lambda{|a| ... }
という1つの引数を伴ったProc(手続きオブジェクト)は、候補リストのフィルタまたは生成する関数として扱われます。この関数は、現在の候補リストが引数として渡され、新しい候補リスト(サンプルの有効なパスのリスト)を返却する必要があります。
1
のような数値は、インデックス(必要があればリングのように先頭に戻る)で、候補から選択します。
例として、あるディレクトリから"foo"
の文字列を含むサンプルを抽出し、そのうちの最初のものを半分のレートで再生するには、次のように書きます。
sample "/path/to/samples", "foo", rate: 0.5
詳細な使用例はsample
のヘルプを参照してください。また、フィルタの順序が尊重されることに注意してください。
最後に、ソースまたはフィルタを配置することが可能な位置であればどこでもリストを使用することができます。リストは自動的に平坦化され、正規のソースとフィルタとして扱われます。したがって、次に示すsample
の呼び出しは意味的には全て同じものになります。
sample "/path/to/dir", "100", "C#"
sample ["/path/to/dir", "100", "C#"]
sample "/path/to/dir", ["100", "C#"]
sample ["/path/to/dir", ["100", ["C#"]]]
このセクションでは、サンプルパックを操作・使用する強力な方法を必要とする人のための高度な内容を紹介しました。このセクションの大部分があまり意味があるように思えなかったとしても心配しないでください。それは、これらの機能のどれもまだあなたが必要としていないというだけだと思います。しかし、サンプルの巨大なディレクトリを扱うことになり、これらの機能が必要なことが分かったときに、またこのセクションに戻って読み直すことができるでしょう。
音楽にすこし面白さを加えるために、ランダムという素晴らしい方法があります。Sonic Piは音楽にランダム性を追加するためにいくつかの素晴らしい機能を持っていますが、Sonic Piのランダムは、真のランダムではありません。これは一体何を意味しているのでしょう? 勉強を開始する前に、この衝撃的な真実を見ていきましょう。
たいへん便利なランダム関数に、2つの数字の間(最小値と最大値)で乱数(ランダムな値)が得られるrrand
があります(rrandはレンジド・ランダムの略です)。ランダムな音階を演奏してみましょう。
play rrand(50, 95)
おぉー、ランダムな音符を演奏しましたね。これは、83.7527
の音符を演奏しました。50と95との間のランダムな音符でしたね。でも、ちょっと待ってください、上記で、私はあなたが再生したランダムな音符を正確に予測していませんか? 何か怪しくないですか? 再度コードを実行してみてください。ランダムのはずが、再び83.7527
が選ばれましたよね? 実は、ランダムにすることができないのです!
答えは、それが真のランダムではなく、擬似ランダムであるということです。Sonic Piは、再現可能なランダム風の数を用意しています。これは、あなたのマシンで作成した音楽が、たとえその中でいくつかランダム性を使用している場合でも、誰か他の人のマシンで同じように聞こえることを保証するのに大変便利な機能です。
もちろん、ある音楽作品において、もし83.7527
が「ランダムに」毎回選択された場合、それは非常に面白くありません。しかし、そうにはなっていません。以下のことを試してみてください。
loop do
play rrand(50, 95)
sleep 0.5
end
そう! 最終的には、ランダムに聞こえますね。ランダム関数へ続いて呼び出されるその後の実行結果はランダムな値を返します。ただし、また再生する場合は正確に乱数値の同じシーケンスを生成し、まったく同じ音が鳴ります。Runボタンが押されるたびに、まるですべてのSonic Piコードが毎回、同じ時間に戻るかように蘇ります。それはまさに映画「恋はデジャ・ブ」のようにシンセの音が繰り返されるのです!
ランダム動作を取り入れたゾクッとするようなベルの音を使った楽しい作例です。繰り返しサンプルのベル音:perc_bellをループさせ、ベル音の再生速度と音の間のsleepにランダムな数値を用いています。
loop do
sample :perc_bell, rate: (rrand 0.125, 1.5)
sleep rrand(0.2, 2)
end
ランダム化のもう1つの楽しみ方の例は、ランダムにシンセのカットオフを加えることです。これを試してみるのに絶好のシンセは、:tb303 エミュレータです。
use_synth :tb303
loop do
play 50, release: 0.1, cutoff: rrand(60, 120)
sleep 0.125
end
もし、Sonic Piが提供する乱数の特定の配列が気に入らない場合、use_random_seed
を介すことで別の開始点を選択することが可能です。シードのデフォルト値は0であるため、異なる乱数を試すために別のシードの値を入力してみましょう!
下記を考えてみてください:
5.times do
play rrand(50, 100)
sleep 0.5
end
このコードを実行するたびに、5音階の同じシーケンスが聞けるでしょう。異なるシーケンスを聞くには、シードの値を変更します。
use_random_seed 40
5.times do
play rrand(50, 100)
sleep 0.5
end
こうして異なる5音階のシーケンスを生成します。シードの値を変更することによって、あなたの好きなフレーズを見つけることができます。他の人と共有するとき、あなたが聞いたものとまったく同様のフレーズを彼らも聞くことができるでしょう。
有用なランダム関数をもう少し見ていきましょう。
あらかじめ用意した数値をリストの中からランダムに選択することは、一般的に行われていることでしょう。例えば、60、65または72の中から1音を演奏することができます。choose
を用いれば、リストから1つの項目をで選択することができます。まず、カンマで区切った番号のリストを角括弧でラップ(包んで)し、配置する必要があります:[60, 65, 72]
。次にそれらをchoose
に渡す必要があります。
choose([60, 65, 72])
どんな音になるか聞いてみましょう。
loop do
play choose([60, 65, 72])
sleep 1
end
すでにrrand
について触れてきましたが、再び実行してみましょう。これは、2つの値の間の乱数(排他的)を返します。この意味するところは上部または下部の番号いずれの値も含まれません。常に両者の間にある値です。そして、その番号は常に浮動小数点になります - それは整数ではなく、分数です。rrand(20, 110)
で返される浮動小数点数の例は次のとおりです。
87.5054931640625 86.05255126953125 61.77825927734375
時々、あなたは小数点ではなく、整数の乱数を望むこともあるでしょう。これはrrand_i
を用いることで解決できます。それは小数点を除いてrrand
と同様に最小値および最大値の範囲(この場合、最長値と最大値も含まれます)に潜在するランダム値を返す動作をします。下記は、rrand_i(20, 110)
によって返される数値の例です。
88 86 62
rand
は、0
を含む最小値と、引数として指定した最大値未満の間のランダムな浮動小数点数を返します。デフォルトでは0
と1
の間の値を返します。このため、amp:
値をランダム化する際に便利です。
loop do
play 60, amp: rand
sleep 0.25
end
rrand_i
とrrand
の関係と同様に、rand_i
は0
と引数として指定した最大値の間の整数値を返します。
ランダムな数字を出す際に、サイコロ投げをまねてみたくなることもあるでしょう。これは、常に下の値が1であるrrand_i
の特殊なケースです。dice
を呼び出す時は、サイコロの面の数を指定する必要があります。標準的なサイコロは6面で、dice(6)
では、1, 2, 3, 4, 5または6を返すサイコロと同様の作用をします。しかし、空想のボードゲームのように、4面、12面または20面サイコロ、さらには120面のサイコロで値を見つけたいこともあるでしょう。
最後に、一般的なサイコロを振って、例えば6を出すということをやってみたくなることもあるでしょう。one_in
はサイコロの面の数分の1の確率でtrueを返します。したがってone_in(6)
では6分1の確率でtrue、それ以外の場合はfalseを返します。true
とfalse
の値は、このチュートリアルの次のセクションで説明するif文で非常に有用です。
さあ、ランダム性を使いこなしてコードをまぜこぜにしていきましょう!
これまでの章で、みなさんはplay
やsample
コマンドを使ったり、sleep
を使ってシンプルなメロディーやリズムを作曲することを通して音楽制作(サウンドプログラミング)の基礎を学ぶことができました。Sonic Piのコードの世界で他にどんなことができるか興味が出てきたことでしょう…
それでは、プログラミングの基礎となるループや条件文、ファンクション(関数)やスレッドなどに進みましょう。それらが、音楽的なアイデアを実現するための驚くほど強力なツールになることでしょう。
それでは、やってみましょう。
Sonic Piでよく見る構造はブロック(block
)といいます。ブロックは沢山のコードをひとかたまりとして、便利に扱うことができます。たとえばsynth
やsample
では、その後ろのパラメータによって音を変えることができました。しかし、場合によってはコード数行に同じ変更内容を反映させたい時などが出てきます。たとえばループする時に、5回のうち1回だけリバーブを加えたい場合を考えてみます。
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
コードのまとまりを使って何かをしようとするときに、コードのブロックの始まりと終わりをSonic Piに伝える必要があります。その際にdo
を始まりに、end
を終わりとして使用します。
do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
しかし、これではまだ完璧ではないので、実行されません(動かしてみてもエラーメッセージが出るだけです)。実行したい始まりと終わりのブロックをSonic Piへ伝達が完了していないからです。do
の前に特別なコードをすこし書くことによってこのブロックをSonic Piに教えることができます。このチュートリアルの後半でこれらの特別なコードを使ったいくつかの事例を紹介していきます。ひとまず、みなさんが特別なコードを使ってSonic Piを動かしたい場合、do
とend
でコードをまとめることが重要であることを覚えておいてください。
以前に我々は、play
とsample
のブロックで、様々な音を作り出せることを見てきました。また、sleep
を使うことで、これらの音を時間に沿って再生する方法も学びました。
これらの基本的なブロックを使用することで多くの楽しさがあることを理解してもらえたのではないでしょうか。しかし、音楽を作るための強力なコードを学べば、その楽しさの次元はまた新しい段階に向かうでしょう。次のいくつかのセクションではパワフルな新しいツールを探っていきます。はじめに「イテレーション(反復)とループ」を学びます。
何回か繰り返しを行うためにはどのようにコードを書いたらよいでしょう? 例えばこのようなコードです。
play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25
これを3回繰り返したい場合、どうしたら良いでしょう? 単純に考えればコピーして貼り付けを3回繰り返せば可能です。
play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25
play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25
play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25
ちょっと長過ぎますよね。もしサンプルを:elec_plip
に変更させたい場合、どうしたら良いでしょうか? 3か所全部の:elec_blup
をひとつひとつ変えなくてはいけません。さらに重要なことですが、繰り返しが50回とか1000回になったとしたらどうでしょう? 変更したいコードがすごくたくさんになってしまいます。
コードの繰り返しは、これを3回やってと言うくらい簡単に出来るべきだし、実際のところ簡単に出来ます。先ほど学んだコードブロックを思い出してください。3回繰り返したいコードのブロックには「始まり」と「終わり」が記されていますね。そんな時にこの特別なコードである3.times
を使いましょう。同じコードを3回繰り返す代わりに、3.times
を書くことで、とても簡単に出来るようになります。その時にコードの最終行にend
を書き入れることも忘れないようにしましょう。
3.times do
play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
sleep 0.25
end
コピーと貼り付けを繰り返すより、ずっと美しいコードになったと思いませんか? このようにブロックを使うと、沢山の繰り返しの構造を作ることが出来るのです。
4.times do
play 50
sleep 0.5
end
8.times do
play 55, release: 0.2
sleep 0.25
end
4.times do
play 50
sleep 0.5
end
繰り返しの中にさらに繰り返しを入れることによって面白いパターンを作ることが出来ます。例えば
4.times do
sample :drum_heavy_kick
2.times do
sample :elec_blip2, rate: 2
sleep 0.25
end
sample :elec_snare
4.times do
sample :drum_tom_mid_soft
sleep 0.125
end
end
もしすごくたくさんの繰り返しをしたい場合、1000.times do
のようにすごく大きな数値の繰り返しをさせることになってしまいます。こういった場合は、おそらく(stopボタンを押すまで)無限に繰り返す機能がほしいと思うでしょう。さあ、アーメン・ブレイクのサンプルを無限にループさせてみましょう。
loop do
sample :loop_amen
sleep sample_duration :loop_amen
end
loopについて知っておかなくてはならない重要な点は、これはコードの中でブラックホールのように動いてしまう点です。一度loop機能が動いてしまうと、stop
ボタンを押さない限り永遠に再生されるということです。つまり、これはloopより後ろにあるコードを絶対に聞くことが出来ないということを意味しています。例えば、下の例で言うと、シンバルの音はloopより後ろにあるため、決して再生されることはありません。
loop do
play 50
sleep 1
end
sample :drum_cymbal_open
さあ、これで回数を指定するイテレーション(反復)と永遠に繰り返すループのコーディング方法を理解することができましたね!
ランダムな音符を再生する(前章参照)だけでなく、あるコードとそれとは別なコードの実行をランダムに決めたくなるかもしれません。例えば、ドラムとシンバルをランダムに再生したいような場合です。このような場合、if
文を使うことで実現できます。
それではコインをトス(投げる)してみましょう。もしもコインが表であればドラムを鳴らし、裏であればシンバルを鳴らします。簡単ですね。コイントスの機能はone_in
という機能(ランダムのセクションで紹介しています)によって実現されます。2つのうちの1つというように条件を細かく指定するときにはone_in(2)
と記述すると、ドラムを鳴らすコードとシンバルを鳴らす2つのコードどちらかを決められるようになります。
loop do
if one_in(2)
sample :drum_heavy_kick
else
sample :drum_cymbal_closed
end
sleep 0.5
end
if文は3つのパートを持っていることに注目してみましょう。
条件 はじめの選択によって実行されるコード(条件が正しかった場合) 次の選択によって実行されるコード(条件が間違っていた場合)
典型的なプログラム言語では、概ね、真(正しいという意味)をtrue
で表現し、偽(正しくない場合)はfalse
と表記します。そのため、先の例でone_in
が行っているような、true
かfalse
か答えることができる質問が必要となります。
はじめの選択では if
とelse
の間に挟まれたプログラムが実行され、そして2番目の選択ではelse
とend
の間が実行されるということに注目しましょう。それは複数行のコードをまとめるdo/endブロックにとても似ていますね。例えば、
loop do
if one_in(2)
sample :drum_heavy_kick
sleep 0.5
else
sample :drum_cymbal_closed
sleep 0.25
end
end
sleep 0.5
やsleep 0.25
など、異なる休符時間を持つ場合、そのどちらかに応じることになります。
時には、任意のコードを1行だけ実行したいときがあるでしょう。これはif
と条件を後ろに記述することで可能です。例えば、
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
上のコードでは、それぞれの音符が持つ別の確率によって、異なる数のコード(和音)を奏でるでしょう。
それでは、強烈なベースラインとかっこいいビートを作った場合、どのようにしてそれらを同時に鳴らしたらいいでしょう? 1つの回答としては、手動でそれらを同時に鳴らす事です ― まず、いくつかのベースを演奏し、その後にいくつかのドラム、またその後にベースというように…しかしながら、すぐに沢山の楽器を処理することが難しいことに気づくでしょう。
もし、Sonic Piが自動的にそれらを作り出せるとしたらどうでしょう? thread(スレッド)と呼ばれる特別な命令によってそれが可能になります。
例を単純にするために、以下のコードを強烈なベースラインとかっこいいビートだと思ってください。
loop do
sample :drum_heavy_kick
sleep 1
end
loop do
use_synth :fm
play 40, release: 0.2
sleep 0.5
end
ループはプログラムのブラックホールのようだと以前にお話しました。一度ループを入れると、stopボタンを押さない限り、そこから抜け出せなくなります。では、どうしたら同時にふたつの繰り返しを演奏することが出来るでしょう? 私たちは、同時にそれらのコードをタイミングを合わせスタートさせるようにSonic Piに伝えなくてはいけません。これがスレッドを使った解決方法なのです。
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
はじめのdo/endブロックをin_thread
で囲むことで、次にくるdo/endブロックをぴったりと同時にループさせるようにSonic Piに命令することができます。それではドラムとベースラインを同時に鳴らすことに挑戦してみましょう!
そして、もう1つの音を追加したいので、先ほどのように繰り返しを入れてみましょう。
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
loop do
use_synth :zawa
play 52, release: 2.5, phase: 2, amp: 0.5
sleep 2
end
前と同じ問題が出てきましたね。in_thread
によって最初の繰り返しと2つ目の繰り返しが同時に演奏されています。しかし3番目の繰り返しが演奏されません。ですので以下のように、もう1つのスレッドが必要となります。
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
驚くべきことにRun
ボタンを押すということは、実際にはコードを実行するための新しいスレッドを作っていることになります。そのために複数回Run
ボタンを押すことは、互いの上に音を階層化することになります。Run
それ自体がスレッドであるために、音を自動的に紡ぎ合わせることになるのです。
Sonic Piをマスターしようとするとき、スレッドが、音楽のために最も重要な構成要素であることに気がつくでしょう。スレッドの重要な役割の1つとして、他のスレッドから現在の設定を分離することがあります。どういうことかというと、例えばuse_synth
を使ってシンセの種類を変更する時、現在のスレッド中にあるシンセだけを変更します。他のどのスレッドも変更しません。そのことを確認してみましょう。
play 50
sleep 1
in_thread do
use_synth :tb303
play 50
end
sleep 1
play 50
真ん中の音だけがほかのものと違うことに注目してみましょう。use_synth
の宣言はスレッドの中だけに影響し、スレッドの外にあるものには影響しません。
in_thread
を使って新しいスレッドを作ると、新しいスレッドには現在のスレッドの全ての設定が自動的に継承されます。ではその機能を見てみましょう。
use_synth :tb303
play 50
sleep 1
in_thread do
play 55
end
2番目の音符は、それが別のスレッドから再生されたにもかかわらず:tb303
シンセで演奏されることに注目してください。use_*
関数を使ったいかなる設定も同様に作用するでしょう。
スレッドが新規に作成されると、元のスレッドからすべての設定を継承しますが、スレッド作成以降の変更を共有することはありません。
最後に、スレッドに名前つける機能を覚えましょう。
in_thread(name: :bass) do
loop do
use_synth :prophet
play chord(:e2, :m7).choose, release: 0.6
sleep 0.5
end
end
in_thread(name: :drums) do
loop do
sample :elec_snare
sleep 1
end
end
このコードを実行した際、ログ画面を見てみましょう。ログの中にスレッドの名前が表示されることを確認できましたか?
[Run 36, Time 4.0, Thread :bass]
|- synth :prophet, {release: 0.6, note: 47}
名前付きのスレッドについて知っておくべき最後のひとつは、ある名前の付いたスレッドは同時に1つだけ実行されることです。では以下を見てみましょう。次のコードを考えてみてください。
in_thread do
loop do
sample :loop_amen
sleep sample_duration :loop_amen
end
end
Bufferに上のコードを貼り付けて、Run
ボタンを押します。数回押してみましょう。複数のアーメン・ブレイクが不協和音として反復されるでしょう。もういいですよね。Stop
ボタンを押しましょう。
この動作はこれまで何度も見てきました。Runボタンを押すと、既に鳴っているサウンドのレイヤーの一番上にサウンドを追加します。このためループが含まれている場合、Runボタンを3回押すと、3つのレイヤーが一斉に再生されます。
ただし、名前付きのスレッドでそれは異なります。
in_thread(name: :amen) do
loop do
sample :loop_amen
sleep sample_duration :loop_amen
end
end
このコードでRunボタン複数回、押してみてください。ひとつのアーメン・ブレイクのループのみが聞こえるでしょう。そして下記のテキストがログ画面に表示されます。
==> Skipping thread creation: thread with name :amen already exists.
Sonic Pi は、:amen
という名前があるスレッドが既に存在するため、別のものを作成しませんと伝えています。
この動作はすぐに使う必要性はないように思えますが、ライブコーディングを始めると、非常に便利なものになるでしょう。
一度、膨大なコードを書き始めると、それらの構造をより簡単かつ整理された状態で把握できるように、構築しまとめたいと感じることになるでしょう。ファンクション
(関数)はそんなことをとても効果的に成し遂げる方法です。この関数を使うとコードのまとまりに対して名前をつけることも可能になります。早速、見ていきましょう。
define :foo do
play 50
sleep 1
play 55
sleep 2
end
ここではfoo
という名前を付けた新しい関数を定義しています。この章ではすっかりお馴染みのdo/endブロックと、define
という魔法の言葉の後ろに、この関数に付けたい名前を続けています。関数の名前はfoo
である必要はなく、bar
やbaz
といったどんなものでも構いませんが、理想的にはmain_section
やlead_riff
といった何か意味のあるものがよいでしょう。
関数を定義するとき、その名前に:
(コロン)を付加することを忘れないでください。
いったん1つの関数を定義すると、ただ名前を書くことでそれを呼びだすことができます。
define :foo do
play 50
sleep 1
play 55
sleep 0.5
end
foo
sleep 1
2.times do
foo
end
foo
は、イテレーション(反復)ブロックの中からも使えたり、play
やsample
が書けるところであればどこからでも使えます。このことは、楽曲の中で利用可能な意味のある言葉を作り出したり、自己表現したりする優れた方法を提供します。
Run
を超えた関数の利用これまでのところ、Run
ボタンを押すたびに、Sonic Piを完全に白紙の状態から始めたことにして、表示されているBuffer以外のコードは無いものとしていました。これは、別のBufferまたは別のスレッド内のコードを参照できなかったからです。しかし、関数はそれを変えることができます。あなたが関数を定義すると、Sonic Piはそれを覚えることができます。では、ちょっとやってみましょう。まずBufferにあるすべてのコードを消して、次のものに変更します。
foo
Run
ボタンを押して、関数のfoo
が再生されることを確認してください。コードはどこにいったのでしょう? また、Sonic Piは、実行の仕方をどのように知っていたのでしょうか? Sonic PiはBufferを消したあとでも、あなたが打ち込んだ関数を覚えていて、定義した関数をしっかりと再生してみせたのです。この動作はdefine
もしくはdefonce
を使用した時にだけ働く機能です。
最小値と最大値の情報をrrand
へ渡すように、引数を受け取る関数についても興味を持つかもしれません。ちょっと見てみましょう。
define :my_player do |n|
play n
end
my_player 80
sleep 0.5
my_player 90
この例はあまり面白いものではありませんが、ポイントとなる点を示しています。ここでは、引数の付いたmy_player
という名前の関数を、play
の独自のバージョンとして作成しています。
この引数はdefine
で括られたdo/endブロックのdoの後に記述する必要があります。引数は、垂直のバー|
で囲み、複数の引数を扱う場合はカンマ ,
で分割し、引数の名前はどんな言葉でも付けることが出来ます。
この魔法は、define
を使いdo/endブロック内で行われます。また、実行されるための値のような変数名を使うことも出来ます。この例で言うと、n
という値の音符を鳴らしています。引数はコードが起動した際にその領域に記憶されている実際の数値に置き換えられるという約束と考えることができます。あなたが関数を呼び出した際は、この数値を関数に置き換えて実行することが出来るのです。このmy_player 80
というのは、80という音符を鳴らすということです。関数の定義の中で、n
はすぐに80
に置き換えられます。そしてplay n
はplay 80
となるのです。また次にmy_player 90
という関数を呼び出すと、今度はn
が90
に置き換えられ、play n
はplay 90
として再生されるのです。
それではさらにおもしろい例を見てみましょう。
define :chord_player do |root, repeats|
repeats.times do
play chord(root, :minor), release: 0.3
sleep 0.5
end
end
chord_player :e3, 2
sleep 0.5
chord_player :a3, 3
chord_player :g3, 4
sleep 0.5
chord_player :e3, 3
ここではrepeats.times do
という行の中で1つの数値のようにrepeats
が使われます。また、play
を呼び出した際の音符の名前と同じようにroot
が使われています。
関数に多くの処理を移動することによって、コードをとても表現力豊かにかつ読み易く書けることがわかりましたね!
コードを書いていく中で役に立つことは、覚えやすい名前を作成することです。Sonic Piはこれをとても簡単に作ることができます。あなたが使用したいと思う名前に続けて、等号のイコール(=
)を書き、そのあとに覚えておきたい名前を書きます。
sample_name = :loop_amen
ここで、:loop_amen
という記号は変数sample_name
に’記憶’されました。:loop_amen
を使いたいところではどこでもsample_name
を使うことが可能です。例えば次のとおりです。
sample_name = :loop_amen
sample sample_name
Sonic Piでは変数を使う際、3つの主要な使い方があります。意味の伝達、重複の管理、そして結果の獲得です。
コードを書くとき、あなたはコンピュータが理解しOKを出してくれることだけを考え、どのようにコンピュータに伝えて動作させるのかを意識するだけであれば、それは簡単な事ですね。しかし、覚えておかなくてはいけない大事なことは、コンピュータがコードを読むということだけではないということです。他の人もそれを読み、何が起こっているか理解をしようとするでしょう。あなた自身も将来、自分の書いたコードを見返して、どんなことをしたのか? 理解する必要がある時が来るかもしれません。たぶん確実にあなたにも他の人にも、そういったことが起こるのです!
あなたのコードがどのように動いているのか他人が理解をするための1つの方法として、コメントを書く(前章で確認できます)という方法があります。もう1つの方法として、理解しやすい変数名を使うという方法があります。次のコードを見てください。
sleep 1.7533
上の例だけを見ると、なぜ1.7533
という数値を使ったのでしょう? その数値はどこから来たのか? それは何を意味しているのか? という疑問がわきます。しかし、次のコードを見てみましょう。
loop_amen_duration = 1.7533
sleep loop_amen_duration
こう書くとすぐに1.7533
がサンプル音源:loop_amen
の長さであるということがわかりますね。もちろん、下記のように一行に書くことも可能です。
sleep sample_duration(:loop_amen)
どちらを用いたとしても、コードの意味がよりわかりやすいものになりました。
コードの中では沢山の重複が頻繁に見られます。また、もし何かを変更したいときは、膨大な場所を変更する必要も出てきます。次のコードをみて下さい。
sample :loop_amen
sleep sample_duration(:loop_amen)
sample :loop_amen, rate: 0.5
sleep sample_duration(:loop_amen, rate: 0.5)
sample :loop_amen
sleep sample_duration(:loop_amen)
上のコードは:loop_amen
で沢山のことをしすぎています! もし:loop_garzul
のような他のサンプルのループによる音が聞きたい場合はどうしましょう? そうするにはすべての:loop_amen
を探しだして:loop_garzul
に変更する必要があります。そんな変更ができる沢山の時間があればいいんですが…もし仮にあなたがステージの上で演奏している最中だったらどうでしょう? 特にみんなのダンスを止めないために、変更するためのそんな優雅な時間はないかもしれません。
下記のようなコードを書いたとして、
sample_name = :loop_amen
sample sample_name
sleep sample_duration(sample_name)
sample sample_name, rate: 0.5
sleep sample_duration(sample_name, rate: 0.5)
sample sample_name
sleep sample_duration(sample_name)
これは先程のコードと同じです(試してみてください)。しかし、sample_name = :loop_amen
の一行をsample_name = :loop_garzul
に変更するだけで多くの箇所を変更できました。そして、それは変数の力によるものです。
最後に、変数を使う優れた理由はそのコードの結果の獲得をするということです。例えば、サンプル音源の長さを使って何かを行いたい時など。
sd = sample_duration(:loop_amen)
上記のように書くことで、今、:loop_amen
というサンプルの長さが必要な時、どこにでもsd
を使うことが出来るようになります。
おそらくもっと重要なのは、変数は、playやsampleの結果をキャプチャすることができることです。
s = play 50, release: 8
またこのように書くことで s
が変数として記憶され、シンセをコントロールできるようになります。
s = play 50, release: 8
sleep 2
control s, note: 62
また、後の章ではもっと詳しくシンセをコントロールすることも学びます。
変数はモノに名前を与えたり、ある処理においてどういった結果が返ってくるのか推測するのに役立ちます。 ただし、通常、変数はスレッド内で完結するローカル変数として定義する必要があることを知っておく必要があります。 したがって、以下のようなことをしてはいけません。
a = (ring 6, 5, 4, 3, 2, 1)
live_loop :sorted do
a = a.sort
sleep 0.5
puts "sorted: ", a
end
live_loop :shuffled do
a = a.shuffle
sleep 0.5
end
In the above example we assign a ring of numbers to a variable a
and then used it within two separate live_loop
s. In the first live loop every 0.5
s we sort the ring (to (ring 1, 2, 3, 4, 5, 6)
) and then print it out to the log. If you run the code, you’ll find that the printed list is not always sorted!. This may surprise you - especially that sometimes the list is printed as sorted, and sometimes it is not. This is called non-deterministic behaviour and is the result of a rather nasty problem called a race-condition. The problem is due to the fact that the second live loop is also manipulating the list (in this case shuffling it) and by the time the list is printed, sometimes it has just been sorted and sometimes it has just been shuffled. Both live loops are racing to do something different to the same variable and every time round a different loop ‘wins’.
There are two solutions to this. Firstly, don’t use the same variable in multiple live loops or threads. For example, the following code will always print a sorted list as each live loop has its own separate variable:
live_loop :shuffled do
a = (ring 6, 5, 4, 3, 2, 1)
a = a.shuffle
sleep 0.5
end
live_loop :sorted do
a = (ring 6, 5, 4, 3, 2, 1)
a = a.sort
sleep 0.5
puts "sorted: ", a
end
However, sometimes we do want to share things across threads. For example, the current key, BPM, synth etc. In these cases, the solution is to use Sonic Pi’s special thread-safe state system via the fns get
and set
. This is discussed later on in section 10.
一度、関数やスレッドを使用したとても高度なライブコーディングを行うと、あるスレッドが止まってしまうような間違いがとても容易に発生することを理解するでしょう。Run
ボタンを押してスレッドを再スタートさせることは容易にできるので、それは全然大した問題ではないのでしょう。しかし、スレッドを再スタートさせるときは、元々のスレッドと時間がずれることになります。
以前話した時に、新しいスレッドがin_thread
として作られると元のスレッドのすべての設定が継承されることを学びました。これは現在の時間を含んでいます。つまり、スレッドが同時にスタートするときには常に他のスレッドと同期していることを意味しています。
しかし、あるスレッドを独自のタイミングで起動したときは、現在実行中の他のスレッドと同期していることはほとんどないでしょう。
Sonic Pi はcue
とsync
という関数を使ってこの問題の解決方法を提供します。
cue
はすべての他のスレッドに向けてビートメッセージを送ることができます。初期状態の他のスレッドでは、これらのビートのメッセージは関係付けられず、無視されます。しかし、sync
関数を使えば、あなたは簡単にこの関連付けを登録することができるのです。
sync
という機能は、一定の時間、実行中のスレッドを止めるsleep
という関数と非常に似ていることに気づくことが重要です。しかし、sleep
ではどのくらい休止させるかを決めることができましたが、sync
ではそれを決めることができず、sync
は長さに関わらず、次のcue
が出てくるまで待つのです。
それでは、もうちょっと詳しく見ていきましょう。
in_thread do
loop do
cue :tick
sleep 1
end
end
in_thread do
loop do
sync :tick
sample :drum_heavy_kick
end
end
ここでは2つのスレッドが使われています。1つは、音は鳴りませんがメトロノームのような機能として1秒ごとに:tick
というビートメッセージを送っています。2つ目のスレッドは、tick
というビートメッセージと同期し、その際にcue
のスレッドの時間の情報を継承して実行を続けます。
この結果、:drum_heavy_kick
のサンプルは、たとえ同時に実行されていない2つのスレッドであったとしても、他のスレッドが:tick
のメッセージを送信したタイミングで、ぴったりと聴くことができるでしょう。
in_thread do
loop do
cue :tick
sleep 1
end
end
sleep(0.3)
in_thread do
loop do
sync :tick
sample :drum_heavy_kick
end
end
このちょっとやっかいなsleep(0.3)
は、1つめのスレッドとは時間がずれた2つめのスレッドを作り出してしまいます。しかしながら、cue
やsync
を使えば、タイミングがずれてしまうようなアクシデントを回避してくれます。
cue
には:tick
以外のどんな好きな名前でも付けられます。その際には他のスレッドと同期させるために必ず正しい名前を使用する必要があります。もし違った場合、永遠に(もしくはストップボタンを押すまで)それはcue
のメッセージを待ち続けることになります。
それではcue
の名前付けを見てみましょう。
in_thread do
loop do
cue [:foo, :bar, :baz].choose
sleep 0.5
end
end
in_thread do
loop do
sync :foo
sample :elec_beep
end
end
in_thread do
loop do
sync :bar
sample :elec_flip
end
end
in_thread do
loop do
sync :baz
sample :elec_blup
end
end
ここではメインのcue
ループでビートメッセージをランダムに:foo
と:bar
、:baz
に送るようにしています。それから3つのスレッドがそれぞれ独自に同期して、それぞれ異なるサンプルの音を再生します。実際には、sync
スレッドとして用意した3つのスレッドのいずれかがcue
スレッドとランダムに同期し、0.5秒毎にサンプル音の再生を聴くことができるでしょう。
逆にsync
スレッドを単に次のcue
まで待たせるようにしても、もちろんそれは動作します。
Sonic Piには、あなたの作ったサウンドに簡単にスタジオ·エフェクトを追加できるという最もやりがいのある楽しい側面があります。たとえば、部分的にリバーブを追加したり、エコーやディストーション(歪み)、ワブルベース(ベース音にフィルタLFOを掛け、断続的な音にすること)を加えることができます。
Sonic Piには、エフェクトを追加する非常にシンプルで強力な方法があります。さらに、それをチェイン(連結)させることができ(これにより、ディストーション(歪み)を通し、その後エコー、さらにリバーブということができます)、またエフェクトユニットのオプションを(シンセやサンプルにオプションを与えるのと同じように)個別に制御することもできます。さらに、エフェクトが実行されている間にも、オプションを変更することができます。これにより、例えば、トラック全体を通してベースのリバーブを強くしていくといったことも可能です。
もし、この話が少し複雑に聞こえる場合でも、心配は無用です。一度、少し触れてみれば、すぐに理解することができることでしょう。いわば、ギターのエフェクターのようなものをイメージしてください。購入できるギターエフェクターには多くの種類がありますが、リバーブ、ディストーションなど幾つかを数珠繋ぎに追加することができます。ギタリストは、自分のギターにエフェクターの1つ(ディストーションなど)を接続し、そして別のケーブルでリバーブエフェクターに繋ぎます。そしてリバーブエフェクターの出口はギターアンプに繋ぐことができるわけです。
ギター -> ディストーション -> リバーブ -> アンプ
これをエフェクトチェインと呼びます。Sonic Piは正にこれをサポートしています。さらに、ディストーション、リバーブ、エコーなどのエフェクターの多くは、どのくらいエフェクトを加えるのか、制御できるようなダイヤルやスライダを持っていて、Sonic Piもこの種の制御をサポートしているということです。最終的に、あなたはギタリストがエフェクターを使いながらギターを演奏する姿を想像することができていることでしょう。ただ、Sonic Piでは、それをコントロールするために他の何かを必要としません。それはコンピュータが代役を務めているのです。
さあ、エフェクトを探究していきましょう!
このセクションでは、エフェクト「リバーブとエコー」の組み合わせを見ていきます。それらをどのようにチェイン接続するか、どのように制御するのか、これらの使用方法について説明します。
Sonic Piのエフェクトシステムは、ブロックを使用します。セクション5.1を読んでいなければ、戻って目を通してください。
リバーブを使用する場合、次のように特殊なコードwith_fx :reverb
をブロックに書きます。
with_fx :reverb do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
早速コードを実行してリバーブを聞いてみましょう。いいでしょ! 音全体が残響効果で素晴らしくなります。
さあ、次はブロックの外にコードを書いて何が起こるか見てみましょう。
with_fx :reverb do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
sleep 1
play 55
どうして最後のplay 55
にリバーブが適用されないのでしょうか。それはブロックの外部に書かれているため、リバーブエフェクトは適応されないのです。
do/endブロックの手前で音を生成する場合も同様にリバーブは適用されません。
play 55
sleep 1
with_fx :reverb do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
sleep 1
play 55
選択できるエフェクトは他にもたくさんあります。エコーはどうでしょうか?
with_fx :echo do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
Sonic Piのエフェクトブロックの強力な側面の1つは、既にplay
とsample
で見てきたオプションと同様のオプションが渡されることです。たとえば、エコーの楽しいオプションは、拍単位で遅れの長さを示すphase
があります。下記のコードで、エコーの遅れをゆっくりにしてみましょう。
with_fx :echo, phase: 0.5 do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
エコーの遅れを早くしてみましょう。
with_fx :echo, phase: 0.125 do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
エコーが8拍の時間でフェードアウトする様に、decay:
を設定してみましょう。
with_fx :echo, phase: 0.5, decay: 8 do
play 50
sleep 0.5
sample :elec_plip
sleep 0.5
play 62
end
エフェクトブロックで最も強力な側面の1つは、入れ子ができるということです。これはとても簡単にエフェクト同士を連結することができます。たとえば、あるコードにエコーとリバーブを掛けたい場合どうしますか? その答えは単純です。1つのエフェクトの内側にもう一方を配置するだけです。
with_fx :reverb do
with_fx :echo, phase: 0.5, decay: 8 do
play 50
sleep 0.5
sample :elec_blup
sleep 0.5
play 62
end
end
オーディオの流れについて内側から外側へ追ってみましょう。play 50
を含むblock
のdo/endブロック内のコード全ては、最初にエコーエフェクトに送られ、その音がリバーブエフェクトへと順に送られていきます。
クレイジーなサウンドを得るために非常に深く入れ子を使用することができます。しかし、一度にたくさんのエフェクトを入れ子で実行すると多くのリソースを必要とするため、注意してください。そのため、特にRaspberry Piのような低電力供給のプラットフォームではエフェクトの使用を節約することも必要です。
Sonic Piは、あなたが演奏するためにたくさんのエフェクトを搭載しています。どういったエフェクトが使えるのかを見つけ出すためには、ヘルプシステム画面の下にあるエフェクト
ボタンをクリックし、利用可能なリストを見てください。ここに私のお気に入りを記載しておきます。
wobble, reverb, echo, distortion, slicer
さあ、エフェクトを追加して驚きの新しいサウンドの虜となってください!
エフェクトの外観は一見シンプルですが、実際には内部は異常に複雑なモンスターです。そのシンプルさは、しばしば、この機能を酷使させようと誘惑します。もしもあなたが強力なマシンを持っている場合は問題は無いかもしれませんが、Raspberry Piで動作させる場合、確実にビートを刻み続けるようにしたいのであれば、どのくらいの負荷をかけているのか注意する必要があります。
このコードを考えてみましょう。
loop do
with_fx :reverb do
play 60, release: 0.1
sleep 0.125
end
end
このコードは非常に短いリリース時間で音符60
を演奏しています。そして、リバーブを加えたいために、コードをリバーブで囲んでいます。問題はなさそうには見えますが…。
コードが何をするかを見ていきましょう。まず、loop
は内側のすべてが永遠に繰り返すことを意味します。次に、with_fx
ブロックがあります。これはループが繰り返される度に、新しいリバーブエフェクトを作成することを意味します。ギターの弦を弾くたびに別々のリバーブエフェクターを用意して演奏しているようなものです。そんなことができたらかっこいいかもしれませんが、それはあなたが望むものとは限らないということです。たとえば、Raspberry Piでこのコードを実行させるためにはとても労力を要します。リバーブはwith_fx
によって制御され、停止か消去されるまで、生成され続け、スム−ズな演奏に必要とする大切なCPUパワーを奪うことになりかねません。
ギタリストのように、すべての音が1つのリバーブエフェクターを通る従来の設定と同様の流れを作るには、どうしたら良いでしょうか? とてもシンプルです。
with_fx :reverb do
loop do
play 60, release: 0.1
sleep 0.125
end
end
with_fx
ブロックの内部にloop
を配置します。この方法では、ループ内すべての音符の再生にリバーブを1つだけ作成します。このコードは効率的で、Raspberry Piで正常に動作します。
loop
内の繰り返しの上位にwith_fx
を使うことで折り合いを付けます。
loop do
with_fx :reverb do
16.times do
play 60, release: 0.1
sleep 0.125
end
end
end
loop
の外部にwith_fx
を引き上げることで、16音符ごとに新しいリバーブを作成しています。
このようなパターンは一般的なので、16.times
のブロックを書かずに全く同じ動作をするオプションをwith_fx
はサポートしています。
loop do
with_fx :reverb, reps: 16 do
play 60, release: 0.1
sleep 0.125
end
end
reps: 16
の例も16.times do
の例も同様に振る舞います。reps: 16
はdo/end
のブロックを16回繰り返すので、どちらも交換可能に使うことができ、どちらか好きな方を選ぶことができます。
「間違いはない、あるのはただ可能性だけ」と言ったのを思い出してください。しかしながら、これらの異なるアプローチからは、異なるサウンド、また異なる性能をもたらします。あなたのプラットフォームの性能の制約の中で、最も良いと思うアプローチを使いながら演奏するようにしましょう。
これまでの章では、どのようにシンセやサンプルを扱い、アンプ(増幅)、パン、エンベロープなどのオプションを変更するのかを見てきました。呼び出された個々の音には、元来、音の継続時間を設定するデュレーションオプションが備わっています。
もしも演奏中にギターの弦を歪めビブラートさせるように、オプションを変更できたなら、それってクールではないでしょうか?
あなたは幸運です - このセクションでは、まさしくそれをどのように行うのかを紹介します。
これまでは、新しいサウンドとエフェクトを引き起こす方法についてだけ見てきましたが、Sonic Piは、演奏中の音を操り、処理する機能を備えています。次のコードのように、シンセの参照を取得するために変数を使用してこれを実現します。
s = play 60, release: 5
ここで、ローカル変数s
が音符60を演奏するシンセを表しています。この変数は、実行毎にローカルである点に注意してください。ある実行のdefineで定義された関数のように他の実行からアクセスすることはできません。
一度s
を用意すれば、control
関数を介して制御することができます。
s = play 60, release: 5
sleep 0.5
control s, note: 65
sleep 0.5
control s, note: 67
sleep 3
control s, note: 72
演奏している間に、1つのシンセのみを呼び出し、3回ピッチを変更しています。ここで注目すべき点は、4つの異なるシンセを呼び出していないということです。
標準的なオプションはcontrol
へ渡すことができるので、amp:
, cutoff:
あるいはpan:
などを制御することができます。
一度シンセが開始されると、一部のオプションは制御することができなくなります。ADSRエンベロープ·パラメータがこれに該当します。そのオプションが制御可能かは、ヘルプシステムのドキュメントを参照してください。ドキュメントに「一度設定されると変更することは出来ません」と書かれている場合、シンセが開始された後にオプションを制御することはできません。
エフェクトも、少々異なる方法をとりますが、制御する事が出来ます。
with_fx :reverb do |r|
play 50
sleep 0.5
control r, mix: 0.7
play 55
sleep 1
control r, mix: 0.9
sleep 1
play 62
end
変数を使用する代わりに、do/endプロックのブロックパラメータを使用します。これは、実行中のエフェクトとしてdo/endプロックの中から参照するパラメータとして、|
と|
の間にユニークな名前を指定する必要があります。このパラメータの振る舞いは、引数の付いた関数を使用する場合と同じです。
さあ、シンセやエフェクトをコントロールしてみよう!
シンセやエフェクトのオプションを見ていくと、_slide
で終わるオプションがあることに気づいたかもしれません。それらを試しに呼び出しても、何の効果も示さなかったかもしれません。これは通常のオプションではなく、前回のセクションで紹介したように、シンセを制御するときのみ動作をする特別なオプションです。
次の例を考えてみましょう。
s = play 60, release: 5
sleep 0.5
control s, note: 65
sleep 0.5
control s, note: 67
sleep 3
control s, note: 72
ここでは、各control
の呼び出し後、すぐにシンセのピッチの変更を聞くことができますが、ピッチが変化する間にスライドさせたくなるかもしれません。ここではnote:
オプションを制御しているので、スライドを追加するためには、シンセのnote_slide
オプションを追加する必要があります。
s = play 60, release: 5, note_slide: 1
sleep 0.5
control s, note: 65
sleep 0.5
control s, note: 67
sleep 3
control s, note: 72
control
の呼び出しの間の音程が滑らかに繋がっていることがわかるはずです。いい感じではないでしょうか。note_slide: 0.2
よりも短いスライド時間を使うことで、スライドをスピードアップすることができますし、もっと長い時間を使ってテンポを遅くすることができます。
制御することのできるオプションは、対応する_slide
オプションを持っています。
一度、実行しているシンセの_slide
オプションを設定したら、それは記憶され、対応するオプションがスライドする度に使用されます。スライドを停止するためには、次のcontrol
を呼び出す前に0
に_slide
値を設定する必要があります。
また、エフェクトオプションをスライドさせることも可能です。
with_fx :wobble, phase: 1, phase_slide: 5 do |e|
use_synth :dsaw
play 50, release: 5
control e, phase: 0.025
end
さあ、滑らかな変化と流れるような制御のために、色々スライドして楽しんでみましょう。
プログラマのツールキットで非常に有用なツールはデータ構造です。
時には、複数の要素を表したものを使いたいかもしれません。例えば、次々に演奏される一連の音符を保持すると便利だと気づくことがあるかもしれません。プログラミング言語は、正にこういったことを行うためにデータ構造を持っています。
プログラマが利用できるエキサイティングで奇抜なデータ構造は沢山あり、また常に新しいものが発明されています。しかし、今の我々が本当に検討するべきものは、とてもシンプルなデータ構造 - リストです。
では、より詳細に見てみましょう。まずは、リストの基本的な形式を学習し、続いて、リストがスケール(音階)やコード(和音)を表現するためにどのように使用されるのかを学習していきましょう。
このセクションでは、非常に有用なデータ構造であるリストについて見ていきます。以前に我々はランダム化の章でリストについて簡単に触れました。音符のリストから無作為に選んで再生する次のようなコードです。
play choose([50, 55, 62])
ここでは、コードやスケールを表現するためのリストの使い方についても見ていきます。最初に、コードを演奏する方法をおさらいしてみましょう。sleep
を使用しない場合、すべての音が同時に演奏されることを思い出してください。
play 52
play 55
play 59
このコードの別の表現方法を見てみましょう。
1つの方法は、[52, 55, 59]のように、すべての音符をリストに配置することです。使いやすいplay関数は、リストになった音符をどのように演奏するかをすぐに理解します。次のコードを試してみてください。
play [52, 55, 59]
おー、これは読みやすいですね。音符リストの演奏は、通常のオプションのいずれも妨げになりません。
play [52, 55, 59], amp: 0.3
もちろん、MIDIの代わりに伝統的な音符の名前を使うこともできます。
play [:E3, :G3, :B3]
多少の音楽理論の知識を持っている方なら、3オクターブでEマイナーのコードが演奏されたことがわかるでしょう。
もう1つの非常に便利なリストの機能は、リストから情報を取得する機能です。これは少し奇妙に聞こえるかもしれなませんが、本の23ページを開いてくださいと誰かに頼まれることよりも簡単なことです。リストの場合は、インデックス23の要素は何ですか? と尋ねればいいのです。唯一、奇妙なことは、プログラミングのインデックスは通常、1ではなく0から開始されることです。
リストのインデックスは1,2,3と数える代わりに、0,1,2と数えていきます。
それではもう少し詳細にみてみましょう。次のリストを見てください。
[52, 55, 59]
これは特に難しいことは何もありません。リストの2番目の要素は何でしょうか? そう、もちろん55
です。簡単ですね。それでは、同様にコンピュータが答えることができるかどうかを見てみましょう。
puts [52, 55, 59][1]
以前にこのようなものを見たことがない場合、少し奇妙に見えるかもしれませんが、大丈夫。私を信頼してください。難しいことはありません。上記の行には、puts
という命令、リストの52, 55, 59
、インデックスが[1]
の3つの部分があります。まずはじめに、Sonic Piへログの中から答えを出力させるためputsを命令します。次にリストを与えています。そして最後に第2の要素を問い合わせています。角括弧でインデックスを囲む必要があり、カウントは0
で始まるので、2番目の要素のインデックスは1
となります。下記、みてみましょう。
# indexes: 0 1 2
[52, 55, 59]
コードputs [52, 55, 59][1]
を実行してみてください。ログに55
と表示されるでしょう。インデックス1
を別のインデックスに変えてみてください。さらに長いlist
を与えて、どのように演奏で使えるのか考えてみてください。例えば、どのような音楽の構造が音符の連続として表現されるか? などです。
Sonic Piは和音名でリストを返す機能を内蔵しています。実際に試してみましょう。
play chord(:E3, :minor)
さあ、本当に動きましたね。そのままのリストよりも美しく見えるし、そして他の人にとっても読みやすいでしょう。では、どんな和音をSonic Pi はサポートをしているのでしょうか。沢山あります。次のように、いくつかのコードを試してみましょう。
chord(:E3, :m7)
chord(:E3, :minor)
chord(:E3, :dim7)
chord(:E3, :dom7)
play_pattern
関数で簡単にコード(和音)からアルベジオ(和音を構成する音を一音ずつ順番に弾いていく奏法)に変更して演奏を行うことができます。
play_pattern chord(:E3, :m7)
このコードでは、とてもゆっくりと演奏をしていて、あまり楽しくないかもしれません。play_pattern
は、リスト内の各音符のplay
を呼び出す度にsleep 1
を呼び出して演奏します。play_pattern_timed
関数を使用することで、独自のタイミングと速度を指定することがきます。
play_pattern_timed chord(:E3, :m7), 0.25
play_pattern
には時間のリストを渡すこともでき、それは循環する時間として扱われます。
play_pattern_timed chord(:E3, :m13), [0.25, 0.5]
これは次のコードと同じです。
play 52
sleep 0.25
play 55
sleep 0.5
play 59
sleep 0.25
play 62
sleep 0.5
play 66
sleep 0.25
play 69
sleep 0.5
play 73
どちらの書き方を好みますか?
Sonic Piは広い範囲の音階を演奏できます。C3メジャースケールの再生はどのように行うのでしょうか?
play_pattern_timed scale(:c3, :major), 0.125, release: 0.1
さらに多くのオクターブを実行することができます。
play_pattern_timed scale(:c3, :major, num_octaves: 3), 0.125, release: 0.1
ペンタトニックスケール(オクターブに5つの音が含まれる音階のこと)のすべての音符はどうでしょう?
play_pattern_timed scale(:c3, :major_pentatonic, num_octaves: 3), 0.125, release: 0.1
コードとスケールは、ランダムな選択を強いるには素晴らしい制約です。コードE3マイナーからランダムに音符を取り出すには次の例を実行してください。
use_synth :tb303
loop do
play choose(chord(:E3, :minor)), release: 0.3, cutoff: rrand(60, 120)
sleep 0.25
end
異なる和音名やカットオフする範囲を試してみましょう。
Sonic Piによってサポートされているスケールやコードを検索するには、このチュートリアルの左にある命令
ボタンをクリックし、APIリストからchord
かscale
を選びます。メインパネルの情報に、コードやスケールの長いリストが現れるまで下にスクロールしてください。
「間違いはない、あるのはただ可能性だけ」ということを思い出して、楽しんでください。
標準のリストを一捻りした面白いものにリングがあります。いくつかのプログラミングを理解していれば、リングバッファやリングアレイなどを見たことがあるかもしれません。ここでは、まさにring
(環状リスト)について見ていきます - それは短く、簡単です。
リストに関する前のセクションでは、インデックスの機構を使用してリストから要素を取り出す方法を説明しました。
puts [52, 55, 59][1]
もしインデックス100を取り出そうとしら、何が起こるでしょう? まあ、3つの要素しか持たないリストの中でインデックス100の要素は、明らかにありません。だからSonic Piは空を意味するnil
を返すでしょう。
ここでは、現在のビート(拍子)が継続的に増加するcounter
を考えてみましょう。まずはカウンタとリストを作成します。
counter = 0
notes = [52, 55, 59]
これで、リストの音符にアクセスするためのカウンタを使用することができます。
puts notes[counter]
素晴らしい、52
を取得しました。カウンタを増やして別の音符を取得してみましょう。
counter = (inc counter)
puts notes[counter]
すごいでしょう、55
を取得し、それを再び繰り返すならば59
を得ます。さらに繰り返す場合は、リスト内の数が不足しnil
になるでしょう。では、ちょうどループのはじめに戻り、再びリストの先頭から開始したい場合はどうしたらようでしょうか? そのためにリングを使います。
リングは、2つの方法のどちらか1つで作成することができます。どちらの方法もリングの要素を引数とするring
関数を利用します。
(ring 52, 55, 59)
また、通常のリストを取得し、それに.ring
メッセージを送ることで、リングに変換することができます。
[52, 55, 59].ring
いったんリングを取得したら、通常のリストを使用する場合とまったく同じ方法で使用することができます。ただし、インデックスがマイナスもしくはリングの数値より大きい場合は、通常のリストと動作が異なり、先頭あるいは末尾に巻き戻ってリングの要素のどれか1つを必ず指します。
(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
ここで、現在のビート(拍子)の値を表すために変数を使用しているとしましょう。その変数は、現在表しているビート値に関わらず、演奏に使用する音符やリリース・タイム、その他リングに格納された何か有用な値を取得するのに、インデックスとして使用できます。
知っておくと役立つこととして、scale
(音階)とchord
(和音)によって返されたリストもリングであり、任意のインデックスでそれらにアクセスすることを可能にします。
ring
関数の他にも、リングを作成する沢山の関数があります。
range
は始点、終点とステップサイズを指定します。
bools
は、1
と0
を使用して簡単にブール値を表すリングを作成できます。
knit
は一連の繰り返される値のリングを作成できます。
spread
はユークリッド分布に従ったブール値のリングを作成します。
詳細については、個々のドキュメントを見てください。
range
やspread
のようなコンストラクタ(作成関数)に加えて、別なリングの作成方法としては、作成したリングを操作する方法があります。
次のような単純なリングを作成します。
(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)
ここまでで既にリングを作成する強力な方法を見てきましたが、これらのチェインコマンドを一緒に用いることで本当の力を発揮します。
リングをシャッフルし、最初の要素を削除し、それに続く3つの要素を得る場合にはどうすればよいでしょう?
段階的に見ていきましょう。
(ring 10, 20, 30, 40, 50)
- リングの最初の状態
(ring 10, 20, 30, 40, 50).shuffle
- シャッフルし - (ring 40, 30, 10, 50, 20)
(ring 10, 20, 30, 40, 50).shuffle.drop(1)
- 最初の要素を削除し - (ring 30, 10, 50, 20)
(ring 10, 20, 30, 40, 50).shuffle.drop(1).take(3)
- 3つの要素を得る - (ring 30, 10, 50)
コマンドを一緒にくっつけるだけで、これらのコマンドの長いチェインを作れることが分かったと思います。チェインコマンドは好きな順序で組み合わせることができます。またそれにより、既に存在するリングから新しいリングを生成する、とても豊かで強力な方法を作り出すことができます。
リングは強力で重要な特徴を持っています。それは不変性と言って、リングを変更できないということを意味しています。このセクションで紹介しているチェインコマンドが、リングを変更するのではなく、新しいリングを作成していることを意味しています。これにより、スレッドを跨いでリングを共有して、同じリングを使っている他のスレッドに影響を与えないで、チェインを開始できることを意味しています。
ここに利用可能なチェインコマンドを記載しておきます。
.reverse
- 逆順のリングを返却します
.sort
- ソートされたリングを作成します
.shuffle
- シャッフルされたリングを作成します
.pick(3)
- .choose
を3回呼び出した結果のリングを返却します
.pick(3)
- .choose
を3回呼び出した結果のリングを返却します
.take(5)
- 最初の5つの要素をのみからなる新しいリングを返却します
.drop(3)
- 最初の3つの要素以外の要素からなる新しいリングを返却します
.butlast
- 最後の要素が欠けた新しいリングを返却します
.drop_last(3)
- 最後の3つの要素が欠けた新しいリングを返却します
.take_last(6)
- 最後の6つの要素をのみからなる新しいリングを返却します
.stretch(2)
- リングの個々の要素を2回ずつ繰り返します
.repeat(3)
- リング全体を3回繰り返します
.mirror
- 逆順のリングを自分自身に追加します
.reflect
- mirrorと同様ですが、真ん中の要素を重複させないようにします
.scale(2)
- returns a new ring with all elements multiplied by 2 (assumes ring contains numbers only)
数字を引数に取っているチェインコマンドは、他の数字を取ることももちろん可能です。最初の5個の要素を削除したい場合には、.drop(3)
の代わりに、気軽に.drop(5)
を呼んでください。
Sonic Piの中で最もエキサイティングな特徴の1つは、ライブでギターをかき鳴らすのと同じように、ライブで音楽を演奏しながら、その場でコードを書き換え、音を変化させていくことができることです。この方法で優れているのは、(シンプルなループを走らせ、そのサウンドが完璧になるまで調整するように)作品を作っている間にどのような音が出来ているかその場でフィードバックを得られることです。ですが、一番の利点は、Sonic Piでステージ上でライブができることです。
このセクションでは、静的なコードのチューニングの基本から動的なパフォーマンスまで扱います。
しっかりついてきてくださいね。
ここまでの章で、我々は実際に楽みながら演奏をする方法を十分に学んできました。この章では、これまでのすべての章から、どの様に作曲を開始し、ライブパフォーマンスに繋げるかを紹介していきます。そのために3つの主な要素が必要になります。
チェック要素:音を作るコードを書く能力 チェック要素:ファンクション(関数)を作成する能力 チェック要素:(名前付き)スレッドを使う能力
よーし、始めましょう。最初の音をライブコーディングしましょう。まず演奏したいコード含む関数が必要です。簡単なところから始めましょう。スレッドでその関数を呼び出すループもほしいところです。
define :my_loop do
play 50
sleep 1
end
in_thread(name: :looper) do
loop do
my_loop
end
end
もし上のコードが少し複雑に見える場合は、ファンクション(関数)とスレッドのセクションに戻って復習してください。既にこれらを頭に焼き付けているならば、それほど複雑ではないでしょう。
ここにあるものは、単にplay 50
を演奏し、ビートのためにsleep 1
を実行するファンクション(関数)です。そして、単に繰り返して定期的にmy_loop
を呼び出す:looper
という名前付きスレッドを定義しています。
このコードを実行すると、音符50を何度も何度も繰り返します。
ここからが面白くなるところです。コードを実行したままで、50を別の数値55に変更し、もう一度Run
ボタンを押してみましょう。わお! 音が変化しましたね! ライブ!
1つの名前に1つのスレッドしか実行されないので、新しいレイヤは追加されませんでした。また、ファンクション(関数)が再定義されることより、音が変化しました。:my_loop
は新しく定義され、:looper
スレッドが新しい定義を繰り返し呼び出します。
スリープ時間をや音符を変更し、再び試してみてください。use_synth
を追加してみるのはどうでしょう? たとえば、次のように変更してみてください。
define :my_loop do
use_synth :tb303
play 50, release: 0.3
sleep 0.25
end
かなり面白くなってきましたが、それをさらに盛り上げることができます。何度も何度も同じ音符を演奏する代わりに、和音を弾いてみましょう。
define :my_loop do
use_synth :tb303
play chord(:e3, :minor), release: 0.3
sleep 0.5
end
和音からランダムな音符を演奏するのはどうでしょう。
define :my_loop do
use_synth :tb303
play choose(chord(:e3, :minor)), release: 0.3
sleep 0.25
end
またはランダムなカットオフ値を使用してみましょう。
define :my_loop do
use_synth :tb303
play choose(chord(:e3, :minor)), release: 0.2, cutoff: rrand(60, 130)
sleep 0.25
end
最後に、ドラムを追加しましょう。
define :my_loop do
use_synth :tb303
sample :drum_bass_hard, rate: rrand(0.5, 2)
play choose(chord(:e3, :minor)), release: 0.2, cutoff: rrand(60, 130)
sleep 0.25
end
どんどんおもしろくなってきましたね!
しかしながら、ファンクション(関数)とスレッドを使ったライブコーディングにステップアップする前に、一息ついて、Sonic Piでのコーディングを劇的に変えてしまうかもしれないlive_loop
について次の章を読んでいきましょう。
このチュートリアルの中でもこの章は、最も重要です。もし1つの章だけを読むのであれば、この章でしょう。もし前の章でライブコーディングの基礎を読んでいるのであれば、live_loop
は、それと同じことを少ないコード量で簡単に実現できる方法と言えます。
前の章を読んでいない場合、live_loop
はSonic Piでジャム(即興演奏)するための最良の方法でしょう。
演奏してみましょう。新しいBufferに次のように書いてください。
live_loop :foo do
play 60
sleep 1
end
Run
ボタンを押してください。1拍毎に基本的なビープ音が鳴ります。これでは楽しくないのですが、まだStop
を押さないでください。60
を65
へ変更して、Run
ボタンを押してください。
わお! リズムを崩さずに自動的に変化しました。これがライブコーディングです。
もっとベースのように変えてみてはどうでしょう? 演奏したままコードを更新しましょう。
live_loop :foo do
use_synth :prophet
play :e1, release: 8
sleep 8
end
ここでRunボタンを押してください。
カットオフを動かしてみましょう。
live_loop :foo do
use_synth :prophet
play :e1, release: 8, cutoff: rrand(70, 130)
sleep 8
end
Run
ボタンをもう一度押しましょう。
ドラムを追加してみましょう。
live_loop :foo do
sample :loop_garzul
use_synth :prophet
play :e1, release: 8, cutoff: rrand(70, 130)
sleep 8
end
e1
からc1
に音符を変更してみましょう。
live_loop :foo do
sample :loop_garzul
use_synth :prophet
play :c1, release: 8, cutoff: rrand(70, 130)
sleep 8
end
このあとは私の言うことを聞くのを止めて、自由に演奏してみましょう! 楽しんでください!
次のライブループを考えていきましょう。
live_loop :foo do
play 50
sleep 1
end
なぜ:foo
という名前をつける必要があるか疑問を持つかもしれません。この名前は、このライブループが他のすべてのライブループと異なっていることを示すために重要です。
同じ名前で実行中の2つのライブループが存在することはできません。
これは、複数同時にライブループを実行したい場合、それぞれに異なる名前を付ける必要があることを意味します。
live_loop :foo do
use_synth :prophet
play :c1, release: 8, cutoff: rrand(70, 130)
sleep 8
end
live_loop :bar do
sample :bd_haus
sleep 0.5
end
各ライブループを個別に変更し更新できます。そしてすべてちゃんと動作します。
既に気づいているかもしれませんが、ライブループは、以前に見てきたスレッドのcueのメカニズムを使用して自動的に動作します。ライブループがループするたびに、それが新しい名前を持つライブループのcue
を生成します。これにより、cue
をきっかけに何も停止せずにサウンドのループを同期させることができます。
次のような同期されていないコードを考えてみましょう。
live_loop :foo do
play :e4, release: 0.5
sleep 0.4
end
live_loop :bar do
sample :bd_haus
sleep 1
end
それを停止することなくタイミングと同期を修正することができるかを見てみましょう。まずは、foo
ループ内のsleep
の引数を0.5に変えてみましょう。
live_loop :foo do
play :e4, release: 0.5
sleep 0.5
end
live_loop :bar do
sample :bd_haus
sleep 1
end
まだ終わりではないですね。あなたはビートがまったく合っていないことに気付くでしょう。これはループがずれているからです。他と同期するように、それを修正していきましょう。
live_loop :foo do
play :e4, release: 0.5
sleep 0.5
end
live_loop :bar do
sync :foo
sample :bd_haus
sleep 1
end
おおー、すべてを停止することなく完璧に同期しましたね。
さあ、ライブループを使ってライブコーディングを始めましょう!
ライブコーディングでリングをループしていて、気が付くとたくさんのことをしていたことはないでしょうか。例えば、メロディーの音符、リズムのためのスリープ時間、コード進行や音色のバリエーションなどをリングに入れたり。
Sonic Piはlive_loop
の中でリングと一緒に使えるとても手軽なツールを提供しています。それはチックシステムと呼ばれ、tick through rings(リングをチックタックと進める) 機能を提供しています。次の例を見てください。
counter = 0
live_loop :arp do
play (scale :e3, :minor_pentatonic)[counter], release: 0.1
counter += 1
sleep 0.125
end
上のコードは次のコードと同じです。
live_loop :arp do
play (scale :e3, :minor_pentatonic).tick, release: 0.1
sleep 0.125
end
ここでは、E3マイナーペンタトニックのスケールを作成し、各要素をチックしています。これは、.tick
をscale
の呼び出しの末尾に追加することによって実現されています。チックはライブループの中でローカルであるため、個々のライブループは別々のチックを持つことができます。
live_loop :arp do
play (scale :e3, :minor_pentatonic).tick, release: 0.1
sleep 0.125
end
live_loop :arp2 do
use_synth :dsaw
play (scale :e2, :minor_pentatonic, num_octaves: 3).tick, release: 0.25
sleep 0.25
end
tick
はまた標準関数としても呼ぶことができ、その値はインデックスとして使うことができます。
live_loop :arp do
idx = tick
play (scale :e3, :minor_pentatonic)[idx], release: 0.1
sleep 0.125
end
しかし、この場合は.tick
を呼ぶほうが良いでしょう。tick
関数の用途は、チックの値で手の込んだことをしたかったり、リングのインデックス以外にチックの値を使いたかったりする場合ではないでしょうか。
チックの魅力的なところは、それが新しいインデックス(もしくはそのインデックスにあるリングの値)を返すだけでなく、次にチックを呼んだときに必ず次の値を返すことを保証していることでしょう。このようなチックの動作は、様々な形でtick
のドキュメントの例で見ることができるでしょう。しかし、ここで、チックの現在の値を見たいだけで、値を増加させたくないの場合もあることを指摘することは重要でしょう。これはlook
関数により実現可能です。look
は、標準関数として呼んだり、リングの後ろに.look
を付けたりできます。
最後に、1つのライブループに複数のチックが必要になることがあるかもしれません。これはチックに名前を付けることで実現できます。
live_loop :arp do
play (scale :e3, :minor_pentatonic).tick(:foo), release: 0.1
sleep (ring 0.125, 0.25).tick(:bar)
end
ここでは2つのチックを使っていて、1つは音符用に、もう1つはスリープ時間用にしています。これらのチックは同じライブループにあるので、別々にしておくためにユニークな名前を与えています。これはちょうどlive_loop
に名前を付ける(:
から始まるシンボル名を渡すだけ)のと同じことです。上の例では1つは:foo
でチックを呼び出し、もう1つは:bar
で呼び出しています。また、これらの値をlook
したい場合には、チックの名前をlook
に渡す必要があります。
チックシステムの能力のほどんどは、最初のうちは役に立たないでしょう。このセクションの全ての内容を学習しようとしないでください。1つのリングでチックすることだけに集中するとよいでしょう。そうすることで、live_loop
でリングをチックする簡単さや楽しみを得ることができるでしょう。
tick
のドキュメントには役に立つ例がたくさんあるので、それを見て楽しくチックを使ってみましょう!
Often it is useful to have information that is shared across multiple threads or live loops. For example, you might want to share a notion of the current key, BPM or even more abstract concepts such as the current ‘complexity’ (which you’d potentially interpret in different ways across different threads). We also don’t want to lose any of our existing determinism guarantees when doing this. In other words, we’d still like to be able to share code with others and know exactly what they’ll hear when they run it. At the end of Section 5.6 of this tutorial we briefly discussed why we should not use variables to share information across threads due to a loss of determinism (in turn due to race conditions).
Sonic Pi’s solution to the problem of easily working with global variables in a deterministic way is through a novel system it calls Time State. This might sound complex and difficult (in fact, in the UK, programming with multiple threads and shared memory is typically a university level subject). However, as you’ll see, just like playing your first note, Sonic Pi makes it incredibly simple to share state across threads whilst still keeping your programs thread-safe and deterministic..
Meet get
and set
…
Sonic Pi has a global memory store called Time State. The two main things you do with it are to set
information and get
information. Let’s dive deeper…
To store information into the Time State we need two things:
the information we want to store, a unique name (key) for the information.
For example, we might want to store the number 3000
with the key :intensity
. This is possible using the set
function:
set :intensity, 3000
We can use any name for our key. If information has already been stored with that key, our new set
will override it:
set :intensity, 1000
set :intensity, 3000
In the above example, as we stored both numbers under the same key, the last call to set
‘wins’, so the number associated with :intensity
will be 3000
as the first call to set
is effectively overridden.
To fetch information from the Time State we just need the key we used to set
it, which in our case is :intensity
. We then just need to call get[:intensity]
which we can see by printing out the result to the log:
print get[:intensity] #=> prints 3000
Notice that calls to get
can return information that was set
in a previous run. Once a piece of information has been set
it is available until either the information is overridden (just like we clobbered the :intensity
value of 1000
to 3000
above) or Sonic Pi is closed.
The main benefit of the Time State system is that it can be safely used across threads or live loops. For example, you could have one live loop setting information and another one getting it:
rrand
The nice thing about using get
and set
across threads like this is that it will always produce the same result every time you hit run. Go on, try it. See if you get the following in your log:
{run: 0, time: 0.0}
└─ 125.72265625
{run: 0, time: 0.5}
└─ 125.72265625
{run: 0, time: 1.0}
└─ 76.26220703125
{run: 0, time: 1.5}
└─ 76.26220703125
{run: 0, time: 2.0}
└─ 114.93408203125
{run: 0, time: 2.5}
└─ 114.93408203125
{run: 0, time: 3.0}
└─ 75.6048583984375
{run: 0, time: 3.5}
└─ 75.6048583984375
Try running it a few times - see, it’s the same every time. This is what we call deterministic behaviour and it’s really very important when we want to share our music as code and know that the person playing the code is hearing exactly what we wanted them to hear (just like playing an MP3 or internet stream sounds the same for all listeners).
rand
## An Example of Non-Deterministic Behaviour
## (due to race conditions caused by multiple
## live loops manipulating the same variable
## at the same time).
##
## If you run this code you'll notice
## that the list that's printed is
## not always sorted!
a = (ring 6, 5, 4, 3, 2, 1)
live_loop :shuffled do
a = a.shuffle
sleep 0.5
end
live_loop :sorted do
a = a.sort
sleep 0.5
puts "sorted: ", a
end
Let’s take a look at how this might look using get
and set
:
## An Example of Deterministic Behaviour
## (despite concurrent access of shared state)
## using Sonic Pi's new Time State system.
##
## When this code is executed, the list that's
## printed is always sorted!
set :a, (ring 6, 5, 4, 3, 2, 1)
live_loop :shuffled do
set :a, get[:a].shuffle
sleep 0.5
end
live_loop :sorted do
set :a, get[:a].sort
sleep 0.5
puts "sorted: ", get[:a]
end
Notice how this code is pretty much identical to the version using a variable before it. However when you run the code, it behaves as you would expect with any typical Sonic Pi code - it does the same thing every time in this case thanks to the Time State system.
Therefore, when sharing information across live loops and threads, use get
and set
instead of variables for deterministic, reproducible behaviour.
Section 5.7 introduced the functions cue
and sync
when dealing with the issue of synchronising threads. What it didn’t explain was that it is the Time State system which provides this functionality. It just so happens that set
is actually a variation of cue
and is built on top of the same core functionality which is to insert information into the Time State system. Additionally, sync
is also designed in such a way that it works seamlessly with Time State - any information that we plan to store in Time State we can sync on. In other words - we sync
on events yet to be inserted into Time State.
Let’s take a quick look at how to use sync
to wait for new events to be added to Time State:
sample :ambi_lunar_land
foo
Note that sync
always waits for future events and that it will block the current thread waiting for a new event. Also, it will inherit the logical time of the thread which triggered it via set
or cue
so it may also be used to sync time.
foo
sample :ambi_lunar_land
Note that values that are passed through set
and cue
must be thread safe - i.e. immutable rings, numbers, symbols or frozen strings. Sonic Pi will throw an error if the value you are attempting to store in the Time State is not valid.
foo
Let’s assume we want to wait for the next event that has three path segments:
sync "/*/*/*"
This will match any Time State event with exactly three path segments, regardless of their names. For example:
foo
foo
cue "/eggs/beans/toast"
cue "/moog/synths/rule"
However, it will not match paths with fewer or more path segments. The following will not match:
foo
foo
cue "/eggs"
Each *
means any content. So we could match paths with just one segment with /*
or paths with five segments with /*/*/*/*/*
foo
foo foo foo
However, it wouldn’t match the following:
foo foo foo
foo
foo
foo foo foo foo
You can use the ?
character to match against a single char such as "/?oo/bar/baz"
which will match:
foo
cue "/goo/bar/baz"
cue "/too/bar/baz"
cue "/woo/bar/baz"
foo
foo foo foo
foo
foo foo foo
foo
foo foo foo foo foo
When calling sync
or get
you are free to combine matchers in any order you see fit to powerfully match any Time State event created by cue
or set
. Let’s look at a crazy example:
sample :loop_amen
For those curious, these matching rules are based on the Open Sound Control pattern matching specification which is explained in detail here: http://opensoundcontrol.org/spec-1_0
Once you’ve mastered converting code to music, you might wonder - what’s next? Sometimes the constraints of working purely within Sonic Pi’s syntax and sound system can be exciting and put you into a new creative position. However, sometimes it is essential to break out of the code into the real world. We want two extra things:
To be able to convert actions in the real world into Sonic Pi events to code with To be able to use Sonic Pi’s strong timing model and semantics to control and manipulate objects in the real world
Luckily there’s a protocol that’s been around since the 80s that enables exactly this kind of interaction - MIDI. There’s an incredible number of external devices including keyboards, controllers, sequencers, and pro audio software that all support MIDI. We can use MIDI to receive data and also use it to send data.
Sonic Pi provides full support for the MIDI protocol enabling you to connect your live code to the real world. Let’s explore it further…
In this section we will learn how to connect a MIDI controller to send events into Sonic Pi to control our synths and sounds. Go and grab a MIDI controller such as a keyboard or control surface and let’s get physical!
In order to get information from an external MIDI device into Sonic Pi we first need to connect it to our computer. Typically this will be via a USB connection, although older equipment will have a 5-pin DIN connector for which you’ll need hardware support for your computer (for example, some sound cards have MIDI DIN connectors). Once you’ve connected your device, launch Sonic Pi and take a look at the IO section of the Preferences panel. You should see your device listed there. If not, try hitting the ‘Reset MIDI’ button and see if it appears. If you’re still not seeing anything, the next thing to try is to consult your operating system’s MIDI config to see if it sees your device. Failing all that, feel free to ask questions in our friendly forums: https://in-thread.sonic-pi.net
Once your device is connected, Sonic Pi will automatically receive events. You can see for yourself by manipulating your MIDI device and looking at the cue logger in the bottom right of the application window below the log (if this isn’t visible go to Preferences->Editor->Show & Hide and enable the ‘Show cue log’ tickbox). You’ll see a stream of events such as:
/midi:nanokey2_keyboard:0:1/note_off [55, 64]
/midi:nanokey2_keyboard:0:1/note_on [53, 102]
/midi:nanokey2_keyboard:0:1/note_off [57, 64]
/midi:nanokey2_keyboard:0:1/note_off [53, 64]
/midi:nanokey2_keyboard:0:1/note_on [57, 87]
/midi:nanokey2_keyboard:0:1/note_on [55, 81]
/midi:nanokey2_keyboard:0:1/note_on [53, 96]
/midi:nanokey2_keyboard:0:1/note_off [55, 64]
Once you can see a stream of messages like this, you’ve successfully connected your MIDI device. Congratulations, let’s see what we can do with it!
These events are broken into two sections. Firstly there’s the name of the event such as /midi:nanokey2_keyboard:0:1/note_on
and secondly there’s the values of the event such as [18, 62]
. Interestingly, these are the two things we need to store information in Time State. Sonic Pi automatically inserts incoming MIDI events into Time State. This means you can get
the latest MIDI value and also sync
waiting for the next MIDI value using everything we learned in section 10 of this tutorial.
Now we’ve connected a MIDI device, seen its events in the cue log and discovered that our knowledge of Time State is all we need to work with the events, we can now start having fun. Let’s build a simple MIDI piano:
live_loop :midi_piano do
note, velocity = sync "/midi:nanokey2_keyboard:0:1/note_on"
synth :piano, note: note
end
There’s a few things going on in the code above including some issues. Firstly, we have a simple live_loop
which will repeat forever running the code between the do
/end
block. This was introduced in Section 9.2. Secondly, we’re calling sync
to wait for the next matching Time State event. We use a string representing the MIDI message we’re looking for (which is the same as was displayed in the cue logger). Notice that this long string is provided to you by Sonic Pi’s autocompletion system, so you don’t have to type it all out by hand. In the log we saw that there were two values for each MIDI note on event, so we assign the result to two separate variables note
and velocity
. Finally we trigger the :piano
synth passing our note.
Now, you try it. Type in the code above, replace the sync key with a string matching your specific MIDI device and hit Run. Hey presto, you have a working piano! However, you’ll probably notice a couple of problems: firstly all the notes are the same volume regardless of how hard you hit the keyboard. This can be easily fixed by using the velocity MIDI value and converting it to an amplitude. Given that MIDI has a range of 0->127, to convert this number to a value between 0->1 we just need to divide it by 127:
live_loop :midi_piano do
note, velocity = sync "/midi:nanokey2_keyboard:0:1/note_on"
synth :piano, note: note, amp: velocity / 127.0
end
Update the code and hit Run again. Now the velocity of the keyboard is honoured. Next, let’s get rid of that pesky pause.
Before we can remove the pause, we need to know why it’s there. In order to keep all the synths and FX well-timed across a variety of differently capable CPUs, Sonic Pi schedules the audio in advance by 0.5s by default. (Note that this added latency can be configured via the fns set_sched_ahead_time!
and use_sched_ahead_time
). This 0.5s latency is being added to our :piano
synth triggers as it is added to all synths triggered by Sonic Pi. Typically we really want this added latency as it means all synths will be well timed. However, this only makes sense for synths triggered by code using play
and sleep
. In this case, we’re actually triggering the :piano
synth with our external MIDI device and therefore don’t want Sonic Pi to control the timing for us. We can turn off this latency with the command use_real_time
which disables the latency for the current thread. This means you can use real time mode for live loops that have their timing controlled by sync
ing with external devices, and keep the default latency for all other live loops. Let’s see:
live_loop :midi_piano do
use_real_time
note, velocity = sync "/midi:nanokey2_keyboard:0:1/note_on"
synth :piano, note: note, amp: velocity / 127.0
end
Update your code to match the code above and hit Run again. Now we have a low latency piano with variable velocity coded in just 5 lines. Wasn’t that easy!
Finally, as our MIDI events are going straight into the Time State, we can also use the get
fn to retrieve the last seen value. This doesn’t block the current thread and returns nil
if there’s no value to be found (which you can override by passing a default value - see the docs for get
). Remember that you can call get
in any thread at any time to see the latest matching Time State value. You can even use time_warp
to jump back in time and call get
to see past events…
choose:選択
In addition to receiving MIDI events we can also send out MIDI events to trigger and control external hardware synths, keyboards and other devices. Sonic Pi provides a full set of fns for sending various MIDI messages such as:
Note on - midi_note_on
Note off - midi_note_off
Control change - midi_cc
Pitch bend - midi_pitch_bend
Clock ticks - midi_clock_tick
There are many other supported MIDI messages too - check out the API documentation for all the other fns that start with midi_
.
In order to send a MIDI message to an external device, we must first have connected it. Check out the subsection ‘Connecting a MIDI Controller’ in section 11.1 for further details. Note that if you’re using USB, connecting to a device which you’re sending to (rather than receiving from) is the same procedure. However, if you’re using the classic DIN connectors, make sure you connect to the MIDI out port of your computer. You should see your MIDI device listed in the preferences pane.
The many midi_*
fns work just like play
, sample
and synth
in that they send a message at the current (logical) time. For example, to spread out calls to the midi_*
fns you need to use sleep
just like you did with play
. Let’s take a look:
midi_note_on :e3, 50
This will send a MIDI note on event to the connected MIDI device with velocity 50. (Note that Sonic Pi will automatically convert notes in the form :e3
to their corresponding MIDI number such as 52 in this case.)
If your connected MIDI device is a synthesiser, you should be able to hear it playing a note. To disable it use midi_note_off
:
midi_note_off :e3
By default, Sonic Pi will send each MIDI message to all connected devices on all MIDI channels. This is to make it easy to work with a single connected device without having to configure anything. However, sometimes a MIDI device will treat MIDI channels in a special way (perhaps each note has a separate channel) and also you may wish to connect more than one MIDI device at the same time. In more complicated setups, you may wish to be more selective about which MIDI device receives which message(s) and on which channel.
We can specify which device to send to using the port:
opt, using the device name as displayed in the preferences:
midi_note_on :e3, port: "moog_minitaur"
We can also specify which channel to send to using the channel:
opt (using a value in the range 1-16):
midi_note_on :e3, channel: 3
Of course we can also specify both at the same time to send to a specific device on a specific channel:
midi_note_on :e3, port: "moog_minitaur", channel: 5
Finally, a really fun thing to do is to connect the audio output of your MIDI synthesiser to one of the audio inputs of your soundcard. You can then control your synth with code using the midi_*
fns and also manipulate the audio using live_audio
and FX:
reverb,
(The fn midi
is available as a handy shortcut to sending both note on and note off events with a single command. Check out its documentation for further information).
In addition to MIDI, another way to get information in and out of Sonic Pi is via the network using a simple protocol called OSC - Open Sound Control. This will let you send messages to and from external programs (both running on your computer and on external computers) which opens up the potential for control way beyond MIDI which has limitations due to its 1980s design.
For example, you could write a program in another programming language which sends and receives OSC (there are OSC libraries for pretty much every common language) and work directly with Sonic Pi. What you can use this for is only limited by your imagination.
By default when Sonic Pi is launched it listens to port 4560 for incoming OSC messages from programs on the same computer. This means that without any configuration, you can send Sonic Pi an OSC message and it will be displayed in the cue log just like incoming MIDI messages. This also means that any incoming OSC message is also automatically added to the Time State which means you can also use get
and sync
to work with the incoming data - just like with MIDI and synchronising live_loops
- see sections 5.7 and 10.2 to recap how this works.
Let’s build a basic OSC listener:
foo
In this example we described an OSC path "/osc*/trigger/prophet"
which we’re syncing on. This can be any valid OSC path (all letters and numbers are supported and the /
is used like in a URL to break up the path to multiple words). The /osc
prefix is added by Sonic Pi to all incoming OSC messages, so we need to send an OSC message with the path /trigger/prophet
for our sync
to stop blocking and the prophet synth to be triggered.
We can send OSC to Sonic Pi from any programming language that has an OSC library. For example, if we’re sending OSC from Python we might do something like this:
from pythonosc import osc_message_builder
from pythonosc import udp_client
sender = udp_client.SimpleUDPClient('127.0.0.1', 4560)
sender.send_message('/trigger/prophet', [70, 100, 8])
Or, if we’re sending OSC from Clojure we might do something like this from the REPL:
(use 'overtone.core)
(def c (osc-client "127.0.0.1" 4560))
(osc-send c "/trigger/prophet" 70 100 8)
For security reasons, by default Sonic Pi does not let remote machines send it OSC messages. However, you can enable support for remote machines in Preferences->IO->Network->Receive Remote OSC Messages. Once you’ve enabled this, you can receive OSC messages from any computer on your network. Typically the sending machine will need to know your IP address (a unique identifier for your computer on your network - kind of like a phone number or an email address). You can discover the IP address of your computer by looking at the IO section of the preferences pane. (If your machine happens to have more than one IP address, hovering the mouse over the listed address will pop up with a list of all known addresses).
Note, some programs such as TouchOSC for iPhone and Android support sending OSC as a standard feature. So, once you’re listening to remote machines and know your IP address you can instantly start sending messages from apps like TouchOSC which enable you to build your own custom touch controls with sliders, buttons, dials etc. This can provide you with an enormous range of input options.
In addition to receiving OSC and working with it using Time State, we can also send out OSC messages in time with our music (just like we can send out MIDI messages in time with our music). We just need to know which IP address and port we’re sending to. Let’s give it a try:
use_osc "localhost", 4560
osc "/hello/world"
If you run the code above, you’ll notice that Sonic Pi is sending itself an OSC message! This is because we set the IP address to the current machine and the port to the default OSC in port. This is essentially the same as posting a letter to yourself - the OSC packet is created, leaves Sonic Pi, gets to the network stack of the operating system which then routes the packed back to Sonic Pi and then it’s received as a standard OSC message and is visible in the cue logger as the incoming message /osc:127.0.0.1:4560/hello/world
. (Notice how Sonic Pi automatically prefixes all incoming OSC messages with /osc
and then the hostname and port of the sender.)
Of course, sending OSC messages to ourselves may be fun but it’s not that useful. The real benefit starts when we send messages to other programs:
use_osc "localhost", 123456
osc "/hello/world"
In this case we’re assuming there’s another program on the same machine listening to port 123456. If there is, then it will receive a "/hello/world
OSC message with which it can do what it wants.
If our program is running on another machine, we need to know its IP address which we use instead of "localhost"
:
use_osc "192.168.10.23", 123456
osc "/hello/world"
Now we can send OSC messages to any device reachable to us via our local networks and even the internet!
So far, in terms of sound production, we’ve explored triggering synths and recorded sounds via the fns play
, synth
and sample
. These have then generated audio which has played through our stereo speaker system. However, many computers also have the ability to input sound, perhaps through a microphone, in addition to the ability to send sound out to more than two speakers. Often, this capability is made possible through the use of an external sound card - these are available for all platforms. In this section of the tutorial we’ll take a look at how we can take advantage of these external sound cards and effortlessly work with multiple channels of audio in and out of Sonic Pi.
One simple (and perhaps familiar) way of accessing sound inputs is using our friend synth
by specifying the :sound_in
synth:
synth :sound_in
This will operate just like any synth such as synth :dsaw
with the exception that the audio generated will be read directly from the first input of your system’s sound card. On laptops, this is typically the built-in microphone, but if you have an external sound card, you can plug any audio input to the first input.
One thing you might notice is that just like synth :dsaw
the :sound_in
synth only lasts for 1 beat as it has a standard envelope. If you’d like to keep it open for a little longer, change the ADSR envelope settings. For example the following will keep the synth open for 8 beats before closing the connection:
synth :sound_in, sustain: 8
Of course, just like any normal synth, you can easily layer on effects with the FX block:
with_fx :reverb do
with_fx :distortion do
synth :sound_in, sustain: 8
end
end
If you have plugged in a guitar to your first input, you should be able to hear it with distortion and reverb until the synth terminates as expected.
You are free to use the :sound_in
synth as many times as you like concurrently (just like you would do with any normal synth). For example, the following will play two :sound_in
synths at the same time - one through distortion and one through reverb:
with_fx :distortion do
synth :sound_in, sustain: 8
end
with_fx :reverb do
synth :sound_in, sustain: 8
end
You can select which audio input you want to play with the input:
opt. You can also specify a stereo input (two consecutive inputs) using the :sound_in_stereo
synth. For example, if you have a sound card with at least three inputs, you can treat the first two as a stereo stream and add distortion and the third as a mono stream and add reverb with the following code:
with_fx :distortion do
synth :sound_in_stereo, sustain: 8, input: 1
end
with_fx :reverb do
synth :sound_in, sustain: 8, input: 3
end
However, although this is a useful technique, there are a couple of limitations to this approach. Firstly, it only works for a specific duration (due to it having an ADSR envelope) and secondly, there’s no way to switch the FX around once the synth has been triggered. Both of these things are typical requests when working with external audio feeds such as microphones, guitars and external synthesisers. We’ll therefore take a look at Sonic Pi’s solution to the problem of manipulating a (potentially) infinite stream of live audio input: live_audio
.
The :sound_in
synth as described in the previous section provides a very flexible and familiar method for working with input audio. However, as also discussed it has a few issues when working with a single input of audio as a single instrument (such as a voice or guitar). By far the best approach to working with a single continuous stream of audio is to use live_audio
.
live_audio
shares a couple of core design constraints with live_loop
(hence the similar name). Firstly it must have a unique name and secondly only one live_audio
stream with that name may exist at any one time. Let’s take a look:
foo
This code will act in a similar fashion to synth :sound_in
with some key differences: it runs forever (until you explicitly stop it) and you can move it to new FX contexts dynamically.
On initial triggering live_audio
works exactly as you might expect it to work with FX. For example, to start a live audio stream with added reverb simply use a :reverb
FX block:
foo
However, given that live_audio
runs forever (at least until you stop it) it would be pretty limiting if, like typical synths, the live audio was bound within the :reverb
FX for its entire existence. Luckily this is not the case and it was designed to be easy to move between different FX. Let’s try it. Run the code above to hear live audio coming directly from the first input of your sound card. Note, if you’re using a laptop, this will typically be out of your built-in microphone, so it’s recommended to use headphones to stop feedback.
reverb,
foo
Now, hit Run, and you’ll immediately hear the audio played through the echo FX and no longer through reverb. If you wanted them both, just edit the code again and hit Run:
foo
foo
Unlike standard synths, as live_audio
has no envelope, it will continue running forever (even if you delete the code, just like a function is still defined in memory if you delete the code in the editor). To stop it, you need to use the :stop
arg:
foo
It can easily be restarted by calling it without the :stop
arg again:
foo
Additionally all running live audio synths are stopped when you hit the global Stop button (as with all other running synths and FX).
With respect to audio channels, by default live_audio
acts similarly to the :sound_in
synth in that it takes a single mono input stream of audio and converts it to a stereo stream using the specified panning. However, just like :sound_in_stereo
it’s also possible to tell live_audio
to read two consecutive audio inputs and treat them as the left and right channels directly. This is achieved via the :stereo
opt. For example, to treat input 2 as the left signal and input 3 as the right signal, you need to configure the input:
opt to 2 and enable stereo mode as follows:
foo
Note that once you have started a live audio stream in stereo mode, you cannot change it to mono without stopping and starting. Similarly, if you start it in the default mono mode, you can’t switch to stereo without starting and stopping the stream.
So far in this section we’ve looked at how to get multiple streams of audio into Sonic Pi - either through the use of the :sound_in
synth or via the powerful live_audio
system. In addition to working with multiple streams of input audio, Sonic Pi can also output multiple streams of audio. This is achieved via the :sound_out
FX.
Let’s quickly recap on how Sonic Pi’s synths and FX output their audio to their current FX context. For example, consider the following:
with_fx :reverb do # C
with_fx :echo do # B
sample :bd_haus # A
end
end
The simplest way to understand what’s happening with the audio stream is to start at the innermost audio context and work our way out. In this case, the innermost context is labelled A
and is the :bd_haus
sample being triggered. The audio for this goes directly into its context which is B
- the :echo
FX. This then adds echo to the incoming audio and outputs it to its context which is C
- the :reverb
FX. This then adds reverb to the incoming audio and outputs to its context which is the top level - the left and right speakers (outputs 1 and 2 in your audio card). The audio flows outwards with a stereo signal all the way through.
The above behaviour is true for all synths (including live_audio
) and the majority of FX with the exception of :sound_out
. The :sound_out
FX does two things. Firstly it outputs its audio to its external context as described above. Secondly it also outputs its audio directly to an output on your sound card. Let’s take a look:
with_fx :reverb do # C
with_fx :sound_out, output: 3 do # B
sample :bd_haus # A
end
end
In this example, our :bd_haus
sample outputs its audio to its external context which is the :sound_out
FX. This in turn outputs its audio to its external context the :reverb
FX (as expected). However, it also outputs a mono mix to the 3rd output of the system’s soundcard. The audio generated within :sound_out
therefore has two destinations - the :reverb
FX and audio card output 3.
choose:選択
As we have also seen, the default behaviour for :sound_out
and :sound_out_stereo
is to send the audio both to their external context (as is typical of all FX) and to the specified output on your soundcard. However, occasionally you may wish to only send to the output on your soundcard and not to the external context (and therefore not have any chance of the sound being mixed and sent to the standard output channels 1 and 2). This is possible by using the standard FX opt amp:
which operates on the audio after the FX has been able to manipulate the audio:
sample :loop_amen
In the above example, the :loop_amen
sample is sent to its outer context, the :sound_out
FX. This then sends a mono mix to audio card output 3 and then multiplies the audio by 0 which essentially silences it. It is this silenced signal which is then sent out to the :sound_out
’s outer context which is the standard output. Therefore with this code, the default output channels will not receive any audio, and channel 3 will receive a mono mix of the amen drum break.
これでSonic Pi入門のチュートリアルを終了します。皆さんがここに至るまでに何かを学べたと願っています。すべてを理解していなくても心配せずに、演奏を楽しんでください。そうすれば、あなたのペースで習得できるはずです。何か疑問点があれば、チュートリアルのどこかに書いてあるかもしれないので、気軽に戻って読み直してみてください。
もし、チュートリアルでカバーしていない疑問がある場合は、Sonic Pi forumsを開いて、質問してみてください。誰かが親身に手を貸してくれるでしょう。
最後に、ヘルプシステムのドキュメントをより深くチェックすることをお勧めします。このチュートリアルでは紹介していない機能がいくつかあるので、新たな発見が待っているでしょう。
遊んで、楽しんで、コードを共有して、そしてスクリーンを見せながら、友人のために演奏してください。そして思い出してください。
間違いはない、あるのはただ可能性だけ
付録Aは、雑誌MagPiのために書かれたSonic Piの記事を集録しています。
付録に集録されている記事は、決まった順序で読むように意図されたものではなく、またチュートリアルとの重複した内容も数多く含まれています。これらの記事は、Sonic Piの全てを紹介するというよりは、Sonic Piの特定の面にフォーカスし、分かりやすく、また楽しく紹介しています。
MagPiは、美しく活字化されたPDFファイルを以下のサイトから無料でダウンロードできます。https://www.raspberrypi.org/magpi/
もしあなたが関心があってこれらのMagPiの記事で紹介されていないトピックがあったら、提案してみてはどうでしょう? 最も簡単な方法は、提案を@Sonic_Pi宛にツイートすることです。あなたの提案が次のMagPiの記事のテーマになるかもしれないのです!
Sonic Piで学ぶ最も重要な教訓は、間違いはないということです。Sonic Piの一番の習得方法は、繰り返し試してみることです。いろんなことを試し、コードから出る音が良いか悪いか気にするのをやめ、できるだけ異なるシンセ、異なる音符、異なるエフェクト、異なるオプションを実験してみましょう。とてもひどくて笑ってしまうものも数多くある一方で、宝石のような本当に素晴らしい音もあるでしょう。そして、単純にあなたの好みの音は取っておき、そうでないものは捨ててしまえばよいのです。より多くの間違い
をすればするほど、あなたにしか出来ないコーディング音楽をより早く発見し、習得できるに違いありません。
sample
やplay
といったSonic Piの音作りの基本をマスターしたとして、次はどうしよう? Sonic Piには、あなたのコードの音を変えることができる27を超えるスタジオ・エフェクトがあるのを知っていますか? エフェクトは、ドローソフトの派手なイメージフィルタと同じようなものです。ただし、イメージフィルタがぼかしを入れたり、白黒にしたりするのに対し、エフェクトは音にリバーブやディストーション、エコーなどを追加します。それはちょうどギターからエフェクトペダルにケーブルを差して、さらにアンプに差すようなものと考えるとよいでしょう。幸いにも、Sonic Piではエフェクトが本当に簡単になっていて、ケーブルも必要としないのです! あなたのやることは、エフェクトを追加したいコード領域を選択し、エフェクトのコードで包むだけです。たとえば、次のようなコードがあったとしましょう。
sample :loop_garzul
16.times do
sample :bd_haus
sleep 0.5
end
:loop_garzul
のサンプルにエフェクトを追加したい場合には、次のようにwith_fx
に押し込むだけでよいのです。
with_fx :flanger do
sample :loop_garzul
end
16.times do
sample :bd_haus
sleep 0.5
end
では次にバスドラムにエフェクトを追加したい場合には、同じようにwith_fx
で包んでみましょう。
with_fx :flanger do
sample :loop_garzul
end
with_fx :echo do
16.times do
sample :bd_haus
sleep 0.5
end
end
どんなコードでもwith_fx
で包めば、どんな音もそのままエフェクトに送られることを覚えておくとよいでしょう。
もしあなた自身のコーディング音楽を本当に発見したい場合に、あなたはすぐにシンセやエフェクトを変更したり制御する方法を知りたくなるに違いありません。たとえば、音符の長さを変更したり、リバーブをもっと追加したり、エコーの間隔を変更したりしたいかもしれません。幸いにも、Sonic Piでは驚くべきレベルの制御の方法が提供されていて、オプション・パラメータ、略してオプションと呼ばれる特別な仕組みによって、まさしくこれと同じことが可能です。ちょっと見てみましょう。以下のコードをBufferにコピーして実行してみましょう。
sample :guit_em9
おお、すてきなギターサウンドですね! では、これで遊んでみましょう。レートを変えてみるのはどうでしょう?
sample :guit_em9, rate: 0.5
行の最後にちょっと付けたrate: 0.5
は何だろう? これはオプションと呼ばれています。Sonic Piの全てのシンセとエフェクトはオプションをサポートしていて、たくさんのオプションで遊べます。エフェクトでもオプションは利用可能です。次を試してみましょう。
with_fx :flanger, feedback: 0.6 do
sample :guit_em9
end
では、feedback
を1に変更して、クレイジーな音を聞いてみましょう! 利用可能な多くのオプションの詳細について、ドキュメントを読んでみましょう。
Sonic Piについて素早く調べてみたり実験したりする一番の方法は、ライブコーディングすることです。ライブコーディングにより、あるコードから演奏を開始して、演奏を止めずに継続してコードをいじったり、変更したりできます。たとえば、sample
でcutoffのオプションがどのように動作するか分からない場合には、ただ実行してみればよいのです。では試し見てみましょう! 以下のコードをSonic PiのBufferにコピーしてみましょう。
live_loop :experiment do
sample :loop_amen, cutoff: 70
sleep 1.75
end
実行すると、こもった音のドラムブレイクを聞くことができるでしょう。では、cutoff:
の値を80
に変更して再度実行してみましょう。違いが分かりますか? 90
, 100
, 110
も試してみましょう。
live_loop
を一度使い始めると、live_loop
を使わないコードに戻れなくなるでしょう。ドラマーがスティックを頼りにするのと同じように、私もライブコーディングするときはいつもlive_loop
を頼りにしています。ライブコーディングについての詳細は、チュートリアルの9章をチェックしてみてください。
最後に、私が好きでよくやるのは、Sonic Piに作曲してもらうズルい方法です。これを実現する本当に卓越した方法は、ランダム化を使用することです。ランダム化と言うと複雑そうに聞こえるかもしれませんが、実際にはそうでもありません。少し見てみましょう。以下のコードをBufferにコピーしてください。
live_loop :rand_surfer do
use_synth :dsaw
notes = (scale :e2, :minor_pentatonic, num_octaves: 2)
16.times do
play notes.choose, release: 0.1, cutoff: rrand(70, 120)
sleep 0.125
end
end
ここで、上記のコードを実行すると、:e2 :minor_pentatonic
のスケールから選ばれた音符の絶え間ないランダムな流れが、:dsaw
のシンセで再生されるのを聞くことができるでしょう。「待って、待って! これはメロディーじゃない」とあなたが叫んでいるのが想像できます。落ち着いてください。これはマジックのトリックの前半部分です。Sonic Piでは、live_loop
を繰り返す度に、特定の位置にランダムストリームをリセットするように指示することができます。それは、「Dr. Who」に登場するタイムマシンのTARDISが、特定の時間と場所に辿り着くのとちょっと似ています。ではやってみましょう。live_loop
にuse_random_seed 1
の行を追加してみてください。
live_loop :rand_surfer do
use_random_seed 1
use_synth :dsaw
notes = (scale :e2, :minor_pentatonic, num_octaves: 2)
16.times do
play notes.choose, release: 0.1, cutoff: rrand(70, 120)
sleep 0.125
end
end
これで、live_loop
がループする度に、ランダムストリームがリセットされるようになりました。これは、ループの度に同じ16の音符が選択されていることを意味しています。あら不思議! 手軽なメロディーでしょう。ここからが本当に面白くなるところです。シードの値を1
から別な数値、たとえば4923
に変更してみましょう。ワオ! 別なメロディーになったでしょう! 1つの数字(ランダムシード)を変更するだけで、あなたの想像する限り多くのメロディーの組合せを試すことができるのです! これがコードのマジックなのです。
漂うスモークをレーザー光線がスライスし、サブウーファーは観衆の体の奥深くまで低音を震わせている。その雰囲気は、眩暈のするようなシンセのミックスとダンスで満たされている。しかし、このクラブでは何かがおかしい。DJブースの上に映し出された明るい色は、小刻みに動き、舞い、きらめく未来的なテキストである。それは、手の込んだビジュアルではなく、Raspberry Pi上で動いているSonic Piを単に映し出したものである。DJブースでは、レコードを回しているのではなく、コードを書き、編集し、実行しているのである。ライブである。これがライブコーディングである。
これは未来のクラブの現実的でない話のように聞こえるかもしれませんが、音楽をコーディングすることは盛り上がりつつあるトレンドであり、しばしばライブコーディング(http://toplap.org)と呼ばれています。この音楽制作アプローチの最近の流れの1つは、Algorave(http://algorave.com)です。私のようなアーティストが、人々をダンスさせるために音楽をコーディングするイベントです。しかし、ライブコーディングするのにクラブに居る必要はありません。Sonic Pi v2.6以上では、ヘッドホンやスピーカーとRaspberry Piを持っていける場所であればどこでも、ライブコーディングができます。一度この記事を最後まで読めば、あなた自身のビートをプログラミングでき、それをライブで変更できるでしょう。その後どこに進むかは、あなたのイマジネーションにだけ制約されるでしょう。
Sonic Piでライブコーディングする鍵は、live_loop
をマスターすることです。次のコードを見てみましょう。
live_loop :beats do
sample :bd_haus
sleep 0.5
end
live_loop
には、4つのコアな構成要素があります。1つめは、その名前です。上のlive_loop
の名前は:beats
です。live_loop
はどんな名前でも自由に付けることができます。創造的に、またクレイジーになりましょう。私は、作っている音楽に関して何か観衆と意思疎通するような名前をしばしば付けます。2つめの構成要素はdo
という単語で、live_loop
の開始する位置を示しています。3つめはend
でlive_loop
を終了する位置を示しています。そして最後は、live_loop
のボディ部分です。これはdo
とend
に囲まれたコードで、ループで何を繰り返すかが記述されている箇所です。上のコードでは、定期的にバスドラムのサンプルを再生と半拍分の待機を繰り返しています。これにより、心地良い規則的なビートが作られています。さあ、Sonic PiのBufferに上のコードをコピーして実行してみましょう。Boom, Boom, Boom!
では、live_loop
の何が特別なのでしょう? 見たところloop
にそっくりですね! ええと、live_loop
の利点は、その場で再定義できることです。これは、ライブループが実行されている間にも、その中でやっていることが変更できるということです。これがSonic Piのライブコーディングの秘訣です。試してみましょう。
live_loop :choral_drone do
sample :ambi_choir, rate: 0.4
sleep 1
end
では、Run
ボタンをクリックするか、キーボードからalt-r
を叩いてみてください。美しいコーラスのサウンドが聞こえると思います。次に、それが演奏されている間に、rateを0.4
から0.38
に変更して、Run
を叩いてみてください。ワオ! コーラスの音程が変わったのが聞こえましたか? rateを0.4
に上げて、値を戻すとどうなるか聞いてみましょう。続いて、rateを0.2
に下げ、さらに0.19
に下げ、再び0.4
にあげてみましょう。たった1つのオプションをその場で変更するだけで、音楽をコントロールできるのを実感できるでしょう。では、rateを自分自身で選んで遊んでみましょう。マイナスの数、とても小さい数や大きい数を試してみましょう。楽しんでみてください!
live_loop
に関する最も重要な教訓の1つは、それを休ませることが必要だということです。次のlive_loop
を考えてみましょう。
live_loop :infinite_impossibilities do
sample :ambi_choir
end
このコードを実行しようとすると、live_loop
がsleep
していないとSonic Piがエラーを出すでしょう。これはセーフティシステムが実行されたことを示しています。このコードがコンピュータに何を実行させようとしているか、少し考えてみてください。そうです。無限の数のコーラスのサンプルを0秒の間に再生するように指示してるのですね。もしセーフティシステムが無ければ、コンピュータはこれを実行しようして壊れてしまうでしょう。そんな訳で、live_loop
には必ずsleep
を含めることを覚えておいてください。
音楽は同時に発生する事象で溢れています。ギターとボーカルが同時に鳴っているところにベースが同時に鳴り、それらと同時にドラムが鳴るといったように…計算機の世界ではこれを並行性と呼び、Sonic Piも驚異的にシンプルな方法で同時に演奏することができます。単純に1つより多いlive_loop
を使えばよいのです。
live_loop :beats do
sample :bd_tek
with_fx :echo, phase: 0.125, mix: 0.4 do
sample :drum_cymbal_soft, sustain: 0, release: 0.1
sleep 0.5
end
end
live_loop :bass do
use_synth :tb303
synth :tb303, note: :e1, release: 4, cutoff: 120, cutoff_attack: 1
sleep 4
end
ここでは、2つのlive_loop
を使っています。1つ目はせわしなくビートを刻み、もう1つはゆっくりとクレイジーなベース音を奏でています。
複数のlive_loop
を使った場合に興味深いのは、それぞれのループがそれぞれの時間を管理しているということです。これは、とても簡単にポリリズム的な構造を作ることを意味していて、スティーヴ・ライヒのような位相のずれを演奏することも簡単にできます。以下を見てください。
# Steve Reich's Piano Phase
notes = (ring :E4, :Fs4, :B4, :Cs5, :D5, :Fs4, :E4, :Cs5, :B4, :Fs4, :D5, :Cs5)
live_loop :slow do
play notes.tick, release: 0.1
sleep 0.3
end
live_loop :faster do
play notes.tick, release: 0.1
sleep 0.295
end
これらの個々のチュートリアルで紹介したアイデアの全てから引き出された新しい楽曲の例で終わりにしたいと思います。以下のコードを読んで、何をしているか想像してみてください。次に、それをSonic Piの新しいBufferにコピーし、Run
を叩いて実際にどんな音がするか聞いてみましょう。最後に、どれかの数値を変更したり、コードをコメントアウトしたりコメントインしたりしてみましょう。そして、このコードが新しいパフォーマンスの開始点として使えるか見てみましょう。これらはとても楽しいと思います! ではまた会いましょう。
with_fx :reverb, room: 1 do
live_loop :time do
synth :prophet, release: 8, note: :e1, cutoff: 90, amp: 3
sleep 8
end
end
live_loop :machine do
sample :loop_garzul, rate: 0.5, finish: 0.25
sample :loop_industrial, beat_stretch: 4, amp: 1
sleep 4
end
live_loop :kik do
sample :bd_haus, amp: 2
sleep 0.5
end
with_fx :echo do
live_loop :vortex do
# use_random_seed 800
notes = (scale :e3, :minor_pentatonic, num_octaves: 3)
16.times do
play notes.choose, release: 0.1, amp: 1.5
sleep 0.125
end
end
end
現代の音楽における技術的な発展で最も刺激的かつ飛躍的なものの1つは、サンプラーの発明だったと言えます。サンプラーは、あらゆる音を記録し、操作し、そしてさまざまな方法でこれらのサウンドを再生することができる箱です。たとえば、もしあなたが古いレコードを持っていたとして、そこからドラムソロ(もしくはブレイク)を探しだし、サンプラーに記録して半分の速度で再生すれば、あなたの作品のビートの下地として利用可能です。これはどのように初期のヒップホップが生まれたかを示すものですが、今日の電子音楽でこのようなサンプルを含まないものを探すことは、ほぼ不可能でしょう。サンプルを使用することは、あなたのライブコーディングのパフォーマンスに、新しく面白い要素を簡単に追加する本当に素晴らしい方法です。
ではサンプラーはどこにあるのでしょう? サンプラーは既にRaspberry Piの中にあります! Raspberry Piに同梱されたSonic Piはとてもパワフルなサンプラーを内蔵しています。これで遊んでみましょう!
古典的でよく知られたドラムブレイクはアーメン・ブレイクと呼ばれるものです。アーメン・ブレイクは、Winstonsによって1969年に”Amen Brother”という曲で、ドラムブレイクの一部として演奏されました。しかし、それは初期のヒップホップミュージシャンによって80年代に発見されてサンプラーで使用された後、ドラムンベース、ブレイクビート、ハードコア・テクノ、ブレイクコアといった他の幅広いジャンルでも頻繁に使用されるようになりました。
アーメン・ブレイクがSonic Piにも内蔵していると聞いて、あなたがワクワクしてくれると思っています。Bufferをきれいにして、次のコードを入力してみてください。
sample :loop_amen
Runを叩いて、ブーンとやってみてください! ダンスミュージックの歴史で最も影響力のあったドラムブレイクの1つを聞くことができるでしょう。しかし、これは1回限りで演奏されることよりも、ループとして演奏されることで有名です。
先月のチュートリアルで紹介した、我々にはもうお馴染みのlive_loop
を使って、アーメン・ブレイクをループしてみましょう。
live_loop :amen_break do
sample :loop_amen
sleep 2
end
ループはしていますね。でもループする度に不快な無音部分がありますね。これは、2
拍sleepするように指示しているのに、:loop_amen
のサンプルは、デフォルトのBPM60で1.753
拍しか持続しないからです。したがって、2 - 1.753 = 0.247
拍の無音が発生していしまいます。その時間は短くはありますが、容易に気づくことができます。
この問題を解決するのに、beat_stretch:
オプションを使うことができます。このオプションは、指定した数値の拍に合うようにサンプルを引き延ばす(あるいは縮める)ことを、Sonic Piに指示します。
Sonic Piのsample
とsynth
関数は、amp:
やcutoff:
、release:
といったオプション引数によって、数多くの操作を提供しています。しかし、オプション引数という言葉は言いにくいので、単純にするためにオプションと呼ぶようにします。
live_loop :amen_break do
sample :loop_amen, beat_stretch: 2
sleep 2
end
これでダンスできますね! だけど、おそらく雰囲気に合わせてこのサンプルを速くしたり遅くしたりしたいと思うのではないでしょうか。
では、オールドスクールのヒップホップやブレイクコアのスタイルに変更したい場合にはどうしたら良いでしょう。それを実現する簡単な方法は、時間に合わせて演奏することです。言い換えると、テンポを操作するということです。これは、Sonic Piではとても簡単です。use_bpm
をライブループに入れるだけでよいのです。
live_loop :amen_break do
use_bpm 30
sample :loop_amen, beat_stretch: 2
sleep 2
end
この遅いビートでラップしている間に、BPM30であっても2拍sleepして全てが時間通りであることに気がつくと思います。全てがただ時間通りに動くように、beat_stretch
オプションが現行のBPMと協調して動作しているのです。
ここからが面白くなるところです。ループが動作している状態のまま、use_bpm 30
の30
を50
に変更してみましょう。ワオ、全てが、時間通りのまま速くなりました! もっと速く、80や、120、そしてもっとクレイジーになって200を打ち込んでみましょう!
サンプルをライブループできるようになったので、sample
で提供されている楽しいオプションを見ていきましょう。最初は、cutoff:
です。これはサンプラーのカットオフ・フィルタを操作します。このオプションはデフォルトでは無効になっていますが、簡単に有効にできます。
live_loop :amen_break do
use_bpm 50
sample :loop_amen, beat_stretch: 2, cutoff: 70
sleep 2
end
続いてcutoff:
オプションを変更してみましょう。たとえば100に変更後Runを叩いて、どう音が変化するかループの終わりまで聞いてみてください。50のような小さい値はメロウで低音が強調され、100や120といった大きい値は、より幅広い音が聞こえ、ザラザラとしていることに気付くでしょう。これはcutoff:
オプションが、ちょうど草刈機が芝生を刈るように、高い周波数の部分を削り取るからです。cutoff:
オプションは長さの設定(どれだけ芝生を残すか)のようなものです。
もう1つの遊んでみるべき凄いツールは、スライサー・エフェクトです。これは音をブツ切り(スライス)にします。sample
の行を次のようにスライサー・エフェクトで包んでみましょう。
live_loop :amen_break do
use_bpm 50
with_fx :slicer, phase: 0.25, wave: 0, mix: 1 do
sample :loop_amen, beat_stretch: 2, cutoff: 100
end
sleep 2
end
音が弾むように聞こえるようになったのに気付くでしょう(mix
オプションを0
に変更することで、エフェクトの掛かっていない元の音を聞くこともできます)。では、phase:
オプションで遊んでみましょう。これは、スライサー・エフェクトの(ビートに対する)レートです。0.125
といった小さい値は速くスライスし、より大きな 0.5
といった値はより遅くスライスします。phase:
を半分にしたり倍にしたりすると、良い感じに聞こえるでしょう。最後に、wave:
オプションを0, 1, 2のいずれかにして、音の変化を聞いてみましょう。これらは波形の形で、0はノコギリ波、1は矩形波、2は三角波です。
最後に、今月の例として、時代を遡って初期のブリストルのドラムンベースシーンを再訪してみましょう。あまり上記の意味するところは気にせずに、ただコードをタイプして実行し、オプションの値を変更してライブコーディングを開始して、どのような音になるか聞いてみましょう。そして、あなたの作ったものを是非共有してください! ではまた。
use_bpm 100
live_loop :amen_break do
p = [0.125, 0.25, 0.5].choose
with_fx :slicer, phase: p, wave: 0, mix: rrand(0.7, 1) do
r = [1, 1, 1, -1].choose
sample :loop_amen, beat_stretch: 2, rate: r, amp: 2
end
sleep 2
end
live_loop :bass_drum do
sample :bd_haus, cutoff: 70, amp: 1.5
sleep 0.5
end
live_loop :landing do
bass_line = (knit :e1, 3, [:c1, :c2].choose, 1)
with_fx :slicer, phase: [0.25, 0.5].choose, invert_wave: 1, wave: 0 do
s = synth :square, note: bass_line.tick, sustain: 4, cutoff: 60
control s, cutoff_slide: 4, cutoff: 120
end
sleep 4
end
リードシンセは、たとえそれがゴロゴロ鳴るオシレーターの浮遊であったり、ミックスを通して耳をつんざくようなデチューンされたノコギリ波であったしても、あらゆる電子音楽において不可欠な役割を果たしています。先月の記事では、ビートをどのようにコーディングするかについて紹介しました。今月の記事では、シンセ・リフの3つのコアな要素、すなわち、その音色、メロディー、リズムをどのようにコーディングするかについて紹介したいと思います。
では、Raspberry Piを起動し、v2.6以降のSonic Piを開いて、音を出してみましょう!
シンセ・リフに不可欠な要素は、音色で遊んだり変更したりすることです。Sonic Piでは、2つの方法で音色を操作することができます。劇的な変化として異なるシンセを選択することと、より微かな調整としてシンセのオプションの設定を変更することです。またエフェクトも使用できますが、これについては別なチュートリアルが必要そうです…
シンセを継続的に変更するシンプルなライブループを作ってみましょう。
live_loop :timbre do
use_synth (ring :tb303, :blade, :prophet, :saw, :beep, :tri).tick
play :e2, attack: 0, release: 0.5, cutoff: 100
sleep 0.5
end
コードを見てみてください。ここでは、シンセの名前のリングを単純にチックしています(リングはリストを何度も繰り返すことで、シンセの名前を循環します)。そして、シンセの名前をuse_synth
関数に渡すことで、live_loop
で使用するシンセを変更しています。また、:e2
(2番目のオクターブのE)の音符を、リリースタイムを0.5拍(デフォルトBPMの60では0.5秒)、cutoff:
オプションを100で演奏しています。
異なるシンセが、全く同じ音符を鳴らしているにもかかわらず、とても異なった音に聞こえるでしょう。では、実験して遊んでみましょう。リリースタイムを大きい値や小さい値に変更してみましょう。たとえば、attack:
やrelease:
オプションを変更して、フェードイン・フェードアウトの時間が音にとても大きなインパクトを与えるのを見てみましょう。最後にcutoff:
オプションを変更して(60と130の間の値が良いでしょう)、カットオフの値もまた音色にとても大きな影響を与えるのを見てみましょう。いくつかの値を変更するだけで、多くの音を作り出せたのではないでしょうか。このことを一度修得してしまえば、ヘルプシステムのシンセ
タブには全てのシンセの一覧と個々のシンセが利用可能な全てのオプションがあり、コーディングの際にすぐ利用できるでしょう。
音色とは、ある音がどう鳴っているかを表現する、ただの聞こえの良い言葉です。もしあなたがバイオリン、ギター、ピアノといった異なる楽器で同じ音符を演奏すると、音程(音が高いか低いか)は同じでも、音の質は違うでしょう。その音の質、つまりピアノとギターとの違いを指摘できるような内容、が音色です。
リード・シンセで重要なもう1つの側面は、演奏する音符の選択です。もしあなたが良いメロディーのアイデアを既に持っていたら、単純にそれをリングに入れてチックしていくことができます。
live_loop :riff do
use_synth :prophet
riff = (ring :e3, :e3, :r, :g3, :r, :r, :r, :a3)
play riff.tick, release: 0.5, cutoff: 80
sleep 0.25
end
ここでは、:e3
といった音符と:r
で表現される休符を含むリングでメロディーを定義しています。そして、リフが繰り返し演奏されるように、.tick
を使ってリングを循環しています。
良いリフを一から思いつくのは、いつも簡単であるとは限りません。ランダムなリフの生成をSonic Piにお願いして、出来たリフから一番良いと思うものを選ぶほうが、より簡単なケースが多いでしょう。これを実現するのに、次の3つのものが必要です。リングとランダム化とランダムシードです。例を見てみましょう。
live_loop :random_riff do
use_synth :dsaw
use_random_seed 3
notes = (scale :e3, :minor_pentatonic).shuffle
play notes.tick, release: 0.25, cutoff: 80
sleep 0.25
end
ここではいくつかのことが実行されています。順番に見ていきましょう。最初に、ランダムシードとしてここでは3を使っています。これは何を意味するのでしょうか? そうですね、シードを設定することで便利な点は、次のランダム値が何になるか正確に予測できることです。つまり、最後にシードを3に設定したときと同じになります。もう1つ便利な点は、音符のリングのシャッフルでも同じように動作することです。上記の例では、標準的なシャッフルのリストの内の3番目のシャッフル
を必然的に要求していることになります。これもシャッフルする直前に設定したランダムシードの値が同じであれば常に同じになります。最後に、シャッフルされた音符を単純にチックして、リフを演奏しています。
ここからが面白くなるところです。ランダムシードを別な値、たとえば3000に変更すると、全く異なったシャッフルの音符が得られるでしょう。これは、新しいメロディーを探索する方法としては、極めて簡単でしょう。シャッフルしたい音符のリスト(スケールはとても良い出発点でしょう)を選択し、続いてシードを選択してみましょう。もし生成されたメロディーが気に入らなかったら、音符のリストかシードのいずれかを変更して、もう一度やってみましょう。気にいったものが生成されるまで、続けてみましょう!
Sonic Piのランダム化は、実際には真のランダムではなく擬似ランダムと呼ばれるものです。サイコロを100回振ってその結果を紙切れに書いておくのを想像してみてください。Sonic Piは、その結果のリストと同等のものを持っていて、ランダムな値を要求されるとそれを使っています。実際のサイコロを振る代わりに、リストから次の値を単純に取得しているのです。そして、ランダムシードの設定は、リストの特定の場所に移動しているに過ぎません。
リフで重要なもう1つの側面は、リズム(いつ音符を演奏していつ演奏しないのか)です。以前に、休符として:r
をリングに使用できることを見たと思います。他の非常に強力な方法としては、spread
関数を使う方法がありますが、これはいずれチュートリアルで扱いたいと思います。今回はリズムの発見にランダム化を使ってみたいと思います。全ての音符を演奏する代わりに、確率によってある特定の条件でのみ演奏することが可能です。次のコードを見てみましょう。
live_loop :random_riff do
use_synth :dsaw
use_random_seed 30
notes = (scale :e3, :minor_pentatonic).shuffle
16.times do
play notes.tick, release: 0.2, cutoff: 90 if one_in(2)
sleep 0.125
end
end
知ってると本当に便利な関数は、one_in
でしょう。この関数は指定した確率に依存してtrue
かfalse
を返します。ここでは、引数として2を使用しているので、one_in
を2回呼ぶ度に1回true
を返します。言い換えると、50%の確率でtrue
を返します。2よりも大きな値を使用するとfalse
をより多く返し、リフにより多くの休符を与えるでしょう。
また、ここで16.times
という繰り返しが追加されていることに気づいたかもしれません。これは、16個の音符の度にランダムシードをリセットしたいためです。これにより、16回の繰り返しの度に、リフのリズムが繰り返されます。これはシャッフルには影響しません。なぜなら、それはシードを設定した直後に実行されているからです。リフの長さを変更するために、繰り返しのサイズを変更することができます。16という値を、8, 4, 3といった値に変更して、それがどのようにリフのリズムに影響するか見てみてください。
今回学習したことをまとめて最後の例としましょう。ではまた!
live_loop :random_riff do
# uncomment to bring in:
# synth :blade, note: :e4, release: 4, cutoff: 100, amp: 1.5
use_synth :dsaw
use_random_seed 43
notes = (scale :e3, :minor_pentatonic, num_octaves: 2).shuffle.take(8)
8.times do
play notes.tick, release: rand(0.5), cutoff: rrand(60, 130) if one_in(2)
sleep 0.125
end
end
live_loop :drums do
use_random_seed 500
16.times do
sample :bd_haus, rate: 2, cutoff: 110 if rand < 0.35
sleep 0.125
end
end
live_loop :bd do
sample :bd_haus, cutoff: 100, amp: 3
sleep 0.5
end
エレクトロニック・ダンス・ミュージックの歴史を俯瞰する上で、ローランドTB-303の多大な影響を無視することは出来ないでしょう。それはアシッドベースサウンドの秘伝のタレであると言えます。古典的なTB-303のベースリフは、初期のシカゴハウスのシーンからPlastikman, SquarepusherやAphex Twinといったより最近の電子音楽のアーティストで聞くことができるでしょう。
興味深いことに、ローランドはTB-303をダンスミュージックで使うことを全く意図していませんでした。それは元々ギタリストの練習の補助として作られ、一緒にジャムセッションする際のベースラインを演奏するのにプログラムされるだろうと思われていました。しかし残念なことに、TB-303には多くの問題がありました。プログラムするのが少し厄介であったり、ベースの代わりとしてはそれ程良い音がしなかったこと、そして購入するのにかなり高かったことがあります。ローランドは利益の損失を削減するために、TB-303が10,000個売れた後で、製造を中止することにしました。そして、ギタリストの棚に数年置かれていた後に、中古ショップのウィンドウで見かけることになりました。これらの寂しく捨てられたTB-303は、ローランドが想像もしなかった方法でクレイジーなサウンドを作り出す新しい時代の実験的なアーティストによって発見されるのを待つことになったのです。そしてアシッドハウスは生まれたのです。
オリジナルのTB-303を入手するのはとても困難ですが、Sonic Piの力でRaspberry PiをTB-303にすることが出来るのです。よく見ていてください。Sonic Piを起動して、空のBufferに以下のコードを打ち込んで、Run
を打ってください。
use_synth :tb303
play :e1
とても簡単なアシッドベースですね! これで遊んでみましょう…
最初に、音が面白くなるようにライブ・アルペジエーターを作ってみましょう。前回のチュートリアルで、リフが音符のリングで実現できるのを見ました。リングは、要素を次々と進めて行って(チックして)、末尾に達すると先頭に戻って繰り返します。それと同じことを実行するライブループを作ってみましょう。
use_synth :tb303
live_loop :squelch do
n = (ring :e1, :e2, :e3).tick
play n, release: 0.125, cutoff: 100, res: 0.8, wave: 0
sleep 0.125
end
一行ごとに見て行きましょう。
最初の行では、use_synth
関数でデフォルトのシンセをtb303
に設定しています。
2行目では、:squelch
という名前のライブループを作って、単純にループを繰り返しています。
3行目ではリフを作っています。1, 2, 3番目のオクターブのEからなる音符のリングを.tick
で単純に進めて行っています。リフの現在の音符を示すのにn
を定義しています。等号は、単に右の値を左の名前に割り当てることを意味しています。この値はループが繰り返される度に異なります。最初の繰り返しでは、n
は:e1
に設定されています。2回目の繰り返しでは:e2
になり、その次は:e3
です。そして、その次には:e1
に戻って、永遠に繰り返し循環しています。
4行目では、実際に:tb303
シンセをトリガーしています。ここで、いくつか興味深いオプションを渡しています。release:
, cutoff:
, res:
とwave:
です。これらについては、この後議論します。
5行目はsleep
です。デフォルトBPMの60で、0.125
秒毎または1秒間に8回ライブループを繰り返すよう指示しています。
6行目はライブループのend
です。これは単にSonic Piにライブループの終わりの箇所を示しています。
このコードで何が起きているか思い描いている途中かもしれませんが、上記のコードをタイプしてRun
ボタンを叩いてみてください。:tb303
が動作し始めるのを聞くことができるでしょう。では、ライブコーディングを始めましょう。
ライブループが動作している最中に、cutoff:
オプションを110
に変更して、Run
ボタンを再度叩いてみてください。音がざらついて押しつぶされたように聞こえると思います。次に120
に変更してRun
を叩いてみてください。更に130
はどうでしょう。より大きなカットオフの値が、よりけたたましく激しい音にしているのを聞くことができるでしょう。最後に、休みたくなったら80
にしてみましょう。これらを好きなだけ繰り返してみてください。心配しないで。私はずっとここに居ますよ…
他に遊んでみる価値のあるオプションは、res:
でしょう。これはフィルタのレゾナンスのレベルを制御しています。高いレゾナンスはアシッドベースサウンドの特徴です。上のコードでres:
は0.8
に設定されています。これを0.85
に上げ、次に0.9
に上げ、最後に0.95
に上げてみましょう。110
やそれより大きいカットオフで、より違いを聞き分けることができるかもしれません。最後に、狂ったサウンドを出すのに、思い切って0.999
にしてみましょう。res
が高いと、カットオフフィルタがより共振し、独特のサウンドを出し始めるのを聞くことができるでしょう。
最後に、音色に大きなインパクトを与えるのに、wave:
オプションを1
に変更してみてください。これはオシレーターの選択です。デフォルトは0
で、ノコギリ波です。1
はパルス波で、2
は三角波です。
もちろん、リングの中の音符を変更したり、スケールやコードから音符を選択して、異なるリフを試してみるのも良いでしょう。はじめてのアシッドベースシンセを楽しんでください。
オリジナルのTB-303の設計は、実際のところとてもシンプルです。以下の略図から分かるように、4つのコアな部分しかありません。
最初はオシレーターです。これは音の原材料となるものです。この図では、矩形波を使っています。次にオシレーターのエンベロープがあります。これは矩形波の音量を時間に沿って制御しています。Sonic Piでは、attack:
, decay:
, sustain:
, release:
オプションで対応する音量レベルにアクセスできます。より詳細な情報は、チュートリアルの’2.4 エンベロープでのデュレーション’を参照してください。エンベロープされた矩形波は、ローパスフィルタに渡しています。これは、高い周波数をカットするとともに、レゾナンスエフェクトを追加します。ここからが面白くなるところです。このローパスフィルタのカットオフの値もまた、独自のエンベロープで制御されているのです! これは、2つのエンベロープを弄ることで、サウンドの音色を驚異的に変化できることを意味しているのです。次のコードを見てみましょう。
use_synth :tb303
with_fx :reverb, room: 1 do
live_loop :space_scanner do
play :e1, cutoff: 100, release: 7, attack: 1, cutoff_attack: 4, cutoff_release: 4
sleep 8
end
end
:tb303
シンセでは、標準的なエンベロープオプションの1つ1つに対応して、cutoff_
に同等のオプションがあります。したがって、カットオフのアタック時間を変更するのには、cutoff_attack:
オプションを使うことができます。上のコードを空のBufferにコピーして実行してみてください。震えたクレイジーな音を聞くことができるでしょう。では遊んでみましょう。cutoff_attack:
を1
に変更し、次に0.5
に変更してみてください。さらに8
を試してみましょう。
追加の雰囲気のために全てを:reverb
エフェクトに渡しているのに気が付いたかもしれません。他のエフェクトもどう作用するか試してみてください!
最後に、今回のチュートリアルのアイデアを使って制作したコードを紹介します。空のBufferにコピーして少しの間聞いてみてください。そしてあなた自身のコードになるようライブコーディングしてみてください。このコードでどんなクレイジーな音が作れたか見てみてください! では次回…
use_synth :tb303
use_debug false
with_fx :reverb, room: 0.8 do
live_loop :space_scanner do
with_fx :slicer, phase: 0.25, amp: 1.5 do
co = (line 70, 130, steps: 8).tick
play :e1, cutoff: co, release: 7, attack: 1, cutoff_attack: 4, cutoff_release: 4
sleep 8
end
end
live_loop :squelch do
use_random_seed 3000
16.times do
n = (ring :e1, :e2, :e3).tick
play n, release: 0.125, cutoff: rrand(70, 130), res: 0.9, wave: 1, amp: 0.8
sleep 0.125
end
end
end
こんにちは、そしてまたお会いしましたね! 前回のチュートリアルでは、純粋にSonic Piの音楽的な可能性に焦点を当てました(Raspberry Piをパフォーマンスに十分対応可能な楽器にしました)。ここまでで、我々は以下のことを学びました:
ライブコーディング - 音楽を止めずに変更する、 大規模なビートをコードする、 強力なシンセリードを生成する、 有名なTB-303のアシッドベースサウンドを再生成する。
他にもたくさん紹介したい内容はあります(いずれこのチュートリアルで掘り下げる予定です)が、今月は、Sonic Piで出来ることのうち、おそらくあなたが知らないものを紹介したいと思います。Minecraftの制御です。
では始めましょう。Raspberry Piをブートし、Minecraft Piを起動して新しいワールドを作りましょう。そして、Sonic Piを起動し、Sonic PiとMinecraft Piの両方が見えるように、ウィンドウをリサイズしたり移動したりしましょう。
新しいBufferに次のコードを入力してみましょう。
mc_message "Hello Minecraft from Sonic Pi!"
では、Run
を叩いてみてください。ブーン! メッセージがMinecraftに表示されましたね! とても簡単だったでしょう? では、チュートリアルを読むのを止めて、少しの間メッセージを変更して遊んでみましょう。楽しでみて!
では、少し探検してみましょう。ワールドで移動する標準的なやりかたは、マウスとキーボードを使って、あたりを歩き始めることです。これは機能しますが、かなり遅いし退屈でしょう。何か瞬間移動マシンのようなものがあると良いのですが。。ええ、Sonic Piのおかげで、それは実現できます。これを試してみてください。
mc_teleport 80, 40, 100
びっくりした! 遠くまで移動できたでしょう。もし飛行モードなかったら、全ての行程を戻って地面に落ちてしまうでしょう。スペースキーをダブルタップして飛行モードに入ってもう一度瞬間移動すると、指定した場所に移動して浮いているでしょう。
では、これらの数字は何を意味するのでしょうか? ワールド内の行きたい場所の座標を表現するのに、3つの数字を使っています。そしてそれらに名前を付けています。x, yそしてzです。
x - どのくらい右端から左に離れてるか(我々の例では80) y - どのくらい高くあがったか(我々の例では40) z - どのくらい手前から奥へ離れてるか(我々の例では100)
異なるx, y, zの値を選ぶことで、ワールドの中のどこでも瞬間移動することができます。試してみよう! 違う値を選んで、どこに辿り着いたか見てみましょう。もし画面が真っ黒になってしまったら、それは地面の下か山の中に瞬間移動してしまったからです。地面よりも上に戻るように大きなyの値を選択してください。何か発見するまで探検を続けましょう…
ここまでのアイデアを使って、Minecraftのワールドを瞬間移動するときの音を面白くするSonic Teleporter
を作ってみましょう。
mc_message "Preparing to teleport...."
sample :ambi_lunar_land, rate: -1
sleep 1
mc_message "3"
sleep 1
mc_message "2"
sleep 1
mc_message "1"
sleep 1
mc_teleport 90, 20, 10
mc_message "Whoooosh!"
では、良い場所が見つかったと思いますので、何か作り始めてみましょう。あなたの慣れたやり方でもできますし、マウスを激しくクリックしてカーソルの部分にブロックを設置することも可能です。それ以外に、Sonic Piの魔法を使うことも可能です。これを試してみてください。
x, y, z = mc_location
mc_set_block :melon, x, y + 5, z
見てみてください! メロンが空中に現れました! ここでは何をしてるのでしょうか? 少し時間を取ってコードを見てみましょう。1行目では、プレイヤーの位置を取得してx, y, zの変数に入れています。これらの対応する座標については上で説明しています。これらの座標は、次の行のmc_set_block
関数で、指定したブロックを設置するのに使用されます。ブロックをより高い位置に設置するには、yの値に5を加えていたのを増やす必要があります。次にブロックの長い軌跡を作ってみましょう。
live_loop :melon_trail do
x, y, z = mc_location
mc_set_block :melon, x, y-1, z
sleep 0.125
end
では、Minecraftを表示して、飛行モードであることを確認して(もし飛行モードなかったらスペースキーをダブルタップしましょう)、ワールド中を飛び回ってみましょう。後ろにメロンのブロックの可愛い軌跡を見ることができたでしょう。どんなに曲がりくねったパターンでも作れたと思います。
このチュートリアルをここ数ヶ月読んできた人は驚いたかもしれません。メロンの軌跡はとてもクールだけど、先程の例の最もエキサイティングな部分はMinecraftでもlive_loop
を使えるということです! 知らない方のために説明すると、live_loop
は他のプログラミング言語が持っていない、Sonic Piの特別な機能です。live_loop
は複数のループを同時に実行し、また実行している最中にそれを変更することができます。それは信じられないほど強力で、驚くほど楽しいものです。私は、Sonic Piを使ってクラブで音楽を演奏するときにlive_loop
を使います。DJはレコードを使い、私はlive_loop
を使います:-) 今日は、音楽とMinecraftをライブコーディングしたいと思います。
では始めましょう。先程のコードを実行し、メロンの軌跡を作ってみましょう。そして、そのコードを止めずに、ただ:melon
を:brick
に変更してRun
を叩いてみてください。あら不思議、レンガの軌跡が作れたでしょう。なんと簡単なのでしょう! それに合わせて何か気の利いた音楽はいかがでしょう? それも簡単です。これを試してみてください。
live_loop :bass_trail do
tick
x, y, z = mc_location
b = (ring :melon, :brick, :glass).look
mc_set_block b, x, y -1, z
note = (ring :e1, :e2, :e3).look
use_synth :tb303
play note, release: 0.1, cutoff: 70
sleep 0.125
end
では、それが演奏されている間に、コードを変更してみましょう。ブロックのタイプを変更してみましょう。:water
や :grass
、そしてあなたの好きなブロックを試してみましょう。それに加えて、カットオフの値を70
から80
に変更し、そして100
に上げてみましょう。楽しいよね?
ここまで見てきた全てに、ちょっとした魔法を追加して組み合わせてみましょう。瞬間移動とブロック設置の機能と音楽を組み合わせて、Minecraftのミュージックビデオを作ってみましょう。全てを理解できなくても気にせずに、ただ以下のコードをタイプして、いくつかの値を実行中に変更してみましょう。楽しんでください。ではまた…
live_loop :note_blocks do
mc_message "This is Sonic Minecraft"
with_fx :reverb do
with_fx :echo, phase: 0.125, reps: 32 do
tick
x = (range 30, 90, step: 0.1).look
y = 20
z = -10
mc_teleport x, y, z
ns = (scale :e3, :minor_pentatonic)
n = ns.shuffle.choose
bs = (knit :glass, 3, :sand, 1)
b = bs.look
synth :beep, note: n, release: 0.1
mc_set_block b, x+20, n-60+y, z+10
mc_set_block b, x+20, n-60+y, z-10
sleep 0.25
end
end
end
live_loop :beats do
sample :bd_haus, cutoff: 100
sleep 0.5
end
先月は、Sonic PiでMinecraftのコーディングの素晴らしい世界に小旅行しましたが、また音楽的なものに戻りましょう。今日は、コードの凄い力を使って、クラシックのオペラ作品を21世紀に持ち込んでみましょう。
タイムマシンに乗って1875年に遡ってみましょう。ビゼーという作曲家が、彼の最後のオペラ作品となるカルメンを書き上げました。不運なことに、その作品は、多くの刺激的で破壊的な新しい音楽作品と同じように、あまりに奇抜でまた普通でないために、当初人々には全く好かれませんでした。そして残念なことに、その作品が国際的に多大な成功を収め、歴史上、最も有名で頻繁に公演されるオペラの1つになる10年前にビゼーは亡くなってしまいました。この悲劇に共感して、カルメンのメインテーマの1つを取り上げ、現代を生きる多くの人々にとって、あまりに奇抜でまた普通でない形式の音楽 - ライブコーディングされた音楽に変換してみましょう!
このチュートリアルでカルメンの全体をライブコーディングしようとするのは少し難しいので、最も有名な部分 - ハバネラのベースラインに着目しましょう。
もしあなたが楽譜について学んでいなかったら、これは全く読めないでしょう。しかし、プログラマとして楽譜を見ると、それはプログラミングコードの別な形式と捉えることができます。つまり楽譜は、コンピュータの代わりに演奏者に対する指示を表していると言えます。したがって我々は楽譜を解読する方法を理解する必要があります。
音符は、左から右に、ちょうどこの雑誌の単語と同じように並んでいますが、それぞれ異なる高さの位置を持っています。楽譜上の高さは、音符のピッチ(音程)を表しています。 つまり、楽譜上高い位置にあるものほど、音符のピッチは高くなります。
Sonic Piでのピッチの変更方法は既に知っているはずです。play 75
やplay 80
といったように数値を使ったり、play :E
やplay :F
といったように音名を使ったりできます。楽譜の上下の位置は、それぞれ特定の音名を表しています。便利な対応表を見てみましょう。
楽譜はとても表現力豊かなコードで、多くのことを伝達できます。したがって、楽譜がどの音符を演奏するかについてのみならず、音符をいつ演奏しないかについて伝達していても、それほど驚くことではないでしょう。これは、プログラミングにおいてはnil
とかnull
(値の無いこと)と同じ考え方です。言い換えると、音符を演奏しないことは、音符が無いことに似ていると言えるでしょう。
楽譜をよく見ると、演奏する音符を表す点と線の記号と、休符を表す曲がりくねった記号との組合せであることが分かると思います。Sonic Piにはとても便利な休符の表現として:r
が用意されていて、play :r
を実行するとSonic Piは無音を演奏するのです! これはまた、play :rest
やplay nil
やplay false
とも書くことができ、これらはみな休符を表す同じ方法です。
楽譜を解読するのに学習する最後の内容は、音符のタイミングです。元の楽譜では、音符同士を繋げる細い線、連桁(beam)と呼ばれているものを見ることができるでしょう。2つ目の音符では2つの連桁があり、これは16分の1拍だけ音が持続することを意味しています。その他の音符は1つの連桁を持っていて、それは8分の1拍だけ音が持続することを意味しています。休符は2つの曲がりくねった連桁を持っていて、これもまた16分の1拍を表しています。
新しいことを探索したり解読したりするときに役立つコツは、全てを可能な限り似たものにし、それらの関係やパターンを見出すことです。たとえば、元の楽譜を純粋に16分で記述し直すと、音符と休符の良い感じのシークエンスに変わるでしょう。
ハバネラのベースラインをSonic Piに翻訳する準備ができました。音符と休符をリングにコード化しましょう。
(ring :d, :r, :r, :a, :f5, :r, :a, :r)
どんな音がするか聞いてみましょう。ライブループに入れて、チックでリングを循環するようにしましょう。
live_loop :habanera do
play (ring :d, :r, :r, :a, :f5, :r, :a, :r).tick
sleep 0.25
end
すばらしい。スピーカーから一瞬でそれと分かるリフが活動的に鳴り始めたと思います。ここまで辿り着くのに多くの苦労がありましたが、その価値はありました。やったね!
ベースラインが出来たので、オペラのシーンの背景音を再生成してみましょう。試してみるシンセの1つは、:blade
です。これは、80年代スタイルのムーディーなリードシンセです。そのシンセを:d
の音で開始し、スライサーとリバーブに渡すようにしてみましょう。
live_loop :habanera do
use_synth :fm
use_transpose -12
play (ring :d, :r, :r, :a, :f5, :r, :a, :r).tick
sleep 0.25
end
with_fx :reverb do
live_loop :space_light do
with_fx :slicer, phase: 0.25 do
synth :blade, note: :d, release: 8, cutoff: 100, amp: 2
end
sleep 8
end
end
では、ベースラインの:a
と:f5
を他の音に変えてみてください。注意すべきは、Stop
を叩く必要はないということです。音楽が演奏されている最中に、だたコードを変更してRun
を再度叩いてください。そして、スライサーのphase:
オプションを、0.5
や0.75
や1
といった異なる値にしてみてください。
最後に全てのアイデアを組合せて、ハバネラの新しいリミックスを作ってみましょう。もう1つのベースラインがコメントアウトされていることに気が付いたかもしれません。新しいBufferにこれらをタイプしたら、Run
を叩いて曲を聞いてみてください。そして、Stop
を叩かずに、2行目のベースラインをコメントを解除して、#
を削除し、Run
を再度叩いてみてください。なんと凄いのでしょう! では、あなた自身でこのコードを弄って楽しんでください。
use_debug false
bizet_bass = (ring :d, :r, :r, :a, :f5, :r, :a, :r)
#bizet_bass = (ring :d, :r, :r, :Bb, :g5, :r, :Bb, :r)
with_fx :reverb, room: 1, mix: 0.3 do
live_loop :bizet do
with_fx :slicer, phase: 0.125 do
synth :blade, note: :d4, release: 8,
cutoff: 100, amp: 1.5
end
16.times do
tick
play bizet_bass.look, release: 0.1
play bizet_bass.look - 12, release: 0.3
sleep 0.125
end
end
end
live_loop :ind do
sample :loop_industrial, beat_stretch: 1,
cutoff: 100, rate: 1
sleep 1
end
live_loop :drums do
sample :bd_haus, cutoff: 110
synth :beep, note: 49, attack: 0,
release: 0.1
sleep 0.5
end
みなさんはMinecraftで遊んだことがあると思います。そして、凄い構造物を建てたり、巧妙なトラップを設計したり、レッドストーンのスイッチで制御された精巧なトロッコの路線を作ったりしたことがあるかもしれません。しかし、Minecraftでパフォーマンスをしたことがある人はどのくらい居るでしょうか? Minecraftを使ってまさにプロフェッショナルなVJのように凄いビジュアルを作れることを知っている人は少ないと思います。
あなたにとって、Minecraftを操作する唯一の方法がマウスだったら、十分に速くそれを実行できるようになるまで苦労するに違いありません。幸運にも、あなたの持っているRaspberry Piには、コードで制御可能なMinecraftが搭載されています。そして、Raspberry Piには、Sonic Piというアプリケーションも搭載されていて、ただ簡単なだけでなく、信じられないほど楽しくMinecraftをコーディングすることが可能です。
今回の記事では、我々が世界中のクラブやホールでパフォーマンスしたヒントとコツをお教えしたいと思います。
では始めましょう…
基本を習得するために、ウォームアップの練習から始めましょう。最初にRaspberry Piを起動し、続いてMinecraftとSonic Piの両方を起動してください。Minecraftでは、新しいワールドを作成し、Sonic Piでは新しいBufferを選択して、以下のコードを書いてください。
mc_message "Let's get started..."
Run
ボタンを叩いて、Minecraftのウィンドウ内にメッセージを見ることができたでしょう。大丈夫ですね。では準備ができました。楽しんでください……
Minecraftを使ってビジュアルを生成する際に、どのようなものが見た目が面白そうで、またコードから生成するのに簡単なのか試行錯誤しました。良さそうなテクニックの1つは、砂のブロックを空から落として砂嵐を作るというものです。これを実現するのに必要なものは、以下の基本的な関数です。
sleep
- アクションの間の遅延を挿入するのに使います
mc_location
- 現在の位置を取得するのに使います
mc_set_block
- 砂のブロックを指定した位置に設置するのに使います
rrand
- ある範囲の乱数を生成するのに使います
live_loop
- 砂嵐が起こったままにするのに使います
もしあなたがrrand
といったSonic Piが内蔵する関数に親しくなかったら、その関数名をBufferにタイプし、クリックして選択した後、Control-i
のキーの組合せを叩いて、内蔵のドキュメントを開いてみてください。あるいは、ヘルプシステムの命令タブを開いて、他にも面白そうな項目がある中から、対象の関数名を直接探すこともできます。
砂嵐のフルパワーを開放する前に少し砂を降らせてみましょう。現在の位置を取得し、近くの空中にいくつか砂のブロックを作ってください。
x, y, z = mc_location
mc_set_block :sand, x, y + 20, z + 5
sleep 2
mc_set_block :sand, x, y + 20, z + 6
sleep 2
mc_set_block :sand, x, y + 20, z + 7
sleep 2
mc_set_block :sand, x, y + 20, z + 8
Run
を叩いたとき、辺りを見回す必要があるかもしれません。プレイヤーがどの方向を向いているかにもよりますが、プレイヤーの後ろに砂が降っているかもしれません。でも心配しないでください。砂が降るのを見逃したとしても、Run
をもう一度叩いて砂を降らせて、プレイヤーが正しい方向を向くようにすればよいのです!
では上のコードで何が起きているか手短に見ていきましょう。1行目では、mc_location
関数を使って、プレイヤーの位置を座標として取得し、x
, y
, z
に設定しています。次の数行では、mc_set_block
関数を使って、プレイヤーの座標から少し変更を加えたところに砂を置いています。x座標は同じで、y座標は20ブロック高く、z座標は順に大きくして、プレイヤーからまっすぐ離れるように砂を落としています。
このコードであなた自身で遊んでみてはどうでしょう。コードを追加したり、sleepの時間を変更したり、:sandと
:gravel`を組合せたり、違う座標を選んでみたりしましょう。色々実験して楽しんでみてください!
では、live_loop
のフルパワーを解放して、嵐を激しくする時が来ました。live_loop
はライブコーディングのフルパワーを開放するSonic Piの特別な機能で、コードを実行したまま変更できてしまうのです!
live_loop :sand_storm do
x, y, z = mc_location
xd = rrand(-10, 10)
zd = rrand(-10, 10)
co = rrand(70, 130)
synth :cnoise, attack: 0, release: 0.125, cutoff: co
mc_set_block :sand, x + xd, y+20, z+zd
sleep 0.125
end
なんと楽しいのでしょう! このコードは、とても速く(毎秒8回)ループしていて、それぞれのループではプレイヤーの位置を前と同じように取得していますが、次の3つのランダムな値を生成しています。
xd
- x座標の差で、-10と10の間の値を取ります
zd
- z座標の差で、同じく-10と10の間の値を取ります
co
- ローパスフィルタのカットオフの値で、70と130の間の値を取ります
そしてこれらのランダムな値をsynth
とmc_set_block
関数で使用して、砂をプレイヤーの周りのランダムな位置に落とし、それに合わせて:cnoise
シンセでパーカッシブな雨のような音を鳴らしています。
ライブループに慣れていない人にお話すると、ここからがSonic Piで本当に面白くなるところです。コードが実行されていて砂が吹き出している最中に、コード内のどれかの値、たとえばsleepの時間を0.25
に変えたり、ブロックタイプを:sand
から:gravel
に変えてみてみましょう。そしてRun
をもう一度叩いてみてください。あら不思議! コードが止まらずに変更されました。これが、本物のVJと同じようにパフォーマンスする入り口です。練習してコードを変更し続けてください。あなたはコードを止めずにどれだけビジュアルを変えることができるかな?
最後に、興味深いビジュアルを生成するためのもう1つの素晴らしい方法は、巨大な模様付きの壁を生成して、そこを行き来することです。この効果のためには、ブロックをランダムに配置することから、規則的に配置することに移る必要があります。これを行うには、2つのイテレーション(反復)を入れ子にします(イテレーションの詳細については、ヘルプボタンをクリックして、チュートリアルのセクション5.2”イテレーション(反復)とループ”に移動してください)。doの後の面白い | xd |
は、イテレーションの各値に対してxd
が設定されることを意味します。 したがって、最初は0, 1, 2…などとなります。このように2回のイテレーションを入れ子にすることで、すべての座標を正方形に生成することができます。また、ブロックのリングからブロックタイプをランダムに選択して、興味深い効果を得ることもできます。
x, y, z = mc_location
bs = (ring :gold, :diamond, :glass)
10.times do |xd|
10.times do |yd|
mc_set_block bs.choose, x + xd, y + yd, z
end
end
かなりかっこいいね。このコードで楽しんでいる最中に、bs.choose
をbs.tick
に変更して、ランダムなパターンからより規則的なものにしてみましょう。ブロックタイプの変更やより冒険的な変更は、live_loop
の中でやってみましょう。そうすればパターンは自動的に変更し続けるでしょう。
では、VJの最後に2つの10.times
を100.times
に変更してRun
を叩いてみましょう。Kaboom! ランダムに配置されたレンガの巨大な巨大な壁。あなたがマウスで手動で構築するのにどれくらいの時間がかかるか想像してみてください! スペースをダブルタップして飛行モードに入り、素晴らしいビジュアルエフェクトを得るために降下してみましょう。しかしここで止まらないでください。あなたの想像力を使ってクールなアイデアを思いついたら、Sonic Piのコーディングの力でそれを形にしましょう。十分に練習したら、明かりを暗くし、友達のためにVJショーを始めましょう!
このチュートリアルの第4話では、いくつかのシンセ・リフをコーディングしながら、ランダム化を簡単に見ました。ランダム化は私のライブコーディングDJセットの重要な部分であることを考えると、その基礎をより詳細に取り上げることが有用であると考えました。では、幸運の帽子を被って、ランダムストリームをサーフィンしましょう!
これはあなたを本当に驚かせるかもしれませんが、Sonic Piのランダム化関数で遊ぶときに最初に学ぶことは、これらの関数が実際にはランダムではないということです。これは実際にはどのような意味でしょう? では、いくつかのテストを試してみましょう。まず、0と1の間の数字をあなたの頭の中で想像してください。そのまま私に教えないでください。私が当ててみましょう…それは0.321567
ですか? 違いましたか? ブー、当然ながら私はこれを上手く当てることができません。ではもう一度やりましょう。今度はSonic Piに番号を選んでもらいましょう。v2.7以降のSonic Piを起動して、乱数を要求してみてください。そして先程と同じように私には教えないでください:
print rand
では当ててみましょう… それは0.75006103515625
ですか? 合ってましたか! でも、あなたが少し疑っているのが分かります。それは多分ただのまぐれ当たりでしょう。もう1度やってみましょう。もう1度実行ボタンを押して、出たものを見て… 何? 0.75006103515625
? これは明らかにランダムではありません! あなたは正しい、ランダムではないですね。
ここでは何が起きてるでしょうか? ここで登場するコンピュータ科学の用語は決定論です。これは、偶然によるものは何も無く、すべてが運命づけられていることを意味します。あなたのバージョンのSonic Piは、上記のプログラムで常に 0.75006103515625
を返すようになっています。これはかなり役に立たないかもしれませんが、Sonic Piの最も強力な部分の1つであることを断言させてください。もしあなたがそれを追求すれば、作曲やライブコーディングDJセットの基本的なビルディング・ブロックとして、Sonic Piのランダム化の決定論的な性質に依存する方法を学ぶことになるでしょう。
Sonic Piが起動すると、441,000の事前に生成された乱数のシーケンスが実際にメモリにロードされます。rand
や rrand
のようなランダム関数を呼び出すと、このランダムストリームが関数の結果を生成するために使われます。ランダム関数の呼び出しする度に、このストリームから値を消費します。したがって、ランダム関数への10回目の呼び出しはストリームからの10番目の値を使用します。また、Runボタンを押すたびに、その実行のためにストリームがリセットされます。これが、私がrand
の結果を予測できたり、’random’なメロディーがいつも同じである理由です。皆さんのSonic Piは、まったく同じランダムストリームを使用しています。これは、私たちの作品をお互いに共有するときに非常に重要です。
繰り返し可能なランダムメロディを作るために、この知識を使ってみましょう。
8.times do
play rrand_i(50, 95)
sleep 0.125
end
これを空いたBufferに入力してRun
を叩いてください。50から95の’ランダムな’音符で構成されるメロディーを聞くことができるでしょう。メロディーが終わったら、もう一度Run
を叩いてみてください。先ほどと全く同じメロディーを聞くことができるでしょう。
Sonic Piにはランダムストリームを扱う便利な関数がたくさんあります。その中でも有用な関数のリストです。
rand
- ランダムストリームの次の値を返します
rrand
- 範囲内のランダムな値を返します
rrand_i
- 範囲内のランダムな整数を返します
one_in
- 与えられた確率でtrueまたはfalseを返します
dice
- サイコロを転がして、1から6までの値をランダムで返します
choose
- リストからランダムに値を1つ選択します
詳細情報や例については、ヘルプにあるそれぞれの関数のドキュメントを参照してください。
選択した音符のシーケンスを繰り返す機能は、リフをダンスフロアで再現するためには不可欠ですが、あなたが望んだリフではないかもしれません。もし、いくつかの異なるリフを試して、一番好きなリフを選ぶことができれば、素晴らしいことではないでしょうか? これが本当のマジックの始まりです。
ランダムストリームをuse_random_seed
関数で手動で設定することができます。コンピュータサイエンスでは、ランダムシードとは、ランダムな値の新しいストリームが芽吹き、開花する出発点です。試してみましょう:
use_random_seed 0
3.times do
play rrand_i(50, 95)
sleep 0.125
end
いいね。上のコードのランダムメロディーの先頭から84
, 83
, 71
の3つの音符が得られました。ここで、シードを別な値に変更できます。これはどうでしょう:
use_random_seed 1
3.times do
play rrand_i(50, 95)
sleep 0.125
end
興味深いことに、ここで83
, ` 71,
61`を取得します。ここの最初の2つの数字は、先程の後ろ2つの数字と同じです - これは偶然ではありません。
ランダムストリームは「あらかじめ準備された」値の巨大なリストに過ぎないことを思い出してください。ランダムシードの使用は、そのリスト内の特定の位置に単にジャンプするだけです。それについて考えるもう1つの方法は、あらかじめシャッフルされたトランプカードの巨大なデッキを想像することです。ランダムシードを使用することは、デッキの特定の位置でカードを分けることです。このことの素晴らしい点の1つは、ランダムストリームを行ったり来たりするこの機能こそ、音楽を作るときに私たちに大きな力を与えるということです。
ランダムメロディーに戻りましょう。今度は新しいランダムストリームのリセットで得られた8つの音符だけでなく、ライブループに入れて演奏中に実験できるようにしています:
live_loop :random_riff do
use_random_seed 0
8.times do
play rrand_i(50, 95), release: 0.1
sleep 0.125
end
end
では、上のコードが動いている間に、シードの値を0
から別な何かに変えてみましょう。100
、999
はどうでしょう。それからあなたの好きな値を試して、実験して遊んでみましょう。そして、どのシードが一番好きなリフを生成するか見てみましょう。
今月のチュートリアルでは、Sonic Piのランダム化機能の動作を技術的に詳しく説明しました。信頼性の高い方法でランダム化を使用して音楽内で繰り返し可能なパターンを作成する方法と、それがどのように動作するのかについて、何らかの示唆を与えられたことを願っています。そして、繰り返し可能なランダム化をどこでも使用できることを強調しておきます。例えば、音符の音量、リズムのタイミング、リバーブの量、現在のシンセ、エフェクトの掛かり具合などをランダム化することができます。これらについて、将来いくつかの応用を詳しく見たいですが、ここでは簡単な例を挙げておきます。
空いたBufferに以下のように入力し、Run
を叩いてみてください。そして、シードを変更してみて、(演奏された状態のまま)もう1度Run
を叩いてみてください。それによって作り出されるさまざまなサウンド、リズム、メロディを探索してみてください。もし素敵なものを見つけたら、シードの数字を覚えておいてください。最後に、あなたが好きなシードがいくつか見つかったら、お気に入りのシードを切り替えて曲にするだけで、ライブコーディングのパフォーマンスを提供できます。
live_loop :random_riff do
use_random_seed 10300
use_synth :prophet
s = [0.125, 0.25, 0.5].choose
8.times do
r = [0.125, 0.25, 1, 2].choose
n = (scale :e3, :minor).choose
co = rrand(30, 100)
play n, release: r, cutoff: co
sleep s
end
end
live_loop :drums do
use_random_seed 2001
16.times do
r = rrand(0.5, 10)
sample :drum_bass_hard, rate: r, amp: rand
sleep 0.125
end
end
ここまでで、このシリーズではサウンドをトリガーすることに焦点を当ててきました。我々は、play
やsynth
でSonic Piに組み込まれた多くのシンセサイザーを起動させることができ、sample
であらかじめ録音されたサンプルをトリガーする方法を見てきました。また、トリガーされたサウンドを、with_fx
コマンドを使ってリバーブやディストーションなどのスタジオ・エフェクト内にどのようにラップできるかを見てきました。これをSonic Piの信じられないほど正確なタイミングシステムと組み合わせると、広大なサウンド、ビート、リフを生成することができます。しかし、特定のサウンドのオプションを慎重に選択してトリガーすると、再生されている間にそのサウンドを変更することはできないでしょうか? それができるのです! 今日は、実行中のシンセをコントロールするとてもパワフルな方法を学びます。
はじめに、良い感じの簡単な音を作ってみましょう。Sonic Piを起動し、新しいBufferに以下のコードを打ち込んでください:
synth :prophet, note: :e1, release: 8, cutoff: 100
では、左上にあるRun
ボタンを押して、素敵な響きのシンセサウンドを聞きましょう。続いて、Run
ボタンを何度か押して、その音の感覚を掴みましょう。できましたか? では制御してみましょう!
play
, synth
, sample
といった関数が、実行中のサウンドを表象するSynthNode
と呼ばれるものを返却することは、Sonic Piで少し知られている機能かもしれません。これらのSynthNode
は標準的な変数に入れることができ、後で制御することができます。例えば、cutoff:
のオプションを1拍後に変更してみましょう。
sn = synth :prophet, note: :e1, release: 8, cutoff: 100
sleep 1
control sn, cutoff: 130
各行を順番に見ていきましょう。
最初に、:prophet
シンセをsynth
関数でいつものようにトリガーしています。しかし、その結果をsn
という変数に入れています。この変数はsynth_node
やjane
といった何か全く異なるものでも構いません。しかし、何か意味のある名前を選ぶことがあなたのパフォーマンスや後でこのコードを読む人々にとって重要でしょう。私は、シンセ・ノードのニーモニック(略名)が良かったので、sn
を選びました。
2行目では、標準的なsleep
コマンドを呼んでいます。これは何も特別なことはありません。次の行に進む前に1拍待つようコンピュータに指示しているだけです。
3行目はコントロールによって楽しくなるところです。ここでは、control
関数を使って実行中のSynthNode
にカットオフの値を130
に変更するよう指示しています。Runボタンを叩くと、:prophet
シンセが前と同じように演奏され、1拍後にそのサウンドが明るくなるのを聞くことができるでしょう。
調整可能なオプション
Sonic Piのシンセやエフェクトのオプションのほとんどは、トリガーされた後に変更できるかもしれません。しかし、これはすべてに当てはまるという訳ではないのです。例えば、エンベロープのオプション attack:
, decay:
, sustain:
とrelease:
は、シンセをトリガーするときだけ設定できます。オプションを変更できるどうかは簡単です。特定のシンセまたはエフェクトのドキュメントに進み、個々のオプションのドキュメントまでスクロールして、”May be changed whilst playing”(演奏中に変更可能です)か”Can not be changed once set”(一度設定されると変更できません)というフレーズを探すだけです。例えば、:beep
シンセのattack:
オプションのドキュメントは、それを変更できないことを明確にしています:
Default: 0 Must be zero or greater Can not be changed once set Scaled with current BPM value
シンセが動作している間は、一度だけ変更することに限らず、何度でも自由に変更することができます。例えば、次のように:prophet
をミニ・アルペジエーターにすることができます:
notes = (scale :e3, :minor_pentatonic)
sn = synth :prophet, note: :e1, release: 8, cutoff: 100
sleep 1
16.times do
control sn, note: notes.tick
sleep 0.125
end
このコードスニペットでは、いくつか余分なものを追加しました。最初に、notes
という新しい変数を定義しました。この変数には、循環させたい音符が含まれています(アルペジエーターは音符のリストを順番に循環する何かに名前を付けたものです)。第二に、私たちは単一の呼び出しをcontrol
に置き換え、それを16回呼び出す反復で置き換えました。control
の呼び出しの度に、notes
のリングを順に.tick
していきます(Sonic Piのリングの素晴らしいパワーのおかげで、リングは末尾に達すると先頭に戻ります)。ちょっとした変化として、.tick
を.choose
で置き換えて、その違いを聞くことができるかどうか確認してください。
複数のオプションを同時に変更することもできます。コントロールの行を次のように変更して、その違いを聞いてみてください:
control sn, note: notes.tick, cutoff: rrand(70, 130)
SynthNode
をコントロールすると、正確に時間通りに応答し、ボタンを押したり、変更を要求するスイッチをフリックしたかのように、オプションの値を新しいものに即座に変更します。これは、特にオプションがのcutoff:
ような音色の1つをコントロールしている場合に、リズミカルでパーカッシブに聞こえることがあります。しかし、瞬間的に変更が発生することを望まないこともあります。その代わりに、スライダーやダイヤルを移動した場合のように、現在の値から新しい値にスムーズに移動したい場合があります。もちろん、Sonic Piでも_slide:
オプションを使うことで、これを行うことができます。
変更可能なオプションには、それぞれ対応する_slide:
という特別なオプションがあり、スライドの時間を指定できます。例えば、amp:
はamp_slide:
を、cutoff:
はcutoff_slide:
を持っています。これらのスライド・オプションは、次にそれらがコントロールされたときにどのように動作するかをシンセの音符に指示するという点で、他のすべてのオプションとは少し異なります。次のコードを見てみましょう:
sn = synth :prophet, note: :e1, release: 8, cutoff: 70, cutoff_slide: 2
sleep 1
control sn, cutoff: 130
この例がcutoff_slide:
を除いて先の例と全く同じであることに注目してください。これは、このシンセで次にcutoff:
をコントロールすると、現在の値から新しい値にスライドするのに2拍かかることを示しています。したがって、control
を使用したとき、カットオフが70から130までスライドするのを聞くことができるでしょう。これは、音に興味深いダイナミックな感触を作り出します。次に、 cutoff_slide:
の時間を0.5などの短い値や4などのより長い値に変更して、音の変化を確認してください。変更可能なオプションであれば、これと同じようにスライドできることを覚えておいてください。それぞれの_slide:
の値は完全に異なるので、あなたがやろうとすれば、カットオフをゆっくりとスライドしつつ、アンプは速くスライドし、パンをどこかの間をスライドさせることも可能です…
シンセがトリガーされた後にコントロールする力を実証する短い例を見てみましょう。エフェクトもシンセと同じようにスライドできますが、少し文法が異なることに注目してください。エフェクトのコントロールについての情報は、チュートリアルのセクション7.2をチェックしてみてください。
以下のコードを使用可能なBufferにコピーして聞いてみてください。そこで止めずに、そのコードで遊んでみてください。スライドの時間や音符、シンセ、エフェクトやスリープの時間を変更して、全く異なるものに変更できたことを確認してください!
live_loop :moon_rise do
with_fx :echo, mix: 0, mix_slide: 8 do |fx|
control fx, mix: 1
notes = (scale :e3, :minor_pentatonic, num_octaves: 2).shuffle
sn = synth :prophet , sustain: 8, note: :e1, cutoff: 70, cutoff_slide: 8
control sn, cutoff: 130
sleep 2
32.times do
control sn, note: notes.tick, pan: rrand(-1, 1)
sleep 0.125
end
end
end
このシリーズでは先月、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
When people discover Sonic Pi, one of the first things they learn is how simple it is to play pre-recorded sounds using the sample
function. For example, you can play an industrial drum loop, hear the sound of a choir or even listen to a vinyl scratch all via a single line of code. However, many people don’t realise that you can actually vary the speed that the sample is played back at for some powerful effects and a whole new level of control over your recorded sounds. So, fire up a copy of Sonic Pi and let’s get started stretching some samples!
To modify the playback rate of a sample we need to use the rate:
opt:
sample :guit_em9, rate: 1
If we specify a rate:
of 1
then the sample is played back at the normal rate. If we want to play it back at half speed we simply use a rate:
of 0.5
:
sample :guit_em9, rate: 0.5
choose:選択
In addition to making the sound longer and lower using a small rate, we can use higher rates to make the sound shorter and higher. Let’s play with a drum loop this time. First, take a listen to how it sounds at the default rate of 1
:
sample :loop_amen, rate: -1
Now, let’s speed it up a little:
sample :loop_amen, rate: 1.5
Ha! We just moved musical genres from old-skool techno to jungle. Notice how the pitch of each drum hit is higher as well as how the whole rhythm speeds up. Now, try even higher rates and see how high and short you can make the drum loop. For example, if you use a rate of 100
, the drum loop turns into a click!
Now, I’m sure many of you are thinking the same thing right now… “what if you use a negative number for the rate?”. Great question! Let’s think about this for a moment. If our rate:
opt signifies the speed with which the sample is played back, 1
being normal speed, 2
being double speed, 0.5
being half speed, -1
must mean backwards! Let’s try it on a snare. First, play it back at the normal rate:
sample :elec_filt_snare, rate: 1
かっこいい! 逆再生になりますね!
sample :elec_filt_snare, rate: -1
Of course, you can play it backwards twice as fast with a rate of -2
or backwards at half speed with a rate of -0.5
. Now, play around with different negative rates and have fun. It’s particularly amusing with the :misc_burp
sample!
One of the effects of rate modification on samples is that faster rates result in the sample sounding higher in pitch and slower rates result in the sample sounding lower in pitch. Another place you may have heard this effect in every day life is when you’re cycling or driving past a beeping pedestrian crossing - as you’re heading towards the sound source the pitch is higher than when you’re moving away from the sound - the so-called Doppler effect. Why is this?
Let’s consider a simple beep which is represented by a sine wave. If we use an oscilloscope to plot a beep, we’ll see something like Figure A. If we plot a beep an octave higher, we’ll see Figure B and an octave lower will look like Figure C. Notice that the waves of higher notes are more compact and the waves of lower notes are more spread out.
A sample of a beep is nothing more than a lot of numbers (x, y, coordinates) which when plotted onto a graph will re-draw the original curves. See figure D where each circle represents a coordinate. To turn the coordinates back into audio, the computer works through each x value and sends the corresponding y value to the speakers. The trick here is that the rate at which the computer works through the x numbers does not have to be the same as the rate with which they were recorded. In other words, the space (representing an amount of time) between each circle can be stretched or compressed. So, if the computer walks through the x values faster than the original rate, it will have the effect of squashing the circles closer together which will result in a higher sounding beep. It will also make the beep shorter as we will work through all the circles faster. This is shown in Figure E.
Finally, one last thing to know is that a mathematician called Fourier proved that any sound is actually lots and lots of sine waves all combined together. Therefore, when we compress and stretch any recorded sound we’re actually stretching and compressing many sine waves all at the same time in exactly this manner.
As we’ve seen, using a faster rate will make the sound higher in pitch and a slower rate will make the sound lower in pitch. A very simple and useful trick is to know that doubling the rate actually results in the pitch being an octave higher and inversely halving the rate results in the pitch being an octave lower. This means that for melodic samples, playing it alongside itself at double/half rates actually sounds rather nice:
sample :bass_trance_c, rate: 1
sample :bass_trance_c, rate: 2
sample :bass_trance_c, rate: 0.5
However, what if we just want to alter the rate such that the pitch goes up one semitone (one note up on a piano)? Sonic Pi makes this very easy via the rpitch:
opt:
sample :bass_trance_c
sample :bass_trance_c, rpitch: 3
sample :bass_trance_c, rpitch: 7
If you take a look at the log on the right, you’ll notice that an rpitch:
of 3
actually corresponds to a rate of 1.1892
and a rpitch:
of 7
corresponds to a rate of 1.4983
. Finally, we can even combine rate:
and rpitch:
opts:
sample :ambi_choir, rate: 0.25, rpitch: 3
sleep 3
sample :ambi_choir, rate: 0.25, rpitch: 5
sleep 2
sample :ambi_choir, rate: 0.25, rpitch: 6
sleep 1
sample :ambi_choir, rate: 0.25, rpitch: 1
Let’s take a look at a simple piece which combines these ideas. Copy it into an empty Sonic Pi buffer, hit play, listen to it for a while and then use it as a starting point for your own piece. See how much fun it is to manipulate the playback rate of samples. As an added exercise try recording your own sounds and play around with the rate to see what crazy sounds you can make.
live_loop :beats do
sample :guit_em9, rate: [0.25, 0.5, -1].choose, amp: 2
sample :loop_garzul, rate: [0.5, 1].choose
sleep 8
end
live_loop :melody do
oct = [-1, 1, 2].choose * 12
with_fx :reverb, amp: 2 do
16.times do
n = (scale 0, :minor_pentatonic).choose
sample :bass_voxy_hit_c, rpitch: n + 4 + oct
sleep 0.125
end
end
end
このシリーズの前回の記事では、ランダム化の力を探求し、それがライブコーディングされたトラックやパフォーマンスに多様性や驚きや変化をもたらすのを示しました。例えば、ある音階からランダムにピックアップした音符で、終わりのないメロディーを作りました。今日は、ランダム化をリズムに適用した新しいテクニック、確率的ビートについて学びます。
新しいビートやシンセのリズムを作り始める前に、確率に関する基本についてざっと見てみる必要があります。これは複雑で骨の折れるように聞こえるかもしれませんが、実際のところ、サイコロを振るのと同じくらい簡単です! 普通の6面のサイコロを振ると何が起きるでしょうか? そうですね。1, 2, 3, 4, 5, 6のいずれかが同じチャンスで得られるでしょう。実際、6面のサイコロであれば、(もしあなたが何度も何度も振れば)平均して6回に1回1の目が出るでしょう。これが1の目を出すのに1/6のチャンスがあることを示しています。Sonic Piでは、サイコロを振るのをdice
関数でエミュレートできます。では8回サイコロを振ってみましょう:
8.times do
puts dice
sleep 1
end
ちょうど実物のサイコロを振ったのと同じように、1から6の間の値をログに表示していることに注目してください。
では、あなたの目の前にドラムがあって、それを叩こうとするときにいつもサイコロを振るのを想像してみてください。もしあなたが1の目を出したらドラムを叩き、それ以外の目を出したら叩かないとしましょう。これであなたは、1/6の確率で動作する確率的なドラムマシーンを手に入れたことになります! どんな音がするか聞いてみましょう:
live_loop :random_beat do
sample :drum_snare_hard if dice == 1
sleep 0.125
end
全てが明確になるよう、各行をざっと見ていきましょう。最初に、:random_beat
という名前を付けたlive_loop
を作って、do
からend
までの2行を繰り返しています。ループ内の最初の行は、sample
を呼んであらかじめ録音された音(この場合は:drum_snare_hard
の音)を再生しています。しかし、この行には特別なif
の条件が末尾に付いています。これは、この行がif
の右側の条件式がtrue
であるときだけ実行されることを意味しています。この場合、条件式はdice == 1
です。dice
関数の呼び出しは、我々が既に見てきたように、1から6の値を返します。つづいて、等価演算子の==
を使って、この値が1
かどうかチェックしています。もし1
であれば、この条件式はtrue
となり、スネアドラムの音が再生され、1
でなければ、この条件式はfalse
となり、スネアドラムはスキップされます。ループ内の2行目は、次にサイコロを振る前に、単に0.125
秒間待っているだけです。
ロールプレイングゲームをプレイしたことがある人の中には、さまざまな範囲を持つ不思議なな形をしたサイコロに馴染みがあるかもしれません。たとえば、三角錐(正四面体)の形をした4面のサイコロや、正二十面体の形をした20面のサイコロがあります。サイコロの面の数はも1の目を出すチャンスや確率を変えます。面が少なければ、より1の目を出しやすくなり、面が多くなれば、より1の目を出しにくくなります。たとえば、4面のサイコロでは、1の目をだすのに1/4のチャンスがありますが、20面のサイコロでは、1の目をだすのに1/20のチャンスがあります。幸いにも、Sonic Piにはちょうどこれと同じことができる便利なone_in
関数があります。次をやってみましょう:
live_loop :different_probabilities do
sample :drum_snare_hard if one_in(6)
sleep 0.125
end
上のライブループを開始すると、馴染みのあるランダムリズムを聞くことができるでしょう。しかし、実行されているコードを止めないでください。そのかわり、6
を異なる値、たとえば2
とか20
に変更して、Run
ボタンを叩いてみてください。小さい数字はスネアドラムがより頻繁に再生され、大きい数字はスネアドラムがあまり頻繁に再生されないということを意味しているのに注目してください。これであなたは確率で音楽を作っていることになるのです!
複数のサンプルが異なる確率でトリガーされるのを組み合せると、本当に刺激的になります。例えば:
live_loop :multi_beat do
sample :elec_hi_snare if one_in(6)
sample :drum_cymbal_closed if one_in(2)
sample :drum_cymbal_pedal if one_in(3)
sample :bd_haus if one_in(4)
sleep 0.125
end
もう一度、上のコードを実行して、リズムを変更するために確率を変更してみてください。また、試しにサンプルを変更してみると、全く新しい感覚を生み出すでしょう。例えば、低音を追加するために、試しに:drum_cymbal_closed
を:bass_hit_c
に変更してみてください!
次に、我々にはすっかりお馴染みのuse_random_seed
を使って、8回の繰り返しの後に、ランダム・ストリームをリセットすると、規則的なビートを作ることができます。次のコードをタイプして、より規則的で再現可能なリズムを聞いてみましょう。一度ビートを聞いたら、シードの値を1000
から別なものにしてみましょう。異なる数字が異なるビートを生成することに注目してください。
live_loop :multi_beat do
use_random_seed 1000
8.times do
sample :elec_hi_snare if one_in(6)
sample :drum_cymbal_closed if one_in(2)
sample :drum_cymbal_pedal if one_in(3)
sample :bd_haus if one_in(4)
sleep 0.125
end
end
この種の構造で私がよくやるのは、よい感じの音がしたらシードを記録しておくことです。それにより、後で練習したりパフォーマンスしたりするときに、簡単にそのリズムを再生成することができます。
最後に、よい感じのメロディーを提供するランダムなベースを入れることができます。我々が新しく発見した確率的なシーケンスの方法は、サンプルと同じようにシンセに対しても同様に使用可能です。このコードをそのままにせずに、数字を操作して、確率の力であなた自身のトラックを是非作ってください!
live_loop :multi_beat do
use_random_seed 2000
8.times do
c = rrand(70, 130)
n = (scale :e1, :minor_pentatonic).take(3).choose
synth :tb303, note: n, release: 0.1, cutoff: c if rand < 0.9
sample :elec_hi_snare if one_in(6)
sample :drum_cymbal_closed if one_in(2)
sample :drum_cymbal_pedal if one_in(3)
sample :bd_haus, amp: 1.5 if one_in(4)
sleep 0.125
end
end
今月は、Sonic Piで最もパワフルでフレキシブルなエフェクトの1つである、:slicer
を深く見ていきたいと思います。この記事の終わりまでに、ライブコーディングされたサウンドの全体的な音量を操作する、新しいパワフルな方法を習得できるでしょう。これは、新しいリズム的・音色的な構造を生成することができ、また音響的な可能性を広げることができるでしょう。
実際のところ、:slicer
エフェクトは何をやってるのでしょうか? 誰かがテレビやオーディオ製品のボリュームコントロールで遊んでいるのと同じようなものと考えてみるのも、1つの方法かもしれません。早速見ていきたいところですが、最初に:prophet
をトリガーする次のコードの深い唸り声を聞いてみてください:
synth :prophet, note: :e1, release: 8, cutoff: 70
synth :prophet, note: :e1 + 4, release: 8, cutoff: 80
では、これを:slicer
エフェクトに通してみましょう:
with_fx :slicer do
synth :prophet, note: :e1, release: 8, cutoff: 70
synth :prophet, note: :e1 + 4, release: 8, cutoff: 80
end
:slicer
が規則的なビートで音をミュートしたりしなかったりするのを聞いてみてください。また、:slicer
がdo
/end
ブロックの中で生成された全ての音に影響していることに注目してください。音のオン・オフの速さは、phase duration
の短縮語であるphase:
オプションを使ってコントロールできます。phase:
オプションのデフォルト値は0.25
で、デフォルトのBPM60だと、1秒間に4回という意味になります。もっと速くしてみましょう:
with_fx :slicer, phase: 0.125 do
synth :prophet, note: :e1, release: 8, cutoff: 70
synth :prophet, note: :e1 + 4, release: 8, cutoff: 80
end
では、異なるphase:
の長さで遊んでみましょう。長い値や短い値を試してみましょう。本当に短い値を選んだら何が起こるか見てみてください。また、:beep
や:dsaw
といった異なるシンセや、異なる音符も試してみましょう。次の図で、異なるphase:
の値が、1拍の間に音の大きさを変更する回数をどのように変化させるか見てみましょう。
phase duration
は、オン・オフの周期の時間の長さを示してします。したがって、より小さい値はエフェクトのオン・オフをより早く切り替えます。はじめに試してみるのに良さそうな値は、0.125
, 0.25
, 0.5
, 1
でしょう。
デフォルトでは、:slicer
エフェクトは音の大きさを操作するのに矩形波を使っています。一定時間音量がオンで聞こえてその後急にオフになるのは、これが理由です。矩形波は、:slicer
がサポートしている4つの制御波形の1つであることが分かるでしょう。それ以外のものは、ノコギリ波、三角波、正弦波(または余弦波)です。下の図はそれぞれがどのような形をしているか示しています。また、それがどのような音がするのか聴くこともできます。例えば、次のコードは正弦波(または余弦波)を制御波形として使用しています。音が急にオン・オフせずにスムーズにフェードイン・フェードアウトするのを聴いてみてください。
with_fx :slicer, phase: 0.5, wave: 3 do
synth :dsaw, note: :e3, release: 8, cutoff: 120
synth :dsaw, note: :e2, release: 8, cutoff: 100
end
wave:
オプションを変更することで、異なる波形で演奏してみましょう。0
がノコギリ波、1
が矩形波、2
が三角波で、3
が正弦波です。 また、異なるphase:
オプションを組み合わせて、それぞれの波形がどのような音がするか試してみましょう。
これらの波形は、invert_wave:
オプションでy軸方向に反転させることができます。例えば、典型的なノコギリ波は、高い値から始まり、徐々に値が下がっていって、ある時点で元の高い値に戻ります。invert_wave: 1
を指定することで、低い値から始まり、徐々に値が上がっていって、ある時点で元の低い値に戻るようになります。また、波形操作は、phase_offset:
オプションに0
から1
の値を指定することにより、波形の任意の位相から開始することができます。phase:
, wave:
, invert_wave:
とphase_offset
オプションを変更することで、時間に沿って音量をどれだけ変化させるかを、劇的に変更することができます。
デフォルトでは、:slicer
エフェクトは1
(最大)と0
(無音)の間の音量を切り替えます。これは、amp_min:
とamp_max:
オプションで変更できます。これを正弦波の設定に適用することで、シンプルなトレモロ効果を作ることができます:
with_fx :slicer, amp_min: 0.25, amp_max: 0.75, wave: 3, phase: 0.25 do
synth :saw, release: 8
end
これはちょうど、オーディオ機器のボリュームつまみをひねって、音をグラグラ
させるのに似ています。
:slicer
エフェクトのパワフルな特長の1つは、スライサーをオン・オフするかしないかを選択するのに、確率を使用可能なことでしょう。:slicer
エフェクトが次の位相を開始する前にサイコロを振って、その結果をもとに選択した波形を使うかもしくは音量をオフにしたままにするかします。聞いてみましょう:
with_fx :slicer, phase: 0.125, probability: 0.6 do
synth :tb303, note: :e1, cutoff_attack: 8, release: 8
synth :tb303, note: :e2, cutoff_attack: 4, release: 8
synth :tb303, note: :e3, cutoff_attack: 2, release: 8
end
興味深いパルスのリズムを生成できたのを聞くことができるでしょう。試しに、probability:
オプションを0
から1
の間の値に変更してみましょう。0
に近い値にすると、音がトリガーされる確率がより低くなるため、それぞれの音の間が広がるでしょう。
他にお伝えしたいのは、:slice
エフェクトにおけるランダム化システムは、rand
やshuffle
といった関数経由でアクセス可能なランダム化システムとちょうど同じであるということです。これらはどちらも完全に決定的です。これはRun
を叩いたときに、指定された確率に対応して毎回同じパルスのリズムを聞くことになることを意味しています。これらを変更したい場合には、seed:
オプションを使って異なるシードを選択することが可能です。これはuse_random_seed
と全く同じように動作しますが、特定のエフェクトにのみ影響します。
最後に、確率的にオフになった場合に制御波形内の’休止する’位置を、prob_pos:
オプションを使って0
から他の値に変更できます:
with_fx :slicer, phase: 0.125, probability: 0.6, prob_pos: 1 do
synth :tb303, note: :e1, cutoff_attack: 8, release: 8
synth :tb303, note: :e2, cutoff_attack: 4, release: 8
synth :tb303, note: :e3, cutoff_attack: 2, release: 8
end
:slicer
エフェクトでドラムビートをブツ切りするのは、やってみると本当に楽しいことの1つです:
with_fx :slicer, phase: 0.125 do
sample :loop_mika
end
これにより、任意のサンプル音源から新しいリズムの可能性を作り出すことができ、とても楽しいでしょう。しかしながら、1つ注意すべきことは、サンプルのテンポがSonic PiのカレントのBPMに合うようにすることです。そうでないと、スライスは全くの無音にしてしまうかもしれません。たとえば、:loop_mika
をloop_amen
サンプルに変更してみて、テンポが揃ってない場合にどれだけひどい音になるか聞いてみましょう。
既に見てきたように、use_bpm
でデフォルトのBPMを変更すると、全てのsleepの長さとシンセのエンベロープの長さがビートに一致するように伸縮されます。:slicer
エフェクトのphase:
オプションな実際には秒単位でなく拍単位なので、同じようにこれを受け入れることができます。したがって、BPMを変更してサンプルに一致させることで、上のloop_amen
の問題を解決できます。
use_sample_bpm :loop_amen
with_fx :slicer, phase: 0.125 do
sample :loop_amen
end
最後に、これらのアイデアを全て適用して1つの例にしましょう。:slicer
エフェクトのみを使って、興味深い組み合わせを作り出してみましょう。ここから変更して自分自身の作品にしてみましょう!
live_loop :dark_mist do
co = (line 70, 130, steps: 8).tick
with_fx :slicer, probability: 0.7, prob_pos: 1 do
synth :prophet, note: :e1, release: 8, cutoff: co
end
with_fx :slicer, phase: [0.125, 0.25].choose do
sample :guit_em9, rate: 0.5
end
sleep 8
end
live_loop :crashing_waves do
with_fx :slicer, wave: 0, phase: 0.25 do
sample :loop_mika, rate: 0.5
end
sleep 16
end
今月のチュートリアルでは、Sonic Piを本物の楽器と同じように扱う方法を見ていきたいと思います。そのため、コードについて今までと全く異なる見方で考える必要があります。ライブコーダーはコードを、バイオリニストにとっての弓と同じように考えています。実際、バイオリニストが異なる音を作るのに様々な弓のテクニックを適用する(長くゆっくりとした動きと短く速い打弦)のとちょうど同じように、Sonic Piで可能な基本的なライブコーディングのテクニックを5つ見ていきます。この記事の終わりまでに、あなたはライブコーディングのパフォーマンスの練習を始めることが出来ているでしょう。
Sonic Piでライブコーディングする際の最初のヒントは、ショートカットを使うことです。例えば、マウスに手を伸ばしてRun
ボタンに合わせてクリックするのに貴重な時間を無駄にするよりも、単にalt
とr
を同時に押すことが可能です。これは速いし、指がキーボードに置かれたままなので、次の編集のための準備が整っています。ショートカットを探すには、画面上部のボタンにそれぞれマウスを乗せると表示されます。ショートカットの一覧を見るには、チュートリアルの10.2を参照してください。
パフォーマンスの際、1つやってみると面白いのは、ショートカットを叩くときの動作に少し装飾を追加してみることです。例えば、あなたが音を変更しようとするときにそれを観客に伝えるのは良いことです。したがって、alt-r
を叩く際の動作を飾るのはギタリストがパワーコードを掻き鳴らすのとちょうど同じことなのです。
コードをキーボードから素早く実行できるようになったら、そのスキルは、手動で音を重ねる2つめのテクニックに適用できます。たくさんのplay
とsample
の呼び出しをsleep
で挟んで’作曲’する代わりに、1つのplay
の呼び出しをalt-r
で手動で実行してみたいと思います。では試してみましょう。次のコードを新しいBufferにタイプしてみてください:
synth :tb303, note: :e2 - 0, release: 12, cutoff: 90
タイプしたら、Run
を叩いて音を出してみてください。音が出ている間に、次のコードのように、4音下げるためにコードを変更してください:
synth :tb303, note: :e2 - 4, release: 12, cutoff: 90
では、再度Run
を叩いてみてください。両方の音がそのまま再生されているが聞こえると思います。これは、Sonic PiのRun
が前回実行したコードが終わるのを待つたずに、新しいコードを開始するためです。これは、実行の度に多少の変更を加えることで、簡単にたくさんの音を重ねることが可能ということです。例えば、note:
とcutoff:
オプションの両方を変更して、再度実行してみてください。
また、このテクニックは長いアブストラクトなサンプルでも試すことができます。例えば、次のコードです:
sample :ambi_lunar_land, rate: 1
最初はサンプル無しで始めて、Run
を叩く度に、rate:
オプションを1
から0.5
, 0.25
, 0.125
に変更し、さらに-0.5
のような負の値も試してみましょう。音を重ね合わせてどう聞こえるか試してみてください。最後に何かエフェクトを追加してみてください。
パフォーマンスの際にこのようなシンプルなコードを使用すると、Sonic Piにあまり馴染みのない観客にとっては、あなたが何をしているのかを追ったり、コードと音を関連付けたりするのに良い機会になると言えるでしょう。
もっとリズミカルな音楽の場合、全てを手動で実行しながら良いタイミングを保つのは難しいでしょう。その場合は、live_loop
を使うのが良いでしょう。これはコードを繰り返しつつ、次にループが先頭に戻ったときに実行されるように、コードを編集できる機能を提供しています。また、ライブループは他のlive_loop
と同時に実行でき、それはすなわち、ライブループ同士を重ねたり、他に手動で実行したコードと重ねたりすることが可能ということです。ライブループに関するより詳細な情報については、チュートリアルの9.2を参照してください。
パフォーマンスの際には、live_loop
のsync:
を使うことを覚えておくと良いでしょう。これは、エラーによってライブループの実行が止まってしまった場合の回復手段として役に立ちます。もし既にsync:
が他の正常に動作しているlive_loop
を指しているのであれば、エラーをすぐに修正してコードを再実行することで、ビートが欠いた状態を解消して再起動できるでしょう。
Sonic Piの最高の秘密の1つは、全ての音が流れるマスターミキサーを持っていることです。そしてこのミキサーはローパスフィルタとハイパスフィルタを内蔵しているので、簡単に音全体を変更できます。マスターミキサーの機能は、set_mixer_control!
関数によりアクセス可能です。例えば、何かコードが実行中で音を出している最中に、次のコードを空いたBufferに入力してRun
を叩いてみてください:
set_mixer_control! lpf: 50
このコードの実行後、既に出ている音とこれから出てくる音の全てにローパスフィルタが適用されるので、ぼんやりとした音になります。これは、先程のコードで設定されたミキサーの値が、再び変更されるまで保持されることを意味しています。しかし、もし値をリセットしたい場合には、reset_mixer!
でいつでもデフォルトの状態に戻すことができます。現在対応しているオプションには、pre_amp:
, lpf:
, hpf:
,amp:
があります。全てのオプションの一覧については、set_mixer_control!
のドキュメントを参照してください。
オプションの値を時間に沿ってスライドさせるために、ミキサーの*_slide
オプションを使ってみましょう。例えば、ミキサーのローパスフィルタを現在の値から30にゆっくりスライドさせるには、次のコードを使ってみてください:
set_mixer_control! lpf_slide: 16, lpf: 30
次に、高い値に素早くスライドして戻すこともできます:
set_mixer_control! lpf_slide: 1, lpf: 130
パフォーマンスの際には、ここでやったようにミキサーのためのBufferを空けておくと便利でしょう。
ライブコーディングの最も重要なテクニックは練習です。すべてのプロのミュージシャンに共通する点は、自分の楽器を練習することです。多くの場合、1日に何時間も練習しています。ギタリストと同じようにライブコーダーにとっても練習は重要です。練習によってあなたの指は特定のパターンや一般的な編集内容を覚えるので、入力や作業がよりスムーズに行えます。練習はまた、新しい音やコード構成を探求する機会をあなたに提供します。
パフォーマンスの際には、やってきた練習が多ければ多いほど、緊張せずにライブに入ることが簡単になると気づくでしょう。練習はまたそこから豊富な経験を提供するでしょう。それにより、どんな種類の変更が面白く、また現在の音に上手く作用するか分かるようになるでしょう。
今月は、全てを組み合わせた例を示す代わりに、課題を設定してお別れにしましょう。今回紹介したアイデアを毎日1つ選んで練習して1週間を過ごせるか試してみてください。例えば、ある日は手動の実行を練習し、その次の日はlive_loop
の基本的な作業をやってみて、その次の日はマスターミキサーで遊んでみます。そしてそれを繰り返します。最初は、全てがゆっくりで不器用に感じられるかもしれませんが、心配しないでください。ただ練習を継続すれば、あなたの知らないうちに実際の聴衆の前でライブコーディングできるようになっているでしょう。
先月は、ライブコーディングをマスターするための5つの重要なテクニックを見ました。言い換えると、楽器と同じようなやり方でコードに接するために、どのようにSonic Piを使うことができるか探求しました。そして、我々が議論した重要なコンセプトの1つに、練習がありました。今月は、なぜライブコーディングの練習が重要で、それをどのように始めるかについて、理解を深めて行きたいと思います。
最も重要なアドバイスとしては、必ず定期的に練習することです。私自身は1日1-2時間練習するようにしていますが、最初は20分でもよいでしょう。少しの時間でも頻繁に練習することを目標にしましょう。もし10分しか捻出できなかったとしても、良いスタートになります。
練習のヒント #1 - 練習ルーチンを開発する。あなたにとって都合の良い時間を見つけて、週のうち可能な限り多くの日にその時間で練習するようにしてみましょう。いずれ定期的なセッションが楽しみになると思います。
ステージで演奏するプロのミュージシャンを見ると、いくつか気が付くことがあると思います。最初に、彼らが演奏するとき楽器を凝視することはないでしょう。指と腕と体が、どのキーを押すか、どの弦を弾くか、どのドラムを叩くかを、深く考えること無く覚えていると思います。これは”運動記憶”として知られているもので、プロの人達だけが出来ることのように聞こえるかもしれませんが、あなたが繰り返し練習して歩いたり自転車に乗ったりできるようになったことと同じです。ライブコーダーはどこに指を動かせば良いか考えずに済むように運動記憶を使い、それによって音楽に集中するのです。これはブラインドタッチと呼ばれるもので、キーボードを見ることなくタイプすることです。
練習のヒント #2 - ブラインドタッチを習得する。ブラインドタッチを習得するためのアプリケション、ウェブサイト、さらにはゲームが数多くあります。どれか好きなものを探して、キーボードを見ずにコーディングできるまで続けてみましょう。
ミュージシャンの体は、それぞれの楽器を演奏するように調整されています。例えば、トランペット奏者は強く吹ける必要がありますし、ギタープレイヤーはフレットを強く握れる必要がありますし、ドラマーは長い時間繰り返し叩くことができる必要があります。では、ライブコーディングではどうでしょうか? ライブコーダーは典型的にはDJのように立ちながらパフォーマンスします。さらには踊りながらということさえあります。ライブコーディングを座ったままで練習して、ライブの際に立たなければならない場合、その違いがとても難しくイライラさせるでしょう。
練習のヒント #3 - 立って練習する。これを実現するのに最も簡単な方法は、スタンディングデスクを使うことです。しかし、もしスタンディングデスクが家に無い場合にも、いくつかローファイな選択肢があります。私はアイロン台を使っていますが、意外に使いやすいです。他にも何かの箱や大きい本を普通の机に置いて、その上にキーボードを置くこともできます。また、練習前にストレッチしておいたり、セッション中に少し踊ってみたりするのもよいでしょう。誰も見ていないので、楽しんでやってみましょう。そうすれば、ステージで緊張しなくなるでしょう。
多くの楽器は、演奏する前にそれを組み立てたりチューニングしたりする必要があります。あなたがバスいっぱいの会場設営スタッフを抱えるロックスターでも無い限り、ライブの前に自分の楽器を準備しなければなりません。これはしばしばストレスの掛かる作業で、問題が発生しやすいです。これに対処する1つの方法は、練習セッションの際に準備のプロセスを組み込んでしまうことです。
練習のヒント #4 - 準備を練習の重要な部分として扱う。例えば、Raspberry Piやキーボードを入れておく箱やバッグを用意します。練習セッションの前に、毎回全ての部品を取り出して接続し、Sonic Piが実行されて音が出るまでの起動プロセスを一通り作業してください。練習が終わったら、時間を取って慎重に全てを詰め直してください。これは最初は時間が掛かるかもしれませんが、あなたはすぐに何も考えずに非常に素早く準備と片付けが出来るようになるでしょう。
音楽を作り始める準備ができたとき、どこから初めて良いか分からないかもしれません。多くの人々が直面する問題の1つは、作りたい音楽がどのようなものであるかは良いアイデアを持っていても、それを作り出すことができずにフラストレーションがたまることではないでしょうか。さらに、自分がどのような音がを作りたいか分かっていない人々さえ居ます! これらに対して第一にやることは、心配しないことです。これはミュージシャンにはよくあることで、長年練習を積み重ねたミュージシャンも例外ではありません。全く何も音を出さないよりも、好みではなくとも何か音を出すことが重要です。
練習のヒント #5 - 好みでない音を作るのに時間を使う。新しい音やアイデアの探求に時間を使いましょう。それがあなたの探しているスタイルでなくひどい音がしても気にしないようにしましょう。実験すると、あなたの好きな音や音の組み合わせに出会う機会を増えるのです。99%の音が悪くても1%があなたの新しい曲のリフやイントロになるかもしれないのです。好みでないものは忘れ、好みのものを覚えておくようにしましょう。これは、コードで音楽を作っていれば全く簡単でしょう。保存を押すだけです!
多くのミュージシャンは、演奏することなしに、楽譜だけを見て彼らの頭の中で音楽を聞くことができます。これは、ライブコーディングの練習セッションに取り入れる価値のある、とても有用なスキルです。重要なポイントは、あるコードがどのような音がするかについて、何らかの理解が得られることです。その際に、必ずしも音そのものを聞こえるようになる必要はなく、その代わりに、そのコードによって、音楽が速くなるのか、遅くなるのか、うるさくなるのか、リズミカルになるのか、メロディアスになるのか、ランダムになるのか、といったことが分かることが有用です。最終的な目標は、このプロセスを逆にしたものです。つまり、頭の中で音楽を聞き、それを作るのにどのようなコードを書くべきか分かるかということです。これをマスターするのには長い時間が掛かるかもしれませんが、一度マスターすれば、ステージ上で即興演奏でき、あなたのアイデアをスムーズに表現できます。
練習のヒント #6 - Sonic Piにコードを書いてもRun
を押さない。その代わり、それがどのような音を作り出すか想像してみてください。次に、Run
を叩いて聞いてみましょう。何が想像した音と合っていて何が合っていなかったか考えましょう。これを、あなたのコーディングのプロセスの一部になるまで繰り返してください。私が練習するとき、普通はコードがどのような音がするか想像できています。しかし、想像していなかった音が未だに出ることがあって驚くことがあります。そのときは、そこで止まって、時間を取ってなぜ私が間違っていたか考えるようにしています。このようなことが起こる度に、私は新しい方法で自分を表現できる新しい技を学んでいます。
練習の際の一般的な問題は、他のことに邪魔されることです。練習は、それがどのような種類の音楽(ジャズからクラシック、ダンス・ミュージック)であれ、過酷で本当の訓練を必要とします。もしあなたが練習を始めたり、進めるのに苦労しているのであれば、それはしばしばソーシャルメディアにアクセスしたり、インターネット上の何かを見るのが簡単すぎることが原因でしょう。仮にあなたが20分間の練習を目標とした場合、その20分間の間可能な限り生産的であるようにすることが重要です。
練習のヒント #7 - 練習を始める前に可能な限り気が散るものを取り除く。例えば、インターネットを切断したり、電話を他の部屋に置いたりして、不意に気をそらされない静かな場所で練習するようにしましょう。練習が終われば、またそれらの気をそらすものに戻れるので、それまでは音楽のコーディングに集中するようにしましょう。
あなたが練習している最中、気がつくと、音楽の方向、試してみたい音、書いてみたい関数など、新しい刺激的なアイデアで頭がいっぱいになることがあるかもしれません。これらのアイデアはしばしばとても面白そうなので、練習をやめてそのアイデアを作業してしまうかもしれません。これは、別な形の’気が散るもの’と言えるでしょう!
練習のヒント #8 - 練習日記をつける。刺激的な新しいアイデアが浮かんだら、一時的に練習セッションを停止し、素早くアイデアを書き留めてください。そして、そのアイデアのことは忘れて、練習を続けてください。そうすれば、練習が終わった後、そのアイデアを集中して検討したり作業できるのです。
ここで紹介したアイデアを可能な限り取り込んだ練習ルーチンを確立するようにしてください。練習セッションは可能な限り楽しくしておくべきですが、ときには練習セッションは過酷で仕事のように感じることもあるでしょう。しかしながら、一度初めての作品を完成させたり、初めてのパフォーマンスを成功させたりしたら、練習はその価値があったと言えるでしょう。覚えておいてください、練習は成功の鍵なのです!
This is the first of a short series of articles on how to use Sonic Pi for sound design. We’ll be taking a quick tour of a number of different techniques available for you to craft your own unique sound. The first technique we’ll look at is called additive synthesis. This may sound complicated - but if we expand each word slightly the meaning pops right out. Firstly, additive means a combination of things and secondly synthesis means to create sound. Additive synthesis therefore means nothing more complicated than combining existing sounds to create new ones. This synthesis technique dates back a very long time - for example, pipe organs in the middle ages had lots of slightly different sounding pipes which you could enable or disable with stops. Pulling out the stop for a given pipe ‘added it to the mix’ making the sound richer and more complex. Now, let’s see how we can pull out all the stops with Sonic Pi.
Let’s start with the most basic sound there is - the humble pure-toned sine wave:
synth :sine, note: :d3
Now, let’s see how this sounds combined with a square wave:
synth :sine, note: :d3
synth :square, note: :d3
Notice how the two sounds combine to form a new, richer sound. Of course, we don’t have to stop there, we can add as many sounds as we need. However, we need to be careful with how many sounds we add together. Just like when we mix paints to create new colours, adding too many colours will result in a messy brown, similarly - adding too many sounds together will result in a muddy sound.
Let’s add something to make it sound a little brighter. We could use a triangle wave at an octave higher (for that high bright sound) yet only play it at amp 0.4
so it adds something extra to the sound rather than taking it over:
synth :sine, note: :d3
synth :square, note: :d3
synth :tri, note: :d4, amp: 0.4
Now, try creating your own sounds by combining 2 or more synths at different octaves and amplitudes. Also, note that you can play around with each synth’s opts to modify each source sound before it is mixed in for even more combinations of sounds.
So far, when combining our different synths we’ve used either the same pitch or switched octave. How might it sound if we didn’t stick to octaves but instead chose a slightly higher or lower note? Let’s try it:
detune = 0.7
synth :square, note: :e3
synth :square, note: :e3 + detune
If we detune our square waves by 0.7 notes we hear something that perhaps doesn’t sound in tune or correct - a ‘bad’ note. However, as we move closer to 0 it will sound less and less out of tune as the pitches of the two waves get closer and more similar. Try it for yourself! Change the detune:
opt value from 0.7
to 0.5
and listen to the new sound. Try 0.2
, 0.1
, 0.05
, 0
. Each time you change the value, take a listen and see if you can hear how the sound is changing. Notice that low detune values such as 0.1
produce a really nice ‘thick’ sound, with both slightly different pitches interacting with each other in interesting, often surprising, ways.
:dsaw
Another way we can finely craft our sound is to use a different envelope and options for each synth trigger. For example this will allow you to make some aspects of the sound percussive and other aspects ring out for a period of time.
detune = 0.1
synth :square, note: :e1, release: 2
synth :square, note: :e1 + detune, amp: 2, release: 2
synth :gnoise, release: 2, amp: 1, cutoff: 60
synth :gnoise, release: 0.5, amp: 1, cutoff: 100
synth :noise, release: 0.2, amp: 1, cutoff: 90
In the example above I have mixed in a noisy percussive element to the sound along with some more persistent background rumbling. This was achieved firstly by using two noise synths with middling cutoff values (90
and 100
) using short release times along with a noise with a longer release time but with a low cutoff value (which makes the noise less crisp and more rumbly.)
Let’s combine all these techniques to see if we can use additive synthesis to re-create a basic bell sound. I’ve broken this example into four sections. Firstly we have the ‘hit’ section which is the initial onset part of the bell sound - so uses a short envelope (e.g. a release:
of around 0.1
). Next we have the long ringing section in which I’m using the pure sound of the sine wave. Notice that I’m often increasing the note by roughly 12
and 24
which are the number of notes in one and two octaves. I have also thrown in a couple of low sine waves to give the sound some bass and depth. Finally, I used define
to wrap my code in a function which I can then use to play a melody. Try playing your own melody and also messing around with the contents of the :bell
function until you create your own crazy sound to play with!
define :bell do |n|
# Triangle waves for the 'hit'
synth :tri, note: n - 12, release: 0.1
synth :tri, note: n + 0.1, release: 0.1
synth :tri, note: n - 0.1, release: 0.1
synth :tri, note: n, release: 0.2
# Sine waves for the 'ringing'
synth :sine, note: n + 24, release: 2
synth :sine, note: n + 24.1, release: 2
synth :sine, note: n + 24.2, release: 0.5
synth :sine, note: n + 11.8, release: 2
synth :sine, note: n, release: 2
# Low sine waves for the bass
synth :sine, note: n - 11.8, release: 2
synth :sine, note: n - 12, release: 2
end
# Play a melody with our new bell!
bell :e3
sleep 1
bell :c2
sleep 1
bell :d3
sleep 1
bell :g2
This is the second in a series of articles on how to use Sonic Pi for sound design. Last month we looked at additive synthesis which we discovered was the simple act of playing multiple sounds at the same time to make a new combined sound. For example we could combine different sounding synths or even the same synth at different pitches to build a new complex sound from simple ingredients. This month we’ll look at a new technique commonly called subtractive synthesis which is simply the act of taking an existing complex sound and removing parts of it to create something new. This is a technique which is commonly associated with the sound of analog synthesisers of the 1960s and 1970s but also with the recent renaissance of modular analog synths through popular standards such as Eurorack.
Despite this sounding like a particularly complicated and advanced technique, Sonic Pi makes it surprisingly simple and easy - so let’s dive right in.
For a sound to work well with subtractive synthesis, it typically needs to be fairly rich and interesting. This doesn’t mean we need something hugely complex - in fact, just a standard :square
or :saw
wave will do:
synth :saw, note: :e2, release: 4
Notice that this sound is already pretty interesting and contains many different frequencies above :e2
(the second E on a piano) which add to create the timbre. If that didn’t make much sense to you, try comparing it with the :beep
:
synth :beep, note: :e2, release: 4
As the :beep
synth is just a sine wave, you’ll hear a much purer tone and only at :e2
and none of the high crispy/buzzy sounds which you heard in the :saw
. It’s this buzziness and variation from a pure sine wave that we can play with when we use subtractive synthesis.
Once we have our raw source signal, the next step is to pass it through a filter of some kind which will modify the sound by removing or reducing parts of it. One of the most common filters used for subtractive synthesis is something called a low pass filter. This will allow all the low parts of the sound through but will reduce or remove the higher parts. Sonic Pi has a powerful yet simple to use FX system that includes a low pass filter, called :lpf
. Let’s play with it:
with_fx :lpf, cutoff: 100 do
synth :saw, note: :e2, release: 4
end
If you listen carefully you’ll hear how some of that buzziness and crispiness has been removed. In fact, all the frequencies in the sound above note 100
have been reduced or removed and only the ones below are still present in the sound. Try changing that cutoff:
point to lower notes, say 70
and then 50
and compare the sounds.
Of course, the :lpf
isn’t the only filter you can use to manipulate the source signal. Another important FX is the high pass filter referred to as :hpf
in Sonic Pi. This does the opposite to :lpf
in that it lets the high parts of the sound through and cuts off the low parts.
with_fx :hpf, cutoff: 90 do
synth :saw, note: :e2, release: 4
end
Notice how this sounds much more buzzy and raspy now that all the low frequency sounds have been removed. Play around with the cutoff value - notice how lower values let more of the original bass parts of the source signal through and higher values sound increasingly tinny and quiet.
The low pass filter is such an important part of every subtractive synthesis toolkit that it’s worth taking a deeper look at how it works. This diagram shows the same sound wave (the :prophet
synth) with varying amounts of filtering. At the top, section A shows the audio wave with no filtering. Notice how the wave form is very pointy and contains lots of sharp edges. It is these hard, sharp angles that produce the high crispy/buzzy parts of the sound. Section B shows the low pass filter in action - notice how it is less pointy and more rounded than the wave form above. This means that the sound will have fewer high frequencies giving it a more mellow rounded feel. Section C shows the low pass filter with a fairly low cutoff value - this means that even more of the high frequencies have been removed from the signal resulting in an even softer, rounder wave form. Finally, notice how the size of the wave form, which represents the amplitude, decreases as we move from A to C. Subtractive synthesis works by removing parts of the signal which means that the overall amplitude is reduced as the amount of filtering that is taking place increases.
So far we’ve just produced fairly static sounds. In other words, the sound doesn’t change in any way for the entirety of its duration. Often you might want some movement in the sound to give the timbre some life. One way to achieve this is via filter modulation - changing the filter’s options through time. Luckily Sonic Pi gives you powerful tools to manipulate an FX’s opts through time. For example, you can set a slide time to each modulatable opt to specify how long it should take for the current value to linearly slide to the target value:
with_fx :lpf, cutoff: 50 do |fx|
control fx, cutoff_slide: 3, cutoff: 130
synth :prophet, note: :e2, sustain: 3.5
end
Let’s take a quick look at what’s going on here. Firstly we start an :lpf
FX block as normal with an initial cutoff:
of a very low 20
. However, the first line also finishes with the strange |fx|
at the end. This is an optional part of the with_fx
syntax which allows you to directly name and control the running FX synth. Line 2 does exactly this and controls the FX to set the cutoff_slide:
opt to 4 and the new target cutoff:
to be 130
. The FX will now start sliding the cutoff:
opt’s value from 50
to 130
over a period of 3 beats. Finally we also trigger a source signal synth so we can hear the effect of the modulated low pass filter.
This is just a very basic taster of what’s possible when you use filters to modify and change a source sound. Try playing with Sonic Pi’s many built-in FX to see what crazy sounds you can design. If your sound feels too static, remember you can start modulating the options to create some movement.
Let’s finish by designing a function which will play a new sound created with subtractive synthesis. See if you can figure out what’s going on here - and for the advanced Sonic Pi readers out there - see if you can work out why I wrapped everything inside a call to at
(please send answers to @samaaron on Twitter).
define :subt_synth do |note, sus|
at do
with_fx :lpf, cutoff: 40, amp: 2 do |fx|
control fx, cutoff_slide: 6, cutoff: 100
synth :prophet, note: note, sustain: sus
end
with_fx :hpf, cutoff_slide: 0.01 do |fx|
synth :dsaw, note: note + 12, sustain: sus
(sus * 8).times do
control fx, cutoff: rrand(70, 110)
sleep 0.125
end
end
end
end
subt_synth :e1, 8
sleep 8
subt_synth :e1 - 4, 8
(This article was published in issue 9 of the Hello World Magazine)
Code is one of the most creative media that humans have created. The initially obscure symbols of parentheses and lambdas are not just deeply rooted in science and mathematics, they are the closest we have managed to get to casting the same kind of magical spells as Gandalf and Harry Potter. I believe that this provides a powerful means of engagement in our learning spaces. Through the magic of code we are able to conjure up individually meaningful stories and learning experiences.
We are surrounded by magical experiences. From the sleight of hand of a stage magician making the ball disappear into thin air, to the wonder of seeing your favourite band perform on a big stage. It is these “wow” moments that inspire us to pick up a magic book and learn the French Drop or to start jamming power chords on an old guitar. How might we create similarly deep and lasting senses of wonder that will motivate people to practice and learn the fundamentals of programming?
The histories of music and computers have been intricately woven together since the inception of computing machines, or “engines” as Charles Babbage’s powerful analytical engine was called. Back in 1842 the Mathematician Ada Lovelace, who worked very closely with Babbage, saw the creative potential of these engines. Whilst these first engines had originally been designed to accurately solve hard maths problems, Ada dreamt about making music with them:
”..the engine might compose elaborate and scientific pieces of music of any degree of complexity or extent.” Ada Lovelace, 1842.
Of course, today in 2019 much of our music, regardless of genre, has either been composed, produced or mastered with a digital computer. Ada’s dream came true. It is even possible to trace the history back even further. If you see coding as the art of writing sequences of special symbols that instruct a computer to do specific things, then musical composition is a very similar practice. In Western music, the symbols are black dots positioned on a stave of lines that tell the musician which notes to play and when. Intriguingly, if we trace the roots of Western music notation back to the Italian Benedictine monk, Guido d’Arezzo, we find that the dots and lines system that modern orchestras use is just one of a number of notation systems he worked on. Some of the others were much closer to what we might now see as code.
In education, magical meaningful experiences with computers and programming languages have been explored since the late ’60s. Computer education pioneers Seymour Papert, Marvin Minsky and Cynthia Solomon explored simple Lisp-based languages that moved pens over large pieces of paper. With just a few simple commands it was possible to program the computer to draw any picture. They even experimented by extending their Logo language from drawing to music. Papert wrote about learning through experiencing the reconstruction of knowledge rather than its transmission. Getting people to play with things directly was an important part of his group’s work.
ライブコーディング
Sonic Pi has been used to perform in a wide range of venues such as school halls, nightclubs, outdoor stages at musical festivals, college chapels and prestigious music venues. For example the amazing Convo project which brought 1000 children together in the Royal Albert Hall to perform an ambitious new composition by composer Charlotte Harding. The piece was written for traditional instruments, choirs, percussion and Sonic Pi code. The pop-artist Jylda also performed with Sonic Pi in the Sage Gateshead for the Thinking Digital Conference, where she created a unique live-coded improvised remix of her song Reeled.
Sonic Pi used as one of the instruments as part of Convo at the Royal Albert Hall. Photo credit: Pete Jones.
Sonic Pi is a code-based music creation and performance tool that builds on all of these ideas. Unlike the majority of computing education software, it is both simple enough to use for education and also powerful enough for professionals. It has been used to perform in international music festivals, used to compose in a range of styles from classical, EDM and heavy metal, and was even reviewed in the Rolling Stone magazine. It has a diverse community of over 1.5 million live coders with a variety of backgrounds all learning and sharing their ideas and thoughts through the medium of code. It is free to download for Mac, PC and Raspberry Pi and includes a friendly tutorial that assumes you know nothing about either code or music.
Sonic Pi was initially conceived as a response to the UK’s newly released Computing curriculum in 2014. The goal was to find a motivating and fun way to teach the fundamentals of programming. It turns out that there is a lot in common and it’s huge fun to explain sequencing as melody, iteration as rhythm, conditionals as musical variety. I developed the initial designs and first iterations of the platform with Carrie Anne Philbin, who brought a teacher’s perspective to the project. Since then, Sonic Pi has undergone iterative improvements thanks to the feedback gained from observing learners and collaborating directly with educators in the classroom. A core design philosophy was to never add a feature that couldn’t be easily taught to a 10 year old child. This meant that most ideas had to be heavily refined and reworked until they were simple enough. Making things simple whilst keeping them powerful continues to be the hardest part of the project.
In order to provide the magical motivation, Sonic Pi’s design was never limited to a pure focus on education. Ideally there would be famous musicians and performers using Sonic Pi as a standard instrument alongside guitars, drums, vocals, synths, violins, etc. These performers would then act as motivational role models demonstrating the creative potential of code. For this to be possible sufficient focus and effort therefore had to be placed on making it a powerful instrument whilst still keeping it simple enough for 10 year olds to pick up. In addition to educators, I also worked directly with a variety of different artists in classrooms, art galleries, studios and venues in the early stages of Sonic Pi’s development. This provided essential feedback which enabled Sonic Pi to grow and ultimately flourish as a tool for creative expression.
There were a number of exciting and unexpected side effects of this dual focus on education and professional musicians. Many of the features are beneficial to both groups. For example, a lot of effort has been put into making error messages more friendly and useful (rather than being a huge complicated mess of jargon). This turns out to be very useful when you write a bug while performing in front of thousands of people. Additionally, functionality such as playing studio quality audio samples, adding audio effects, providing access to live audio from the microphone all turn out to make the learning experience more fun, rewarding and ultimately meaningful.
The Sonic Pi community continues to grow and share amazing code compositions, lesson plans, musical algorithms, and much more. Much of this happens on our friendly forum in_thread (in-thread.sonic-pi.net) which is home to a very diverse group of people that includes educators, musicians, programmers, artists and makers. It is a real joy to see people learn to use code to express themselves in new ways and for that in turn to inspire others to do the same.
From a Computer Science perspective, Sonic Pi provides you with the building blocks to teach you the basics as found in the UK’s curriculum such as sequencing, iteration, conditionals, functions, data structures, algorithms, etc. However, it also builds on a number of important and relevant concepts which have become adopted in mainstream industry such as concurrency, events, pattern matching, distributed computing and determinism - all whilst keeping things simple enough to explain to a 10 year old child.
Getting started is as simple as:
play 70
A melody can be constructed with one more command, sleep:
play 72
sleep 0.5
play 75
sleep 0.5
play 79
In this example, we play the note 70 (roughly the 70th note on a piano), wait for 1 second, play note 72, wait for half a second and then play note 75. What’s interesting here is that with just two commands we have access to pretty much all of Western notation (which notes to play and when) and learners can code any melody they’ve ever heard. This leads to huge variety in expressive outcomes whilst focussing on the same computing concept: sequencing in this case.
Taking ideas from the professional music world, we can also play back any recorded sound. Sonic Pi can play any audio file on your computer but also has a number of sounds built-in to make things easy to get started:
sample :loop_amen
This code will play back the drum break which was a pillarstone to early hip-hop, Drum and Bass and Jungle. For example, a number of early hip-hop artists played this drum break back at half speed to give it a more laid-back feeling:
sample :loop_amen, rate: 0.5
In the 90s a number of music scenes burst out of new technology which enabled artists to take drum breaks like this apart and reassemble in a different order. For example:
sample :loop_amen
rand
この章ではSonic Piを最大限に活用するために、いくつかの非常に便利で、実際のところ不可欠な知識を紹介します。
利用可能な多くのキーボードのショートカットを活用する方法と、作品を共有する方法、そしてSonic Piでパフォーマンスする際のいくつかのヒントを見ていきます。
Sonic Piは、コーディング環境であると同時に楽器でもあります。したがって、あなたが観客の前でライブ演奏している場合は特に、ショートカットを使うことで、はるかに効率的で自然にSonic Piの演奏を行うことができます。
Sonic Piの多くの機能は、キーボードを介して制御することができます。Sonic Piの演奏や作業により慣れるために、ショートカットをもっと使いこなしましょう。私個人はブラインドタッチができ(あなたにも習得をお勧めします)、マウスを使う必要があるときにはいつも、動作が遅れるのでイライラしてしまいます。このため、私は普段からこれらのショートカットのすべてを使っています!
ショートカットを学べば、効果的にキーボードを使用でき、すぐにプロのようなライブコーディングができるようになるでしょう。
しかし、一度にすべてを憶えようとしないで、最初はあなたが最も使うものを試しながら憶えていき、その後継続して他のショートカットを追加していくと良いでしょう。
クラリネットを習っているところを想像してみてください。すべてのクラリネットは、指使いや操作の全てが一貫してしていることを前提として作られていますが、もしそうでなかったら、別のクラリネットに乗り換えるには大変な時間を費やしてしまうだろうし、1回だけの制作のためにそれを使用することについて戸惑ってしまうでしょう。
残念なことに3つの主要なオペレーティングシステム(Linux、Mac OS XおよびWindows)では、カット&ペーストなどの操作のために独自の基準が用意されています。Sonic Piは、これらの基準を尊重します。しかしながら、Sonic Piでは、プラットフォームの基準に対応することよりも、プラットフォーム間での一貫性を優先しています。これはRaspberry PiでSonic Piを演奏してショートカットを学んだら、MacやPCに乗り換えても違和感無く同じように操作できることを意味しています。
一貫性への考え方のひとつにショートカットの命名があります。Sonic Piにおいて、主要な2つの組み合わせキーを当てはめるために、ControlキーとMetaキーを用います。すべてのプラットフォームでは、Controlキーは同じです。しかし、LinuxとWindowsでは、実際のMetaキーはAltキーで、MacのMetaキーはコマンド⌘キーです。一貫性のために、Metaキーという言葉を使いますが、あなたのオペレーティングシステムにおける適切なキーに置き換えるようにしてください。
シンプルで読みやすくするために、Ctrlキー+その他のキーは「C-」、Metaキー+その他のキーは「M-」の略語を使います。例えば、あるショートカットがMetaキーと’r’を同時に押さえる必要がある場合、「M-r」と表記します。そして、-は、”同時に押さえる”を意味しています。
以下は、僕が見つけたとっても有用なショートカットのいくつかです。
マウスを使う代わりに、M-r
でコードを実行することができます。同様に、M-s
でコードを停止することができます。
ナビゲーションのショートカットを使わない操作は実にもどかしいです。そのため、ショートカットを学ぶことに時間を費やすことを強くお勧めします。ブラインドタッチを習得すれば、マウスやキーボードの矢印キーに手を移動させる必要が無くなるので、これらのショートカットをさらに有効に活用することができます。
行の先頭に移動するにはC-a
、行の末尾に移動するにはC-e
、1行上はC-p
、1行下がるにはC-n
、1文字進むにはC-f
、そして、1文字戻るにはC-b
。C-k
でカーソルから行の末尾まで全ての文字を消去する事ができます。
コードを自動整形するにはM-m
を押します。
ヘルプシステムを切り替えるには、M-i
を押します。しかし、何かを見つける場合、もっとはるかに便利なショートカットは、カーソル下の単語検索し、ドキュメントを表示するC-i
です。簡単でしょう!
完全なリストについては、セクション10.2ショートカット一覧表を見てみましょう。
以下は、Sonic Piで利用可能な主なショートカットをまとめたものです。動機と背景については、セクション10.1を参照してください。
このリストでは下記の規定に準拠します(WindowsとLinuxのMetaキーはAltキー、そしてMacはCmdキー):
C-a
はControlキーを押さえながらaキー、両方を同時にを押した後に離す事を意味しています。
M-r
はMetaキーを押さえながらrキー、両方を同時にした後に離す事を意味しています。
S-M-z
はShiftキーを押さえながらMetaキー、そして最後にzキー全てを同時に押した後に離す事を意味しています。
C-M-f
はControl キーを押さえながらMetaキー、そして最後にfキー全てを同時に押した後に離す事を意味しています。
M-r
- コードを実行
M-s
- コードを停止
M-i
- ヘルプシステムを表示
M-p
- 設定を表示
M-{
- 左のBufferに切り替え
M-}
- 右のBufferに切り替え
M-+
- 文字サイズを大きく
M--
- 文字サイズを小さく
M-a
- 全てを選択
M-c
- 選択箇所をコピー
M-]
- 選択箇所をコピー
M-x
- 選択箇所をカット
C-]
- 選択箇所をカット
C-k
- カーソルから行の末尾まで全ての文字を消去する
M-v
- エディタへ張り付け
C-y
- エディタへ張り付け
C-SPACE
- マークを設定します。以降のナビゲーション操作で選択箇所を変更できます。C-g
でマークを解除します。
M-m
- テキストを整形
Tab
- 現在の行または選択箇所のテキストを整形(または、自動補完を選択)
C-l
- 真ん中へ移動
M-/
- 現在の行または選択箇所をコメント/コメント解除
C-t
- カーソルの前後の文字を入れ替え
M-u
- カーソルの後ろの単語(または選択箇所)を大文字に変換
M-l
- カーソルの後ろの単語(または選択箇所)を小文字に変換
C-a
- 行の先頭に移動
C-e
- 行の末尾に移動
C-p
- ひとつ前の行に移動
C-n
- 次の行に移動
C-f
- 一文字進む
C-b
- 一文字戻る
M-f
- 一単語進む
M-b
- 一単語戻る
C-M-n
- 現在の行または選択箇所を下に移動
C-M-p
- 現在の行または選択箇所を上に移動
S-M-u
- 10行上に移動
S-M-d
- 10行下に移動
M-<
- Bufferの先頭に移動
M->
- Bufferの末尾に移動
C-h
- 前の文字を削除
C-d
- 次の文字を削除
C-i
- カーソルの下の単語のドキュメントを表示
M-z
- アンドゥ(行った操作を取り消し、元の状態に戻る)
S-M-z
- リドゥ(一旦取り消した操作をやり直す)
C-g
- エスケープ
S-M-f
- フルスクリーンモードを切り替え
S-M-b
- ボタンの表示を切り替え
S-M-l
- ログの表示を切り替え
S-M-m
- ライト/ダークモードを切り替え
S-M-s
- Bufferの内容をファイルに保存
S-M-o
- Bufferの内容をファイルから読み込む
Sonic Piで最も大事なことは、お互いに共有し学習することです。
いったん、どのように音楽をコード化するかを学んだら、作曲したコードを共有することは電子メールを送信するのと同じくらい簡単なことです。あなたの作品から学び、さらに新しいマッシュアップで部品を使えるように、他の人とコードを共有しましょう。
もしあなたの作品を他者と共有するためのよい方法が見当たらなければ、あなたの音楽をSoundCloudへ、そしてコードをGitHubに置くことをお勧めします。それらの方法で、あなたの作品は、容易にたくさんの人に届けることができるでしょう。
GitHubは、コードを共有し作業するためのサイトです。コードの共有や共同作業のためにプロの開発者と同じくアーティストも使用しています。新しい作品のコード(あるいは未完の作品)を共有する最も簡単な方法は、このGitHubでGistを作成することです。Gistは、コードを簡単にアップロードする方法で、これにより他の人が簡単に参照、コピーし共有することができます。
作品を共有するもう1つの重要な方法は、音を録音しSoundCloudにアップロードすることです。作品をアップロードしたら、他のユーザがコメントしあなたの作品について話し合うことができます。また、トラックの詳細にあなたのコードのGist へリンクを貼ることをお勧めします。
作品を記録するには、ツールバーのRec
ボタンを押すと、すぐに録音を開始します。もしコードがすでに実行中でなければ、開始するためにRun
を押してください。録音が完了したら、再び点滅しているRec
ボタンを押すと、ファイル名を入力するよう求められます。WAVファイルとして保存された録音は、無料のソフトウェア(例えば、Audacityを試してみてください)で編集したりMP3に変換することができます。
私はみなさんが作った作品を共有し、我々がお互いにSonic Piの新しいトリックや動作を教えあえることを願っています。あなたが何を見せてくれるか本当に楽しみにしています。
Sonic Piの中で最もエキサイティングな側面の1つは、楽器としてコードを使うことができるということです。これは、コードをライブで書くことが、音楽を演奏する新しい方法とみなすことができることを意味します。
我々は、これをライブコーディングと呼んでいます。
ライブコーディングするとき、観客にあなたの画面を表示することをお勧めします。そうでなければ、ギターを指や弦を隠しながら演奏するようなものです。私は家で練習するときは、Raspberry Piと小型プロジェクターでリビングルームの壁に投影しています。テレビや学校/職場のプロジェクターを使ってみましょう。挑戦してみてください。とても楽しいですよ。
Don’t just play on your own - form a live coding band! It’s a lot of fun jamming with others. One person could do beats, another ambient background, etc. Use the live_audio
functionality to combine code with traditional instruments such as a guitar or a microphone.
See what interesting combinations of sounds you can create with code.
ライブコーディングは新しいものではありません。一部の人々は、自ら構築した特注システムを使用して、ここ数年ライブコーディングに取り組んできました。他のライブコーダーやシステムについての詳細を知るには、TOPLAPは絶好の場所でしょう。
ライブコーディングの世界を探索するためのもう1つの偉大なリソースは、Algoraveです。ここで、クラブシーンでのライブコーディングに特化した情報を見つけることができます。
Sonic Piは現在、Minecraft Piと対話するためのシンプルなAPIをサポートしています。Minecraftの特別版は、Raspberry PiのLinuxベースのオペレーティングシステムRaspbianにデフォルトでインストールされています。
Minecraft Piは、とっても簡単に扱えるよう設計されています。必要なことは、Minecraft Piを起動してワールドを作成するだけです。その後、play
やsynth
を扱うようにmc_*
関数を自由に使えます。何かのライブラリをインストールしたり、インポートする必要はなく、そのまま使えます。
Minecraft Pi APIはMinecraft Piアプリケーションへの接続を可能にします。あなたは何も心配をしなくてもよいということです。Minecraft Piを起動せずに、Minecraft Pi APIを使おうとした場合には、Sonic Piはこれを丁寧に教えてくれます。同様に、Minecraft Pi APIを使っているlive_loop
が実行されている最中にMinecraft Piを閉じてしまった場合には、そのライブループを停止し、接続できてないことを丁寧に伝えてくれます。再接続するには、Minecraft Piを再び起動するだけで、Sonic Piが自動検出して、再接続を試みます。
Minecraft Pi APIはlive_loop
内でシームレスに動作するように設計されています。これは、Sonic Piの音に変更を加え、Minecraft Piのワールドの変更と同期させることが可能であることを意味します。インスタントなMinecraftベースのミュージックビデオです! Minecraft Piはアルファ版のソフトウェアであり、わずかに不安定であることに注意してください。何か問題が発生した場合は、単純にMinecraft Piを再起動し、以前と同様に続けましょう。Sonic Piの自動接続機能が対応します。
Sonic PiとMinecraftの両方を同時に実行したい場合、特にSonic Piのサウンド機能を使用したい場合は、Raspberry Pi 2を使用することをお勧めします。
現段階では、Sonic Piは、次のセクション11.1に詳述されている基本ブロックとプレイヤーの操作をサポートしています。ワールド内のプレイヤーの相互作用によってトリガーされるイベントのコールバックのサポートは、将来のリリースバージョンで予定されています。
Sonic Piは現在、下記のMinecraft Piの基本インタラクションをサポートしています:
チャットメッセージの表示 ユーザの位置設定 ユーザの位置情報の取得 指定した座標のブロックタイプを設定 指定した座標のブロックタイプを取得
これらをそれぞれ順番に見てみましょう。
それではSonic PiからのMinecraft Piの制御が、どれだけ簡単か見てみましょう。まずはじめにMinecraft PiとSonic Piが同時に起動していることを確認し、Minecraftのワールドに入って歩くことができることを確認してください。
新しいSonic PiのBufferで、次のコードを入力してください。
mc_message "Hello from Sonic Pi"
Runボタンを押すと、Minecraftウィンドウにメッセージが表示されます。おめでとう、あなたは初めてのMinecraftコードを書きました! 簡単でしたよね。
では、ちょっとした魔法を試してみましょう。どこかに瞬間移動してみましょう! 以下を試してください。
mc_teleport 50, 50, 50
Run
を押すと、ブーン! 新しい場所へあなたの座標が移動しました。たいていは、乾燥した土地、または水に落ちたか、空中のどこかでしょう。50, 50, 50
、これらの数字は何でしょう? これらは瞬間移動しようとしている場所の座標です。座標とは何なのか、そして座標がどのように動作するのかは、Minecraftをプログラムするにあたって本当に重要なので、少し時間を取って見ていきましょう。
いくつかの宝の場所が大きなX
でマーキングされた海賊の地図を想像してみてください。X
の正確な位置は、左から右へ向かってどれくらい離れているか、下から上へ向かってどのくらい離れているか、この2つの数字で場所を記述することができます。例えば、横へ10cm
、上に8cm
。これら2つの数字10
と8
が座標です。他に隠された宝物の在処も別の2つの数字で容易に記述できることが想像できますね。おそらく、2
つ横切り、9
つ上には大きな金脈がありそうです…
さて、Minecraftの中では2つの数字では十分ではありません。それに加えて、私たちがどれだけ高い所にいるのかを知る必要があります。したがって、3つの数字が必要になります。
どのくらい右端から左に離れてるか - x
どのくらい手前から奥へ離れてるか - z
どのくらい高くあがったか - y
通常、x
, y
, z
でこれらの座標を記述します。
座標を使って遊んでみましょう。Minecraftのマップで素敵な場所に移動した後、Sonic Piに切り替え、次を入力してください。
puts mc_location
Run
ボタンを押すと、ログ画面に、現在位置の座標が表示されます。座標の値を書き留め、続いてワールド内で前方に移動し、再び試してみてください。座標がどのように変化するかに注目しましょう! これを繰り返すのに時間を使うことをお勧めします。すなわち、ワールド内で少し動いては座標を見てみるということです。あなたが移動すると座標がどのように変化するか感触を得られるまで、これを行いましょう。これを調整する方法が理解できれば、MinecraftのAPIを使用したプログラミングがほぼ完了します。
現在位置を取得する方法と、座標を利用して瞬間移動する方法を覚えたので、あなたはコードでMinecraft内に何かを構築し始めるために必要な道具をすべて持っています。たとえば、座標40
, 50
, 60
にガラスのブロックを作りたかったら、それはとっても簡単ですね。
mc_set_block :glass, 40, 50, 60
ハハ、本当に簡単だったでしょう。作ったものを見るには、近くに瞬間移動してみましょう。
mc_teleport 35, 50, 60
振り向くと、あなたの作ったガラスのブロックが表示されるはずです! それをダイヤモンドに変更してみましょう。
mc_set_block :diamond, 40, 50, 60
見る角度が合えば、それがあなたの目の前で変更されることだってあるのです! これはエキサイティングな何かの始まりです…
少し複雑なことに移る前に、最後の1つを見てみましょう。座標を与え、特定のブロックの種類が何であるかをMinecraftに尋ねることができます。では、先ほど作成したダイヤモンドブロックで試してみましょう。
puts mc_get_block 40, 50, 60
イェイ! それは:diamond
(ダイヤモンド)ですね。ガラスに戻して、もう一度尋ねてみましょう。:glass
を示しましたか? きっとそうなったでしょう(^o^)
Minecraft Piでコーディングで暴れに行く前に、利用可能なブロックタイプのリストがあると便利でしょう。以下に示します。
:air 空気
:stone 石
:grass 草
:dirt 汚れ
:cobblestone 石畳
:wood_plank 木の板
:sapling 苗木
:bedrock 岩盤
:water_flowing 水流
:water 水
:water_stationary 静止した水
:lava_flowing 溶岩流
:lava 溶岩
:lava_stationary 固まった溶岩
:sand 砂
:gravel 砂利
:gold_ore 金の鉱石
:iron_ore 鉄鉱石
:coal_ore 石炭鉱石
:wood 木材
:leaves 葉
:glass ガラス
:lapis ラピス
:lapis_lazuli_block ラピスラズリブロック
:sandstone 砂岩
:bed ベッド
:cobweb クモの巣
:grass_tall 背の高い草
:flower_yellow 黄色い花
:flower_cyan シアン色の花
:mushroom_brown 茶色いキノコ
:mushroom_red 赤いキノコ
:gold_block 金のブロック
:gold 金
:iron_block 鉄のブロック
:iron 鉄
:stone_slab_double 石板(ダブル)
:stone_slab 石板
:brick レンガ
:brick_block レンガブロック
:tnt TNT
:bookshelf 本棚
:moss_stone 苔石
:obsidian 黒曜石
:torch トーチ
:fire 火
:stairs_wood 木の階段
:chest チェスト
:diamond_ore ダイアモンドの鉱石
:diamond_block ダイアモンドのブロック
:diamond ダイアモンド
:crafting_table 作業テーブル
:farmland 農地
:furnace_inactive 廃炉
:furnace_active 炉
:door_wood 木のドア
:ladder はしご
:stairs_cobblestone 石畳の階段
:door_iron 鉄のドア
:redstone_ore レッドストーン鉱石
:snow 雪
:ice 氷
:snow_block 雪のブロック
:cactus サボテン
:clay 粘土
:sugar_cane サトウキビ
:fence フェンズ
:glowstone_block 光る石のブロック
:bedrock_invisible 目に見えない岩盤
:stone_brick 石レンガ
:glass_pane ガラス板
:melon メロン
:fence_gate フェンスゲート
:glowing_obsidian 輝く黒曜石
:nether_reactor_core 原子炉コア