yoppa.org


immediate bitwave

コンピュータミュージック 2017 - 明治大学先端メディアサイエンス学科

SuperCollider基礎 3 – エンベロープ (Envelop)、加算合成、減算合成

今回も引き続きSuperColliderによる音響合成について探求していきます。

まず始めに音の時間的変化であるエンベロープ(Envelope)をSuperColliderで実装してみます。エンベロープを変化させるだけで、例えば同じSin波でも様々に表情が変化します。また音響合成のパラメータにエンベロープを使用することで、時間経過によって複雑に変化する音色のデザインが可能となります。

後半は音の「足し算」「引き算」を行います。音の足し算は加算合成(Additive Synthesis)です。複数の音(例えばSin波)の周波数を変化させてミックスしていくことで音色をデザインしていきます。楽器で例えるとオルガンのような合成方法です。音の引き算は減算合成(Subtractive Syntesis)です。こちらは周波数成分を多く含んだ音(ノイズ、ノコゴリ波、パルスなど)を入力して、特定の周波数帯域のみ通過させます。この特定の周波数帯域のみ通過させる仕組みをフィルター(Filter)と呼びます。SuperColliderには様々なフィルターが存在していてそれぞれ特徴があります。実際に音を聞きながら試していきましょう。

スライド資料

サンプルコード

//エンベロープ (Envelope)

// Env.linen - アタック、サステイン、リリース、レベルで指定
Env.linen(0.05, 0.2, 0.5, 0.7).plot;

SynthDef("EnvTest", {
    var env, out;
    env = Env.linen(0.05, 0.1, 0.5);
    out = SinOsc.ar(440).dup * EnvGen.kr(env, doneAction: 2);
    Out.ar(0, out);
}).play;

// Env.perk - パーカッシブなエンベロープ
Env.perc(0.01, 2.0).plot;

SynthDef("EnvTest", {
    var env, out;
    env = Env.perc(0.01, 2.0);
    out = SinOsc.ar(440).dup * EnvGen.kr(env, doneAction: 2);
    Out.ar(0, out);
}).play;

// Env.triangle - 三角形のエンベロープ
Env.triangle(1, 1).plot;

SynthDef("EnvTest", {
    var env, out;
    env = Env.triangle(1, 1);
    out = SinOsc.ar(440).dup * EnvGen.kr(env, doneAction: 2);
    Out.ar(0, out);
}).play;

// Env.triangle - 三角形のエンベロープ
Env.sine(1, 1).plot;

SynthDef("EnvTest", {
    var env, out;
    env = Env.sine(1, 1);
    out = SinOsc.ar(440).dup * EnvGen.kr(env, doneAction: 2);
    Out.ar(0, out);
}).play;

// Env.new - 完全に自由なエンベロープ生成
// レベルの配列と、時間の配列で指定
Env.new([0, 1, 0.9, 0], [0.1, 0.5, 1],[-5, 0, -5]).plot;

SynthDef("EnvTest", {
    var env, out;
    env = Env.new([0, 1, 0.9, 0], [0.1, 0.5, 1],[-5, 0, -5]);
    out = SinOsc.ar(440).dup * EnvGen.kr(env, doneAction: 2);
    Out.ar(0, out);
}).play;


//加算合成 (Additive Synthesis)

//加算合成基本
SynthDef("AdditiveSynth", {
    var n = 12;
    var out;
    out = Mix.arFill(n,  {
        SinOsc.ar(
            [rrand(40, 2000), rrand(40, 2000)],
            0,
            n.reciprocal * 0.75;
        )
    });
    Out.ar(0, out);
}).play;

//加算合成、全体にエンベロープ
SynthDef("AdditiveSynth", {
    var n = 12;
    var out;
    out = Mix.arFill(n,  {
        SinOsc.ar(
            [rrand(40, 2000), rrand(40, 2000)],
            0,
            n.reciprocal * 0.75;
        )  *  EnvGen.kr(Env.perc(11, 6), doneAction:2);
    });
    Out.ar(0, out);
}).play;


//加算合成、ひとつひとつのSin波にエンベロープ
SynthDef("AdditiveSynth", {
      var n = 12;
      var out;
      out = Mix.arFill(n,{
            SinOsc.ar(
                  [rrand(40, 2000), rrand(40, 2000)],
                  pi.rand,
                  n.reciprocal)
            * EnvGen.kr(Env.sine(rrand(2, 20)),  doneAction: Done.none)
      }) * EnvGen.kr(Env.perc(11, 6), doneAction: Done.freeSelf, levelScale: 0.75);
      Out.ar(0, out);
}).play;


//減算合成 (Subtractive Synthesis)

//減算合成 - LPF ローパスフィルター
SynthDef("SubtractiveSynth", {
    var out;
    out = LPF.ar(
        Saw.ar([80, 81] ),
        [LFNoise0.kr(4, 800, 840), LFNoise0.kr(8, 800, 840)]
    );
    Out.ar(0, out);
}).play;

//減算合成 - RLPF レゾナンス付きローパスフィルター2
SynthDef("SubtractiveSynth", {
    var out;
    out = RLPF.ar(
        Saw.ar([80, 81] ),
        [LFNoise0.kr(4, 800, 840), LFNoise0.kr(8, 800, 840)],
        Saw.kr(0.2, 0.5, 0.2)
    );
    Out.ar(0, out);
}).play;

//減算合成 - RLPF レゾナンス付きローパスフィルター2
SynthDef("SubtractiveSynth", {
    var out;
    out = RLPF.ar(
        Saw.ar([80, 81] ),
        [LFNoise0.kr(4, 800, 840), LFNoise0.kr(8, 800, 840)],
        0.2
    );
    Out.ar(0, out);
}).play;

//減算合成 - RLPF レゾナンス付きローパスフィルター2
SynthDef("SubtractiveSynth", {
    var out;
    out = RLPF.ar(
        Saw.ar([80, 81] ),
        [LFNoise0.kr(4, 800, 840), LFNoise0.kr(8, 800, 840)],
        Saw.kr(0.2, 0.5, 0.2)
    );
    Out.ar(0, out);
}).play;

//減算合成 - RLPF レゾナンス付きローパスフィルター3
SynthDef("SubtractiveSynth", {
    var out;
    out = RLPF.ar(
        Saw.ar([80, 81] ) + Saw.ar([121, 120]) + Saw.ar([161, 160]),
        [LFNoise0.kr(4, 800, 840), LFNoise0.kr(8, 800, 840)],
        Saw.kr([0.2, 0.15], 0.5, 0.2)
    );
    Out.ar(0, out);
}).play