scel: install files to site-lisp/SuperCollider
[supercollider.git] / HelpSource / Tutorials / A-Practical-Guide / PG_06c_Composition_of_Patterns.schelp
blob2b3e430b8629158e7fb798e6f4ba8efa86ee0c88
1 title:: PG_06c_Composition_of_Patterns
2 summary:: Making multiple event patterns act as one
3 related:: Tutorials/A-Practical-Guide/PG_06b_Time_Based_Patterns, Tutorials/A-Practical-Guide/PG_06d_Parallel_Patterns
4 categories:: Streams-Patterns-Events>A-Practical-Guide
6 section::Adding values to a base event pattern (Or, "Pattern Composition")
8 One way to use patterns is to write everything into the pattern up front. This has the advantage of clarity and ease of understanding. Another way is to modularize the behavior by creating smaller, simpler patterns and combining their results into single events that have keys and values from all the component patterns.
10 This is related to the computer science concept of "function composition," in which a complex calculation can be written not as a single large function, but as several smaller functions that are then chained together into a single function. Since Functions are normal objects in SuperCollider, it's easy to do an operation on a function that returns a composite function (which may then be used like any other function). http://en.wikipedia.org/wiki/Function_composition_(computer_science)
12 In mathematics, the code::·:: operator represents function composition.
14 code::
15 f(x) = x + 1
16 g(x) = x * 2
18 g · f = g(f(x)) = (x + 1) * 2
21 code::g · f:: means to evaluate code::f:: first, then pass its result to code::g::. The code::·:: operator is written as code::<>:: in SuperCollider.
23 code::
24 f = { |x| x + 1 };
25 g = { |x| x * 2 };
27 h = (g <> f);
28 --> a Function
30 h.value(1);
31 --> 4   // == (1+1) * 2
33 (f <> g).value(1)
34 --> 3   // == (1*2) + 1
36 // g · f == g(f(x)) -- f is evaluated first, and its result is passed to g
37 g.value(f.value(1));
38 --> 4
41 Event patterns can be similarly composed.
43 definitionList::
44 ## code::Pbindf(pattern, pairs):: || Adds new key-value pairs onto a pre-existing Pbind-style pattern. code::Pbindf(Pbind(\a, patternA), \b, patternB, \c, patternC):: gets the same result as code::Pbind(\a, patternA, \b, patternB, \c, patternC):: .
45 ## code::Pchain(patterns):: || Chains separate Pbind-style patterns together, so that all their key-value pairs go into the same event. For example, if one part of your code creates a Pbind instance code::a = Pbind(\a, patternA):: and another part creates code::b = Pbind(\b, patternB, \c, patternC)::, you could append code::\b:: and code::\c:: into the code::\a:: result using code::Pchain(b, a):: . The subpatterns evaluate in reverse order, in keeping with function composition notation.
47 For musical purposes, you could have one part of your code create a pattern defining rhythm and another part defining pitch material, then combine them with link::Classes/Pchain::.
49 code::
50 ~rhythm = Pbind(
51         \dur, Pwrand(#[0.125, 0.25, 0.5], #[0.3, 0.5, 0.2], inf),
52         \legato, Pwrand(#[0.1, 0.6, 1.01], #[0.1, 0.3, 0.6], inf)
54 ~melody = Pbind(
55         \degree, Pwhite(-4, 11, inf)
58 p = Pchain(~melody, ~rhythm).play;
59 p.stop;
62 That in itself has some good potential for algorithmic composition. Introducing link::Classes/EventPatternProxy:: into the mix makes it possible to swap different melody and rhythm components in and out on the fly, with no interruption. We can even change the type of pattern ( link::Classes/Pbind::, link::Classes/Pmono::, link::Classes/PmonoArtic:: ) with no ill effect.
64 code::
65 ~rhythm = EventPatternProxy(Pbind(
66         \dur, Pwrand(#[0.125, 0.25, 0.5], #[0.3, 0.5, 0.2], inf),
67         \legato, Pwrand(#[0.1, 0.6, 1.01], #[0.1, 0.3, 0.6], inf)
68 ));
70 ~melody = EventPatternProxy(Pbind(
71         \degree, Pwhite(-4, 11, inf)
72 ));
74 p = Pchain(~melody, ~rhythm).play;
76 ~melody.source = PmonoArtic(\default, \degree, Pseries(4, Prand(#[-1, 1], inf), inf).fold(-4, 11));
78 ~melody.source = Pbind(\degree, Pseries(4, Pwrand(#[-2, -1, 1, 2], #[0.3, 0.2, 0.2, 0.3], inf), inf).fold(-4, 11));
80 p.stop;
84 subsection::Pset and cousins
86 A group of pattern classes allow single event keys to be overwritten, or one addition or multiplication to be performed. link::Classes/Pkey::, in combination with the link::Classes/Pchain:: or link::Classes/Pbindf:: "pattern composition" classes, can do everything the following classes can do (though this alternate notation may be more convenient in certain cases).
88 definitionList::
89 ## code::Pset(name, value, pattern):: || Get one event from code::pattern::, and then put the next value from the code::value:: pattern into the code::name:: key. If the source pattern specifies a value for the same name, the value from the source will be replaced with the new one.
90 ## code::Padd(name, value, pattern):: || After getting the next event, replace the code::name:: value with its existing value code::+:: the next number from code::value::.
91 ## code::Pmul(name, value, pattern):: || After getting the next event, replace the code::name:: value with its existing value code::*:: the next number from code::value::.
94 These patterns remain in the library mainly for reasons of backward compatibility, since their behavior can be replicated easily using link::Classes/Pbindf::.
96 table::
97 ## code::Pset(name, value, pattern):: || code::Pbindf(pattern, name, value)::
98 ## code::Padd(name, value, pattern):: || code::Pbindf(pattern, name, Pkey(name) + value)::
99 ## code::Pmul(name, value, pattern):: || code::Pbindf(pattern, name, Pkey(name) * value)::
102 The patterns link::Classes/Psetpre::, link::Classes/Paddpre::, and link::Classes/Pmulpre:: reverse the order of evaluation. link::Classes/Pchain:: is able to duplicate this functionality.
104 definitionList::
105 ## code::Psetpre(name, value, pattern):: || Get the next code::value:: and put it into the event prototype before evaluating code::pattern::.
108 table::
109 ## code::Psetpre(name, value, pattern):: || code::Pchain(pattern, Pbind(name, value))::
110 ## code::Paddpre(name, value, pattern):: || code::Pchain(pattern, Pbind(name, Pkey(name) + value))::
112 Similar for code::Pmulpre::.
114 A third group -- link::Classes/Psetp::, link::Classes/Paddp::, link::Classes/Pmulp:: -- behave slightly differently, nesting pattern evaluation.
116 Previous:       link::Tutorials/A-Practical-Guide/PG_06b_Time_Based_Patterns::
118 Next:           link::Tutorials/A-Practical-Guide/PG_06d_Parallel_Patterns::