Jump to content

Make your own Logic Pro X MIDI Plug-ins in JavaScript!


Recommended Posts

Hi Ombudsman,

 

Thanks so much for your reply. Indeed, I'm always explicit when it comes to NoteOn and NoteOff. But if I wanted a shortcut for detecting (and filtering, say) any kind of note message (both on or off), it seems like testing for Note would make quick work of writing that routine.

 

Regarding global variables, I've written several routines where I declare a variable outside of the HandleMIDI() function and it isn't recognized within a later an if-else statement (yes, got an error message). Could well be pilot error. I'll experiment some more and see what's going on.

 

Thanks again,

 

Ski

Link to comment
Share on other sites

Ski, sure thing, and I should say thank YOU for all the knowledge you've shared on this forum! I've lurked on here for a while and have found your posts extremely helpful in learning how to think about Logic's environment. I finally registered an account just to write in this thread! Yeah, MIDI Scripter is just that exciting.

 

I'm pretty disappointed, though, that the MIDI Plugins seem to exist within their own restricted scope on the software instrument channel strip. They just live on the channel strip where they're inserted and can only talk to that software instrument object and other MIDI plugins in series. As far as I can tell, there's no way to access their output in the environment. If you cable the software instrument object to a monitor, you see that the MIDI originally sent via the Sequencer Input is passed through, while no MIDI data generated by a MIDI Plugin is passed through. So, no way to route the plugin-generated MIDI data to environment objects or record it to a region... Also, you can't use these plugins on external MIDI tracks. I'll be thrilled if somebody proves otherwise...

 

That said, using the Scripter can vastly extend one's control of a software instrument, especially in combination with the environment. It's just that the signal flow has to be [environment manipulation] >> [MIDI Scripter manipulation] >> [software instrument performance].

Link to comment
Share on other sites

Now that i red the documentation, and i do have background in web design, i'm thrilled!. Now i just need good bottle of whiskey and come up with some nice idea!.

 

It also good to keep "Logic midi scripter" column on your twitter app, just picked up this from some japanese guy (@kyodosaeki) :mrgreen:

 

//************************************************

// nabeatsu of the world

//************************************************

 

var c = 0;

var i = 0;

var m;

 

function HandleMIDI(event)

{

i = i + 1;

if(i % 2){

c = c + 1;

j = c % 3;

k = c / 10;

k1 = Math.floor(k);

l = c - k1 * 10

if(j == 0 || k1 == 3 || l == 3) {

event.pitch += 12;

m = 1;

}

}

else{

if(m){

event.pitch += 12;

m = 0;

}

}

event.trace();

event.send();

}

Link to comment
Share on other sites

Thanks for your kind words ombuds!

 

I'm pretty disappointed, though, that the MIDI Plugins seem to exist within their own restricted scope on the software instrument channel strip. They just live on the channel strip where they're inserted and can only talk to that software instrument object and other MIDI plugins in series. As far as I can tell, there's no way to access their output in the environment. If you cable the software instrument object to a monitor, you see that the MIDI originally sent via the Sequencer Input is passed through, while no MIDI data generated by a MIDI Plugin is passed through. So, no way to route the plugin-generated MIDI data to environment objects or record it to a region... Also, you can't use these plugins on external MIDI tracks. I'll be thrilled if somebody proves otherwise...

 

While I suspect you're 100% right on this, I'm going to try a little voodoo and see if there isn't a way around this. :mrgreen:

 

And indeed, it would be a real boon to have an Environment-based scripter object. If we want to process MIDI data before it ever enters Logic from the outside world, we still have to use Environment objects to do that processing. Put another way, if we want to have MIDI processing that occurs between the output of the Physical Input and the Sequencer Input, it still has to be done with Transformers and so on.

 

Of course, we could write a script to do this and insert a Scripter on the input of every single Instrument channel, but that would mean a lot of redundancy. And since MIDI Instrument objects don't provide MIDI FX inserts, we still need to use the Environment to process MIDI going to them.

 

Anyway... on to my experiments!

 

// Global Variables

var yay = "post about it on forum";

var nay = "don't post about it on forum";

var experiment = undefined;

 

if (experiment) {

Trace(yay);

} else {

Trace(nay);

}

 

:mrgreen:

Link to comment
Share on other sites

Strangely, my function returned both "yay" and "nay". :shock: :mrgreen:

 

Here's the deal... I used the Scripter to test my theory, having it generate CC1 values in response to notes. Turns out you can indeed transmit the MIDI messages generated from the Scripter to the outside world (drum roll please) via the IAC bus. Now for the details...

 

Just as you pointed out, when you connect a monitor to the output of an instrument cs it will not display MIDI generated by the Scripter. However...

 

• Connect the output of the instrument cs to an environment MIDI instrument object. Set its Port to output to the IAC bus.

 

At this point, don't play anything or move any controls because you've got a MIDI feedback loop just waiting to happen.

 

• Go to the Clicks & Ports layer and connect a monitor object to the IAC port on the Physical Input. (Doing this will break the feedback path and now it's safe to play).

 

Voila! As you play you will see the Scripter's MIDI data appear in that monitor! So yes, it's true, the monitor showing output from the instrument cs is lying to us!

 

Here's another way to do it...

 

• Create an instrument cs and install the External MIDI I/O plug. Set it to output via the IAC bus. Then, run a cable from the IAC bus port on the Physical Input to the desired destination.

Edited by ski
Link to comment
Share on other sites

I didn't mean for my code to be taken literally. It was a "code joke" intended to reflect that I didn't know what kind of experiment I was actually going to undertake or what the results would be. However... what you wrote is very instructive & informative all the same. Thanks!
Link to comment
Share on other sites

I did see some related stuff in the Logic bundle framework with lists of supported javascript methods I can try to find again...

 

If you wouldn't mind digging that up again, I'd be very interested to see it. I'm not sure where to look, but I'll see if I can find it myself this evening.

 

Think it was this one:

/Applications/Logic Pro X.app/Contents/Frameworks/MADSP.framework/Versions/A/Resources/EventTypes.js

Link to comment
Share on other sites

@ Beej, yup, the internet is our friend! Just boned up (ooh matron) on arrays, .push and .splice on http://www.javascripter.net. There's also .sort which is gonna come in mighty useful! Gonna check out the link you just posted too.

 

@ mcng, thanks for the extra clarification. Really appreciate it!

 

Yes it's funny to fiddle and try to make things behave as they shouldn't be

 

Indeed! By fiddling around I discovered that aside from creating sliders and menus with var = PluginParameters you can create checkboxes too! It's just a matter of time before I figure out how to get several checkboxes to act like radio buttons. :)

 

I tried to add scripter on an external midi track but couldn't do it the midi instrument track way. Is it impossible?

 

Yes, it's impossible. One way to do it would be to create a new Instrument cs and install a Scripter or other MIDI FX. Then use the External Instrument plugin to send MIDI to the desired port on your MIDI interface.

 

If you haven't seen it already, scroll up a few posts where I explain this in a little more detail. (viewtopic.php?p=509817#p509817)

 

Cheers guys, this is exciting stuff!

Edited by ski
Link to comment
Share on other sites

Best guess: Note is a subclass of Event and a superclass of both NoteOn and NoteOff. I would imagine that it defines most of the properties and methods that NoteOn and NoteOff inherit, but you'll probably never have occasion to instantiate a Note object per se, right? In any scenario where you're creating MIDI to send, you'll want to go one step down in the hierarchy and work with either a NoteOn or a NoteOff object. Still, it's useful to be aware of Note as a class for use in conditionals--say, to filter all NoteOn and NoteOff events in one logical operation.

 

Yep, that would be my interpretation too. I say this, I haven't actually done much actual playing with this stuff yet, but that would make sense.

Link to comment
Share on other sites

The only way to do it would be to create a new Instrument cs and install a Scripter or other MIDI FX. Then use the External Instrument plugin to send MIDI to the desired port on your MIDI interface.

 

Yes, that's how I was envisaging getting Scripter output to the "real" MIDI world, or back into the environment via IAC...

 

Good to know it works...

Link to comment
Share on other sites

Turns out you can indeed transmit the MIDI messages generated from the Scripter to the outside world (drum roll please) via the IAC bus.

 

Excellent, thanks Ski! I've never had to use the IAC driver (don't think I even have the bus enabled) so this didn't occur to me. Can't wait to try this out. Oh, the possibilities...

 

By fiddling around I discovered that aside from creating sliders and menus with var = PluginParameters you can create checkboxes too! It's just a matter of time before I figure out how to get several checkboxes to act like radio buttons. :)

 

How do you do checkboxes? I recall seeing some on/off radio buttons in one of the preset scripts in Scripter, I forget which one. I glanced at the code but don't remember what was different about the arguments to PluginParameters() for the radio buttons.

 

On a related note, there's a GetParameter() function, but has anyone tried to see if there's a SetParameter() function as well? It would be nice if those UI elements (slider positions, checkbox status, menu selections) could be updated programmatically within the script, either based on MIDI events or within the ParameterChanged() callbacks.

 

/Applications/Logic Pro X.app/Contents/Frameworks/MADSP.framework/Versions/A/Resources/EventTypes.js

 

Thanks!

