(Teletype) EVERY+SKIP+OTHER+SYNC

I kind of took an hour and implemented EVERY and it kind of kicks ass. Check out this 1-script clock divider:

EVERY 2: TR.P 1
EVERY 4: TR.P 2
EVERY 8: TR.P 3
EVERY 16: TR.P 4

Here’s a build based on 2.1.0-rc1 that includes EVERY if anyone wants to take it for a spin:

teletype-2.1.0-rc1-every.zip (482.8 KB)

10 Likes

and perhaps RESET op? (even better if there was a way to group and reset specific groups)

agreed that this is a useful musical technique.

but is it substantially more elegant than:

IF % T 2: TR.P 1

seems a minor typing shortcut, and adds an auto-counter that will require (as @scanner_darkly points out) some form of RESET which is way to vague of a op term (reset could apply to any many things, ie, KILL).

furthermore, consider this:

T ADD T 1
IF % T 4: TR.P 1
ELSE: TR.P 2

auto bassdrum + hihat filling the in-between pulses

in a sense, EVERY seems like a shortcut with less flexibility than just using standard conditionals-- if that’s useful for people to get using TT, perhaps that’s enough of an argument for its inclusion?

2 Likes

How about EVERY.SYNC to reset all every counters to MOD-1 or 0, depending on whether you want the condition to be true on next call or not. (I can’t see resetting an individual counter by script and line number TBH)

Obvious advantages of EVERY:

  • Automaitic counter increment and reset
  • 60 independent counters
  • Clean, readable syntax

I would argue that it expands the capabilities of the Teletype in addition to being a shortcut to common conditionals.

Quick, without EVERY, create a clock divider that divides by 13, 16, 17, 19, 23, and 25 with no errors. Each general-purpose variable and line of code you don’t use earns you 1 bonus point. (</tongue_in_cheek>)


I toyed around with the idea that each EVERY call would touch the if_else_condition flag, so that you could:

EVERY 4: // kick
ELSE:    // hat

Would that have any support? I think it’s logical and readable, but that’s subjective.

3 Likes

What happens if you type EVERY 4: TR.P 1 in live mode?

How do you stop an EVERY? edit don’t bother with this I’m being daft

whoa, i didn’t understand on the first take that each EVERY had a state. i made an assumption that each SCRIPT had an internal counter that was referenced by the EVERY mod.

certainly that seems logical, though perhaps it’s worth fencing EVERY into its own feature set and keep the conditionals separate? ie, there are already mechanisms (as i showed) to do if/else tricks.


syncing individual lines is somewhat impossible-- a global sync would be fine. 0 would be all-firing?

still thinking over the feature. it seems interesting. would like others to weigh in.

Nothing, the first three times. TR.P 1 the fourth. Technically, LIVE mode commands are all SCRIPT 11, COMMAND 1, 1-indexedly speaking.

Actually, you can stop an every by disabling (commenting) the line with <Alt> + /.

I agree. I forgot that there are a few other tricks recommended in the Advanced section, such as interstitial, always-executing commands between IF and ELSE, and this would break that if there were an interstitial EVERY.

Hmmm… how about EVERY X: and OTHER:?

If you set it to 0, the next call to EVERY will not fire, as the count would increase to 1.

If you set each counter to its own MOD value minus 1, each next call to EVERY would fire.

1 Like

where OTHER executes on the proceeding false-EVERY?

what would it mean to have a script with just OTHER at the top? is EVERY a global state conditional?

Yup.

OTHER at the top of the script should probably be interpreted as bad user behaviour, and could be programmed to either always fire or never fire.

EVERY counters are tracked by script line.

Why not ignore the if_else_condition and have

SKIP 4: TR.P 2  // run each time except the 4th.
1 Like

right-- but OTHER would then assume there’s a previous EVERY, so the idea is that it looks up an index position of the previous line? what i was suggesting was a global true/false of the most recently run EVERY. then the lone OTHER is not necessarily bad, just weird (aka interesting)

this is interesting as another feature in this set. OTHER would then make even more sense perhaps to reference the most-recently true/false of EVERY/SKIP

ok, i’m into these. i propose an un-subbed SYNC to sync both EVERY and SKIP (and clear the OTHER state)

3 Likes

aside:

for these new feature “clusters” (ie turtle, every/skip/other) we need to produce some “teletype micro-studies” that follow some sort of format of the existing studies…

9 Likes

Oh yeah, that’s right! Still waking up here. Global T/F will seem odd given that there are 61 (forgot about live!) possible counters that could tick it asynchronously. I’ll give it a ponder.

I like this, too.

Would anyone (@cmcavoy?) mind porting this conversation to an independent thread, or should we hash out the rest here? (Edit: EVERYthing from post 345 inclusive is the entire conversation.)

2 Likes

Next annoying question. I haven’t got enough time to think it through myself this evening, but I just want to make sure it’s thought about.

What happens if the first argument to EVERY changes?

e.g.

EVERY RRAND 1 10: TR.P 1

(edit: I’m kinda hopping that things just get really funky)

(as another aside, I’m pleased to see TR.P being used so much!)

4 Likes
void every_set_mod(every_count_t *e, int16_t mod) {
    if (mod < 0)
        mod = -mod;
    else if (mod == 0)
        mod = 1;        // lazy initialization
    e->mod = mod;
    e->count %= e->mod;
}

(Edit: why did I post this code? I need to slow down. :upside_down_face:)

You can check out the implementation details here: https://github.com/burnsauce/teletype/commit/8e9c3b78fec17a6bff051e76fffc727377273a58

The resultant behaviour right now is that the new mod is applied to the old value immediately before the increment. The count could be zeroed to “reset it” or set to mod - 1 to force it to fire immediately when the mod changes, or it could only do that if the mod shrunk beyond the current count.

Edit2: EVERY RRAND 1 10: should probably be equivalent to IF EZ % O RRAND 1 10:

3 Likes

i was leaning towards @tehn’s reasoning that an existing IF % already covers this and provides more flexibility. here is why: in addition to reset i’d want to add an offset, which would be an equivalent of doing IF EQ 2 % T 5, basically comparing the result of MOD with an arbitrary value. and i’m starting to like an idea of having a dedicated op for comparing the result of MOD op, like %= X Y Z or %EQ X Y Z being a shortcut for EQ Z MOD X Y.

having said that it does seem to fit well within the ecosystem, it’s concise, logical and non coder friendly, especially if supplemented with additional sync and skip, and i would most definitely use it if it became available!

this also makes me think again i’d love to see more variables. especially with a couple of new variations: variables that are local to a script (like I will be), this would work really well as a temp variable where you don’t have to worry about it being overwritten by another script, and a variable that acts like O except that it increments on each script execution, not each time it’s called (but otherwise would behave like O).

i would say that when your complete cycle is 38630800 long you won’t notice when some of the counters reset too soon :wink:

2 Likes

Just to clarify, what do you mean by ‘un-subbed’ SYNC?

OTHER.SYNC with no arguments, or just plain SYNC?

I had a dream that I connected my modular’s output to a ham transmitter’s input with an encoded message.

BE SURE TO DRINK YOUR OVALTINE.

5 Likes

one more reason to have offsets! :slight_smile:

I think that this advanced use case is covered by your already-concise use of IF, and would complicate EVERY et. al.

1 Like