SynthMaker

How to test for reverse triggers?

Archive · 2011 12 old posts

From the original SynthMaker forum (2004–2014), with its members’ names and dates.

infuzion ·

In page 6 of Trog's Trigger Tutorial, "reverse" triggers is explained (red arrows). How can we test & count those reverse triggers please? TIA

attic ·

I also would like to know how to do this.

trogluddite ·

A reverse trigger counter seems to be out of the question - i would have loved to have included one in the tutorial examples. Because reverse triggers (and the responses to them) never generate any new forward triggers, there is never a way to update a counter or display. If the display is updated some other way (e.g.tickers), then the display itself will request updates. Just like quantum physics/chaos theory, the very act of doing a test will always change the results.

However there is one little trick I have discovered - though use at your own risk, as I cannot guarantee 100% reliability, and it is rather limited in application...

If you change the index input to the selector, nothing happens due to the trigger blocker - however, if you click the trigger (causing the add to request the selector output value), you will see that the selector graphic gets updated to show the correct path, but will always output zero so as not to change any values. The selection index can be made to change automatically from a 'ticked' loop counter etc. so that the the movement of the graphic gives some indication of the rate of reverse triggers - but there's still no way to count them, and you always need the selector on screen to see what's happening.

Take care when interpreting the results - in the example above, the add would send a reverse trigger to the selector if; (a) the add itself receives a reverse trigger at its output, OR (b) the add is getting a forward trigger from its other input - there's no way to distinguish the two cases unless your schematic has S&H or Blockers that rule out one case or the other.

Hope that helps

PS) I am thoroughly bogged down in alpha testing and de-bugging of a monster schematic at the moment, but I will be adding to the tutorials once I have a release candidate.

infuzion ·

Thanks for that trick Trog, but I still don't understand it yet :/

trogluddite ·

infuzion wrote: Thanks for that trick Trog, but I still don't understand it yet :/

Triggers are weird like that - the more you get to know them, the more if feels like you don't know them at all! I've had a few hairy moments when trying to write the tutorials when contradictions in my own explanations have made me realise that I must have missed something.

I asked Malc for a better explanation back when we were having 'teething troubles' with SM2.0 - he said that we should assume that the trigger system 'just works', and that we had no need to know any more than that! Judging from the response to the tutorials, I think he might want to re-consider his position!

Anyhow, here a better example of the 'reverse trigger detector' technique, which is a better demonstration of both it's usefulness and weakness.

Apart from a teeny toggle logic for the GUI flashing, the schematic has virtually no forward triggers apart from to a GUI ReDraw inside the 'Graphics Thingy' - and even if there were any, the zillions of trigger blockers would kill them anyway. You can easily see that the looper/selector 'reverse trigger detector' is producing no output triggers at all - yet you can see the selector 'pointer' moving. The ReDraw is creating flurries of reverse triggers from the GUI primitives inside the 'Thingy' which are flowing backwards all the way to the 'detector', returnng data values back (forward ?!?!) to the GUI as they go. So the selector is 'wobbling' purely in response to reverse triggers.

But, you can also see that the 'detector' is not totally reliable - sometimes the triggers arrive while the selector index is at the same value, so no change is seen - by juggling ticker/timer arrangements it can even appear that there are no reverse triggers, even though they must be there for the schematic to work. That's why the selector index counter uses a Timer (rather than Ticker) - I always test at several different rates just to be sure I'm not missing something.

Note also that the 'colour selector' inside the flasher doesn't seem to move, even though the value must be changing - no idea why, maybe something to do with the way that the editing workspace gets refreshed, or because it is colours rather than numbers.

attic ·

Thanks for this.

infuzion ·

I think I'm starting to get it now! With your tests, seems that placing a Trigger Blocker after a Sample & Hold is redundant & is not needed? & seems the Switch (primitives with the L in middle) also block backwards triggers behind them?

trogluddite ·

infuzion wrote: Switch (primitives with the L in middle) also block backwards triggers behind them?

Yes, that's right. I think that's one big thing that is sorely missing from the tutorials - there are quite a few primitives that for one reason or another do not pass reverse triggers. Slowly but surely, I am trying to work out what the 'exceptions to the rule' are...

infuzion wrote: With your tests, seems that placing a Trigger Blocker after a Sample & Hold is redundant & is not needed?

That depends on the situation - a S&H blocks only backwards triggers, a blocker blocks only forwards triggers. A S&H and blocker 'back to back' can sometimes be useful if you want to block both. That might seem a weird thing to want to do at first glance, but it creates a little 'buffer' - the parts of the schematic either side of the 'buffer' will then have their own independent trigger 'zones'. In fact, it's when using something like your 'Heartbeat Trigger' system to control ReDraws that this can be most useful...

...the 'Heartbeat' is deliberately very slow - for super economical redraws!

This example relies on two things...

1) When there is a ReDraw, we can safely assume that the input value is already correct - it doesn't need re-calculating when the GUI is ReDrawn. So there is a S&H at the module input to prevent 'backwards triggers' from escaping into the rest of the schematic and causing unnecessary processing of the input value.

