Two pre-existing gaps in the unary and binary operator units, surfaced while reviewing #12.
Demand-rate op variants are missing
scsynth implements _d calc variants for its op ugens (rrand_d, exprand_d, the arithmetic ops, unary thru_d, BinaryOpUGens.cpp and UnaryOpUGens.cpp), so an op ugen can sit inside a demand chain and is pulled per demand, propagating NaN end-of-stream. plyphon registers BinaryOpUGen and UnaryOpUGen as calc units only, so a demand-rate op ugen in a def fails to build with an unknown-unit or rate error. sclang emits these for expressions over demand ugens, for example Dseq([...]) + 1.
Scalar-rate op units re-run every block
scsynth runs a scalar-rate unit's calc once at ctor and holds the output. plyphon runs .ir units every block. For pure ops the result is identical, but the RNG-driven rrand/exprand ops are impure: a scalar rrand in plyphon redraws every control block (and advances the graph's shared stream while doing so), where scsynth draws once. sclang folds scalar rrand(a, b) in the language, so only hand-built defs hit this today, but any future impure scalar unit inherits the same divergence.
A general once-at-first-process convention for scalar units (or a baked-at-build value for scalar RNG ops) would close it.
Two pre-existing gaps in the unary and binary operator units, surfaced while reviewing #12.
Demand-rate op variants are missing
scsynth implements
_dcalc variants for its op ugens (rrand_d,exprand_d, the arithmetic ops, unarythru_d,BinaryOpUGens.cppandUnaryOpUGens.cpp), so an op ugen can sit inside a demand chain and is pulled per demand, propagating NaN end-of-stream. plyphon registersBinaryOpUGenandUnaryOpUGenas calc units only, so a demand-rate op ugen in a def fails to build with an unknown-unit or rate error. sclang emits these for expressions over demand ugens, for exampleDseq([...]) + 1.Scalar-rate op units re-run every block
scsynth runs a scalar-rate unit's calc once at ctor and holds the output. plyphon runs
.irunits every block. For pure ops the result is identical, but the RNG-drivenrrand/exprandops are impure: a scalarrrandin plyphon redraws every control block (and advances the graph's shared stream while doing so), where scsynth draws once. sclang folds scalarrrand(a, b)in the language, so only hand-built defs hit this today, but any future impure scalar unit inherits the same divergence.A general once-at-first-process convention for scalar units (or a baked-at-build value for scalar RNG ops) would close it.