見出し画像

Pbindでライブコーディングを実現する2つの「P」


例えば下記のコードで、
・SynthDefを実行した(.addした)あと
・Pbindを実行してそのSynthDefを鳴らします。

[ex1]

// 最初にcommand+bでサーバをブートしておきます。
// 音源syn1
(
SynthDef(\syn1, {
arg freq=220, gate=1, cof=800;
var sig, env;
env = EnvGen.kr(Env.asr(0.01, 1, 0.4), gate, doneAction:2);
sig = Saw.ar(freq);
sig = RLPF.ar(sig, cof, 0.6) * env;
sig = Pan2.ar(sig, 0);
Out.ar(0, sig * 0.3);
}).add;
)

//Pbind
(
t = TempoClock(140/60);
Pbind(
\instrument, \syn1,
\midinote, Pseq([41, 64, 62, 67, 53, 57, 60, 64], inf),
\dur, 0.5,
).play(t);
)

Pbindのフレーズを聴きながら、\syn1のパラメータをいじって再度SynthDefを実行すると、フレーズを止めることなく音色をチェンジしていくことができます。
RLPFのカットオフフリケンシー(上記ではcof)をいじったりするのは音色変化がわかりやすいですし、Saw.arをPulse.arなどに入れ替えてやるのも全然アリですし、フレーズを聴きながらどんどんSynthDefを実行していく(音色変更していく)ことができます。

これは、\syn1と名付けた音源をサーバに置いたあと(SynthDefを.addしたあと)、\syn1をどんどん上書き更新している、という状態です。
一般的なDAWで例えると、シーケンスを走らせながらプラグインの音源パラメータをいじっている(=更新している)、ような感じでしょうか。

ただ、、Pbindのフレーズ自体を変えたい場合は、一度command+ピリオドでシーケンスを止める必要があります。そしてフレーズを変えて、再度Pbindを実行。。。

ライブコーディングをやるなら、Pbindを止めることなくフレーズ自体もどんどん変えていきたい。でもPbindを止めないまま再度Pbindを実行すると、フレーズが二重に鳴ってしまう。。orz

そこで役に立つのが

Pdefn
Pbindef

です。
今日はこのふたつのP(パターン)ファミリーについて書きます。


Pdefn


ぶっちゃけ言いますと、このあと紹介するPbindefのほうが便利に使えるんですが、まずはPdefnについて書きます。
Pdefnを使うと、PbindをプレイしながらPbind内のパラメータをチェンジていくことができます。

先ほどと同じPbindを使います。
「フレーズ」をリアルタイムにチェンジしたいのでPbindの音程を設定しているパラメータ\midinoteにちょっと細工をします。

[ex2]

//Pbind(Pdefn)
(
t = TempoClock(140/60);
Pbind(
\instrument, \syn1,
\midinote, Pdefn(\p_note, Pseq([41, 64, 62, 67, 53, 57, 60, 62], inf)),
\dur, 0.5,
).play(t);
)

\midinoteに元々あったPseqのフレーズをPdefn(\p_note, と ) で囲った、という状態になってます。
簡略化して書くと
Pdefn(\p_note, Pseqフレーズ)
こんな感じですね。

この、細工したPbindを実行すると、先ほどと同じフレーズが流れます。
フレーズを流しっぱなしの状態で、次のコードを実行すると・・・

[ex3]

Pdefn(\p_note, Pseq([41, 62, 59, 67, 53, 57, 60, 59], inf));

Pbindを止めることなくフレーズが変わります!
続けて他のフレーズを実行することで、どんどんフレーズをチェンジしていけます。

//ex4

//1行ずつ実行するたびに、フレーズが変更されます。
Pdefn(\p_note, Pseq([41, 64, 62, 67, 53, 57, 60, 62], inf));
Pdefn(\p_note, Pseq([41, 55, 57, 59, 60, 62, 64, 67], inf));
Pdefn(\p_note, Pseq([53, 60], inf));

でもこれ、フレーズの頭からタイミングよく切り替えたいですよね。
その場合はquantメソッドを使います。

[ex5]

Pdefn(\p_note, Pseq([41, 62, 59, 67, 53, 57, 60, 59], inf)).quant_(4);
Pdefn(\p_note, Pseq([41, 64, 62, 67, 53, 57, 60, 62], inf)).quant_(4);
Pdefn(\p_note, Pseq([41, 55, 57, 59, 60, 62, 64, 67], inf)).quant_(4);
Pdefn(\p_note, Pseq([53, 60], inf)).quant_(4);
Pdefn(\p_note, 53).quant_(4);

こうすると、4拍をひとくくりとしてフレーズをチェンジしていけます。
*各行をどのタイミングで実行してもフレーズがチェンジされるのは次の1拍目の頭のタイミング。
8拍ひとくくりにしたい場合はquant_(8)とします。

(音を止めるにはいつも通り「command + ピリオド」です。)


さて、\midinoteだけでなく\durに対しても同じことができますので、やってみます。
まずは元のPbindにPdefnを仕込みます。

//ex6

