A technical support community for Apple Logic Pro users.

 
User avatar
eserpa
Topic Author
Posts: 7
Joined: Sun Jun 28, 2020 12:28 am
Location: Los Angeles
Contact:

Slew/Glide for Aftertouch/Midi CC

Sun Jun 28, 2020 12:39 am

Hey everyone, this site has been a fantastic source of knowledge through the years, yet this is my first post ever.

I been toying around with a Roli controller and I’ve encountered that the aftertouch (and many other keyboards) tends to be way too abrupt and inexpressive.

Using Alchemy’s envelope follower or Kontakt’s lag has helped a lot but not all plugins are as easy to workaround, hence this post.

I’m wondering if there is a way to script a midi message like aftertouch to midi cc with lag/smooth/glide (attach and decay could be useful too) functions to smooth out the abrupt changes. Minimum and maximum values would be great too. I know a little bit of code but this has been way out of my league.

Polyphonic aftertouch would be great also but probably a nightmare to script.

This slew/glide script could also help with jumpy cc midi cc data and make it smoother.

Looking forward to all your comments and suggestions, thanks in advance!
Last edited by eserpa on Tue Jun 30, 2020 9:11 pm, edited 4 times in total.
 
User avatar
Mark R
Posts: 392
Joined: Thu Jan 26, 2006 9:50 am
Location: Tumwater, WA

Re: Slew/Glide for Aftertouch/Midi CC

Sun Jun 28, 2020 8:05 am

Agreed, aftertouch is often way too touchy to be usable.
I too would like a way to slow down (slew) aftertouch messages...
Preferably with separate Attack and Release time controls.
Logic 10.5.1 | Mojave | retina iMac 4GHz i7 32GB
Logic 10.4.8 | High Sierra | MacMini 2.3GHz, i7 16GB
 
User avatar
fuzzfilth
Posts: 4919
Joined: Mon Aug 03, 2009 2:31 am
Location: Germany

Re: Slew/Glide for Aftertouch/Midi CC

Sun Jun 28, 2020 8:25 am

Here's one concept:
- receive an AT event
- if it's the first AT event, store it in "currentAT"
- also store it in "lastAT"
- pause for "lagMS"
- if lastAT > currentAT, increase currentAT by 1
- if lastAT < currentAT, decrease currentAT by 1
- send currentAT
- if another AT event has come in in the meantime, store it in lastAT
- if currentAT ≠ lastAT, jump to the pause for lagMS line

lagMS is your ramp speed control, you can set up a GUI fader for this. Start with a center value of, say, 5ms, this will spread 127 steps over 640ms.

I'm sure there's more elegant ways to code this, but this can get you started.
Christian Obermaier
Contact me for private Logic Consulting, Training, Troubleshooting via Skype, Zoom or Teamviewer

1 x MacPro 6core 2010 24Gb RAM
2 x MacBookPro i7 2012 16Gb RAM
OSX.14.6. Mojave, Logic X.5.1
 
User avatar
Dewdman42
Posts: 3307
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Slew/Glide for Aftertouch/Midi CC

Sun Jun 28, 2020 12:19 pm

eserpa wrote:
I’m wondering if there is a way to script a midi message like aftertouch to midi cc with lag/smooth/glide functions to smooth out the abrupt changes. Minimum and maximum values would be great too. I know a little bit of code but this has been way out of my league.


Please describe what you mean exactly by "lag/smooth/glide".

Polyphonic aftertouch would be great also but probably a nightmare to script.


its not really that hard
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram
 
User avatar
Dewdman42
Posts: 3307
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Slew/Glide for Aftertouch/Midi CC

Sun Jun 28, 2020 4:55 pm

so one quick fix for now...might be to use this site and adapt it:

https://sumire-io.gitlab.io/midi-veloci ... generator/

gen.jpg
gen.jpg (197.84 KiB) Viewed 3380 times


You can basically drag the curve to a velocity curve you like and then copy and paste the javascript into Scripter. But in order to work with aftertouch, you'd need to modify the code slightly.. Modify just the HandleMIDI function more like this:

function HandleMIDI(event) {
  if(event instanceof ChannelPressure) {
    event.value = velocities[event.value];
  }
  event.send();
}


