• ### fexpr~ for a flip-flop toggle but getting only 0s

I was just pondering a signal-rate flip-flop toggle.

The "easy way" is a pulse counter, modulo 2 (left side). This works, but will eventually overflow.

Then I thought... if you have a "true" signal `a`, and a "false" signal `b`, and a condition signal `x` (0 or 1), then `if(x, a, b)` == `(a-b) * x + b` (algebraic reduction of `a*x + (b * (1-x))` = `ax + b - bx`).

If the "true" signal flips the last output -- `a = 1 - y1[-1]` -- and the false signal just outputs the previous value -- `b = y1[-1]` -- then:

((1 - \$y1[-1]) - \$y1[-1]) * \$x1[0] + \$y1[-1]
(1 - (2 * \$y1[-1])) * \$x1[0] + \$y1[-1]

... which does satisfy the cases:

• if \$x1[0] == 0, the first term disappears and it outputs the previous sample, ok.
• if \$x1[0] == 1:
• if \$y1[-1] == 0 (as it is initially), then: (1 - (2*0)) * 1 + 0 == 1, ok.
• if \$y1[-1] == 1, then: (1 - (2*1)) * 1 + 1 == -1 + 1 == 0, ok.

So, in theory, that should work in fexpr~. But I only get zeros.

23-0224-toggle-ff.pd

I can imagine only a couple of possibilities. One is that I misunderstood what is \$y1[-1]. The other is that there might be a bug.

(Yes, I know fexpr~ is slow... but it should be able to do this, no...?)

Just before posting, I tried replacing \$x1[0] with \$x1[-1] and... it starts toggling! Uh... why? In theory I should be taking the current trigger sample vs the previous output sample, which is what I wrote, but it only works to take the previous trigger sample...? (Point being, if I did this in a class, I couldn't explain why \$x1[0] is bad while \$x1[-1] is good. These are all deterministic operations, so it should be explainable.)

EDIT: Checking the tables' list views, I found that the fexpr~ with \$x1[-1] is one sample late... confirming that \$x1[0] is theoretically correct. So I'm puzzled why it fails.

EDIT EDIT: After quitting and relaunching Pd, \$x1[0] works soo... never mind... weird.

hjh

• Posts 15 | Views 2618

Work in progress : FCPD a FreeCAD PureData connexion

• @FFW It's different behavior. When you feed an osc~ into a flip flop toggle, the toggle will change state once per cycle. The comparator approach will change state twice per cycle.

When following triggers in this way, the only thing it should care about is the moment when it was zero-or-negative and becomes positive. The input signal can go negative again and there won't be another trigger until it goes positive. This could be useful for audio-rate thresholds for instance. A comparator changes output state when the input goes negative, so it isn't the same.

hjh

• Ok, so you improved [threshold~ 0.5 0 0.5 0] to ouput audio.

Work in progress : FCPD a FreeCAD PureData connexion

• @FFW I think it's a little more than that--the output frequency of @ddw_music's flipflop is half that of the hypothetical [threshold~] with audio output, am I mistaken?

• @jameslo is correct. This is not "flip and flop within one cycle."

Perhaps some of the confusion is that Pd signal processing doesn't do a lot with this definition of a trigger (whereas, it's everywhere in SuperCollider -- which also natively has a ToggleFF, what set this off was, "how to do ToggleFF in Pd/Max?").

Maybe this patch illustrates better:

The [threshold~] idea is that it flips up when the wave goes above 0, and flips down when it goes below 0. But the toggle idea is that it changes state only at the shown triggers.

A use case would be, say, volume tracking, where you want to cross fade between a couple of audio sources for every amplitude trigger. Audio source A should turn on at the first trigger, and off at the second trigger. You don't want audio source A to choose an arbitrary point in between the two triggers to switch off.

hjh

• @jameslo said:

@FFW I think it's a little more than that--the output frequency of @ddw_music's flipflop is half that of the hypothetical [threshold~] with audio output, am I mistaken?

[threshold~] left outlet trigger only at rising edge and right outlet only at falling ones so the left frequency is the same as in ddw_music abstraction.
This patch acts at buffer size accuracy:

Work in progress : FCPD a FreeCAD PureData connexion

• @FFW Oh I see, you're focusing on the trigger detection, in which case I agree. But @ddw_music is trying to do that AND frequency division, which you're doing in control domain with a toggle. That's why he's calling it a "flipflop".

• OK, right, if you're using one [threshold~] outlet to trigger the toggling operation, then it would be the same.

Would be nice if there were a signal-rate threshold~ (basically a Schmitt trigger).

hjh

• @ddw_music Does this fit the bill? You prob wanted an external.
threshold~~.pd
threshold~~-help.pd

• @jameslo said:

@ddw_music Does this fit the bill? You prob wanted an external.

Busy with other things yesterday... so that's: signal >= thresh = on and signal <... 0 for off? A Schmitt trigger has two thresholds. Anyway I might play with it a bit later.

hjh

• @ddw_music No, as configured the threshold is either higher by 0.25 or lower by 0.25 dependent on whether the last comparison result was less than or greater than respectively. It's just a translation of an op-amp comparator with hysteresis which is what first pops into my head when anyone writes "Schmitt trigger". The only exception is when it first starts up--in that case the threshold is unmodified.

Edit: I thought of a way to use [rpole~] as an audio rate toggle that doesn't have that overflow problem. Not sure why that delay is necessary though.
ddw-music ff.pd

Edit 2: I figured out what the delay is doing. [rzero~]'s state = 0 when the patch is loaded. But [osc~] starts at 1, so the first sample through [clip~ -1 1] is -1. And that means that first sample out of [rzero~] is -1, so that the right inlet of [rpole~] sees 0, and therefore [rpole~] forgets the state I was trying to initialize it to. A less hacky solution is to set both [rpole~] and [rzero~] to 1 on [loadbang]. Whew!

• @jameslo said:

@ddw_music No, as configured the threshold is either higher by 0.25 or lower by 0.25 dependent on whether the last comparison result was less than or greater than respectively. It's just a translation of an op-amp comparator with hysteresis which is what first pops into my head when anyone writes "Schmitt trigger".

My exposure to the concept is by way of (misspelled) `Schmidt.kr(signal, lo, hi)` in SC -- I'll admit that I didn't get it via engineering. If the threshold is changing then that would do it, yes.

That is kinda cool about rpole~ for flip-flop. In my abstraction pack, I ended up generalizing it to n states rather than just 2.

hjh

• @ddw_music As a terrible speller myself I try to remember not to make fun of other's bad spelling. But "Schmidt" is funny.

RE your first one with the potentially overflowing [rpole~], I remember addressing an issue like that by occasionally (once every three minutes?) resetting [rpole~] to a lower equivalent value. In your case you could [snapshot~] the output of [wrap~} and use the value to [set \$1( [rpole~].

• @jameslo said:

RE your first one with the potentially overflowing [rpole~], I remember addressing an issue like that by occasionally (once every three minutes?) resetting [rpole~] to a lower equivalent value. In your case you could [snapshot~] the output of [wrap~} and use the value to [set \$1( [rpole~].

Sure, yeah, that's a good workaround... I'd almost thought of that but didn't quite go that far. (Anyway by my estimation it'll last for well over a day, unless it's being triggered a few hundred times per second.)

hjh

Posts 15 | Views 2618
Internal error.

Oops! Looks like something went wrong!