LoginSignup
1
0

More than 1 year has passed since last update.

【TidalCycles】オリジナルエフェクトの追加方法

Last updated at Posted at 2021-08-17

はじめに

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エフェクトが定義されたので、実際に音を聴いてみましょう。

おわりに

意外と簡単にオリジナルエフェクトを追加できるので、表現の幅もさらに広がりそうな気がします。個人的には、このような「技術・機能的ハードルによるちょっとした制約」がその楽器を使うことのオリジナリティだと思っているので、思い通りに定義できないところも含めて楽しむのがいいかなと思っています。

また今回実装したリバーブにもいろいろ改善点があるので、より魅力的なリバーブなどのエフェクトができたら紹介していきます!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0