はじめに
TidalCyclesは、Haskellライクなコードによってリズムパターンを生成できるソフトウェアです。
個人的にTidalCyclesで作曲していて、記事も書いているのでこちらもぜひみてください!
TidalCyclesのエフェクト
デフォルトエフェクトの使い方などについては公式のドキュメントに詳しく書いてあるので以下をみてください。
エフェクトの追加
デフォルトエフェクトだけでなく、自分で新たに定義したエフェクトを追加した場合があります。
今回は新たにreverb
エフェクトを追加できるようにしようと思います。
この方法だと、音が再生されている間のみしかエフェクトがかかりません。
そのため、リバーブやディレイなどはこの方法ではなく、globalEffectsとして定義したほうが良いです。以下の記事も参考にしてみてください。
結論
結論からいうと、このようになります。
SuperCollider側
(
~dirt.addModule('myreverb', { |dirtEvent|
dirtEvent.sendSynth('myreverb' ++ ~dirt.numChannels,
[
reverb: ~reverb,
out: ~out
]
)
}, { ~reverb.notNil });
SynthDef("myreverb" ++ ~dirt.numChannels, { |out, reverb|
var signal, chain, in, z, y;
signal = In.ar(out, ~dirt.numChannels);
// SchroederReverb
z = DelayN.ar(signal, 0.048);
y = Mix.ar(Array.fill(7,{ CombL.ar(z, 0.1, 1, 15) }));
32.do({ y = AllpassN.ar(y, 0.050, [0.050.rand, 0.050.rand], 1) });
signal = signal + (0.2*reverb*y);
ReplaceOut.ar(out, signal)
}, [\ir]).add;
)
TidalCycles側
do
let
reverb = pF "reverb"
d1
$ s "superpiano"
# n "<a2,a4,b4,af5>"
# sustain 3
# reverb 0.4
解説
TidalCyclesは、明示的に設定されていないエフェクト名は受け付けない仕様となっているので、まずTidalCycles側で# reverb
を使える状態にします。今回は# reverb 0
でリバーブなし、#reverb 1
でリバーブ最大、のようにしたいので、基本的に引数としてとる値はFloatとなります。
よって以下のように定義してあげます
let
reverb = pF "reverb"
(もし引数にとるものがIntegerである場合は、このpF
部分をpI
に変更します。)
この時点で
d1
$ s "superpiano"
# n "<a2,a4,b4,af5>"
# sustain 3
# reverb 0.4
のようにして実行しても特にエラーがでなくなっていると思います。(もちろんエフェクトの中身はまだ定義していないのでエフェクトはかかりません。)
次にエフェクトの定義ですが、こちらはSuperColliderで定義します。
エフェクト定義スクリプトはdefault-effects-extra.scdに例がたくさん載っているのでこちらを参考にしながら定義していきます。
今回はSchroederReverbという古典的なアルゴリズムリバーブを実装していきたいのですが、SuperCollider公式ページのリバーブレーションについての解説項目が参考になりそうなので、こちらに手を加えていい感じなリバーブを作っていきます。
(
~dirt.addModule('myreverb', { |dirtEvent|
dirtEvent.sendSynth('myreverb' ++ ~dirt.numChannels,
[
reverb: ~reverb,
out: ~out
]
)
}, { ~reverb.notNil });
SynthDef("myreverb" ++ ~dirt.numChannels, { |out, reverb|
var signal, chain, in, z, y;
signal = In.ar(out, ~dirt.numChannels);
// SchroederReverb
// リバーブのプリ・ディレイ・タイム
z = DelayN.ar(signal, 0.048);
// 並列に7つのcombによるディレイ
y = Mix.ar(Array.fill(7,{ CombL.ar(z, 0.1, 1, 15) }));
// 32つのallpassによるディレイの2つの並列したチェーン(合計64個)
32.do({ y = AllpassN.ar(y, 0.050, [0.050.rand, 0.050.rand], 1) });
// 0.2*reverbだけ原音に混ぜて返す
signal = signal + (0.2*reverb*y);
ReplaceOut.ar(out, signal)
}, [\ir]).add;
)
以上でreverbエフェクトが定義されたので、実際に音を聴いてみましょう。
おわりに
意外と簡単にオリジナルエフェクトを追加できるので、表現の幅もさらに広がりそうな気がします。個人的には、このような「技術・機能的ハードルによるちょっとした制約」がその楽器を使うことのオリジナリティだと思っているので、思い通りに定義できないところも含めて楽しむのがいいかなと思っています。
また今回実装したリバーブにもいろいろ改善点があるので、より魅力的なリバーブなどのエフェクトができたら紹介していきます!