File: PG_Cookbook06_Phrase_Network.schelp

package info (click to toggle)
supercollider 1%3A3.13.0%2Brepack-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 80,292 kB
  • sloc: cpp: 476,363; lisp: 84,680; ansic: 77,685; sh: 25,509; python: 7,909; makefile: 3,440; perl: 1,964; javascript: 974; xml: 826; java: 677; yacc: 314; lex: 175; objc: 152; ruby: 136
file content (186 lines) | stat: -rw-r--r-- 8,114 bytes parent folder | download | duplicates (4)
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
title:: Pattern Guide Cookbook 06: Phrase Network
summary:: Sequencing by a network of phrases, Articulating notes with PmonoArtic
related:: Tutorials/A-Practical-Guide/PG_Cookbook05_Using_Samples, Tutorials/A-Practical-Guide/PG_Cookbook07_Rhythmic_Variations
categories:: Streams-Patterns-Events>A-Practical-Guide

section::Sequencing by a network of phrases
section::Articulating notes with PmonoArtic

Two for one here!

Most conventional synthesizers have a mode where playing a note while the previous note is still sustaining slides from one note to the other. The link::Classes/PmonoArtic:: pattern does this based on the event's sustain value. The delta value is the number of beats until the next event; sustain is the number of beats until the note releases. If sustain is shorter than delta, the note should cut off early and the next event should produce a new synth.

The example uses link::Classes/Pfsm:: (finite state machine) to arrange a set of predefined phrases in a partially randomized order. Each phrase is followed by a list pointing to the phrases that could legitimately follow the current phrase. That is, it might make musical sense to go from phrase 1 to phrase 2, but not from 1 to 3. Defining the successors for 1 appropriately makes sure that a nonsense transition will not be made.

This is a long example, but it's only because there are lots of phrases. The structure is very simple: just a set of phrases chosen in succession by Pfsm.

- strong::Third-party extension alert:: : In this example, the selection of the next phrase is explicitly weighted by repeating array elements, such as code::#[1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5]::. A more elegant way to do this is using the strong::WeighBag:: class in the strong::MathLib:: quark.

code::
// the following are equivalent:
a = #[1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5];
({ a.choose } ! 100).histo(5, 1, 5);

