2017/05/09

SuperCollider - オシレータの位相

トーンクラスターを作るときなどは音が演奏されるたびに位相をリセットしたくない場合があります。以下の例ではパターンから現在の時刻をシンセに与えることで位相の進みを計算しています。

位相は普通 [0, 2pi) の範囲の値を指定しますが LFSaw では [0, 2) の範囲で位相を指定します。

SystemClockInterpreter 側で動作しているようで SynthDef の中で呼び出した場合は add でサーバに送られる時点で計算されて定数になるようです。パターンで指定する場合も {} で囲って関数にしないと play が呼び出された時点で定数になってしまいます。

SynthDef(\phase,
  { | out, freq, dur, pan, amp, seconds |
    var env = Env([1, 0], [dur], 6);
    var envGen = EnvGen.ar(env, doneAction: 2);
    var osc = LFSaw.ar(freq, (2 * freq * seconds) % 2);
    OffsetOut.ar(out, Pan2.ar(osc, pan, amp * envGen))
  }
).add;

SynthDef(\reset,
  { | out, freq, dur, pan, amp, seconds |
    var env = Env([1, 0], [dur], 6);
    var envGen = EnvGen.ar(env, doneAction: 2);
    var osc = LFSaw.ar(freq, 0);
    OffsetOut.ar(out, Pan2.ar(osc, pan, amp * envGen))
  }
).add;

TempoClock.default.tempo = 70 / 60;

~scale = Scale.chromatic(Tuning.chalmers);
~root = 0;

~seqPhase = Pbind(
  \instrument, Pseq([Pseq([\phase], 8), Pseq([\reset], 8)], inf),
  \scale, ~scale,
  \root, ~root,
  \degree, Pseq([[-7, -3.05, -2.98, 0, 1.98, 2, 4, 4.01, 4.02, 5, 5.04, 7]], inf),
  \dur, 0.25,
  \amp, 0.05,
  \seconds, {SystemClock.seconds}
).play;