Transform Tutorial and Cookbook Development Topic

I thought it might be useful to build a resource which unpicks the huge flexibility of the Transform pipe and points community members to usages they may not have thought of.

In the next few posts, I’ll try to cover part of the tutorial aspect…
…then make a start describing a few ‘recipes’ using some Transform strategies…

If, with the help of others, the tutorial bits end up good enough to transfer to a new entry in How To’s section then maybe more ‘recipes’ can be added as time goes on, hopefully building a resource that’ll be useful for a wide range of users




and so to the tutorial content.
This is like a bit more in-depth version of the Context Help with some graphics thrown in.
Probably mostly obvious to experienced users; my aim is help more newer users click with Transform’s full power quicker than certainly I did…

Any comments – critical or otherwise – welcome!
(If you haven’t got that sort of time, clicking :hearts: –or not!– on a section will tell @Giedrius something, I guess)

7 Likes

Aim

This tutorial aims to explain the different aspects of the Transform pipe
and then give different usage examples to spark ideas for your projects


Intro

If Midihub is the “Swiss Army knife for MIDI”, then perhaps the Transform pipe is “Swiss Army knife of Midihub”


The Basics

Transform changes MIDI messages into other MIDI messages…
…of a different type
Transform_iconEgs

… or maybe the same type
Transform_CC_CC


Transform can be set to Replace the incoming message…

Replace


or create a new message and Insert Before

Insert Before


…or Insert After the original message

Insert After

2 Likes

Input Ranges

Some messages are simple...

… a Stop is just a stop -

Other ‘simple’ messages:

  • Start
  • Continue
  • Tune Request
  • Clock
  • Active Sense
  • Reset

.…

Other messages have an "id" and (maybe) a "value"...
What ‘id’ Range ‘value’ Range
Note On Note Number Velocity
Note Off Note Number Velocity
Note On & Note Off Note Number Velocity
Control Change CC Number Value
Poly Aftertouch Note Number Pressure
Program Change Program Number n/a
Channel Pressure Pressure n/a
Song Select Song n/a

.…

and some are defined by two values...
What LSB Range MSB Range
Pitch Bend Pitch Bend LSB Pitch Bend MSB
Song Position Pointer Song Pos LSB Song Pos MSB
What's LSB & MSB?

Some messages like Pitch Bend have a finer ‘resolution’ than CCs.
They work like two linked CCs; MSB (‘Most Significant Bit’) taking one step for every 128 LSB (‘Least Significant Bit’) steps:

Transform gives a lot of control over which ‘ids’(or LSBs) and ‘values’(or MSBs) it will use to create a new message.

