1 FilterPattern : Pattern {
5 ^super.new.pattern_(pattern)
12 *new { arg pattern, repeats=inf, key;
13 ^super.newCopyArgs(pattern, repeats, key )
15 storeArgs { ^[pattern,repeats, key] }
16 embedInStream { | event |
18 repeats.value(event).do { event = pattern.embedInStream(event) };
20 repeats.value(event).do {
21 event = pattern.embedInStream(event);
31 *new { arg pattern, repeats=inf, key ;
32 ^super.new(pattern).repeats_(repeats).key_(key)
34 storeArgs { ^[pattern,repeats, key] }
35 embedInStream { | event |
38 stream = pattern.asStream;
39 output = stream.next(event);
41 if (event[key] == true) { output = stream.next(event) };
44 event = output.copy.embedInStream(event)
51 FuncFilterPattern : FilterPattern {
54 *new { arg func, pattern;
55 ^super.new(pattern).func_(func)
57 storeArgs { ^[func,pattern] }
60 Pcollect : FuncFilterPattern {
61 embedInStream { arg inval;
63 stream = pattern.asStream;
65 outval = stream.next(inval);
66 if (outval.isNil) { ^inval };
67 inval = yield(func.value(outval));
71 ^pattern.asStream.collect(func);
75 Pselect : FuncFilterPattern {
76 embedInStream { arg inval;
78 stream = pattern.asStream;
81 outval = stream.next(inval);
82 if (outval.isNil) { ^inval };
83 func.value(outval).not
85 inval = yield(outval);
89 ^pattern.asStream.select(func);
93 Preject : FuncFilterPattern {
94 embedInStream { arg inval;
96 stream = pattern.asStream;
99 outval = stream.next(inval);
100 if (outval.isNil) { ^inval };
103 inval = yield(outval);
107 ^pattern.asStream.reject(func);
111 Pfset : FuncFilterPattern {
113 *new { |func, pattern, cleanupFunc|
114 ^super.new(func, pattern).cleanupFunc_(cleanupFunc)
116 embedInStream { arg inevent;
117 var event, cleanup = IneventStreamCleanup.new;
118 // cleanup should actually not be passed in
119 // but retaining (temporarily) for backward compatibility
120 var envir = Event.make({ func.value(cleanup) });
121 var stream = pattern.asStream;
125 inevent = inevent.copy;
126 inevent.putAll(envir);
127 event = stream.next(inevent);
129 cleanup.addFunction(event, { |flag|
130 envir.use({ cleanupFunc.value(flag) });
135 ^cleanup.exit(inevent)
137 cleanup.update(event);
139 inevent = yield(event);
140 if(inevent.isNil) { ^cleanup.exit(event) }
146 Psetpre : FilterPattern {
148 *new { arg name, value, pattern;
149 ^super.new(pattern).name_(name).value_(value)
151 storeArgs { ^[name,value,pattern] }
152 filterEvent { arg event, val;
155 embedInStream { arg event;
156 var val, inevent, filteredEvent;
157 var valStream = value.asStream;
158 var evtStream = pattern.asStream;
161 val = valStream.next(event);
162 // if (val.isNil or: event.isNil) { ^event };
163 // event = this.filterEvent(event, val);
164 if (val.isNil or: event.isNil) {
168 filteredEvent = this.filterEvent(event, val);
170 inevent = evtStream.next(filteredEvent);
171 if (inevent.isNil) { ^event };
172 event = yield(inevent);
173 if(event.isNil) { nil.yield; ^inevent }
179 filterEvent { arg event, val;
180 ^event[name] = event[name] + val;
185 filterEvent { arg event, val;
186 ^event[name] = event[name] * val;
190 Pset : FilterPattern {
192 *new { arg name, value, pattern;
193 ^super.new(pattern).name_(name).value_(value)
195 storeArgs { ^[name,value,pattern] }
196 filterEvent { arg event, val;
199 embedInStream { arg event;
201 var valStream = value.asStream;
202 var evtStream = pattern.asStream;
205 inEvent = evtStream.next(event);
206 if (event.isNil) { ^nil.yield };
207 if (inEvent.isNil) { ^event };
208 val = valStream.next(inEvent);
209 if (val.isNil) { ^event };
211 this.filterEvent(inEvent, val);
212 event = inEvent.yield;
219 filterEvent { arg event, val;
220 ^event[name] = event[name] + val;
225 filterEvent { arg event, val;
226 ^event[name] = event[name] * val;
232 embedInStream { arg event;
233 var evtStream, val, inevent;
234 var valStream = value.iter;
237 val = valStream.next(event);
240 evtStream = pattern.asStream;
242 inevent = evtStream.next(event);
243 if(event.isNil) { ^nil.yield };
246 this.filterEvent(inevent, val);
247 event = inevent.yield;
255 filterEvent { arg event, val;
256 ^event[name] = event[name] + val;
261 filterEvent { arg event, val;
262 ^event[name] = event[name] * val;
267 Pstretch : FilterPattern {
269 *new { arg value, pattern;
270 ^super.new(pattern).value_(value)
272 storeArgs { ^[value,pattern] }
273 embedInStream { arg event;
276 var valStream = value.asStream;
277 var evtStream = pattern.asStream;
280 inevent = evtStream.next(event);
281 if (inevent.isNil) { ^event };
282 val = valStream.next(inevent);
283 if (val.isNil) { ^event };
285 delta = event[\delta];
287 inevent[\delta] = delta * val;
289 inevent[\dur] = inevent[\dur] * val;
290 event = yield(inevent);
297 Pstretchp : Pstretch {
299 embedInStream { arg event;
300 var evtStream, val, inevent, delta;
301 var valStream = value.asStream;
303 val = valStream.next(event);
306 evtStream = pattern.asStream;
308 inevent = evtStream.next(event);
309 if(event.isNil) { ^nil.yield };
312 delta = inevent[\delta];
314 inevent[\delta] = delta * val;
316 inevent[\dur] = inevent[\dur] * val;
317 event = inevent.yield;
325 // needs testing - hjh
326 Pplayer : FilterPattern {
328 *new { arg playerPattern, subPattern;
329 ^super.newCopyArgs(playerPattern, subPattern)
331 storeArgs { ^[ pattern, subPattern ] }
332 embedInStream { arg event;
334 var playerStream = pattern.asStream;
335 var stream = subPattern.asStream;
337 inevent = stream.next(event);
338 if (inevent.isNil) { ^event };
339 player = playerStream.next(event);
340 if (player.isNil) { ^event };
341 inevent.parent = player.event;
342 event = yield(inevent);
345 // backward compatibility: unnecessary var playerPattern was removed
346 playerPattern { ^pattern }
347 playerPattern_ { |playerPattern| pattern = playerPattern }
352 Pdrop : FilterPattern {
354 *new { arg count, pattern;
355 ^super.new(pattern).count_(count)
357 storeArgs { ^[count,pattern] }
358 embedInStream { arg event;
360 var stream = pattern.asStream;
362 count.value(event).do {
363 inevent = stream.next(event);
364 if (inevent.isNil, { ^event });
367 inevent = stream.next(event);
368 if (inevent.isNil, { ^event });
369 event = inevent.yield;
374 Pfin : FilterPattern {
376 *new { arg count, pattern;
377 ^super.new(pattern).count_(count)
379 storeArgs { ^[count,pattern] }
380 asStream { | cleanup| ^Routine({ arg inval; this.embedInStream(inval, cleanup) }) }
382 embedInStream { arg event, cleanup;
384 var stream = pattern.asStream;
385 cleanup ?? { cleanup = EventStreamCleanup.new };
386 count.value(event).do({
387 inevent = stream.next(event) ?? { ^event };
388 cleanup.update(inevent);
389 event = inevent.yield;
397 // it is not correct to call stream.next(nil) on a value stream
398 // but there is no good way to distinguish in Pfin so we need a subclass
399 // might be ok to deprecate this now
402 embedInStream { arg event;
404 var stream = pattern.asStream;
406 count.value(event).do({
407 inevent = stream.next(event);
408 if (inevent.isNil, { ^event });
409 event = inevent.yield;
415 Pfindur : FilterPattern {
416 var <>dur, <>tolerance;
417 *new { arg dur, pattern, tolerance = 0.001;
418 ^super.new(pattern).dur_(dur).tolerance_(tolerance)
420 storeArgs { ^[dur,pattern,tolerance] }
421 asStream { | cleanup| ^Routine({ arg inval; this.embedInStream(inval, cleanup) }) }
423 embedInStream { arg event, cleanup;
424 var item, delta, elapsed = 0.0, nextElapsed, inevent,
425 localdur = dur.value(event);
426 var stream = pattern.asStream;
428 cleanup ?? { cleanup = EventStreamCleanup.new };
430 inevent = stream.next(event) ?? { ^event };
431 cleanup.update(inevent);
432 delta = inevent.delta;
433 nextElapsed = elapsed + delta;
434 if (nextElapsed.roundUp(tolerance) >= localdur) {
435 // must always copy an event before altering it.
436 // fix delta time and yield to play the event.
437 inevent = inevent.copy.put(\delta, localdur - elapsed).yield;
438 ^cleanup.exit(inevent);
441 elapsed = nextElapsed;
442 event = inevent.yield;
448 Psync : FilterPattern {
449 var <>quant, <>maxdur, <>tolerance;
450 *new { arg pattern, quant, maxdur, tolerance = 0.001;
451 ^super.new(pattern).quant_(quant).maxdur_(maxdur).tolerance_(tolerance)
453 storeArgs { ^[pattern,quant,maxdur,tolerance] }
455 embedInStream { arg event;
456 var item, stream, delta, elapsed = 0.0, nextElapsed, clock, inevent;
457 var localquant = quant.value(event), localmaxdur = maxdur.value(event);
458 var cleanup = EventStreamCleanup.new;
460 stream = pattern.asStream;
463 inevent = stream.next(event);
465 if(localquant.notNil) {
466 event = Event.silent(elapsed.roundUp(localquant) - elapsed, event);
467 ^cleanup.exit(event).yield;
470 cleanup.update(inevent);
472 delta = inevent.delta;
473 nextElapsed = elapsed + delta;
475 if (localmaxdur.notNil and: { nextElapsed.round(tolerance) >= localmaxdur }) {
476 inevent = inevent.copy;
477 inevent.put(\delta, localmaxdur - elapsed);
478 event = inevent.yield;
479 ^cleanup.exit(event);
481 elapsed = nextElapsed;
482 event = inevent.yield;
489 Pconst : FilterPattern {
490 var <>sum, <>tolerance;
491 *new { arg sum, pattern, tolerance=0.001;
492 ^super.new(pattern).sum_(sum).tolerance_(tolerance)
494 storeArgs { ^[sum,pattern,tolerance] }
496 embedInStream { arg inval;
497 var delta, elapsed = 0.0, nextElapsed, str=pattern.asStream,
498 localSum = sum.value(inval);
500 delta = str.next(inval);
502 (localSum - elapsed).yield;
505 nextElapsed = elapsed + delta;
506 if (nextElapsed.round(tolerance) >= localSum) {
507 (localSum - elapsed).yield;
510 elapsed = nextElapsed;
517 Plag : FilterPattern {
519 *new { arg lag, pattern;
520 ^super.new(pattern).lag_(lag)
522 storeArgs { ^[lag,pattern] }
523 embedInStream { arg event;
525 var stream = pattern.asStream;
526 var inevent = event.copy;
528 event = Event.silent(lag.value(event), event).yield;
531 inevent = stream.next(event);
532 if (inevent.isNil) { ^event};
533 event = inevent.yield;
539 Pbindf : FilterPattern {
541 *new { arg pattern ... pairs;
542 if (pairs.size.odd, { Error("Pbindf should have odd number of args.\n").throw });
543 ^super.new(pattern ? Event.default).patternpairs_(pairs)
545 storeArgs { ^[pattern] ++ patternpairs }
546 embedInStream { arg event;
549 var streampairs = patternpairs.copy;
550 var endval = streampairs.size - 1;
552 forBy (1, endval, 2) { arg i;
553 streampairs.put(i, streampairs[i].asStream);
555 eventStream = pattern.asStream;
559 eventStream.next(nil);
562 inevent = eventStream.next(event);
564 if (inevent.isNil) { ^event };
565 forBy (0, endval, 2) { arg i;
566 var name = streampairs[i];
567 var stream = streampairs[i+1];
568 var streamout = stream.next(inevent);
570 if (streamout.isNil) { ^event };
571 if (name.isSequenceableCollection) {
572 if (name.size > streamout.size) {
573 ("the pattern is not providing enough values to assign to the key set:" + name).warn;
576 name.do { arg key, i;
577 inevent.put(key, streamout[i]);
580 inevent.put(name, streamout);
584 event = yield(inevent);
590 Pstutter : FilterPattern {
592 *new { arg n, pattern;
593 ^super.new(pattern).n_(n)
595 storeArgs { ^[n,pattern] }
596 embedInStream { arg event;
599 var stream = pattern.asStream;
600 var nstream = n.asStream;
603 (inevent = stream.next(event)).notNil
605 if((nn = nstream.next(event)).notNil) {
607 event = inevent.copy.yield;
616 PdurStutter : Pstutter { // float streams
618 embedInStream { arg event;
620 var durs = pattern.asStream;
621 var stutts = n.asStream;
623 (dur = durs.next(event)).notNil
624 and: {(stut = stutts.next(event)).notNil}
626 if(stut > 0,{ // 0 skips it
641 Pclutch : FilterPattern {
643 *new { arg pattern, connected = true;
644 ^super.new(pattern).connected_(connected)
646 storeArgs { ^[ pattern, connected ] }
647 embedInStream { arg inval;
648 var clutchStream = connected.asStream;
649 var stream = pattern.asStream;
652 clutch = clutchStream.next(inval);
655 if(clutch === true or: { clutch == 1 }) {
656 outval = stream.next(inval);
657 if(outval.isNil) { ^inval };
658 inval = outval.yield;
660 outval ?? { outval = stream.next(inval) };
661 inval = outval.copy.yield;
667 Pwhile : FuncFilterPattern {
668 embedInStream {arg event;
669 while({ func.value(event) },{
670 event = pattern.embedInStream(event);
676 Pwrap : FilterPattern {
678 *new { arg pattern,lo,hi;
679 ^super.new(pattern).lo_(lo).hi_(hi)
682 storeArgs { ^[pattern,lo,hi] }
684 embedInStream { arg event;
686 var stream = pattern.asStream;
687 var loStr = lo.asStream;
688 var hiStr = hi.asStream;
691 loVal = loStr.next(event);
692 hiVal = hiStr.next(event);
693 next = stream.next(event);
694 next.notNil and: { loVal.notNil } and: { hiVal.notNil }
696 event = next.wrap(loVal, hiVal).yield
702 Ptrace : FilterPattern {
703 var <>key, printStream, prefix;
705 *new { arg pattern, key, printStream, prefix = "";
706 ^super.newCopyArgs(pattern, key, printStream, prefix)
708 storeArgs { ^[ pattern, key, printStream, prefix ] }
710 embedInStream { arg inval;
712 printStream = printStream ? Post;
714 collected = pattern.collect {|item| printStream << prefix << item << Char.nl; item }
716 func = { |val, item, prefix|
717 if(val.isKindOf(Function) and: { item.isKindOf(Environment) })
719 val = item.use { val.value };
720 printStream << prefix << val << "\t(printed function value)\n";
722 printStream << prefix << val << Char.nl;
725 collected = pattern.collect {|item|
726 var val = item.atAll(key.asArray).unbubble;
727 func.value(val, item, prefix);
731 ^collected.embedInStream(inval)
735 Pclump : FilterPattern {
737 *new { arg n, pattern;
738 ^super.new(pattern).n_(n)
740 embedInStream { arg event;
741 var next, list, nval;
742 var stream = pattern.asStream;
743 var nstream = n.asStream;
746 nval = nstream.next(event);
747 if (nval.isNil) { ^event };
749 next = stream.next(event);
751 if (list.size > 0) { event = list.yield };
754 list = list.add(next);
759 storeArgs { ^[ n, pattern ] }
763 embedInStream { arg event;
765 var stream = pattern.asStream;
766 var nstream = n.asStream;
768 next = stream.next(event);
769 nval = nstream.next(event);
770 next.notNil and: { nval.notNil };
772 if (next.isKindOf(SequenceableCollection)) {
773 next = next.flatten(nval);
774 next.do {|item| event = item.yield };
783 Pdiff : FilterPattern {
784 embedInStream { arg event;
785 var stream = pattern.asStream;
786 var next, prev = stream.next(event);
788 next = stream.next(event);
791 event = (next - prev).yield;
798 Prorate : FilterPattern {
801 *new { arg proportion, pattern=1;
802 ^super.new(pattern).proportion_(proportion)
805 embedInStream { arg inval;
807 var str = pattern.asStream;
808 var prop = proportion.asStream;
810 val = str.next(inval);
811 c = prop.next(inval);
812 if(val.isNil or: { c.isNil }) { ^inval };
813 if(c.isSequenceableCollection) {
815 inval = yield(el * val)
818 inval = yield(c * val);
819 inval = yield(1 - c * val);
823 storeArgs { ^[proportion,pattern] }
826 Pavaroh : FilterPattern {
828 var <>aroh, <>avaroh, <>stepsPerOctave;
829 *new { arg pattern, aroh, avaroh, stepsPerOctave=12;
830 ^super.newCopyArgs(pattern, aroh, avaroh, stepsPerOctave)
833 storeArgs { ^[pattern, aroh, avaroh, stepsPerOctave ] }
835 embedInStream { arg inval;
836 var me, melast = 0, scale;
837 var mestream = pattern.asStream;
838 var stepsStr = stepsPerOctave.asStream, stepVal;
841 stepVal = stepsStr.next(inval);
842 me = mestream.next(inval);
843 me.notNil and: { stepVal.notNil }
845 scale = if(me >= melast) { aroh } { avaroh };
847 inval = me.degreeToKey(scale, stepVal).yield