You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a potential approach for making lfos hopefully both simpler to use and more aesthetically in-line with chuck as a language. What if making an LFO was this simple?
Currently the Patch UGen is a little hacky and takes in a function arg as a string and does member func lookup in-chugin due to the lack of function pointers in chuck currently. But ideally, a Patch UGen will eventually look like this:
SinOsc sin => Pan2 pan => dac;
// Our LFO is fed into Patch's input...
SinOsc lfo => Patch p => blackhole;
1 => lfo.freq;
// ... where it then updates the pan position at every tick
p.connect(pan.pan);
1::eon => now;
This is great! And it works with any member function that is
defined in C++ (not chuck)
has the type fun Any someFun(float) or is a member variable that is a float
While this isn't completely general, I think it's good enough until chuck has a more robust type system.
However, this still feels kind of annoying to use (you have to remember to feed stuff into blackhole, p.connect has to be it's own separate line) and it doesn't really feel in-line with how chuck handles ugens in general. However, if the Patch ugen existed in this ideal form there's nothing stopping us from using some syntactic sugar to make this a much more intuitive experience.
The Syntactic Sugar
So in order to get this:
SinOsc s => dac;
SinOsc lfo => s.phase;
we basically need to have a translation step in the compiler to turn it into:
Doesn't seem too hard! The main hangup I see is when someone disconnects the ugen
lfo =< s.phase
This would have to somehow become
lfo =< lfo_patch;
Performance Questions
One concern is that not all parameters should be updated at signal rate, or it's recommended against because it's worse performance. In the simple case where it's literally just setting a variable the performance loss really isn't that bad and I don't think would be a bottleneck in most situations. However, when it's needed the control rate could be set like this:
SinOsc s => dac;
SinOsc lfo.rate(10::ms) => s.phase; // this would require constructors I think
Where rate sets how frequently the Patch ugen calls the update function
One weird quirk would be that if you tried to set lfo.rate later in the program, how would chuck know that it's specifically
pointing to s.phase
Edge Cases
SinOsc lfo => s.phase => s.freq
this should be allowed, but
SinOsc lfo => s.phase => NRev rev;
Probably shouldn't
Feature Dependencies
Function pointers
Constructors (not required, but would make for better ergonomics)
The text was updated successfully, but these errors were encountered:
yeah I guess one fully shaven yak version of this is
support for variable rate processing graphs (e.g. SinOsc lfo.rate(10::hz) => (scaling, etc) => ug.param;
support for arbitrary math in ugen chains (SinOsc s / 2 => dac;) or something
IMO its super useful to just have arbitrary math/expressions/functions instead of a bunch of one-off ugens for scaling/etc. because then you can easily do like dB, exponential, and various other transforms easily
also unlocks fun stuff like exponential FM
Could potentially do this via ugen syntactic sugar or via chugens
This is a potential approach for making lfos hopefully both simpler to use and more aesthetically in-line with chuck as a language. What if making an LFO was this simple?
This would ideally combine the ideas from the Patch chugin and @AndrewAday's tweens and signals proposal.
The Patch UGen
Currently the Patch UGen is a little hacky and takes in a function arg as a string and does member func lookup in-chugin due to the lack of function pointers in chuck currently. But ideally, a Patch UGen will eventually look like this:
This is great! And it works with any member function that is
fun Any someFun(float)
or is a member variable that is a floatWhile this isn't completely general, I think it's good enough until chuck has a more robust type system.
However, this still feels kind of annoying to use (you have to remember to feed stuff into blackhole, p.connect has to be it's own separate line) and it doesn't really feel in-line with how chuck handles ugens in general. However, if the Patch ugen existed in this ideal form there's nothing stopping us from using some syntactic sugar to make this a much more intuitive experience.
The Syntactic Sugar
So in order to get this:
we basically need to have a translation step in the compiler to turn it into:
Doesn't seem too hard! The main hangup I see is when someone disconnects the ugen
This would have to somehow become
Performance Questions
One concern is that not all parameters should be updated at signal rate, or it's recommended against because it's worse performance. In the simple case where it's literally just setting a variable the performance loss really isn't that bad and I don't think would be a bottleneck in most situations. However, when it's needed the control rate could be set like this:
Where rate sets how frequently the Patch ugen calls the update function
One weird quirk would be that if you tried to set lfo.rate later in the program, how would chuck know that it's specifically
pointing to
s.phase
Edge Cases
this should be allowed, but
Probably shouldn't
Feature Dependencies
The text was updated successfully, but these errors were encountered: