Last active
February 8, 2022 22:42
-
-
Save scztt/dcd493c32ac772716cb905cf4eb635b4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PparStream : Stream { | |
var <>initStreamAction, <>endStreamAction; | |
var priorityQ, <now; | |
var <injectFunc; | |
*initClass { | |
Class.initClassTree(Event); | |
Event.addEventType(\fork, { | |
var event, outerEvent, recursionLevel, instrument, embeddingLevel, freq, rest; | |
var args, defaults, timingOffset, sustain; | |
var size, pattern; | |
pattern = ~pattern ?? { ~instrument }; | |
if(pattern.notNil) { | |
// preserve information from outer pattern, but not delta. | |
if (pattern.isKindOf(Function)) { | |
defaults = pattern.def.prototypeFrame; | |
args = pattern.def.argNames.collect { | |
|name, i| | |
currentEnvironment[name].value ?? { defaults[i] } | |
}; | |
pattern = pattern.value(*args); | |
}; | |
if(~transparency ? true) { | |
outerEvent = currentEnvironment.copy; | |
outerEvent.putPairs( | |
[ | |
\instrument, \pattern, \type, | |
\parentType, \addToCleanup, \removeFromCleanup, \sustain, \legato | |
].collect([_, nil]).flatten | |
) | |
} { | |
outerEvent = Event.default.copy; | |
}; | |
outerEvent.put(\delta, nil); // block delta modification by Ppar | |
outerEvent.put(\instrument, ~synthDef); | |
if (~flop ?? { false }) { | |
outerEvent = outerEvent.asPairs.flop.collect(_.asEvent); | |
outerEvent.do(_.parent_(currentEnvironment.parent)); | |
} { | |
outerEvent = [outerEvent] | |
}; | |
outerEvent.do { | |
|outerEvent, i| | |
var innerPattern, timingOffset, gatePattern, localPattern; | |
outerEvent.use { | |
innerPattern = pattern; | |
if (innerPattern.isKindOf(Symbol)) { | |
innerPattern = Pdef(pattern); | |
}; | |
if (outerEvent.size > 1) { | |
innerPattern = innerPattern.copy; | |
}; | |
innerPattern = innerPattern.value; | |
if (innerPattern.isKindOf(Event)) { | |
Error("Event patterns must be wrapped in a Ref or a function when passed in as an \instrument argument").throw; | |
}; | |
if (innerPattern.isKindOf(PatternProxy)) { | |
innerPattern = innerPattern.pattern; // optimization. outer pattern takes care for replacement | |
}; | |
if (innerPattern.notNil) { | |
timingOffset = (~timingOffset.value ? 0); | |
gatePattern = (~gatePattern.value ? true); | |
// not sure why we DON'T need to account for positive timingOffset here, | |
// but if we do it breaks.... | |
if (gatePattern) { | |
innerPattern = innerPattern.finDur(~sustain.value - timingOffset.min(0)); | |
}; | |
innerPattern = Pevent(innerPattern, outerEvent); | |
if (timingOffset < 0) { | |
innerPattern.fastForward(timingOffset.neg, 0, outerEvent); | |
}; | |
currentEnvironment['injectStream'].value(timingOffset, innerPattern, outerEvent) | |
} | |
} | |
} | |
} | |
}, Event.parentEvents.default.copy.putAll((legato:1))); | |
} | |
*new { | |
^super.new.init | |
} | |
init { | |
priorityQ = PriorityQueue(); | |
now = 0; | |
injectFunc = { |delta, stream, inval| this.injectStream(delta, stream, inval) }; | |
} | |
reset { | |
this.init(); | |
} | |
injectStream { | |
|delta, stream, inval| | |
stream = stream.asStream; | |
initStreamAction !? { | |
stream = initStreamAction.value(stream, inval).asStream | |
}; | |
priorityQ.put(now + delta, stream); | |
^stream; | |
} | |
embedInStream { | |
|inval| | |
var stream, nextTime, outval; | |
now = 0; | |
while { priorityQ.notEmpty } { | |
nextTime = priorityQ.topPriority; | |
if (nextTime > now) { | |
inval = Event.silent(nextTime - now, inval).yield; | |
now = nextTime; | |
} { | |
stream = priorityQ.pop; | |
outval = stream.next(inval).asEvent; | |
if (outval.notNil) { | |
// requeue stream | |
priorityQ.put(now + outval.delta, stream); | |
outval[\delta] = 0; | |
outval['injectStream'] = injectFunc; | |
inval = outval.yield; | |
} { | |
endStreamAction.value(stream, inval); | |
} | |
}; | |
}; | |
^inval | |
} | |
} | |
Ppar2 : ListPattern { | |
var <>initStreamAction, <>endStreamAction; | |
embedInStream { | |
|inval| | |
var parStream = PparStream() | |
.initStreamAction_(initStreamAction) | |
.endStreamAction_(endStreamAction); | |
repeats.value(inval).do({ | |
list.do(parStream.injectStream(0, _, inval)); | |
parStream.embedInStream(inval); | |
parStream.reset(); | |
}) | |
} | |
} | |
Pb : Ppar2 { | |
*new { | |
|...keysValues| | |
^super.new([ | |
Pbind( | |
*keysValues | |
) | |
]) | |
} | |
} | |
+Ppar { | |
*new { | |
|list, repeats=1| | |
^Ppar2.new(list, repeats); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment