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, inval));
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, inval).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 };
101 func.value(outval, 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 = EventStreamCleanup.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 cleanup = EventStreamCleanup.new;
157 var val, inevent, filteredEvent;
158 var valStream = value.asStream;
159 var evtStream = pattern.asStream;
162 val = valStream.next(event);
163 if (val.isNil or: event.isNil) {
167 filteredEvent = this.filterEvent(event, val);
169 inevent = evtStream.next(filteredEvent);
170 if (inevent.isNil) { ^cleanup.exit(event) };
171 cleanup.update(inevent);
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;
200 var cleanup = EventStreamCleanup.new;
202 var valStream = value.asStream;
203 var evtStream = pattern.asStream;
206 inEvent = evtStream.next(event);
207 // if (event.isNil) { ^nil.yield };
208 if (inEvent.isNil) { ^cleanup.exit(event) };
209 val = valStream.next(inEvent);
210 if (val.isNil) { ^cleanup.exit(event) };
212 this.filterEvent(inEvent, val);
213 cleanup.update(inEvent);
214 event = inEvent.yield;
221 filterEvent { arg event, val;
222 ^event[name] = event[name] + val;
227 filterEvent { arg event, val;
228 ^event[name] = event[name] * val;
234 embedInStream { arg event;
235 var evtStream, val, inevent;
236 var valStream = value.iter;
239 val = valStream.next(event);
242 evtStream = pattern.asStream;
244 inevent = evtStream.next(event);
245 if(event.isNil) { ^nil.yield };
248 this.filterEvent(inevent, val);
249 event = inevent.yield;
257 filterEvent { arg event, val;
258 ^event[name] = event[name] + val;
263 filterEvent { arg event, val;
264 ^event[name] = event[name] * val;
269 Pstretch : FilterPattern {
271 *new { arg value, pattern;
272 ^super.new(pattern).value_(value)
274 storeArgs { ^[value,pattern] }
275 embedInStream { arg event;
276 var cleanup = EventStreamCleanup.new;
279 var valStream = value.asStream;
280 var evtStream = pattern.asStream;
283 inevent = evtStream.next(event).asEvent;
284 if (inevent.isNil) { ^cleanup.exit(event) };
285 val = valStream.next(inevent);
286 if (val.isNil) { ^cleanup.exit(event) };
288 delta = event[\delta];
290 inevent[\delta] = delta * val;
292 inevent[\dur] = inevent[\dur] * val;
293 cleanup.update(inevent);
294 event = yield(inevent);
301 Pstretchp : Pstretch {
303 embedInStream { arg event;
304 var evtStream, val, inevent, delta;
305 var valStream = value.asStream;
307 val = valStream.next(event).asEvent;
310 evtStream = pattern.asStream;
312 inevent = evtStream.next(event);
313 // if(event.isNil) { ^nil.yield };
316 delta = inevent[\delta];
318 inevent[\delta] = delta * val;
320 inevent[\dur] = inevent[\dur] * val;
321 event = inevent.yield;
329 // needs testing - hjh
330 Pplayer : FilterPattern {
332 *new { arg playerPattern, subPattern;
333 ^super.newCopyArgs(playerPattern, subPattern)
335 storeArgs { ^[ pattern, subPattern ] }
336 embedInStream { arg event;
338 var playerStream = pattern.asStream;
339 var stream = subPattern.asStream;
341 inevent = stream.next(event);
342 if (inevent.isNil) { ^event };
343 player = playerStream.next(event);
344 if (player.isNil) { ^event };
345 inevent.parent = player.event;
346 event = yield(inevent);
349 // backward compatibility: unnecessary var playerPattern was removed
350 playerPattern { ^pattern }
351 playerPattern_ { |playerPattern| pattern = playerPattern }
356 Pdrop : FilterPattern {
358 *new { arg count, pattern;
359 ^super.new(pattern).count_(count)
361 storeArgs { ^[count,pattern] }
362 embedInStream { arg event;
364 var stream = pattern.asStream;
366 count.value(event).do {
367 inevent = stream.next(event);
368 if (inevent.isNil, { ^event });
371 inevent = stream.next(event);
372 if (inevent.isNil, { ^event });
373 event = inevent.yield;
378 Pfin : FilterPattern {
380 *new { arg count, pattern;
381 ^super.new(pattern).count_(count)
383 storeArgs { ^[count,pattern] }
384 asStream { | cleanup| ^Routine({ arg inval; this.embedInStream(inval, cleanup) }) }
386 embedInStream { arg event, cleanup;
388 var stream = pattern.asStream;
389 cleanup ?? { cleanup = EventStreamCleanup.new };
390 count.value(event).do({
391 inevent = stream.next(event) ?? { ^event };
392 cleanup.update(inevent);
393 event = inevent.yield;
401 // it is not correct to call stream.next(nil) on a value stream
402 // but there is no good way to distinguish in Pfin so we need a subclass
403 // might be ok to deprecate this now
406 embedInStream { arg event;
408 var stream = pattern.asStream;
410 count.value(event).do({
411 inevent = stream.next(event);
412 if (inevent.isNil, { ^event });
413 event = inevent.yield;
419 Pfindur : FilterPattern {
420 var <>dur, <>tolerance;
421 *new { arg dur, pattern, tolerance = 0.001;
422 ^super.new(pattern).dur_(dur).tolerance_(tolerance)
424 storeArgs { ^[dur,pattern,tolerance] }
425 asStream { | cleanup| ^Routine({ arg inval; this.embedInStream(inval, cleanup) }) }
427 embedInStream { arg event, cleanup;
428 var item, delta, elapsed = 0.0, nextElapsed, inevent,
429 localdur = dur.value(event);
430 var stream = pattern.asStream;
432 cleanup ?? { cleanup = EventStreamCleanup.new };
434 inevent = stream.next(event).asEvent ?? { ^event };
435 cleanup.update(inevent);
436 delta = inevent.delta;
437 nextElapsed = elapsed + delta;
438 if (nextElapsed.roundUp(tolerance) >= localdur) {
439 // must always copy an event before altering it.
440 // fix delta time and yield to play the event.
441 inevent = inevent.copy.put(\delta, localdur - elapsed).yield;
442 ^cleanup.exit(inevent);
445 elapsed = nextElapsed;
446 event = inevent.yield;
452 Psync : FilterPattern {
453 var <>quant, <>maxdur, <>tolerance;
454 *new { arg pattern, quant, maxdur, tolerance = 0.001;
455 ^super.new(pattern).quant_(quant).maxdur_(maxdur).tolerance_(tolerance)
457 storeArgs { ^[pattern,quant,maxdur,tolerance] }
459 embedInStream { arg event;
460 var item, stream, delta, elapsed = 0.0, nextElapsed, clock, inevent;
461 var localquant = quant.value(event), localmaxdur = maxdur.value(event);
462 var cleanup = EventStreamCleanup.new;
464 stream = pattern.asStream;
467 inevent = stream.next(event).asEvent;
469 if(localquant.notNil) {
470 event = Event.silent(elapsed.roundUp(localquant) - elapsed, event);
471 ^cleanup.exit(event).yield;
474 cleanup.update(inevent);
476 delta = inevent.delta;
477 nextElapsed = elapsed + delta;
479 if (localmaxdur.notNil and: { nextElapsed.round(tolerance) >= localmaxdur }) {
480 inevent = inevent.copy;
481 inevent.put(\delta, localmaxdur - elapsed);
482 event = inevent.yield;
483 ^cleanup.exit(event);
485 elapsed = nextElapsed;
486 event = inevent.yield;
493 Pconst : FilterPattern {
494 var <>sum, <>tolerance;
495 *new { arg sum, pattern, tolerance=0.001;
496 ^super.new(pattern).sum_(sum).tolerance_(tolerance)
498 storeArgs { ^[sum,pattern,tolerance] }
500 embedInStream { arg inval;
501 var delta, elapsed = 0.0, nextElapsed, str=pattern.asStream,
502 localSum = sum.value(inval);
504 delta = str.next(inval);
506 (localSum - elapsed).yield;
509 nextElapsed = elapsed + delta;
510 if (nextElapsed.round(tolerance) >= localSum) {
511 (localSum - elapsed).yield;
514 elapsed = nextElapsed;
521 Plag : FilterPattern {
523 *new { arg lag, pattern;
524 ^super.new(pattern).lag_(lag)
526 storeArgs { ^[lag,pattern] }
527 embedInStream { arg event;
529 var stream = pattern.asStream;
530 var inevent = event.copy;
532 event = Event.silent(lag.value(event), event).yield;
535 inevent = stream.next(event);
536 if (inevent.isNil) { ^event};
537 event = inevent.yield;
543 Pbindf : FilterPattern {
545 *new { arg pattern ... pairs;
546 if (pairs.size.odd, { Error("Pbindf should have odd number of args.\n").throw });
547 ^super.new(pattern ? Event.default).patternpairs_(pairs)
549 storeArgs { ^[pattern] ++ patternpairs }
550 embedInStream { arg event;
551 var cleanup = EventStreamCleanup.new;
554 var streampairs = patternpairs.copy;
555 var endval = streampairs.size - 1;
557 forBy (1, endval, 2) { arg i;
558 streampairs.put(i, streampairs[i].asStream);
560 eventStream = pattern.asStream;
563 outevent = eventStream.next(event);
564 if (outevent.isNil) { ^cleanup.exit(event) };
566 forBy (0, endval, 2) { arg i;
567 var name = streampairs[i];
568 var stream = streampairs[i+1];
569 var streamout = stream.next(outevent);
571 if (streamout.isNil) { ^cleanup.exit(event) };
572 if (name.isSequenceableCollection) {
573 if (name.size > streamout.size) {
574 ("the pattern is not providing enough values to assign to the key set:" + name).warn;
577 name.do { arg key, i;
578 outevent.put(key, streamout[i]);
581 outevent.put(name, streamout);
585 cleanup.update(outevent);
586 event = yield(outevent);
592 Pstutter : FilterPattern {
594 *new { arg n, pattern;
595 ^super.new(pattern).n_(n)
597 storeArgs { ^[n,pattern] }
598 embedInStream { arg event;
601 var stream = pattern.asStream;
602 var nstream = n.asStream;
605 (inevent = stream.next(event)).notNil
607 if((nn = nstream.next(event)).notNil) {
609 event = inevent.copy.yield;
618 PdurStutter : Pstutter { // float streams
620 embedInStream { arg event;
622 var durs = pattern.asStream;
623 var stutts = n.asStream;
625 (dur = durs.next(event)).notNil
626 and: {(stut = stutts.next(event)).notNil}
628 if(stut > 0,{ // 0 skips it
643 Pclutch : FilterPattern {
645 *new { arg pattern, connected = true;
646 ^super.new(pattern).connected_(connected)
648 storeArgs { ^[ pattern, connected ] }
649 embedInStream { arg inval;
650 var clutchStream = connected.asStream;
651 var stream = pattern.asStream;
654 clutch = clutchStream.next(inval);
657 if(clutch === true or: { clutch == 1 }) {
658 outval = stream.next(inval);
659 if(outval.isNil) { ^inval };
660 inval = outval.yield;
662 outval ?? { outval = stream.next(inval) };
663 inval = outval.copy.yield;
669 Pwhile : FuncFilterPattern {
670 embedInStream {arg event;
671 while({ func.value(event) },{
672 event = pattern.embedInStream(event);
678 Pwrap : FilterPattern {
680 *new { arg pattern,lo,hi;
681 ^super.new(pattern).lo_(lo).hi_(hi)
684 storeArgs { ^[pattern,lo,hi] }
686 embedInStream { arg event;
688 var stream = pattern.asStream;
689 var loStr = lo.asStream;
690 var hiStr = hi.asStream;
693 loVal = loStr.next(event);
694 hiVal = hiStr.next(event);
695 next = stream.next(event);
696 next.notNil and: { loVal.notNil } and: { hiVal.notNil }
698 event = next.wrap(loVal, hiVal).yield
704 Ptrace : FilterPattern {
705 var <>key, printStream, prefix;
707 *new { arg pattern, key, printStream, prefix = "";
708 ^super.newCopyArgs(pattern, key, printStream, prefix)
710 storeArgs { ^[ pattern, key, printStream, prefix ] }
712 embedInStream { arg inval;
714 printStream = printStream ? Post;
716 collected = pattern.collect {|item| printStream << prefix << item << Char.nl; item }
718 func = { |val, item, prefix|
719 if(val.isKindOf(Function) and: { item.isKindOf(Environment) })
721 val = item.use { val.value };
722 printStream << prefix << val << "\t(printed function value)\n";
724 printStream << prefix << val << Char.nl;
727 collected = pattern.collect {|item|
728 var val = item.atAll(key.asArray).unbubble;
729 func.value(val, item, prefix);
733 ^collected.embedInStream(inval)
737 Pclump : FilterPattern {
739 *new { arg n, pattern;
740 ^super.new(pattern).n_(n)
742 embedInStream { arg event;
743 var next, list, nval;
744 var stream = pattern.asStream;
745 var nstream = n.asStream;
748 nval = nstream.next(event);
749 if (nval.isNil) { ^event };
751 next = stream.next(event);
753 if (list.size > 0) { event = list.yield };
756 list = list.add(next);
761 storeArgs { ^[ n, pattern ] }
765 embedInStream { arg event;
767 var stream = pattern.asStream;
768 var nstream = n.asStream;
770 next = stream.next(event);
771 nval = nstream.next(event);
772 next.notNil and: { nval.notNil };
774 if (next.isKindOf(SequenceableCollection)) {
775 next = next.flatten(nval);
776 next.do {|item| event = item.yield };
785 Pdiff : FilterPattern {
786 embedInStream { arg event;
787 var stream = pattern.asStream;
788 var next, prev = stream.next(event);
790 next = stream.next(event);
793 event = (next - prev).yield;
800 Prorate : FilterPattern {
803 *new { arg proportion, pattern=1;
804 ^super.new(pattern).proportion_(proportion)
807 embedInStream { arg inval;
809 var str = pattern.asStream;
810 var prop = proportion.asStream;
812 val = str.next(inval);
813 c = prop.next(inval);
814 if(val.isNil or: { c.isNil }) { ^inval };
815 if(c.isSequenceableCollection) {
817 inval = yield(el * val)
820 inval = yield(c * val);
821 inval = yield(1 - c * val);
825 storeArgs { ^[proportion,pattern] }
828 Pavaroh : FilterPattern {
830 var <>aroh, <>avaroh, <>stepsPerOctave;
831 *new { arg pattern, aroh, avaroh, stepsPerOctave=12;
832 ^super.newCopyArgs(pattern, aroh, avaroh, stepsPerOctave)
835 storeArgs { ^[pattern, aroh, avaroh, stepsPerOctave ] }
837 embedInStream { arg inval;
838 var me, melast = 0, scale;
839 var mestream = pattern.asStream;
840 var stepsStr = stepsPerOctave.asStream, stepVal;
843 stepVal = stepsStr.next(inval);
844 me = mestream.next(inval);
845 me.notNil and: { stepVal.notNil }
847 scale = if(me >= melast) { aroh } { avaroh };
849 inval = me.degreeToKey(scale, stepVal).yield