Play around with different aftertouch scaling curves until maybe it responds the way you want it too.

If you want to elaborate more on what you had in mind for glide, etc.. I can comment more...
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram
 
User avatar
eserpa
Topic Author
Posts: 7
Joined: Sun Jun 28, 2020 12:28 am
Location: Los Angeles
Contact:

Re: Slew/Glide for Aftertouch/Midi CC

Tue Jun 30, 2020 6:25 pm

Thank you so much! This will definitely get me started.
 
User avatar
eserpa
Topic Author
Posts: 7
Joined: Sun Jun 28, 2020 12:28 am
Location: Los Angeles
Contact:

Re: Slew/Glide for Aftertouch/Midi CC

Tue Jun 30, 2020 6:29 pm

Dewdman42 wrote:
eserpa wrote:
I’m wondering if there is a way to script a midi message like aftertouch to midi cc with lag/smooth/glide functions to smooth out the abrupt changes. Minimum and maximum values would be great too. I know a little bit of code but this has been way out of my league.


Please describe what you mean exactly by "lag/smooth/glide".

Polyphonic aftertouch would be great also but probably a nightmare to script.


its not really that hard


What I mean is that these changes in pressure are far to abrupt to be musical in most situations in my opinion. It is a great to have if you want to do a fast swell or transition fx but for evolving and smooth filter cutoffs it tends to be too fast.
 
User avatar
eserpa
Topic Author
Posts: 7
Joined: Sun Jun 28, 2020 12:28 am
Location: Los Angeles
Contact:

Re: Slew/Glide for Aftertouch/Midi CC

Tue Jun 30, 2020 6:30 pm

Dewdman42 wrote:
so one quick fix for now...might be to use this site and adapt it:

https://sumire-io.gitlab.io/midi-veloci ... generator/

gen.jpg

You can basically drag the curve to a velocity curve you like and then copy and paste the javascript into Scripter. But in order to work with aftertouch, you'd need to modify the code slightly.. Modify just the HandleMIDI function more like this:

function HandleMIDI(event) {
  if(event instanceof ChannelPressure) {
    event.value = velocities[event.value];
  }
  event.send();
}


Play around with different aftertouch scaling curves until maybe it responds the way you want it too.

If you want to elaborate more on what you had in mind for glide, etc.. I can comment more...


What an interesting solution. Thanks again for being super helpful. Will test all these options and report back!
 
User avatar
eserpa
Topic Author
Posts: 7
Joined: Sun Jun 28, 2020 12:28 am
Location: Los Angeles
Contact:

Re: Slew/Glide for Aftertouch/Midi CC

Tue Jun 30, 2020 6:40 pm

Mark R wrote:
Agreed, aftertouch is often way too touchy to be usable.
I too would like a way to slow down (slew) aftertouch messages...
Preferably with separate Attack and Release time controls.


Yes! I think this would be great too. Logic's Alchemy has Attack Release and Scale, personally scale is usually at 100% but over scaling could interesting too, a great way yo make it smooth but have a shorter span of pressure.

Thanks to everyone, I don't know why I didn't joined this community sooner, what a great forum!
 
User avatar
eserpa
Topic Author
Posts: 7
Joined: Sun Jun 28, 2020 12:28 am
Location: Los Angeles
Contact:

Re: Slew/Glide for Aftertouch/Midi CC

Tue Jun 30, 2020 9:09 pm

fuzzfilth wrote:
Here's one concept:
- receive an AT event
- if it's the first AT event, store it in "currentAT"
- also store it in "lastAT"
- pause for "lagMS"
- if lastAT > currentAT, increase currentAT by 1
- if lastAT < currentAT, decrease currentAT by 1
- send currentAT
- if another AT event has come in in the meantime, store it in lastAT
- if currentAT ≠ lastAT, jump to the pause for lagMS line

lagMS is your ramp speed control, you can set up a GUI fader for this. Start with a center value of, say, 5ms, this will spread 127 steps over 640ms.

I'm sure there's more elegant ways to code this, but this can get you started.


Gosh I wish I knew more Java. But these variables sound like they would do the trick.
 
DGB111
Posts: 21
Joined: Sun Apr 02, 2017 2:36 pm

Re: Slew/Glide for Aftertouch/Midi CC

Thu Oct 15, 2020 2:18 pm

Quick question

How would you:

- pause for "lagMS"

I figure you could sendAfterMilliseconds, but there doesn't seem to be any wait or timing functions while inside a script, only delaying sending the midi data unless I'm missing something?

Thanks!
 
User avatar
Dewdman42
Posts: 3307
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Slew/Glide for Aftertouch/Midi CC

Thu Oct 15, 2020 2:21 pm

you can use Javascripter timing functions to delay based on the real time clock sure. That is always possible, but keep in mind that Scripter operates on the midi AHEAD of schedule. Its operating on the midi before you actually hear it...so... realtime functions like that may not be that precise. But you can definitely use them.

if you want to delay things synchronized to the music you hear, then you have to use functions that inspect the current beat position and make calculations as you go to figure out if you have passed the lag time you seek to wait for, then do whatever you want...based on the beat position which now matches however many MS you wanted to lag for.
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram
 
User avatar
Dewdman42
Posts: 3307
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Slew/Glide for Aftertouch/Midi CC

Thu Oct 15, 2020 2:22 pm

you do that by using the ProcessMIDI function and that gets called over and over again every couple of ms. So each time it gets called you check the beat position to see if its time to do what you want to do.
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram
 
DGB111
Posts: 21
Joined: Sun Apr 02, 2017 2:36 pm

Re: Slew/Glide for Aftertouch/Midi CC

Thu Oct 15, 2020 2:36 pm

cool! I'll have to look into how to do that!

Can you send AT messages from ProcessMIDI? Or somehow do the calculations in ProcessMIDI, then schedule the sending in HandleMIDI...?

Thanks for the quick reply!
 
User avatar
Dewdman42
Posts: 3307
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Slew/Glide for Aftertouch/Midi CC

Thu Oct 15, 2020 2:43 pm

yes you can send from ProcessMIDI(). The only difference is that HandleMIDI gets called once per incoming event. ProcessMIDI gets called over and over again once per process-block...without receiving any midi event. So you use HandleMIDI always to process incoming midi, and you can use it to send out midi. PRocessMIDI you use just to do whatever you want to do, including send midi, but it doesn't know about incoming midi, that is handled in HandleMIDI.

Use global variables to share data between the two functions and over hte course of multiple calls to them.
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram
 
DGB111
Posts: 21
Joined: Sun Apr 02, 2017 2:36 pm

Re: Slew/Glide for Aftertouch/Midi CC

Thu Oct 15, 2020 5:45 pm

Very cool! playing with that now.

About the timing though, I haven't been able to get setTimeout to work, though I might be doing it wrong, or that might not be the javascript time function you were suggesting.
 
User avatar
Dewdman42
Posts: 3307
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Slew/Glide for Aftertouch/Midi CC

Thu Oct 15, 2020 6:00 pm

setTimeout is a javascript function that is generally only applicable to web browsers and yea, won't work in Scripter. Can you elaborate more specifically what you are wanting to do?
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram
 
User avatar
Dewdman42
Posts: 3307
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Slew/Glide for Aftertouch/Midi CC

Thu Oct 15, 2020 6:20 pm

so a few more words about timers and such in Scripter...

First, generally any of the javascript functions you normally might use in say a browser to set a "timer" that triggers a function call later at a predetermined amount of time.... these won't work in Scripter. Scripter operates in a very short period of time called a "process block". This is how all AU plugins work actually. Scripter is no different. When you have a chain of plugins, they each take turns doing their work on the current process-block..which will be some short period of time, likely closely resembling your buffer size.

Scipter is the same way. ProcessMIDI is called once for every process-block of time. During this short period of time you can call many javascript functions, but it has to execute very short and quickly...in much less time then the actual process-block...since other plugins also need time to do their work for that process-block, etc. So the idea is ProcessMIDI does some work, hopefully nothing taking too long, and then control is passed back to LogicPro...and there is no javascript context to fire off a timer event..

So what CAN you do...

