TUTORIAL DE SUPERCOLLIDER 3 - PARTE 10 Rodrigo F. Cadiz, basado en apuntes de Gary S. Kendall Northwestern University ( Server.internal.boot; Server.default = Server.internal; s = Server.default; ) Patterns Making Music with Patterns Here is an example that uses a Pattern to create two instances of the random melody stream. ( SynthDef( "SPE2", { arg i_out=0, i_dur=1, freq; var out; out = RLPF.ar( LFSaw.ar( freq ), LFNoise1.kr(1, 36, 110).midicps, 0.1 ) * EnvGen.kr( Env.perc, levelScale: 0.3, timeScale: i_dur, doneAction: 2 ); 4.do({ out = AllpassN.ar(out, 0.05, [0.05.rand, 0.05.rand], 4) }); Out.ar( i_out, out ); }).send(s); ) ( // streams as a sequence of pitches var pattern, streams, dur, durDiff; dur = 1/7; durDiff = 3; pattern = Prout.new({ loop({ if (0.5.coin, { #[ 24,31,36,43,48,55 ].do({ arg fifth; fifth.yield }); }); rrand(2,5).do({ // varying arpeggio 60.yield; #[63,65].choose.yield; 67.yield; #[70,72,74].choose.yield; }); // random high melody rrand(3,9).do({ #[74,75,77,79,81].choose.yield }); }); }); streams = [ // Stream.at(0) combines Prout's output with Pfunc transposing notes randomly (pattern - Pfunc.new({ #[12, 7, 7, 0].choose })).midicps.asStream, // 0 in array pattern.midicps.asStream // 1 in array ]; Routine({ loop({ // Do this Synth( "SPE2", [ \freq, streams.at(0).next, \i_dur, dur * durDiff ] ); durDiff.do({ // then do this durDiff times Synth( "SPE2", [ \freq, streams.at(1).next, \i_dur, dur ] ); dur.wait; }); }) }).play )
TUTORIAL DE SUPERCOLLIDER 3 - PARTE 11 Rodrigo F. Cadiz, basado en apuntes de Gary S. Kendall Northwestern University ListPatterns ListPatterns are Patterns that iterate over arrays of objects in some fashion. All ListPatterns have in common the instance variables list and repeats. The list variable is some Array to be iterated over. The repeats variable is some measure of the number of times to do something, whose meaning varies from subclass to subclass. The default value for repeats is 1. Making Music with ListPatterns Here is an example we have heard before rewritten to use ListPatterns. It uses nested patterns and results in much more concise code. ( SynthDef( "Allpass6", { arg freq, dur= 1.0; // Frequency and duration parameters var out, env; out = RLPF.ar( LFSaw.ar( freq, mul: EnvGen.kr( Env.perc, levelScale: 0.15, timeScale: dur, doneAction: 2 ) ), LFNoise1.kr(1, 36, 110).midicps, 0.1 ); 6.do({ out = AllpassN.ar(out, 0.05, [0.05.rand, 0.05.rand], 4) }); Out.ar( 0, out ); }).send(s) ) ( // This is a good more complex model var freqStream; freqStream = Pseq( // list, repeats, offset [Prand([ nil, Pseq(#[24, 31, 36, 43, 48, 55])]), // no repeat, nil causes pattern to end Pseq([ 60, Prand(#[63, 65]), 67, Prand(#[70, 72, 74]) ], rrand(2, 5)), Prand(#[74, 75, 77, 79, 81], { rrand(3, 9) }) ], inf).asStream.midicps; Task({ loop({ Synth( "Allpass6", [\freq, freqStream.next]); 0.13.wait; }); }).play; ) Here is an example that uses a Pattern to create a rhythmic solo. The values in the pattern specify the amplitudes of impulses fed to the Decay2 generator. ( SynthDef( "Mridangam", { arg t_amp; // Amplitude is argument (dur isn't meaningful) var out; out = Resonz.ar( WhiteNoise.ar(70) * Decay2.kr( t_amp, 0.002, 0.1 ), 60.midicps, 0.02,4 ).distort * 0.4; Out.ar( 0, out ); DetectSilence.ar( out, doneAction: 2 ); }).send(s); SynthDef( "Drone", { var out; out = LPF.ar( Saw.ar([60, 60.04].midicps) + Saw.ar([67, 67.04].midicps), 108.midicps, 0.007 ); Out.ar( 0, out ); }).send(s); ) (// percussion solo in 10/8 var stream, pat, amp; pat = Pseq([ Pseq(#[0.0], 10), // intro Pseq(#[0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 2), Pseq(#[0.9, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.2, 0.0, 0.0], 2), Pseq(#[0.9, 0.0, 0.0, 0.2, 0.0, 0.2, 0.0, 0.2, 0.0, 0.0], 2), Pseq(#[0.9, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.2, 0.0, 0.2], 2), // solo Prand([ Pseq(#[0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0]), Pseq(#[0.9, 0.2, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0]), Pseq(#[0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.2]), Pseq(#[0.9, 0.0, 0.0, 0.7, 0.2, 0.2, 0.0, 0.7, 0.0, 0.0]), Pseq(#[0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.2, 0.7, 0.2, 0.0]), Pseq(#[0.9, 0.2, 0.2, 0.7, 0.2, 0.2, 0.2, 0.7, 0.2, 0.2]), Pseq(#[0.9, 0.2, 0.2, 0.7, 0.2, 0.2, 0.2, 0.7, 0.0, 0.0]), Pseq(#[0.9, 0.0, 0.0, 0.7, 0.2, 0.2, 0.2, 0.7, 0.0, 0.0]), Pseq(#[0.9, 0.0, 0.4, 0.0, 0.4, 0.0, 0.4, 0.0, 0.4, 0.0]), Pseq(#[0.9, 0.0, 0.0, 0.4, 0.0, 0.0, 0.4, 0.2, 0.4, 0.2]), Pseq(#[0.9, 0.0, 0.2, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0]), Pseq(#[0.9, 0.0, 0.0, 0.7, 0.0, 0.0, 0.0, 0.7, 0.0, 0.0]), Pseq(#[0.9, 0.7, 0.7, 0.0, 0.0, 0.2, 0.2, 0.2, 0.0, 0.0]), Pseq(#[0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]) ], 30), // conclusion Pseq(#[2.0, 0.0, 0.2, 0.5, 0.0, 0.2, 0.9, 1.5, 0.0, 0.2, 0.5, 0.0, 0.2, 0.9, 1.5, 0.0, 0.2, 0.5, 0.0, 0.2], 3), Pseq(#[5], 1), Pseq(#[0.0], inf) ]); stream = pat.asStream; Task({ Synth("Drone"); loop({ if( ( amp = stream.next ) > 0, { Synth("Mridangam", [ \t_amp, amp ]) } ); (1/8).wait; }) }).play )