【TidalCycles】 SuperDirtにSideChain Compressorを追加する
誰しも人生に一度はサイドチェインの音作りに夢中になる時がくるかと思います。
本記事ではTidalCyclesのサウンドエンジン、SuperDirtをハックして即興演奏にインタラクティブなコンプレッションを導入する方法を紹介します。
ゴール
Tidalでfunctionとしてコンプレッサーを適用し、以下を目指します。
- Tidalからthresholdとreleaseをコントロールすること
- コントロールもとのBusをd2やd3など自由に指定すること
- デフォルトのエフェクトと同様、面倒な準備なしでBootしたら即使えること
実はコンプレッサーの実装自体は、SuperDirtのhacksフォルダの中にいくつかの例
(adding-a-compressor.scd
filtering-dirt-output.scd
など)があり、これらを参考にすればすぐできてしまいます。
ただ複数のBusからの信号の入出力の管理や、モジュール化に際してのエラーなどTidalとスマートに連携させようとするとちょっと大変でした。コンプの動作確認からモジュール化まで順を追って説明します。
実装にあたり、概要や手順の確認にはmoxusさんの記事が大変参考になりました( https://qiita.com/moxuse@github/items/8da28584e5348463af25 )。
またサイドチェインの詳細な解説はAbletonの記事がアツいです( https://www.ableton.com/ja/blog/sidechain-compression-part-1/ )。
僕の開発環境は(macOS:10.13.6, Tidal:1.7.4, SuperCollider:3.11.1, Editor:Emacs)です。
1.Tidalにパラメーターを追加
SoundのParams.hs
に書き込む方法や別のスクリプトに記述して起動時に読み込む方法などがあるようですが、シンプルなのはTidalの起動後に直接実行するやり方です。
let compthr = pF "compthr"
comprel = pF "comprel"
compbus = pI "compbus"
コンプレッサーのThresholdであるcompthr
、Releaseのcomprel
、コントロール信号のBusを指定するcompbus
の3種類を設定しました。pF
はpattern Float(小数)、pI
はpattern Int(整数)を指定しており、なんと"0.25 0.5"
のように引数をパターンで記述もできてしまいます。
compbus
は、例としてd1にd2からの信号をトリガーにコンプをかけたいとき、
d1 $ s "padlong" # compthr 0.1 # compbus 2 -- d2を指定
d2 $ s "bd hc sd hc"
このように使うことを想定しています。
2.SuperDirtにモジュールを追加
次にSuperDirtにモジュールを追加します。あとで起動時の統合のために別ファイルに記述することになりますが、ひとまず適当な場所にmyEffects.scd
として保存します。
(
~dirt.addModule('dirt_compressor', { |dirtEvent|
dirtEvent.sendSynth('dirt_compressor' ++ ~dirt.numChannels,
[
compthr: ~compthr,
comprel: ~comprel,
compbus: ~compbus,
out: ~out
]
)
}, { ~compthr.notNil });
~dirt.orderModules(['dirt_compressor']);
)
hacksのcompressorのサンプルではdryBusとeffectBusを使うやり方が書いてありましたが、サイドチェインで他のorbitから信号をとりたいときはOutを使うとうまくいきました。11行目の~compthr.notNil
は、tidalでcompthrが記述されるまでエフェクトを適用しないようにするための命令です。
3.エフェクト(Synthdef)の実装
こちらもひとまずmyEffects.scd
の下のスペースに記述します
(
var numChannels = ~dirt.numChannels;
SynthDef("dirt_compressor" ++ numChannels, { |out, compbus, compthr=0.1, comprel=0.01, gate = 1|
var signal = In.ar(out, numChannels);
var control = In.ar(Select.kr(max(0, compbus-1), ~dirt.orbits.collect { |x| x.dryBus };), 2).sum;
var thrround = min(compthr, 0.99);
thrround = max(thrround, 0.0001);
signal = Compander.ar(signal, control,
thresh: compthr,
slopeBelow: 1,
slopeAbove: 0.1,
clampTime: 0.1,
relaxTime: comprel
);
signal = signal * EnvGen.kr(Env.asr, gate, doneAction:2);
ReplaceOut.ar(out, signal);
}, [\ir, \ir]).add;
)
4行目のvar signal
にエフェクトを適用する音が入ってきます。その下のvar control
がサイドチェインコンプをコントロールする信号で、Selekt.krを使ってcompbus
でBusを指定しています。max(0,compbus-1)
としているのはorbitは0はじまり(d1は0、d2は1)なので直感的に扱うため-1してます。また間違えて0や負の数が入った時のためにmaxで最大値が返るようにしています。その下のvar thrround
でも同様に、thresholdの設定ミスで音が爆発しないようmax
とmin
で丸め込みしました。そしてCompander
でコンプレッサーを適用しています。今回Tidalから操作できるようパラメーター化したのはthresholdとreleaseに相当するrelaxTimeの2種類ですが、叩く量を決めるslopeAbove
、attackに相当するclampTimeなどもパラメーター化すると面白そうです。ただしスピード感ある即興演奏のために要素を削ぎ落とすことも時として大切になるのではと思います.
ここまでできたらテストしてみましょう。起動手順は
- SCDで
SuperDirt.start
- myEffect.scdで、モジュール追加のブロックとSynthdefのブロックをれぞれ実行
- テキストエディタでTidalをBootし、パラメーター追加の行を実行
- 演奏する
d1 $ s "padlong" # speed (range 0.5 4 rand) # compthr "0.2" # comprel 0.01 # compbus "2"
d2 $ rarely (ply 8) $ s "md [hh bd?] cp bd" # shape 0.85
d3 $ s "808bd" # gain 1.1 # shape 0.8
d4 $ s "casio*4" # legato 0.1
d1のcompbus
を3や4, "2 3 4 3"
などにしてみるとわかりやすいでしょう。
4.起動時の読み込み設定
最後に上記の実行手順を簡略化し、SuperDirt.startするだけでコンプにアクセスできるようにします。スタートアップに自作のエフェクトを組み込むためにはファイルロードするのが安全かと思いますが、ちょっとよくわからなかったためここでは直接ソースに書き加える方法をとります(敗北)。しかしこの方法のメリットとして、任意のタイミング(例えばLowpass Filterの前/後など)でコンプを適用することができます。ただファイルロードでもできそうな雰囲気があるのでこれは今後の課題ですね・・・
まずはTidalのパラメーター宣言の3行ですが、これはBootTidal.hs
の一番下に書き加えました。こうするとエディタでTidalのBoot時に自動実行されます。
次にmyEffects.scd
に書いたモジュールの追加ブロックは、SuperDirtのsynths
フォルダにあるcore-modules.scd
に加えました。ここでは一番下にdirt_compressorがくるようにしています(ブロック全体の終了を示す);
を超えないように注意していください)。
最後にmyEffects.scd
に書いたSynthdefのブロックは、同フォルダにあるcore-synths.scd
のSynthdefが並ぶブロックに加えます。ここでmyEffects.scd
の時に書いていた一番上のvar numChannels = ~dirt.numChannels;
は、core-synth.scd
の冒頭で既に宣言されているので削除しましょう。
これでエラーがなければ、SuperDirt.start
からのTidal起動ですぐにコンプが使えるようになるはずです。
Thresholdをパターン化して複数レイヤーでのグルーヴを作ったり、テストの時にも触れたcompbus
をパターン化してサイクル毎に別のソースからサイドチェインしたりと、Tidalならではの可能性がかなりありそうです。Tidalは慣れたらシンプルなハードウェアのごとく素早く構造を組めるので、サイドチェイン実験もはかどりそうですね。
Discussion