Injecting last known Bank Select (CC 0 / CC 32) before standalone Program Changes (Octatrack workflow)

Hi everyone,

I am trying to solve a specific MIDI workflow issue between an Elektron Octatrack and the Oxi E16.

The issue is that the Oxi strictly requires both Bank Select MSB (CC 0), LSB (CC 32), and Program Change (PC) messages sent together for every preset change, otherwise it acts weird.

Inside Midihub, I have already built a pipe that successfully intercepts the Octatrack’s native bank message and remaps it to the proper MSB/LSB structure the Oxi expects.

Currently, Midihub transforms this incoming stream:

CC#0 2

PgmChg 9

Into this output:

CC#0 0

CC#32 2

PgmChg 9

The Problem comes when I switch to an Octatrack pattern that uses a different program but stays within the same MIDI Bank: the Octatrack will omit the CC 0 message entirely and only send the standalone PC to save bandwidth. So if i change from Bank 2 Pgm 9 to Bank 2 Pgm 15, the Octatrack will only send this:

PgmChg 9

When this happens, my current Midihub pipeline gets bypassed because no CC 0 triggers it, and the Oxi receives a standalone PC, which meses things up.

I would need Midihub to act as a state memory for the Bank value (the value that currently goes into CC 32).

If a CC 0 arrives followed by a PC, it should update the memory and pass through my current pipeline.

If a standalone PC arrives without a preceding CC 0, Midihub should recall the last known Bank value, inject both CC 0 (Value 0) and CC 32 (Stored Value), and then send the PC.

So for the example above, i would need something like this:

Midihub Input from Octatrack:

CC#0 2

PgmChg 9

Output:

CC#0 0

CC#32 2

PgmChg 9

Midihub Input from Octatrack:

PgmChg 15

Output:

CC#0 0

CC#32 2 (Recalled from the last known state)

PgmChg 15

Is there anyway to “stored” this variable? Or any other approach to this topic?

Pchg.mhp (411 Bytes)

I attach the simple pipe i’m using now

Thanks!!

Hello again @DiegoC!

You’re right in looking for stored values; the way to do this is with mapped Transform Arguments.

Here’s a sketch looking at two scenarios:

it uses roughly the same idea as yours.
The difference is that only the PC is allowed through and it creates both the CCs.
and here, the CC32’s value is set by the mapped Arg2 as shown.

Notes:

  1. Don’t have Midihub to hand so not tested: you might need to swap the Transform order.
    (I can never remember how two Insert Befores order themselves…)

  2. Notice I have two scenarios:

    The second is to solve the problem of the PC reaching the mapped Transform before MH has had the time to update the value.

    Here I do PC → Note On, set its length to 1ms, then use the NoteOFF to “carry” the PC# and Transform that in the same way.
    Then the last Transform recreates the PC itself.

One of these strategies should enable MH to send 3 messages for every PC received.

Thanks @resonotter ! I also don’t have the MH right now, but I think i didn’t explain correctly -or maybe i did and i’m not understanding your replay, that’s perfectly possible too :sweat_smile:

So the problem here is that if i send a program change with the same Bank number than the last program change i sent, the Octatrack will not generate the CCs 0 and 32 again (which i need), It just sends the program change. But i’m not talking about send them instantly, but maybe 5 minutes later :slight_smile:

Is this what you understood?

Thanks and sorry if its me!

Yes, it’s you @DiegoC, I understood your requirements.

Let me take you through the mapped Transform strategy (this applies to both “scenarios”)

  • The Incoming CC#0 is ignored in terms of message flow…
  • …it is, however, “registered” at MIDI-A-IN as a mapping. This mapping stores the value in Arg1 of the CC#32 Transform.
  • Instead of using CC#0 in the message flow, we use the PC to create the CC#0, CC#32 (and the outgoing PC if necessary)



    (so the Filter now looks like this)

So what this means is that everytime a CC#0 is received it updates the CC#32 Transform Arg1 value…
…but when OT doesn’t send CC#0, the previous value is still there waiting for the next PC to create a CC#0~CC#32~PC triple message.

Voila!


Now, a quick look at the timings at MIDI-A-IN will tell you whether you might need the more complex Scenario2 version.
If they’re all in the same millisec, you might need it.

Why?

here’s what might go wrong with the simpler version:
intially Arg2 = 0
you send
CC#0 2
PgmChg 9

but you receive

CC#0 0
CC#32 0 (ie. not 2)
PgmChg 9
all because the PC gets to the Transform before it gets updated to the new value.

Happy to post up the preset but you may want to try it yourself from the sketch I’ve given.