you can use event.sendAfterMilliseconds or event.sendAfterBeats for one thing. For the actual sending of events, that works good for scheduling them in the future.

But what if you need to execute some Javascript code at some point in the future? Well that is the question then.

what you can do is use the Date.now() function to look at the current timestamp (in ms since 1970). Every time ProcessMIDI is called you look at Date.now() and you will know when so many ms have gone by, when enough have gone by, then go ahead and fire off your javascript.

That will work, but it's imprecise. For one thing, that will fire off javascript code to happen at the time the code is actually executed, which will always be ahead of the actual real time music. Javascript doesn't run in real time like you hear the metronome going by. LogicPro is always trying to run all kinds of calculations ahead fo the music. All plugins process their part of the process-block ahead of time and fill the buffer and finally when the buffer is flushed to your sound card later, then the results are heard. But the exact timing of when each plugin will have its turn on the process block, ahead of time...is not knowable. You will never know exactly when this code is executing in non-realtime ahead of the music. So this will definitely work...but its not completely precise. Depending on how accurate you need to be, this may work totally fine.

If you absolutely want sample accurate timing of things to happen, then you have to get used to working with the beatPosition every time ProcessMIDI is called. In that way you always run whatever javascript code you need to do, but the main thing is, if you plan to send out some midi, you schedule it on the proper beatPosition (which is a sample accurate fractional value) and the results will be exactly in the timing you want.

One downside is that beatPosition is not an exact amount of real time. 1.5 beats represents a completely different mount of time at one tempo compared to 1.5 beats at a different tempo. So how can you know when so many ms have gone by? You'd literally have to calculate it each process-block, look at the tempo for that process-block and use the beatPosition delta and guess at how many ms have gone by. But this is a little imprecise too.

well anyway, It depends on what you're wanting to do, but generally I would recommend you work with beatPosition if you are planning to output midi using correct timing. But there you have some options to play with.
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram
 
DGB111
Posts: 21
Joined: Sun Apr 02, 2017 2:36 pm

Re: Slew/Glide for Aftertouch/Midi CC

Thu Oct 15, 2020 6:23 pm

Thanks!

Just trying to wrap my head around exactly how to lag midi data via a script (like applying a lag amount in Kontakt modulators) like mentioned above. Would be super helpful for a project I'm working on.

I know that the AT info can be sent delayed, but then it's not able to be used by the script anymore, like if new AT data came in that might conflict with it.

Was thinking of something like, when you release AT - start sending the AT value slowly down to zero - then if new AT info comes in - interrupt that descent and start sending the AT value up to the new info.

All the experiments I've been playing around with in ProcessMIDI (thanks again for that!) have worked, but since the calculations all happen instantly there's no time to check for changed conditions.

Is there a way to wait inside of a loop, and break the loop under conditions? Or do you check every x milliseconds (some way other than setTimeout)?

Thanks again!!!
 
User avatar
Dewdman42
Posts: 3307
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Slew/Glide for Aftertouch/Midi CC

Thu Oct 15, 2020 6:32 pm

no you have to bear in mind that each time process-block of time goes by.... two things will happen, where LogicPro will call callback functions that you provide in Scripter.

  1. ProcessMIDI will be called once
  2. if there are any incoming midi events in that process-block, then each one will cause HandleMIDI to be called on its behalf.

So anyway, what I hear you saying is that you can't use sendAfterMilliseconds to send a trail of AT events, because if more AT events come in from the midi controller you want that to supersede the stuff you may have tried to schedule. And once you schedule it with sendAfterMilliseconds, you can't take it back.

But anyway what you can do is create global variables to keep track of your AT value. When HandleMIDI is called with an AT event, you set the global variable to that value, and probably send the event right now. and at that time maybe you set some other variables for whatever future trail of automatic AT events you are hoping to send.

then each time ProcessMIDI is called, you look at the current beat position and you look at those global variables and you send out just the AT events for that brief little period of time. the next call to ProcessMIDi will send the next slice of the AT trail, etc..

then if HandleMIDI is called again with another AT, you overwrite those global variables to change the AT curve to where it needs to be so that the following calls to ProcessMIDi will be on a new curve with a new trail of AT to send out.
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram