latchgate~ ?

Psyko Logical's icon

I need a signal rate object that outputs 1 on a change from 0 to 1, and stays that way until it receives another 0 to 1 transition, at which point it resets back to 0.

I've been racking my brain trying to come up with an abstraction that does this, but just keep going in circles. I'm hoping there's some simple bit of trickery that I'm just not seeing at the moment.

Thanks for any help

andrea agostini's icon
Max Patch
Copy patch and select New From Clipboard in Max.

a solution I came out with...

cheers
aa

Tim Lloyd's icon
Max Patch
Copy patch and select New From Clipboard in Max.

Does this do what you need?

Psyko Logical's icon

Thanks guys, they both work great. [+=~] was the piece I was missing. I don't see it in the max help file. Another one of those objects I wish I'd known about a long time ago that just pops out of nowhere.

Thanks again.

andrea agostini's icon
Max Patch
Copy patch and select New From Clipboard in Max.

Just one remark:
in Tim's patch, the feedback loop introduces a latency of one signal vector. So, in fact what you obtain is that the 0-1 transition is sample accurate, but the 1-0 transition is not - it goes from 1 to 2, stays at 2 for one vector and then goes back to 0:

cheers
aa

Tim Lloyd's icon

That's true about my patch. Andrea's is definitely the better all-around solution. Just make sure that you reset the accumulator every so often, or it's possible for it to stop working completely ;) That would be pretty unlikely, but if you're using the abstraction with a fast flow of 0-1 transitions, it's possible that you could run in to rounding error issues after the patch has been running for a while. It depends on the context you're using it in though, so just make sure you reset [+=~ ] when it's not in use.

andrea agostini's icon

this is also true.

In fact, it would take many hours, even if the incoming samples are constantly switching between 0 and 1, to run into rounding error issues with integers. But yes, eventually the problem arises if +=~ is never reset.

I think Psyko's problem is a quite interesting one. I can't figure out a perfectly satisfying solution in Max (but this doesn't mean there isn't one, of course!) but the problem becomes trivial in C or Java... maybe it's time to write a small [flipflop~] external!

aa

Tim Lloyd's icon

It wouldn't necessarily take hours. At 44.1k it would only take 12 minutes of sample-rate flipping between 0 and 1 for rounding error to stop it working. That would be a worst-case scenario though and it isn't likely to happen so fast in an actual patch.

I think the only way to do it with standard objects would be to put the feedback-loop method into a poly~ with a signal vector size of 1. That would be fairly cpu-intensive, so an external would definitely be better! I've had the zipped-up SDK sitting on my desktop for a long time taunting me about my non-existant ability to write externals!

Tim Lloyd's icon

I just tried the poly~ approach and it didn't work, the feedback still makes the down-transition lag.

However, I just remembered Andrew Benson's [steps~ ] external, which does exactly what Psyko wants already. give it an argument of 2 and it does the job; I can't believe I didn't think of it before, I've been using his audio rate objects for ages for things like this *facepalm* :)

Eric Lyon's [el.mask~ 1 2] > [el.clickhold~ ] > [-~ 1 ] will also do the trick sample-accurately.

Psyko Logical's icon

Yeah, I played around with both patches for a little while this morning. Seems like you get a choice between an infinite counter or a feedback loop, no matter how you slice it.

Sticking a [%~ 2] at the end of Tim's version fixes the vector size latency on reset as far as output goes, but would still cause problems if you tried to retrigger it faster than the vs.

Neither drawback is really an issue for me right now, as I don't plan on triggering it fast enough to make it skip or often enough for it to lose count. But I'd still like a complete solution.

Looks like it might be time to write my 1st external. I'm surprised this hasn't come up more often. It's one of those things that seems simple until you actually try to do it.

Max Patch
Copy patch and select New From Clipboard in Max.

Here's what I finally settled on (for now):

Psyko Logical's icon

Where can I find these steps~?

Tim Lloyd's icon

Good idea with the modulo! Check my above post, there are already externals that do this that my brain withheld from me somehow :)

Psyko Logical's icon

Thanks a lot Tim. As always, you're a big help.

andrea agostini's icon

12 minutes, not hours... that's dramatically true - I miscalculated
I didn't know steps~ and I didn't think about Eric Lyon's things, thank you very much!
aa

Tj Shredder's icon
Max Patch
Copy patch and select New From Clipboard in Max.

Another solution without feedback is zerox~ the +=~ reset isn't a drama, it will count on from almost -inf and still switch back and forth...

Tim Lloyd's icon

A little test shows that rounding error is actually a problem for this type of patch. Above the value 16,777,621 the math no longer works as expected. You can keep accumulating above that value if you want, but you'll be accumulating by more than 1 at a time, and the patch won't keep flipping back and forth with the same behaviour.

Psyko Logical's icon

For anyone interested, I finally figured out how to do this with native objects. My 1st thought was to use [groove~] to advance a buffer~ one sample at a time and use it's looping capability to auto reset. Then I distilled this thought further and realized what I really needed was a phasor~ receiving a pulse multplied by 1/2 sample rate.

Max Patch
Copy patch and select New From Clipboard in Max.

Anyway, here's a patch that can replace [steps~] with native objects. Not exactly as light weight as a single object, but it gets the job done, and adds some functionality.

Tim Lloyd's icon

niice :)

props for beating the puzzle!

Andrew Benson's icon

Nice one. FWIW, I found that there were a lot of instances in dealing with signal-rate timing where a (very) simple external would do the job better than a mess of patching. That's what prompted me to write these objects (steps~,wait~,etc.). The source for them is really simple. If anybody has ideas to improve the current set, let me know.

Tj Shredder's icon

@Tim
You are correct, but its easy to reset the accumulation from time to time.
It might flip at the reset point, depends on the application if it matters or not...

Max Patch
Copy patch and select New From Clipboard in Max.