Map Aftertouch to CC

danielleoh's icon

I've successfully hijacked Aftertouch and can convert it back to a Midi CC in one of two ways, but whatever CC I select it affects that one but also Midi CC1. Have spent dozens of hours trying to figure out a way to get it to work on only the selected CC.
In the example below I have routed AT data into one side of a Join, and then the selected CC# into the other side. (In this example I am trying to use AT to change Vibrato depth in BBC SO strings, which is controlled by CC21).
If I run these two integers into a ctlout, it works but AT also affects CC1 (and maybe others, I just realized that I didn't check for that!) If I try to combine that data stream with the original controller signals, as output from the midiselect, the problem persists.
Note that it took a few tries to realize that failure to add "@touch 1" to the midiselect will mean that AT is being passed through the unselected data output.
There must be a fairly simple fix for this, in which the original controller values are passed through and the AT values are mapped only to Controller 21?
Thanks in advance for the help!!

Does what I want it to, but then does too much...

Pedro Santos's icon

Everytime any "midiin" event is received you are triggering a new CC (right part of the patch).
Does this work better?

Max Patch
Copy patch and select New From Clipboard in Max.

Andy Maskell's icon

I can't see anything glaringly wrong with your code and when I tried it myself in Max it seemed to work. The only thing that bothers me a bit is that you have two threads in your code that need to process data simultaneously in real time and that is never a good idea. I suggest rejigging it a bit to make it simpler:

However, why that should result in output to multiple controllers is a bit of a mystery. I suppose the other possibility is that where you merge the MIDI from the midiformat and the midiselect overflow into the midiout, the MIDI messages could be getting jumbled up because of the fact that you have two threads firing off data simultaneously. This doesn't usually cause a problem in Max but it might be a problem in M4L? Are you allowed to send them out via two separate instances of midiout, as I have done?

Edit: Merging the output from the midiformat and midiselect output 8 should not cause a conflict. It's documented that way in the manuals and I've done some tests to confirm that there is no overlap of the outputs:

Andy Maskell's icon

Yes Pedro, that is what I was trying to get across really. If the bang is essential for whatever reason then it needs to be triggered by the midiselect AT output rather than the midiin. However, with both our methods it's not needed.

Roman Thilenius's icon


did anyone yet measured what routes faster, midiselect or midiparse? ;)

Andy Maskell's icon

I don't think there will be any significant difference. It's more a question of choosing the correct method given the different options that each object offers.

danielleoh's icon

I appreciate all the input. Still working on it, after a long night's sleep.

Here's a list of what I've tried so far today:
I have used both midiselect and midiparse, with the same results.
I tried moving the bang from midiin to AT out. It still does the same thing.
Tried removing the bang, and it doesn't work at all.
Tried Pedro's patch; same result as before in that AT triggers every CC in use at the time.
Tried dialing in different cc's and realized that it triggers all CC's in use in my patch, no matter what I put on the dial.

I've moved my output to a ctlout, have used print to verify that the list is properly formatted (it comes out as 21, 127 with full aftertouch applied) and tried telling the midiselect to choose particular controllers in use; 1, 11 and 21. Still all results are the same.
One more thing that I thought simply had to work, even if it used more cpu that I'd prefer; added another midiselect after the join and before the midiformat. The idea was to select only cc 21 data; this blocked all output...

Andy Maskell's icon

Here's my patch if you want to try that (I have tested it and it does exactly what I expected):

Max Patch
Copy patch and select New From Clipboard in Max.

Are you trying these patches completely on their own or do you have other patches or bits of code running at the same time?

I'd strongly recommend that you try one of these simple patches running completely on it's own first to check that it works.

If you have other stuff going on alongside this then there could be all manner of places where you have unwittingly crossed connections between this and other parts of your patch. For example, if the CC# Live.dial has parameter definitions attached it could cause other dials to change their settings too!

Perhaps you could upload your whole patch for us to look at?

Andy Maskell's icon

There are few things that you've tried that simply won't work!

The patches that Pedro and I have posted don't need that bang at all. We've achieved exactly the same thing in two slightly different ways. Our patches are complete replacements for the code in your original post - don't assume that they only replace the bits on the left hand side.

The fact that changing the CC# dial triggers all other CC's in you patch makes me think that you have copied the live.dial from somewhere else, along with all its settings, rather than creating a new one. Try deleting it and use a completely new one.

The output of a midiformat must go to a midiout as it generates fully formatted MIDI messages. If you want to use ctlout then just take its feed from what fed the CC input of midiformat.

Telling midiselect to choose specific controllers won't help as you are only converting the AT messages.

Putting a midiselect after the join definitely won't work as the midiselect needs fully formatted MIDI messages. It might well hang because it will never receive anything to tell it what sort of MIDI message it's getting.

The patches Pedro and I have posted really couldn't be any simpler. Mine only took five minutes to write! They definitely work so you really need to consider what else is going on in your patch (or Live settings for that track) that could be confusing things.

danielleoh's icon

Thank you, thank you!! I don't know what was wrong with my patch, but it seems that you're 100% correct; adding your code to mine doesn't work, but starting fresh with yours does. I'm off to the races!!!
:-)

Final thought of the day: it worked, but only a couple of times before the entire patch froze up. I ran it multiple times and each time it does seem to work fine but then... no output, nothing. I have to completely reload the VST to fix that problem. I'll likely switch to a different method for awhile (like assigning a fader to the cc that controls vibrato) and then maybe circle back at some point in the future. Frustrating...

Andy Maskell's icon

Phew! Glad you've fixed it. :-)

danielleoh's icon

Captain's Log, final entry:
You were all right! I had left unused functions in my code that were creating problems. Once I cleaned it out so that it only uses what's below, all is well.
Again, my thanks to everyone who helped out. It takes a village to raise an idiot, and I'm your idiot! :-P

Andy Maskell's icon

Still looks over-complicated but if you’re happy with it and it works then fair enough.

It just goes to show that there is always more than one way to do things. ;-)

danielleoh's icon

Yeah. Mostly I've been fighting the same battle for days now and want to actually make a little music, instead. I'll circle back at some point and try to make it as simple and clean as possible.
Meanwhile, I added functionality in the form of a low limit, high limit and scale factor for the controller value. Since I'm now mapping AT to the CC that controls vibrato intensity, I'm finding that the libraries I've layered on top of one another are reacting very differently to the same amount of input. Makes life a little easier...