As a logic problem, I've been pondering for while how to replicate the behavior of [cyclone/speedlim], and... I have to admit defeat. As a long-time programmer, I don't like to admit defeat, but I just can't come up with an elegant way to do it with the available objects.
Either there is an elegant way to do it, or this is a particular problem that is difficult to formulate with boxes/wires.
In SC it looks like this:
(
~makeSpeedLim = { |time, action|
var state = \idle;
var value;
var gotNew = false;
{ |inval|
value = inval;
if(state == \idle) {
action.value(value);
gotNew = false;
state = \pending;
SystemClock.sched(time, {
if(gotNew) {
action.value(value);
};
state = \idle;
});
} {
gotNew = true;
};
inval
};
};
)
l = ~makeSpeedLim.(1.0, _.postln);
l.(100);
100 // only this one posting
fork {
l.(100);
0.2.wait;
l.(200);
};
100
200 // printed 1 sec later
fork {
l.(100);
2.0.wait;
l.(200);
};
100
200 // printed 2 sec later -- only these 2 posts
Two states:
- Idle: Upon receipt of a message, immediately pass it through, and also schedule a future check for a message arriving within the interval (and set pending state).
- Pending: Simply register that a new message has been received and wait for the scheduled check.
One might think "just use [delay]," but you can't only do that because if you send a single message in, while it's in idle state, then you want to pass a single message through and nothing else. So it would be necessary to suppress the delayed output, but un-suppress it if a message arrived during the delay period.
I guess I'm interested in this question because it's at the edge of my comfort with Max/Pd methodology -- I can almost see how to do it, but not quite. I have a feeling it would be much easier in Pd with built-in switch and gate objects, but these never made the cut, so I'm getting my head tied up in knots trying to manipulate multiple [spigot]s and that has a sour code smell.
hjh