Submit
Browse
Anonymous
Login
RSS
SuperCollider Code
Fork Code: simple timeline for patterns
name
code content
// // Did you ever wonder how to easily schedule starting/stopping patterns at specific times // as part of building up and evolving a piece from a smaller building blocks? // Here's a simple approach. // // It can be kept very basic because it specifies start and stop in beats, // and not in absolute time. This means that the TempoClock used for playing the pattern // will influence the timeline. // // Nevertheless, it can already be useful. // // // Manual: // // schedule pattern to start on beat a and run until beat b with: // // ptl.beat(a, b, pattern) // // schedule pattern to start on beat a, and stop after producing N events with: // // ptl.number(a, N, pattern) // // finally, after configuring your timeline, it's time to play it. Do: // // ptl.asPattern.play // // don't pay attention to the stupid patterns in the example below, they are just // for demoing the timeline // ( s.waitForBoot({ var ptl = ( \internallist : [], \beat : { | self, start_beat, stop_beat, pattern | self[\internallist] = self[\internallist].add(Ptpar([start_beat, Pfindur(stop_beat - start_beat, pattern)])); }, \number : { | self, start_beat, no_of_events, pattern | self[\internallist] = self[\internallist].add(Ptpar([start_beat, Pfin(no_of_events, pattern)])); }, \asPattern : { |self| Ppar(self[\internallist]); } ); ~bpm = 60; // at 60 beats per minute, one beat takes one second ~tc = TempoClock(~bpm/60); // now schedule patterns in any order ptl.beat(0, 10, // first pattern to run from beat 0 to beat 10 Pbind(\instrument, \default, \midinote, Pseq([65], inf).trace, \amp, 0.8, \dur, 1)); ptl.beat(5.7, 7.3, // second pattern to run from beat 5.7 to beat 7.3 Pbind(\instrument, \default, \midinote, Pseq([70], inf).trace, \amp, 0.8, \dur, 0.1)); ptl.beat(3, 10, // fourth pattern to run from beat 3 and produce 10 notes Pbind(\instrument, \default, \midinote, Pseq([53], inf).trace, \amp, 0.8, \dur, 0.3)); // don't start multiple instances of the same timeline simultaneously if (~player.notNil) { ~player.stop; }; ~player = ptl.asPattern.play(~tc); }); ) // here's an experimental (not very well tested) extension of the system that also supports // scheduling using absolute time moments (start/stop time independent of tempoclock) // // note that the patterns scheduled with absolute time still obey the tempoclock // // extra calls are // // ptl.abstime(abs_start_time, abs_duration, pattern) // // ptl.abstimenumber(abs_start_time, number, pattern) // // other changes: // // asPattern call is removed and timeline self-manages its players // ptl is now equipped with a "start" and "end" api call to start/end playing ( s.waitForBoot({ var ptl = ( \internalcounter : 0, \internalnewcounter : { | self | var cnt = self[\internalcounter]; self[\internalcounter] = self[\internalcounter] + 1; cnt; }, \internallist : [], \abssched : [], \internalplayers : (), \beat : { | self, start_beat, stop_beat, pattern | self[\internallist] = self[\internallist].add(Ptpar([start_beat, Pfindur(stop_beat - start_beat, pattern)])); }, \abstime : { | self, delta_time, duration, pattern | self[\abssched] = self[\abssched].add((\dt: delta_time, \dur: duration, \p : pattern, \type : \time)); }, \number : { | self, start_beat, no_of_events, pattern | self[\internallist] = self[\internallist].add(Ptpar([start_beat, Pfin(no_of_events, pattern)])); }, \abstimenumber : { | self, delta_time, no_of_events, pattern | self[\abssched] = self[\abssched].add((\dt: delta_time, \dur: no_of_events, \p : pattern, \type : \number)); }, \start : { |self, tempoclock | if (tempoclock.isNil) { tempoclock = TempoClock.default; }; self[\abssched].do({ |el| var cnt = self.internalnewcounter; var type = el.type; if (type == \time) { SystemClock.sched(el.dt, { self[\internalplayers][cnt.asSymbol] = el.p.play(tempoclock); nil}); SystemClock.sched(el.dt + el.dur, { self[\internalplayers][cnt.asSymbol].stop; nil}); } { SystemClock.sched(el.dt, { self[\internalplayers][cnt.asSymbol] = Pfin(el.dur, el.p).play(tempoclock); nil}); }; }); self[\internalplayers][self.internalnewcounter.asSymbol] = Ppar(self[\internallist]).play(tempoclock); }, \end : { | self | self[\internalplayers].keysValuesDo({ | key, value | value.stop; }); self[\internalplayers] = (); }; ); ~bpm = 120; // at 60 beats per minute, one beat takes one second ~tc = TempoClock(~bpm/60); // now schedule patterns in any order ptl.beat(0, 10, // first pattern to run from beat 0 to beat 10 Pbind(\instrument, \default, \midinote, Pseq([65], inf).trace, \amp, 0.8, \dur, 1)); ptl.beat(5.7, 7.3, // second pattern to run from beat 5.7 to beat 7.3 Pbind(\instrument, \default, \midinote, Pseq([70], inf).trace, \amp, 0.8, \dur, 0.1)); ptl.abstimenumber(2, 10, Pbind(\instrument, \default, \midinote, Pseq([90], inf).trace, \amp, 0.8, \dur, 1)); ptl.beat(3, 10, // fourth pattern to run from beat 3 and produce 10 notes Pbind(\instrument, \default, \midinote, Pseq([53], inf).trace, \amp, 0.8, \dur, 0.3)); ptl.start(~tc); }); )
code description
simple timeline for scheduling start and stop of patterns at specific beats (and an experimental extension with absolute time scheduling)
use markdown for formating
category tags
comma separated, i.g. "wild, siren" (do not enter default SC class names, please)
ancestor(s)
comma separated identificators, i.g. "1-C,1-1,1-4M,1-x"
Private?
the code will be accessible by direct url and not visible in public activity
signup to submit public code without captcha
comment of change