2) The draw area for the circle only needs calculating when the screen is ReDrawn - it would be wasteful to work out the area for frames that are not displayed. So the S&H is followed by a trigger blocker. When there is a ReDraw, the 'Filled Ellipse' will send out a reverse trigger to request the value from the S&H so that the area can be worked out.

When a ReDraw happens, every GUI element within the area will send backwards triggers - and that can include primitives in completely different modules if they happen to have a GUI that overlaps with the area to be re-drawn. For example, if you have a frequency plot overlaid on a vector 'grid' background, every change in the frequency graph could cause the vector background to be completely re-calculated from scratch, even if it hasn't changed. (This is partly why 'bitmap buffers' are so useful for saving GUI CPU).

This is why the next part of the tutorials will be about the GUI components, as they can create lot of backwards triggers - sometimes in quite unexpected places!

infuzion ·

Thanks for the awesome example troggie! Here is a test & some more reduction (I think could improve CPU & load time?)

trogluddite wrote: This is why the next part of the tutorials will be about the GUI components, as they can create lot of backwards triggers - sometimes in quite unexpected places!

Yes, Area maths are very trigger-happy for sure. Looking forward to your new installment!

trogluddite ·

infuzion wrote: (I think could improve CPU & load time?)

Oh yes, that looks good - it should pre-calculate the 'half window size' 'contants' only once when the MGUI is resized, and four less Area calculations at load time! (why four? - see below)

infuzion wrote: Yes, Area maths are very trigger-happy for sure.

Maybe worse than you think...

...change the float, and weep. 😝

These kind of multiple paths between the same source and destination can be a complete bu**er for generating unnecessary triggers. But they are also unpredictable - quite complex arrangements of simple maths primitives seem to work intelligently, with one trigger in creating only one trigger out - whereas other primitives are like the F-to-A, create duplicate triggers even if there is a common input source. For this reason it is not good to convert between floats and areas mutliple times (e.g. when calculating small sub-areas from a parent area) - better to grab the overall MGUI parameters once, and do a little more maths if necessary.

I haven't tested all of the primitives exhaustively for this behaviour, and it get complicated once you start connecting multiple links between modules -but, luckily it is easily checked with a trigger counter, and corrected by trigger blocking all but one of the paths to the common source.

infuzion ·

trogluddite wrote: For this reason it is not good to convert between floats and areas multiple times (e.g. when calculating small sub-areas from a parent area) - better to grab the overall MGUI parameters once, and do a little more maths if necessary.

Yes, just as in almost all SM's default modules translate Float to Area, Area to Float, then again Float to Area, Area to Float again! Might be OK for small modules, but I think this causes the issues with slower load times & patch changes that larger OSMs have.

trogluddite wrote: I haven't tested all of the primitives exhaustively for this behavior, and it get complicated once you start connecting multiple links between modules -but, luckily it is easily checked with a trigger counter, and corrected by trigger blocking all but one of the paths to the common source.

Now this is where I would take a different path than you will take, if it were not for this forum thread. I would try to reduce triggers just before or after the final Float to Area. Perhaps your way is better; this is why a reverse-trigger counter would be handy.

edit: hmmm, still trying to figure out why one is better than another.... I would assume my last version is better due to the reverse-trigger is blocked early...

trogluddite ·

infuzion wrote: this is why a reverse-trigger counter would be handy.

indeed - the investigations of triggers have turned many "unknown unknowns" into "known unknowns" - there are a few 'exceptions to the rule' for forward triggers, but a trigger counter will soon find them - with reverse triggers it is hard to even find out what the rules are.

infuzion wrote: Perhaps your way is better

Perhaps not? You would be surprised at how much of this I am making up as I go along. When you first asked the question "how to test for reverse triggers" - I didn't think that you could at all - I was half way through writing a terribly negative reply when I suddenly remembered that I had seen selectors flickering whenever draw loops got triggered. Hence, the 'Reverse Trigger Detector' was born. Of course, such a moment of serendipity was bound to happen to somebody,, once someone as thorough as yourself had thought to ask the right question (sorry if that sounds facetious, it really is meant as a complement)

General principles I am not too bad at, but I am terribly lazy when it comes to details - your questions have revealed uncharted seas upon which I am too inexperienced to comment (but really enjoying exploring)- Thank you for being an 'inpertinent student' - it brightens my day! 🙂

Wrote something here? To have a post removed or your name hidden, write to [email protected].

Before your first post

A few rules keep this a friendly place. You agree to them once.

Shown next to what you post, here and in the app. It doesn’t have to be your real name: 3–24 lower-case letters, digits or _ (capitals become lower case, spaces become _).

    Then your post goes up straight away.

    Delete this reply?

    Open it in SynthMaker?

    It goes on the track you’re editing there, in place of that track’s sound, and into My sounds. Your other tracks stay as they are.

    Want to keep that track’s sound? Start a new song in SynthMaker first (Song › New song), then open this.

    Report this reply?

    Only the developer reads reports. The person isn’t told who reported them.

    What’s wrong with it?

    Block this person?

    You won’t see their posts and replies here any more. They aren’t told, and you can unblock them at any time.

    People you’ve blocked

    Their posts and replies are hidden from you. Unblock someone to see them again.

    The community rules

    A few rules keep this a friendly place. Everyone agrees to them once, before their first post.