Sequential global variables (undo button)

Hello, I need an advice with this rule.

if ha==-1 then ha=pp
if ha==-1 then exit rules, execute Outgoing Action
if hb==-1 then hb=pp
if hb==-1 then exit rules, execute Outgoing Action
if hc==-1 then hc=pp
if hc==-1 then exit rules, execute Outgoing Action
if hd==-1 then hd=pp
if hd==-1 then exit rules, execute Outgoing Action
if he==-1 then he=pp
if he==-1 then exit rules, execute Outgoing Action
if hf==-1 then hf=pp
if hf==-1 then exit rules, execute Outgoing Action

What I want is to populate the first available global variable (meaning the first one that is equal to -1 with the note value of incoming note), and as soon as I populate one variable, I want the rules to exit and execute the outgoing

currently I have all variables populating with the same note value each time

thanks

Hi, maybe a construct that looks like this. In your construct you are changing the value in the first rule so the second rule never executes. I use a local variable tt to determine which value to populate.

tt=0
if ha==-1 then goto "found"
tt=1
if hb==-1 then goto "found"
tt=2
if hc==-1 then goto "found"

exit rules, skip outgoing action

label "found"
// determine which value to populate

if tt==0 then ha=pp
if tt==1 then hb=pp
if tt==2 then hc=pp

Steve Caldwell
Bome Customer Care


Also available for paid consulting services: bome@sniz.biz

perfect thank you

do you know if it’s possible to define a global variable to remember which global variable (ha, hb, hc etc.) has been populated last ?

because the rule will be copied to many translator, and I want an exit translator that “undo” the last note sent

You would need anothe global variable to keep a value of the last global variable populated.

So instead of tt, in the last posting, you could use ga and then based on it’s current value figure which of the others was populated last.

The thing about global variables is that due to possible race conditions, it is best to have a single translator update a given global variable and then only read the global variable with other translators.
Trying to write the same global variable with multiple translators simultaneosly is not really a good idea.

Maybe you can explain on a higher level, what you are trying to accomplish and I can guide you in a different method to achieve your needs.

Steve Caldwell
Bome Customer Care


Also available for paid consulting services: bome@sniz.biz

THank you

I’m developing a chord-building system where individual notes are entered sequentially. Only note-on messages are passed through, allowing me to audition and sustain the chord as it’s being constructed. Once I’m satisfied with the chord, a global note-off message is sent to release all notes.

Additionally, I’ve implemented a trigger that replays the full chord: it sends a combined note-on/note-off message containing all stored variables, enabling me to recall and play the entire chord with a single input. This functionality is already fully operational.

My next step is to add an “undo” button, allowing me to remove the most recently entered note from the stored chord before committing or replaying it.


I use this first translator to store the last used variable into zz

tt=0
if ha==-1 then Goto ‘found’
tt=1
if hb==-1 then Goto ‘found’
tt=2
if hc==-1 then Goto ‘found’
tt=3
if hd==-1 then Goto ‘found’
tt=4
if he==-1 then Goto ‘found’
tt=5
if hf==-1 then Goto ‘found’
tt=6
if hi==-1 then Goto ‘found’
tt=7

Label ‘found’
// determine which value to populate

if tt==1 then zz=ha
if tt==2 then zz=hb
if tt==3 then zz=hc
if tt==4 then zz=hd
if tt==5 then zz=he
if tt==6 then zz=hf
if tt==7 then zz=hi
if tt==8 then zz=hj


I use a second translator that simply send the “zz” variable as a note off message to cancel the last note

the above 2 translators are already working


Where it gets tricky is that I am looking for the undo button to work decrementally when I press it more that once, so if last variable stored is hc, I want to undo hc with the first press, then undo hb with the second press, then undo ha and make zz=-1 with the third press

I also made a third translator to turn the current zz variable into -1 everytime I press the undo button to “empty the variable”

if zz==ha then ha=-1
if zz==hb then hb=-1
if zz==hc then hc=-1
if zz==hd then hd=-1
if zz==he then he=-1
if zz==hf then hf=-1
if zz==hi then hi=-1
if zz==hj then hj=-1


I am hitting a wall now with the decremental function

// Store the current zz value before modifying it
uu=zz

// Clear the current variable
if zz==ha then ha=-1
if zz==hb then hb=-1
if zz==hc then hc=-1
if zz==hd then hd=-1
if zz==he then he=-1
if zz==hf then hf=-1
if zz==hi then hi=-1
if zz==hj then hj=-1

// Move zz to the previous variable in sequence
if zz==hj then zz=hi
if zz==hi then zz=hf
if zz==hf then zz=he
if zz==he then zz=hd
if zz==hd then zz=hc
if zz==hc then zz=hb
if zz==hb then zz=ha
if zz==ha then zz=-1

I am trying this approach all in one translator for the undo button

storing current zz in uu

sending uu as outgoing message to act as a cancel note off

update the variables

but it doesn’t seems to be working

I did it !

// Store the current zz value before modifying it
uu=zz

// Move zz to the previous variable in sequence
if uu==hj then zz=hi
if uu==hi then zz=hf
if uu==hf then zz=he
if uu==he then zz=hd
if uu==hd then zz=hc
if uu==hc then zz=hb
if uu==hb then zz=ha
if uu==ha then zz=-1

// Clear the current variable
if uu==ha then ha=-1
if uu==hb then hb=-1
if uu==hc then hc=-1
if uu==hd then hd=-1
if uu==he then he=-1
if uu==hf then hf=-1
if uu==hi then hi=-1
if uu==hj then hj=-1

I used uu as an intermediary variable to store current zz

Great, so essentually you are using global variables ha,hb,hc,hd,he,hf and hi as a stack and zz as a stack pointer. Not sure why use used hj, however unless your plans are to make a bigger stack.

I’m thinking of trying perform to do this where we would have a
perform ‘push’,pp to push something onto the stack and perform ‘pop’ to pop it off of the stack. Of course the return value in pop would just be to set a single return value global variable that we later use since perform doesn’t have a way to return to the caller.

I’ll play with it when I get time.

Steve Caldwell
Bome Customer Care


Also available for paid consulting services: bome@sniz.biz

Here is an example stack implemenation using perform. I only have The stack size as 4 and use ga,gb,gc, and gd for the values
The global variable “sp” is the current stack pointer.
The global varialbe “rs” is the value of the last item pushed onto the stack. When a value is popped then the variable gets set back to -1 allowing for it to be filled again.

If the stack pointer value is less than 1, I display the stack as empty. If it greater than 4, I display the stack if full.

Allocation to the stack always starts with ga and goes to gd.

Translator 1.2 adds notes to the stack and translator 1.3 pops that last note. The logic of 1.0 and 1.1 handle the stack logic.

You should be able to adjust for larger stack sizes so this is just a small example.

Since it uses Perform, it requires Bome MIDI Translator Pro 1.9.0 or later.

stack-perform-2025-09-23.bmtp (3.2 KB)

Steve Caldwell
Bome Customer Care


Also available for paid consulting services: bome@sniz.biz
1 Like

thank you that’s clever

1 Like