By default, Transform will act on the full range of ‘ids’ (Note#, CC#, Program#, Pressure, Song) of that message type (and the full range of ‘values’ (Velocity, Value, Pressure) – if the type has them) across all channels

But Transform lets you choose the ranges of either the ‘values’ or ‘ids’ it will transform


or restrict both (and focus on just one channel, if you choose)

So Transform can be allowed to act on every message of the chosen What
(say note/CC).

or narrowed to act on just a single id/value pair
(say Channel 10, C3, velocity127 / Channel 1, CC#3, value 64)



Plus, Transform gives the option to act on everything outside a range

(for example, to trigger new events when the Channel Pressure on Channel 8 is very high or very low)

6 Likes

Next…
Setting ‘ids’ and ‘values’

The visualizations for transform pipe ranges look great! :slight_smile:

Setting ‘ids’ and ‘values’

Once the range of ‘ids’ and ‘values’ have been set…
…a new message of the Into type will be created every ‘What’ message in that range.

Transform gives a lot of scope for how to set the new message:

The id (or LSB) of the new message can be set to…

  • …the id of the incoming message
  • or its value
  • or a the value currently in the Argument 1 or Argument 2 property

Similarly, the value (or MSB) of the new message can be also set to…

  • …the id or value of the incoming message
  • or one of the current Argument 1 or Argument 2 values

Here are just a few examples:



(new) ‘id’ = Argumentand… (new)‘value’ = (original) ‘value’

Example
Poly AfterTouch → CC#120
Pressure → CC value

PolyAfterTouch note doesn’t matter; all notes in range create a CC#120 value



‘id’ = Argument … ‘value’ = ‘id’

Example
note_on in range → CC#120
note number → CC value
velocity doesn’t matter; all notes in range create a CC#120 with the current Argument(1/2) value



‘id’ = ‘id’ … ‘value’ = Argument

Example
note_on in Note Range → CC
note number → CC#
velocity doesn’t matter; all velocities in range create a CC with value 10



‘id’ = ‘id’ … ‘value’ = ‘value’

Example
PolyAfterTouch on notes in range → CC# = note#
Pressure → CC value



‘id’ = Argument … ‘value’ = Argument

Example
Song Position Pointer LSB in range and
Song Position Pointer MSB in range
→ note_on 60, velocity 64
(say, at the start of bars 8-12, trigger a note on channel 13 to be processed in other pipelines…)


summing up…


Combining the WhatInto combinations…
…with the Input Ranges
and ‘id’ and ‘value’ setting permutations

...not forgetting...

…the choices of Replace vs Insert Before|After

and that Argument 1/2 values… might be constant/fixed…
…but could be linked to other inputs by mappings

…the huge capabilities and possibilities of the Transform pipe can be almost daunting!


The recipes in the “Cookbook” below aim to give some practical use examples of Transform in action…

@Giedrius and everybody else: does this sort of ‘work’ graphically and example-wise?
comments most welcome
Also if anyone has anyone other/better Set Value x Set Arg combos, I’d be very grateful (I’d particularly like a real-life Valueid x idValue example)
Thx in advance!

1 Like

For some reason it took a while for me to understand what these headings mean, at first I thought it was supposed to read as ‘argument transformed to value’ or something. I considered ‘x’ to be the equivalent of the word ‘transform’ due to ‘xform’ being used as a short for it. I’d suggest using more explicit headings like ‘Id = Argument1, Value = Value’.

I think it’d be good to display the names of the axis in the graphics. I think the examples would benefit from having concrete numbers to the transformations they’ve done, it could be cumbersome to place in the graphics, but using different colors for a couple of different examples would make the transformation that happened easier to understand.

Set Value x Set Arg - generating different pitch of notes based on incoming note’s velocity, the new notes velocity set to a fixed value. This would have to be used together with a Fixed Note Length pipe to produce the necessary Note Offs.

real-life Valueid x idValue - this is sometimes useful to temporarily swap the MIDI data bytes places, in order to make use of other Midihub pipes that only work on the first data byte of the message, like to use Note Range Filter pipe to work on velocity instead of note number, then to swap them back into their place. It might be interesting to try swapping Pitch bend’s MSB and LSB places and see if the result is usable.

Btw, some section explaining how MIDI messages look like might be helpful for understanding the possibilities of the Transform pipe better. A good quick reference to MIDI messages is available here: Summary of MIDI 1.0 Messages - what it is missing is some explanation on how to make sense of it. :smiley:

Thanks @Giedrius good comments

took a while for me to understand what these headings mean, at first I thought it was supposed to read as ‘argument transformed to value’ or something. I considered ‘x’ to be the equivalent of the word ‘transform’ due to ‘xform’ being used as a short for it. I’d suggest using more explicit headings like ‘Id = Argument1, Value = Value’.

If not obvious to you then doubt you’re in a minority!

Want to use ‘Argument’ instead of ‘Argument1’ as 1/2 is arbitrary in most use cases, but will make more specific along lines suggested & see what it looks like

display the names of the axis in the graphics…would benefit from having concrete numbers to the transformations they’ve done, it could be cumbersome to place in the graphics, but using different colors for a couple of different examples would make the transformation that happened easier to understand.

Yeah, if markdown allowed coloured text I’d go for that. I’ll look at labelled graphics.
Always a tension between clarity and clutter!

real-life Valueid x idValue - this is sometimes useful to temporarily swap the MIDI data bytes places, in order to make use of other Midihub pipes that only work on the first data byte of the message, like to use Note Range Filter pipe to work on velocity instead of note number, then to swap them back into their place. It might be interesting to try swapping Pitch bend’s MSB and LSB places and see if the result is usable.

Yeah, I’ve got one or two myself. I’ve just got a feeling that ‘cookbook’ examples which relate to a real usage solution will make better sense to Midihub users down the road.

btw On matter of ‘real’ patches, do you have a way of being able to trawl the site for the .mhp files that have been uploaded? would save me a lot of plodding if there are any forthcoming user suggestions

See also updated graphics headings above

here’s example of an scaled and labelled graphic, :
(with updated heading and original Example text)





(new) ‘id’ = Argumentand… (new)‘value’ = (original) ‘value’

Example
Poly AfterTouch → CC#120
Pressure → CC value

PolyAfterTouch note doesn’t matter; all notes in range create a CC#120 event



(x-scale left implicit as hinted by message ‘id’ labels)


compare with original graphic…

...here:


PS would possibly look less cluttered with new border (original not yet edited; only added layer)

first of the ‘recipes’



Recipe 1
Transform part of the keyboard to change its role

Element433_PA_CC&Noo_PA

Transform is used twice but only for top notes

  1. for Poly Aftertouch → Breath Control CC (id =2 , value = Pressure)
  2. for (same) Notes → Poly Aftertouch (id = note 99, Pressure = Velocity)

Element433_PolyAfter~CC02_top_notes.mhp
This enables a continuous Breath Control while other notes are played for the pitch


:fondue:@Element433 Oct22

@Element433 does the PA on note 99 just get ignored?

Recipe 2
Split a CC value range to create distinct events

8noteBopPad

Two Transform pipes set to the same CC single-id range…
…with two different value ranges to create different notes

velocity is set to Argument…
…which is mapped to a separate velocity-based CC

This idea is repeated for each quadrant of the device
BopPadWithMidihub


recipe variations

Split a modulation strip into two CCs.
For each set ‘id’ = Argument, ‘value’ = ‘value’
use two Rescale pipes to scale each value range to what you need

Split an X-Y pad into events:
splitting the ‘X’ CC into separate CC’s/Notes
using the ‘Y’ CC to map to the events’ values/velocities


:fondue:@AlexMcMahon @resonotter Nov22-Mar23

Hey @Giedrius (or anyone else!) can you give me a few words on

  • Note On & Off
  • Prioritize Real-Time
    please?

I read

  • (useful when remapping the note number)

and

Whether the Real Time messages produced should be prioritized. If off, logical order of the messages is retained.

respectively, but a few extra words to help me flesh out the meaning/usage would be useful.

Cheers!

1 Like

Note On & Off - it’s so that you don’t have a nearly equivalent duplicate for both Note On and Note Off, it saves one pipe for you to do the same transformation on both events.

Prioritize Real-Time - It’s a param introduced here: Xform PC -> Stop, PC, Start - #8 by Giedrius

Normally, the Real Time MIDI messages get pushed right at the front of the MIDI message queue, so they get in front of the remaining non-realtime data, such as Note On, CC, etc… Disabling Prioritize Real-Time will actually place the produced real-time messages not at the front, but the back of the queue, so whatever Transformation you’re working on, stays in that order.

Hey all.
Thanks for the likes for my (unfinished ) first edition of this. (people seem to particularly like Ranges section in post3)

Apologies for not having finished it:

I stepped back to have a re-think and a rewrite.
Then came the 1.14.0 Transform which needs a bit more of a review.

I think it’s now even more important to have something to help demystify this deeply powerful pipe

I promise to have at least part of Version2 out “soon” …

2 Likes