Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / HelpSource / Tutorials / A-Practical-Guide / PG_Cookbook01_Basic_Sequencing.schelp
blobcbf82200e1fdf69a4657a7592c6554600e66cfe7
1 title:: PG_Cookbook01_Basic_Sequencing
2 summary:: Sequencing basics
3 related:: Tutorials/A-Practical-Guide/PG_08_Event_Types_and_Parameters, Tutorials/A-Practical-Guide/PG_Cookbook02_Manipulating_Patterns
4 categories:: Streams-Patterns-Events>A-Practical-Guide
6 section::Cookbook: Sequencing basics
8 subsection::Playing a predefined note sequence
10 The following are three different ways of playing the same famous fugue subject.
12 The first is brute force, listing all the scale degrees mechanically in order. The second and third recognize the A pedal point and use interlacing operations to insert the pedal notes in between the changing notes.
14 The example demonstrates the use of the code::\scale:: and code::\root:: event keys to define tonality. Root = 2 is D, and the scale defines a natural minor mode. The degree sequence also uses accidentals. Subtracting 0.1 from an integer scale degree flattens the note by a semitone; adding 0.1 raises by a semitone. -0.9 is 0.1 higher than -1; a natural minor scale degree below the tonic is a flat 7, and a half step higher than that is the leading tone.
16 code::
18 TempoClock.default.tempo = 84/60;
20 p = Pbind(
21         \scale, #[0, 2, 3, 5, 7, 8, 10],
22         \root, 2,
23         \degree, Pseq(#[rest, 4, 3, 4, 2, 4, 1, 4, 0, 4, -0.9, 4, 0, 4, 1, 4, 2, 4,
24                 -3, 4, -1.9, 4, -0.9, 4, 0, 4, -0.9, 4, 0, 4, 1, 4, 2], 1),
25         \dur, 0.25
26 ).play;
30 p = Pbind(
31         \scale, #[0, 2, 3, 5, 7, 8, 10],
32         \root, 2,
33         \degree, Place([#[rest, 3, 2, 1, 0, -0.9, 0, 1, 2, -3, -1.9, -0.9, 0, -0.9, 0, 1, 2],
34                 (4 ! 16) ++ \rest], 17),
35         \dur, 0.25
36 ).play;
40 p = Pbind(
41         \scale, #[0, 2, 3, 5, 7, 8, 10],
42         \root, 2,
43         \degree, Ppatlace([Pseq(#[rest, 3, 2, 1, 0, -0.9, 0, 1, 2, -3, -1.9, -0.9, 0, -0.9, 0, 1, 2], 1),
44                 Pn(4, 16)], inf),
45         \dur, 0.25
46 ).play;
50 subsection::"Multichannel" expansion
52 In a SynthDef, using an array as the input to a UGen expands the UGen into an array of UGens (see link::Guides/Multichannel-Expansion::). Something similar happens in patterns. Normally a value sent to a Synth node should be a single number, but if it's an array instead, the pattern expands the event to produce emphasis::multiple synth nodes instead:: of just one.
54 The code::\degree:: pattern applies a set of chord intervals to a melody that's always on top. It's a compound pattern, Pseries(...) + Prand(...), where Pseries returns a single number and Prand returns an array. As with regular math operations, a number plus an array is an array. If the current Pseries value is 7 and Prand returns [0, -3, -5], the result is [7, 4, 2] and you would hear a C major triad in first inversion.
56 code::
58 p = Pbind(
59         \degree, Pseries(7, Pwhite(1, 3, inf) * Prand(#[-1, 1], inf), inf).fold(0, 14)
60                 + Prand(#[[0, -2, -4], [0, -3, -5], [0, -2, -5], [0, -1, -4]], inf),
61         \dur, Pwrand(#[1, 0.5], #[0.8, 0.2], inf)
62 ).play;
65 p.stop;
68 subsection::Using custom SynthDefs (including unpitched SynthDefs)
70 Patterns have special features to support several styles of pitch organization, but those features are strictly optional. Here we play a SynthDef that has no frequency argument whatsoever.
72 Note the use of code::add:: to prepare the SynthDef. Without it, most of the SynthDef inputs would not be recognized and the pattern would not send values to them.
74 It's worth noting that the pattern runs in beats, whose real duration in seconds depends on the clock's tempo. The SynthDef, however, always measures time in seconds. This example keeps things simple by setting the clock to 1 beat per second. If the tempo needs to be something else, though, the code::\time:: key should be divided by the tempo:
76 code::
77         \time, Pkey(\delta) / Pfunc { thisThread.clock.tempo },
80 code::
82 b = Buffer.read(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav");
84 SynthDef(\stretchedFragments, { |out, bufnum, start, time = 1, stretch = 1, amp = 1, attack = 0.01, decay = 0.05|
85         var     sig = PlayBuf.ar(1, bufnum, rate: stretch.reciprocal, startPos: start, doneAction:2);
86         sig = PitchShift.ar(sig, pitchRatio: stretch)
87                 * EnvGen.kr(Env.linen(attack, time, decay), doneAction: 2);
88         Out.ar(out, sig ! 2)
89 }).add; // note add! Without this, arguments won't work
93 TempoClock.default.tempo = 1;
95 p = Pbind(
96         \instrument, \stretchedFragments,
97         \bufnum, b,
98         \start, Pwhite(0, (b.numFrames * 0.7).asInteger, inf),
99         \delta, Pexprand(0.2, 1.5, inf),
100         \time, Pkey(\delta),
101         \stretch, Pexprand(1.0, 4.0, inf),
102         \amp, 0.5,
103         \attack, 0.1,
104         \decay, 0.2
105 ).play;
108 p.stop;
109 b.free; // be tidy! remember to clean up your Buffer
112 Previous:       link::Tutorials/A-Practical-Guide/PG_08_Event_Types_and_Parameters::
114 Next:           link::Tutorials/A-Practical-Guide/PG_Cookbook02_Manipulating_Patterns::