Super! It wasn’t you, its just i didn’t trust myself :sweat_smile:

Will check carefully when at home, thanks!!

Thanks again, already at home but It seems to complex for me to replicate (i’m not that MH expert). I would appreciate to have the preset and try to reverse engineer It :sweat_smile:

As you’re chez Midihub @DiegoC, would you post a screenshot of the MIDI Monitor showing the CC#0 and PC coming into MH from Octatrack?
I might then be able to see which strategy we need to use.

Thanks :smiley:

Sure! Here are the Ocatrack Out → MH In. So the 3 messages sent are:
1- Bank 0 Pgm 0
2- Bank 1 Pgm 1
3- Bank 1 Pgm2

And the outputs of my Pipeline for the 3 messages:

So as you see, the 3rd one comes without CC’s because there’s no Bank change, so the output obiously lacks those CC’s, there’s where I need to have them :slight_smile:

Is this what you need?

Thanks!

Thanks @DiegoC, very clear.

I’ve just done a quick test and it looks like the simple version might be OK:
Mapped_Pch_SimpleVersion.mhp

Let me know if you need the delayed-PC version
(or if the 3 messages in such quick succession upset the Oxi!)

Ok, not sure if it’s because of the delay needed, but with exactly the same messages (sent from Ableton, clean pipe, no transforms) it works, but with the Octatrack using your pipe, it still goes wrong :smiley: these are the snapshots of the Ableton / Octatrack

Ableton (working):

Octatrack (failing):

The timestamp is the same, I guess it needs some delay there :thinking:

The timestamps are the same since the events get generated at the same instant, but actually they get buffered at the Midihub’s output port and sent ~1ms apart.

Could you upload your latest preset? The issue may be elsewhere too. :slight_smile:

Thanks @resonotter and @Giedrius ! You were right, I had another pipe that was actually duplicating the Program Change, and removing it did the trick… BUT :smiley:

I just found out another issue, and this one could be more difficult to fix. So I found out that, not only the CCs are omitted when the bank doesn’t change, but also (and this I didn’t know), the PC is not sent when the Bank change but the Program doesn’t. So what I knew so far:

This is what sending Bank 0 Program 0 → Bank 0 Program 2 looked like:

What I have discovered:
This is how it sends Bank 0 Program 0 → Bank 1 Program 0:

So if I send the same Program for two different Banks, it will save the Program too! Damn Octatrack :smiley: I was trying to do a similar mapping to remember the last Program sent, but I didn’t manage to do it… Do you think it’s feasible?

Thanks again!!

The Program Change event could be converted to a CC and memorized in another Transform pipe through a virtual mapping, so it can be recalled later, to produce the same Program Change.

The most difficult part would be to cleanly trigger the event sequence only once. Probably a oneshot LFO could help delay triggering, waiting for CC Bank MSB, LSB and Program change events, before producing the sequence once.

I’m thinking i could also try to use a trig for this, instead of the Native program change. I could transform Velocity into Program Number and… Maybe note number into Bank? I would prefer to use always the same note, but that doesn’t give me many other options to have both messages in the same trig (maybe pitch bend?)

Yeah, so we need a timer (one Shot as @Giedrius hints; probably only need a PWM) triggered by the CC#0.
Then if a #PC isn’t received before the timer ends the last LFO value triggers the sequence.

Upload your mhp please, @DiegoC

Midihub 2026.05.18 08.50.30.mhp (2.8 KB)
here it is - the last two bypassed pipelines were my previous attempts :smiley: (one of them was the one making it fail before)

Dunno how trigs work, but yea, maybe.

Let’s try to get the native PC working first (just for completeness!)
I’ve got some timer presets lying around, I’ll dig one out when I’ve seen what your current work in progress looks like…

Thanks a lot!

About the trigs, they are just note steps in the sequencer that you can parameter lock.
Transforming the Velocity of the step into PC works great, i do It for other stuff, but in order to have also bank sent i need to use another parameter that could be locked (so i can use just one note instead of 16, which is the amount of banks the Oxi has)

So if it’s simplest to stick to one MIDI Channel, I guess your PB is the way to go to get 2 data bytes in one message. Avoids the native bank change with all its Octatrack penny-pinching.

Let me know if you want the “See Whether a CC0 is Accompanied by a PC” approach…

I still need to check something, i’m not sure if when sending two trigs with the same PB, Octatrack also ignores the second one (which It Will be the same issue :grinning_face_with_smiling_eyes:), i think It does with CCs, so probably It does with PB too. For sure It doesnt with velocity