前回まではコードを書いて音楽をつくってきました。今回は前回の最後にご覧いただいたコードをもとに、プログラミング構造についてお話ししていきます。
プログラミング構造
プログラミングには構造があり、その構造によって命令を操作することができます。
まずは前回のコードを見ていきましょう。
use_bpm 124
val = 0
loop do
use_synth :tb303play_pattern_timed [36,38,40,41], [0.25], release: 0.3, cutoff: 60 + val, res: rand()
val += 5
val = 0 if val > 60
end
繰り返し
これをご覧いただくと、すでにいくつもの構造が登場していることがわかります。まず、一番大きな構造としてブロックというものがあります。これは「do」で始まって「end」で終わる部分のことです。loopという命令のあとには、ブロックが続いているということになります。loopという命令は「ずっと繰り返す」という命令になっているので、みなさんはいちいちstopをクリックしていると思います。
決まった回数だけ繰り返すということもできます。上記のコードのloopを「4.times」に変更してみてください。
use_bpm 124
val = 0
4.times do
use_synth :tb303play_pattern_timed [36,38,40,41], [0.25], release: 0.3, cutoff: 60 + val, res: rand()
val += 5
val = 0 if val > 60
end
実行すると、4回繰り返すと自動的に終了したはずです。数値の後にドット記号「.」をつけて、さらに「times」という命令をつけると「○回ブロックを繰り返す」という意味になります。
条件分岐
さて、前回のコードの中に「if」というものが登場したと思います。これは英語のifと同様に「もし~ならば」という意味になります。
if 条件があってる
なにか命令をする
else
条件に合わなかったときの命令をするend
という形で記述することができます。条件が合わなかったときには何も命令しなくてよい場合は「else」の部分は省略して次のように書くことができます。
if 条件があってる
なにか命令をする
end
条件が複数ある場合は次のように書くこともできます。
val = 32
if val > 32
puts "aaa"
elsif val = 32puts "bbb"
else
puts "ccc"
end
このコードはSonic Piで実行することができ、画面にログを表示させている場合はそこへ結果が表示されているはずです。
ここではテキストをログへ出力する「puts」命令を使っていますし、見てのとおり条件に合致するのは「elsif」のところなので「bbb」と表示されています。
でも待ってください。前回のコードとは違いますね。命令があって、ifが続いています。
val = 0 if val > 60
これは条件が1つしかないときに命令の後ろへ配置することができるということを活用しているのです。この場合は変数valの値が60を超えているときだけ変数valがゼロにされます。
変数
変数は前回もお話ししたかもしれませんが、データに名前をつけることができるというものです。名前をつけるときは、イコール記号を使って左側につけたい名前、右側にデータを置きます。
val = 60
もちろん数値だけでなく、シンセの名前や発音させたいノート番号の集まりも名前付けすることができます。すべてに名前付けすると、前回のコードは以下のようになります。
use_bpm 124
notes = [36, 38, 40, 43]
timings = [0.25]minCutoff = 60
upRate = 5
minVal = 0
bassR = 0.3
biyobiyo = :tb303
val = minVal
loop do
use_synth biyobiyo
play_pattern_timed notes, timings, release: bassR, cutoff: minCutoff + val, res: rand()
val += upRate
val = minVal if val > minCutoff
end
ご覧いただくとわかるとおり、演奏のコードから数値やシンセ名が消えました。
代わりに変数が並んでいると思います。このようにすると「どういった値だったのか」など意図がわかりやすくなるので便利ですし、同じ名前を使えば値が変化したとしてもコードを書き換える必要がありません。
関数
いきなり数学かのような名前が登場して面食らうかたもいらっしゃるかもしれません。関数というのは、命令をまとめておくことができるものです。まとめた命令には名前で利用することができます。以下のようにすると関数を決めることができます。
define :bassline do
# ベースラインのコードを書くとか…
end
とすると、前回のコードは次のようにもできます。
use_bpm 124
# ここが関数「bassline」define :bassline do |v|
notes = [36, 38, 40, 43]
timings = [0.25]
bassR = 0.3
biyobiyo = :tb303
use_synth biyobiyo
play_pattern_timed notes, timings, release: bassR, cutoff: v, res: rand()
end
minVal = 0
minCutoff = 60
upRate = 5
val = 0
# ここからがいままでの演奏コード部分
loop do
# 関数「bassline」の呼び出し
bassline minCutoff + val
val += upRate
val = minVal if val > minCutoff
end
関数「bassline」をループの中で繰り返し呼び出して音を鳴らしています。さらに、関数にはパラメータを渡しています。渡しているのは「カットオフ値の変化させたもの」で、関数「bassline」ではパイプ記号で囲まれた「v」という変数で受け取っています。関数の外側から受け取った値でカットオフ値を指定できているのでplay_pattern_timed命令は少し短く記述できるようになっています。また、呼び出すループではカットオフ値の制御だけを行うようになりました。
便利ですね!!
もちろんカットオフ値の制御部分だけをさらに関数にすることもできますし、もっと複雑なものにすることもできます。
最後に
今回はSonic Piのプログラミング構造についてお話ししました。
次回はいよいよSonic Piの醍醐味であるライブループについてお話ししたいと思います。
0コメント