(
t = TempoClock(140/60);
Pbind(
\instrument, \syn1,
\midinote, Pdefn(\p_note, Pseq([41, 64, 62, 67, 53, 57, 60, 62], inf)),
\dur, Pdefn(\p_dur, 0.5),
).play(t);
)

そして、Pbindを鳴らしながら\p_durに対して変更を加えていきます。

[ex7]

Pdefn(\p_dur, 1.0).quant_(4);
Pdefn(\p_dur, Pseq([0.5, 0.25], inf)).quant_(4);
Pdefn(\p_dur, 0.2).quant_(4);

//\p_noteに対してももちろん変更を加えていけます。
Pdefn(\p_note, Pseq([53, 64, 60], inf)).quant_(4);

このとき重要なのが、デュレーションに変更を加えていく場合は
Pdefn(\p_dur,
フレーズに変更を加えていく場合は
Pdefn(\p_note,
というふうに使い分けることです。


ところで、\p_noteや\p_durという部分ですが、実はこの部分はどんなふうに書いても構いません。
つまり、例えば\abcでもいいですし\test1でもいい、です。

Pdefn(\abc, Pseqフレーズ)でもいいし
Pdefn(\test1, Pseqフレーズ)でもいい。

この
Pdefn(\xxxx, Pseqフレーズ)

という書き方は、「Pseqフレーズに\xxxxという名前をつけた」という意味なんです。
なので、つける名前は何でもいいです。(\p_noteや\p_durは僕が勝手につけたもの。)
重要なのは、Pbindを鳴らしながら変更を加えていくときに「どのPdefnに対して変更を加えるのか」を区別できることです。


余談


この
Pdefn(\名前, Pseqフレーズ)
という書き方、なんとなくどこかで見覚えありません?

SynthDefも似たような書き方ですよね。
SynthDef(\名前, {音})

SuperColliderでクラス名に"def"があると、"名前をつける"っていう意味があるのではないかと思います。
他にもMIDIdefやOSCdefなど、"def"があると名前をつけますので。

名前をつけておくと、後から行なう変更やエディットが「その名前に対して行われる」ということを明確にしてくれます。
これはPbindの例がわかりやすいです。Pbindでは一番最初に\instrument, に続けてSynthDefの名前を書きますが、これは「どのSynthDefを鳴らすか」を明確にします。

また、(冒頭で紹介したSynthDefの上書き更新のように)名前をつけたものに対してはそのパラメータを上書き更新していける、というイメージかなぁと僕はそんなふうに思っています。


Pbindef


もうひとつのPファミリーのご紹介、Pbindefです。
これもクラス名に"def"がありますよね。
Pdefnは、名前をつけたパラメータに対して、そのパラメータをどんどん上書きしていくことができましたが・・・
PbindefはPbind内の全パラメータに対して名前をつけます。

ではその使い方です。

[ex8]

//Pbind(Pbindef)
(
t = TempoClock(140/60);
Pbindef(
\pb1,
\instrument, \syn1,
\midinote, Pseq([36, 55, 48, 55], inf),
\dur, 0.5,
\cof, 800,
).play(t);
)

簡略化して書くと
Pbindef(\名前, パラメータたち)
というかたちになってます。
名前はこれも何でもいいですが、今回僕は\pb1という名前にしました。

さてこのPbindefを鳴らしながら、次のコードを1行ずつ実行していくと、フレーズが変わっていきます。
フレーズだけでなくカットオフ周波数も。

[ex9]

Pbindef(\pb1, \midinote, Pseq([36, 55, [48,62], [59,64]], inf)).quant_(4);
Pbindef(\pb1, \midinote, Pseq([36, 55, [48,62], [59,64]]+5, inf)).quant_(4);
Pbindef(\pb1, \midinote, Pseq([40, 50, [55,62], 59], inf)).quant_(4);
Pbindef(\pb1, \midinote, Pseq([45, 57, [55,62], 59], inf)).quant_(4);
Pbindef(\pb1, \cof, Pseq([1000, 400, 700, 500], inf)).quant_(4);
Pbindef(\pb1, \cof, 350);
Pbindef(\pb1, \cof, 1400);

***memo***
Pseq内の音符は、[各カッコ]でくくってカンマで区切ると和音になります。([48,62]とか[59,64]の部分です。)
[ex9]では2和音を使いましたが3和音もいけます。
*********


それと、Pbindefのいいところは、ふたつのパラメータを同時にチェンジしていくこともできます。下記のex10のように。

[ex10]

Pbindef(\pb1, \midinote, Pseq([36, 60, 50, 72], inf), \cof, Pseq([100, 400, 1000], inf)).quant_(4);

Pbindef(\名前, \midinote, パラメータ, \cof, パラメータ)
という書き方です。


Pdef


さて。
実はもうひとつ、Pdefっていうのもあって、
Pdef(\名前, Pbind(各パラメータたち))
という形で使うんですが、PdefだとPbind内のパラメータを直接書き換えては実行することでフレーズなどどんどんチェンジしていくことができます。

なので超便利、「なぁんだ、じゃあこのPdefさえ使えればいいじゃん」って感じなのですが。。。

どうやらこのPdefはバグることが多々ありまして、Eli Fieldsteelさんの動画でも「あれ?動かない?なんでだろう」みたいな瞬間があったりするんですよ。
https://youtu.be/8Is3hJvzjvs?t=1005
僕もよくそうなります。

そんなわけで、ここでは一応コード例だけ書いておきます。

あ、Pdefを使う前は一度サーバをリブートしたほうがいいです。
そしてex1のSynthDefを実行しておきます。(\syn1の音源を鳴らすために。)
そのあとに下記コードを実行。

[ex11]

//Pdef

(
Pdef(\pb2,
	Pbind(
		\instrument, \syn1,
		\midinote, Pseq([38, 50, 57, 62], inf),
		\dur, 0.5,
		\cof, 300,
		));
)

//Pdefをプレイ
Pdef(\pb2).play(TempoClock(150/60)).quant_(4);

Pdef(\pb2).stop;
Pdef(\pb2).clear;

最初にPdefの部分を実行したあと、次に
Pdef(\pb2).play(TempoClock(150/60)).quant_(Quant(4));を実行します。
そうするとフレーズが流れ始めるので、そうなったらPbind内のどのパラメータでもチェンジ可能です。パラメータを変えてはPdefを実行、を繰り返すことができます。
Pseq内の数字(音符)の数を変えるなどでも全然OKです。

シーケンスを止める場合には下記の実行を。
Pdef(\pb2).stop;

一度シーケンスを止めたら次にplayする前に下記のクリアの実行を。
Pdef(\pb2).clear;

そうやっていくことでバグる回数は減るみたいです。
(それでもバグるときはバグります。その場合はサーバ又はSC3自体を再起動!です。)


Pfx(エフェクト)付き


Pbindをプレイする時って、たいてい音源にはエフェクトを通してますよね。
その場合Pfxを使うことになると思いますが、PfxとPdefn, Pbindefの併用例を書いて終わりにしたいと思います。(一応Pdefも書いておきます。)

まずはエフェクトと音源(今回の SynthDefは\syn2という名前)を実行しておきます。

[ex12]

//エフェクト
(
~rvbBus = Bus.audio(s, 2);
SynthDef(\rvb, {
var eff, in;
in = In.ar(~rvbBus, 2);
eff = FreeVerb2.ar(in[0], in[1], 1, 0.7, 0.9);
eff = LPF.ar(eff, 1500);
Out.ar(0, eff);
}).add;
)

// 音源syn2(Pulse.arにしてみました。)
(
SynthDef(\syn2, {
arg freq=220, gate=1, cof=900;
var sig, env;
env = EnvGen.kr(Env.asr(0.01, 1, 0.4), gate, doneAction:2);
sig = Pulse.ar(freq);
sig = LPF.ar(sig, cof) * env;
sig = Pan2.ar(sig, 0);
Out.ar(~rvbBus, sig * 0.2);
Out.ar(0, sig * 0.3);
}).add;
)



Pdefn + Pfx

[ex13]

//Pdefn + Pfx
(
t = TempoClock(140/60);
~pb2 = Pbind(
\instrument, \syn2,
\midinote, Pdefn(\p_note, Pseq([36, 55, 48, 55, 72, 55, 60, 48], inf)),
\cof, Pdefn(\p_cof, 400),
\dur, 0.5,
);
)

Pfx(~pb2, \rvb).play(t);

Pdefn(\p_note, Pseq([36, 55, 48, 72], inf)).quant_(Quant(4));
Pdefn(\p_note, Pseq([43, 57, 48, 58]-3, inf)).quant_(Quant(4));
Pdefn(\p_cof, 800);

Pbind(又はPbindefやPdef)を変数に入れておくと、Pfxに入れるとき見た目がシンプルになります。
今回の例では全て、~pb2という変数に入れました。



Pbindef + Pfx


[ex14]

//Pbindef + Pfx
(
t = TempoClock(140/60);
~pb2 = Pbindef(
\pb1,
\instrument, \syn2,
\midinote, Pseq([45, 48, 52, 55], inf),
\cof, 400,
\dur, 0.5,
);
)

Pfx(~pb2, \rvb).play(t);


Pbindef(\pb1, \midinote, Pseq([45, 64, 62, 55], inf)).quant_(Quant(4));
Pbindef(\pb1, \midinote, Pseq([41, 64, 60, 55], inf)).quant_(Quant(4));
Pbindef(\pb1, \cof, 800);



Pdef + Pfx


[ex15]

//Pdef + Pfx
(
Pdef(\pb2,
	Pbind(
		\instrument, \syn2,
		\midinote, Pseq([36, 55, 48, 57], inf),
		\dur, 0.5,
		\cof, 400,
		));
)

Pdef(\pb2).play(TempoClock(110/60));


Pdef(\pb2).stop;
Pdef(\pb2).clear;


今日は以上です。


<目次へ>
https://note.com/sc3/n/nb08177c4c011


この記事が気に入ったらサポートをしてみませんか?