Link to comment
Share on other sites

How do you do checkboxes?

 

Create a menu with values of 0 and 1 for min & max value, respectively.

 

On a related note, there's a GetParameter() function, but has anyone tried to see if there's a SetParameter() function as well?

 

Good question. Automation displays items for Scripter controls, but moving controls doesn't write data to Automation! Examining this all more closely is on today's Logic X "honey do" list.

 

It would be nice if those UI elements (slider positions, checkbox status, menu selections) could be updated programmatically within the script, either based on MIDI events or within the ParameterChanged() callbacks.

 

Sure would!

Edited by ski
Link to comment
Share on other sites

I reallly don't want to spoil the fun but in my experience, routing midi through IAC has alwas caused severe midi latency and midi jitter for me.

I think because the midi data through IAC is not timestamped.

So recording midi from IAC back into Logic always needed additional quantizing and lining up midi events, which i found irritating.

I am excited to hear your point of view concerning this issue !

Link to comment
Share on other sites

@ vanhaze, thanks for inviting my input on this. Yes it's exactly what you said; the downside of using IAC is timing problems (jitter, latency, even re-ordering of events and duplication of MIDI events). If might be useful for sending controller information where timing wasn't critical, but that's about all.

 

@ ashermusic, thanks! Yeah, the Script I wrote (which will be included as a free download) might make some people scratch wonder not so much how it works but why it works at all LOL!

Link to comment
Share on other sites

I've got one that remaps the keyswitches for the single instrument sounds in Cinematic Strings 2. The way CS2 is set up, some keyswitches are velocity-sensitive. For example, on the Arco articulation (C0), hitting that kswitch note softly gives you the "low" playing position, while hitting C0 hard gives you the "high" position.

 

Other articulations, such as Staccato, give you a choice of normal staccato or staccatissimo depending on how hard or soft you hit the Staccato keyswitch. Personally, I can't stand this velocity-sensitive keyswitching feature though I admire it all the same because it's a very clever idea.

 

There are also keyswitches to turn unison and live modes on/off which I never use (four in all) and which I accidentally hit all the time LOL! Fumbling notwithstanding, those keys are a waste of keyswitch "real estate". So...

 

Using the Scripter, I wrote a simple keyswitch-note-remapper to solve these problems. Now I have two individual keyswitches for selecting between the low/high arco positions, two more for selecting between staccatissimo/staccato, and so on. And I'm using additional keys to turn on/off some of the other features in CS 2, like the staccato overlay.

 

It could have done exactly the same thing using Kontakt Scripting, but using the Scripter is much easier (plus I know javascript a whole lot better than KSP).

Edited by ski
Link to comment
Share on other sites

[talk show host voice] "Before the show started, we asked our studio audience to write down questions for our guests. So now we throw the question back at you, Mr. Timbers. Kathy-Ann McGuillicutty from Pacoima wants to know what would YOU find interesting when it comes to MIDI Scripting."
Link to comment
Share on other sites

Great possibilitys with that Scripter.

 

Has anybody found a way to Set PluginParameters? Let's say i would like a menu Item to display the midi note that I'm playing.

 

 

The article has been published ahead of schedule! It's a Free Stuff article with a link to a project containing my custom script for EXS-24's "Full Strings+".

 

http://www.macprovideo.com/hub/logic-pro/logic-pro-x-free-script-for-incredible-new-scripter-midi-fx-plug-in

 

Cool, just one note...

 

Instead of writing all the Midi Note names down... "C-2", "C#-2", "D-2", "D#-2", "E-2","F-2","F#-2","G-2","G#-2","A-2","A#-2","B-2", etc

you can simply say: valueStrings: MIDI._noteNames

Link to comment
Share on other sites

SPUMD,

 

Funny you should write about that because only a few minutes after I got word that my article was published, I discovered MIDI._noteNames. But thanks for the heads-up all the same.

 

 

Cool, just one note...

 

Instead of writing all the Midi Note names down... "C-2", "C#-2", "D-2", "D#-2", "E-2","F-2","F#-2","G-2","G#-2","A-2","A#-2","B-2", etc

you can simply say: valueStrings: MIDI._noteNames

Link to comment
Share on other sites

Translation of the above, for anyone interested...

 

In the script included in the MacProVideo article linked to above, to cause the Split Point menu to list each of the 128 note names, I typed them out, one by one, in the code that creates the menu itself. But as it turns out, there's a routine built in to the Scripter that creates all 128 note names. All you have to do to access that list is call the variable MIDI._noteNames for the valueStrings attribute of the code that creates the menu. Voila!

 

There's a similar variable that will provide all 128 CC names as well: MIDI._ccNames

Edited by ski
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...