«A Modular Approach To Phase Modulation» by bp

on 29 Mar'21 04:37 in modularpm

In messing around with PM/FM synthesis, I had this idea to make a SynthDef that represents one individual operator in a PM synth. Then the operators are wired together by busses and played together in a Pbind. This moves the wiring logic out of the SynthDef and into the Pbind, which allows for any number of operators in each note, arranged in whatever configuration you want. You are only limited by CPU and the number of available busses. The Pbind I have included here reuses the same set of busses for every note, which means that when the notes overlap each other, the modulators from the current event will be summed with the modulators of the next event, on the shared bus. This creates some growl-y, screechy effects while the notes overlap. When playing only harmonics, the overlapping modulators are still harmonically related and so they produce harmonious sidebands. When the scale degree is changed (every fifth note), you will hear some nasty dissonant distortion during the transition. Try messing with \legato, \atk, and \rel times to see what I mean.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
(
s.waitForBoot{
    SynthDef(\pmOperator, {
        var sig, env, freq, vibrato, detune;
        env = Env.adsr(
            \atk.kr(0.01), \dec.kr(0.3), \sus.kr(0.5), \rel.kr(1.0),
            curve: \curve.kr(-4)).ar(2, \gate.kr(1));
        detune = LFNoise1.kr(\detuneRate.kr(0.2)!2).bipolar(\detuneAmt.kr(0.1)).midiratio;
        vibrato = SinOsc.kr(\vibRate.kr(2)).bipolar(\vibAmt.kr(0.2)).midiratio;
        freq = \freq.kr(440) * vibrato * detune;
        sig = SinOsc.ar(freq * \ratio.kr(1), In.ar(\in.kr(0), 2));
        sig = Balance2.ar(sig[0], sig[1], \pan.kr(0), env);
        sig = LeakDC.ar(sig);
        Out.ar(\out.kr(0), sig * \amp.kr(0.3));
    }).add;

    s.sync;

    // use busses to connect modulators to carriers:
    s.newBusAllocators;
    ~b0 = Bus.audio(s, 2);
    ~b1 = Bus.audio(s, 2);
    ~b2 = Bus.audio(s, 2);
    ~b3 = Bus.audio(s, 2);
    ~b4 = Bus.audio(s, 2);
    ~b5 = Bus.audio(s, 2);

    // use groups to ensure modulators are before carriers on the node tree:
    ~g0 = Group.new;
    ~g1 = Group.after(~g0);
    ~g2 = Group.after(~g1);
    ~g3 = Group.after(~g2);
    ~g4 = Group.after(~g3);
    ~g5 = Group.after(~g4);

    s.sync;

    // use arrays in Pbind to play multiple operators simultaneously:
    Pbind(
        \instrument, \pmOperator,
        \tempo, 1,
        \dur, Pwhite(3.0, 6.0),
        \root, -5,
        \octave, Pfunc{{rrand(2, 3)} ! 6},
        \degree, Pxrand((0..7), inf).stutter(5),
        \harmonic, Pfunc{{rrand(1, 8)} ! 6},
        \group, [~g0, ~g1, ~g2, ~g3, ~g4, ~g5],
        \in, [~b0, ~b1, ~b2, ~b3, ~b4, ~b5],
        \out, [~b1, ~b2, 0, ~b4, ~b5, 0],
        \ratio, Pfunc{[1, 1, 2, 2, 3, 3].scramble},
        \vibAmt, Pfunc{{rrand(0.0, 0.2)} ! 6} * 0.3,
        \vibRate, Pfunc{[2, 3, 4, 4, 6, 8].scramble},
        \detuneAmt, Pfunc{{rrand(0.0, 0.2)} ! 6} * 0.2,
        \detuneRate, Pfunc{{rrand(0.1, 0.5)} ! 6},
        \legato, Pfunc{{rrand(0.4, 0.8)} ! 6} * 1.2,
        \atk, Pfunc{{rrand(1.5, 4.5)} ! 6},
        \dec, Pfunc{{rrand(0.9, 1.6)} ! 6},
        \sus, Pfunc{{rrand(0.4, 0.9)} ! 6},
        \rel, Pfunc{{rrand(1.5, 4.5)} ! 6} * 2.5,
        \curve, Pfunc{{rrand(-5, -1)} ! 6},
        \amp, [1.2, 1.4, 0.3, 1.4, 1.2, 0.3],
        \pan, [-0.8, 0.8, -0.3, -0.8, 0.8, 0.3],
    ).play;
}
)
descendants
«Re: A Modular Approach To Phase Modulation» by eliacools (private)
full graph
raw 2356 chars (focus & ctrl+a+c to copy)
reception
comments