a = WeighBag.with((1..5), #[4, 2, 2, 2, 1]);
({ a.wchoose } ! 100).histo(5, 1, 5);
::

subsection::Example

code::
(
// this SynthDef has a strong attack, emphasizing the articulation
SynthDef(\sawpulse, { |out, freq = 440, gate = 0.5, plfofreq = 6, mw = 0, ffreq = 2000, rq = 0.3, freqlag = 0.05, amp = 1|
	var sig, plfo, fcurve;
	plfo = SinOsc.kr(plfofreq, mul:mw, add:1);
	freq = Lag.kr(freq, freqlag) * plfo;
	fcurve = EnvGen.kr(Env.adsr(0, 0.3, 0.1, 20), gate);
	fcurve = (fcurve - 1).madd(0.7, 1) * ffreq;
	sig = Mix.ar([Pulse.ar(freq, 0.9), Saw.ar(freq*1.007)]);
	sig = RLPF.ar(sig, fcurve, rq)
		* EnvGen.kr(Env.adsr(0.04, 0.2, 0.6, 0.1), gate, doneAction: Done.freeSelf)
		* amp;
	Out.ar(out, sig ! 2)
}).add;
)

(
TempoClock.default.tempo = 128/60;

// Pmul does only one thing here: take ~amp from each event
// and replace it with ~amp * 0.4
p = Pmul(\amp, 0.4, Pfsm([
	#[0, 3, 1],		// starting places
	PmonoArtic(\sawpulse,
		\midinote, Pseq([78, 81, 78, 76, 78, 76, 72, 71, 69, 66], 1),
		\dur, Pseq(#[0.25, 1.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25], 1),
		\sustain, Pseq(#[0.3, 1.2, 0.3, 0.2, 0.3, 0.2, 0.3, 0.2, 0.3, 0.2],1 ),
		\amp, Pseq(#[1, 0.5, 0.75, 0.5, 0.75, 0.5, 0.75, 0.5, 0.75, 0.5], 1),
		\mw, Pseq([0, 0.03, Pseq(#[0], inf)], 1)
	), #[1, 2, 3, 4, 7],

	PmonoArtic(\sawpulse,
		\midinote, Pseq([64, 66, 69, 71, 72, 73], 1),
		\dur, Pseq(#[0.25], 6),
		\sustain, Pseq(#[0.3, 0.2, 0.2, 0.2, 0.3, 0.2], 1),
		\amp, Pseq(#[1, 0.5, 0.5, 0.5, 0.5, 0.5], 1),
		\mw, 0
	), #[1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5],

	PmonoArtic(\sawpulse,
		\midinote, Pseq([69, 71, 69, 66, 64, 69, 71, 69], 1),
		\dur, Pseq(#[0.125, 0.625, 0.25, 0.25, 0.25, 0.25, 0.25, 0.75], 1),
		\sustain, Pseq(#[0.2, 0.64, 0.2, 0.2, 0.2, 0.3, 0.3, 0.75], 1),
		\amp, Pseq(#[0.5, 0.75, 0.5, 0.5, 0.5, 1, 0.5, 0.5], 1),
		\mw, 0
	), #[0, 1, 1, 1, 1, 3, 3, 3, 3, 5],

	PmonoArtic(\sawpulse,
		\midinote, Pseq([72, 73, 76, 72, 71, 69, 66, 71, 69], 1),
		\dur, Pseq(#[0.25, 0.25, 0.25, 0.083, 0.083, 0.084, 0.25, 0.25, 0.25], 1),
		\sustain, Pseq(#[0.3, 0.2, 0.2, 0.1, 0.07, 0.07, 0.2, 0.3, 0.2], 1),
		\amp, Pseq(#[1, 0.5, 0.5, 1, 0.3, 0.3, 0.75, 0.75, 0.5], 1),
		\mw, 0
	), #[1, 1, 1, 1, 3, 3, 4, 4, 4],

	PmonoArtic(\sawpulse,
		\midinote, Pseq([64, 66, 69, 71, 72, 73, 71, 69, 66, 71, 69, 66, 64, 69], 1),
		\dur, Pseq(#[0.25, 0.25, 0.25, 0.25, 0.125, 0.375, 0.166, 0.166, 0.168,
				0.5, 0.166, 0.166, 0.168, 0.5], 1),
		\sustain, Pseq(#[0.3, 0.2, 0.2, 0.2, 0.14, 0.4, 0.2, 0.2, 0.2, 0.6, 0.2, 0.2, 0.2, 0.5],1),
		\amp, Pseq(#[0.5, 0.5, 0.6, 0.8, 1, 0.5, 0.5, 0.5, 0.5, 1,
			0.5, 0.5, 0.5, 0.45], 1),
		\mw, 0
	), #[0, 1, 1, 1, 1, 3, 3, 5],

	PmonoArtic(\sawpulse,
		\midinote, Pseq([72, 73, 76, 78, 81, 78, 83, 81, 84, 85], 1),
		\dur, Pseq(#[0.25, 0.25, 0.25, 0.25, 0.5, 0.5, 0.5, 0.5, 0.125, 1.125], 1),
		\sustain, Pseq(#[0.3, 0.2, 0.2, 0.2, 0.95, 0.25, 0.95, 0.25, 0.2, 1.13], 1),
		\amp, Pseq(#[0.7, 0.5, 0.5, 0.5, 0.7, 0.5, 0.8, 0.5, 1, 0.5], 1),
		\mw, Pseq([Pseq(#[0], 9), 0.03], 1)
	), #[6, 6, 6, 8, 9, 10, 10, 10, 10, 11, 11, 13, 13],

	PmonoArtic(\sawpulse,
		\midinote, Pseq([83, 81, 78, 83, 81, 78, 76, 72, 73, 78, 72, 72, 71], 1),
		\dur, Pseq(#[0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25,
				0.25, 2], 1),
		\sustain, Pseq(#[0.3, 0.3, 0.2, 0.3, 0.3, 0.3, 0.2, 0.3, 0.2, 0.3, 0.2, 0.3, 2], 1),
		\amp, Pseq(#[0.5, 0.5, 0.5, 0.8, 0.5, 0.5, 0.5, 0.8, 0.5, 0.8, 0.5,
				1, 0.4], 1),
		\mw, Pseq([Pseq([0], 12), 0.03], 1)
	), #[0, 7, 7, 7, 7, 7, 3, 3, 3, 3],

	PmonoArtic(\sawpulse,
		\midinote, Pseq([69, 71, 72, 71, 69, 66, 64, 69, 71], 1),
		\dur, Pseq(#[0.25, 0.25, 0.25, 0.25, 0.166, 0.167, 0.167, 0.25, 0.25], 1),
		\sustain, Pseq(#[0.2, 0.2, 0.3, 0.2, 0.2, 0.2, 0.14, 0.3, 0.2], 1),
		\amp, Pseq(#[0.5, 0.5, 0.8, 0.5, 0.5, 0.5, 0.5, 0.8, 0.5], 1)
	), #[3, 3, 3, 4, 4, 5],

	PmonoArtic(\sawpulse,
		\midinote, Pseq([84, 85, 84, 84, 88, 84, 83, 81, 83, 81, 78, 76, 81, 83], 1),
		\dur, Pseq(#[0.125, 0.535, 0.67, 1.92, 0.25, 0.166, 0.167, 0.167,
				0.25, 0.25, 0.25, 0.25, 0.25, 0.25], 1),
		\sustain, Pseq(#[0.2, 3.12, 0.2, 0.2, 0.2, 0.2, 0.2, 0.15, 0.3, 0.2, 0.2, 0.2,
				0.3, 0.2], 1),
		\amp, Pseq(#[1, 0.8, 0.8, 0.8, 1, 1, 0.8, 0.8, 1, 0.8, 0.8, 0.8,
				1, 0.8], 1),
		\mw, Pseq([0, 0.005, 0.005, 0.06, Pseq(#[0], 10)], 1)
	), #[10, 10, 10, 11, 11, 11, 11, 12, 12, 12],

		// same as #4, 8va
	PmonoArtic(\sawpulse,
		\midinote, Pseq(([64, 66, 69, 71, 72, 73, 71, 69, 66, 71, 69, 66, 64, 69]+12), 1),
		\dur, Pseq(#[0.25, 0.25, 0.25, 0.25, 0.125, 0.375, 0.166, 0.166, 0.168,
				0.5, 0.166, 0.166, 0.168, 0.5], 1),
		\sustain, Pseq(#[0.3, 0.2, 0.2, 0.2, 0.14, 0.4, 0.2, 0.2, 0.2, 0.6, 0.2, 0.2, 0.2, 0.5],1),
		\amp, Pseq(#[0.5, 0.5, 0.6, 0.8, 1, 0.5, 0.5, 0.5, 0.5, 1,
			0.5, 0.5, 0.5, 0.45], 1),
		\mw, 0
	), #[11, 11, 11, 11, 11, 12, 12],

	PmonoArtic(\sawpulse,
		\midinote, Pseq([81, 84, 83, 81, 78, 76, 81, 83], 1),
		\dur, Pseq(#[0.25], 8),
		\sustain, Pseq(#[0.2, 0.3, 0.3, 0.2, 0.3, 0.2, 0.3, 0.2], 1),
		\amp, Pseq(#[0.5, 1, 0.5, 0.5, 0.6, 0.5, 0.8, 0.5], 1),
		\mw, 0
	), #[0, 9, 9, 11, 11, 12, 12, 12, 12, 12],

		// same as #1, 8va
	PmonoArtic(\sawpulse,
		\midinote, Pseq(([64, 66, 69, 71, 72, 73]+12), 1),
		\dur, Pseq(#[0.25], 6),
		\sustain, Pseq(#[0.3, 0.2, 0.2, 0.2, 0.3, 0.2], 1),
		\amp, Pseq(#[1, 0.5, 0.5, 0.5, 0.5, 0.5], 1),
		\mw, 0
	), #[6, 6, 8, 9, 9, 9, 9, 10, 10, 10, 10, 13, 13, 13],

	PmonoArtic(\sawpulse,
		\midinote, Pseq([78, 81, 83, 78, 83, 84, 78, 84, 85], 1),
		\dur, Pseq(#[0.25, 0.25, 0.5, 0.25, 0.25, 0.5, 0.25, 0.25, 1.75], 1),
		\sustain, Pseq(#[0.2, 0.3, 0.2, 0.2, 0.3, 0.2, 0.2, 0.3, 1.75], 1),
		\amp, Pseq(#[0.4, 0.8, 0.5, 0.4, 0.8, 0.5, 0.4, 1, 0.8], 1),
		\mw, Pseq([Pseq([0], 8), 0.03], 1)
	), #[8, 13, 13],

	PmonoArtic(\sawpulse,
		\midinote, Pseq([88, 84, 83, 81, 83, 81, 78, 76, 81, 83], 1),
		\dur, Pseq(#[0.25, 0.166, 0.167, 0.167,
				0.25, 0.25, 0.25, 0.25, 0.25, 0.25], 1),
		\sustain, Pseq(#[0.2, 0.2, 0.2, 0.15, 0.3, 0.2, 0.2, 0.2,
				0.3, 0.2], 1),
		\amp, Pseq(#[1, 1, 0.8, 0.8, 1, 0.8, 0.8, 0.8,
				1, 0.8], 1),
		\mw, 0
	), #[10]
], inf)).play;
)

p.stop;
::

Previous:	link::Tutorials/A-Practical-Guide/PG_Cookbook05_Using_Samples::

Next:		link::Tutorials/A-Practical-Guide/PG_Cookbook07_Rhythmic_Variations::