Jump to content

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


Recommended Posts

I'm sure scripts will be popping up, for sure, but there won't be any money in it for anyone. This is, after all, the internet, where everyone expects everything for free. And there's no way to lock a script or copy protect it.
Link to comment
Share on other sites

Since we can create midi events in a script, it should be possible to access/address any element in a logic instrument plugin that is capable of being controlled via a midi controller assignment . . . right?

 

So say for a random example: I want to lower the cutoff on the exs low pass filter based on the number of midi notes played simultaneously. More notes => darker filter. I set the exs filter to be modulated by some midi controller and then I write a script which looks at the number, n, of midi note-on events and creates/sends a controller change with magnitude proportional to n.

 

Many exciting possibilities.

Link to comment
Share on other sites

Re your example, indeed. You can set up both a note counter (and range), and if you satisfy the condition of X number of notes in that range, you can output a CC to modulate a filter, with a value that's proportional to (whatever). Or, you can count notes and output a CC that decreases in value with each note played, with the value determined by the setting of a user-defined slider. Etc. :mrgreen:
Link to comment
Share on other sites

Diving into MIDI Scripting. I've already written a few little routines and (drum roll please) they work!

 

What can be done with MIDI Scripting far outweighs what can be accomplished using environment objects alone, both in terms of function and complexity. For example, it's fairly simple (though awkward) to create the equivalent of a simple "if-then" or "if-else" function (comparator) using a transformer. For this you'd use the Condition Splitter mode, define a condition, and have all data that meets the condition output on the top cable. Everything else outputs on the bottom cable. Simple. But if you need to test for more than one condition (if A, then, if B...), the awkwardness factor of programming individual transformers increases logarithmically because you have to cascade the various transformer's outputs, and when it comes to editing their values you can only view one transformer's window at a time.

 

With Javascript, all you have to do is write a few lines of code to accomplish these tasks and the order of operations is laid out before your eyes in one window.

 

Also, it's extremely difficult to create the equivalent of variables using Environment programming. Again, with Javascript it's a piece of cake..

 

Nerdily delicious! Looking forward to diving into this! :)

 

J.

Link to comment
Share on other sites

I made my Hello World script. Takes Program Change messages and converts them to MIDI notes. Useful for keyswitching using program changes. So fun.

 

//************************************************
// Convert Program Changes into MIDI Note on messages
//************************************************

var PluginParameters = [{name:"Key Offset", type:"lin", minValue:1, maxValue:127, numberOfSteps:126,defaultValue:1}];


function HandleMIDI(event)
{
var progchange = 0;
var keyswitch = new NoteOn;
var offset = 1;

event.send();

offset = GetParameter("Key Offset");

if (event instanceof ProgramChange) {

	progchange = event.number + offset;
	keyswitch.pitch = progchange;
	keyswitch.send();
	var off = new NoteOff(keyswitch);
	off.send();
}


 

And somehow my inline comments didn't get saved... bad coder, bad coder :)

Link to comment
Share on other sites

Iteration! Kind of a big deal. :)

 

I'm curious how this can be integrated into the environment.

 

It's also very interesting with the ipad control support and enhanced control and automation over Logic's interface available in X.

 

This could be a way to automap a bunch of parameters with minimal clicks.

Link to comment
Share on other sites

Related but not precisely on-topic: Does anyone know if LPX has better support for AppleScript/Automator? I'd love to be able to control the transport from a script outside of Logic,. e.g. play from, say, bar 13 to bar 17, then bar 5 to bar 7, etc.

 

Why use Automator when you can now use Arrange Markers to do what you just described? :)

Link to comment
Share on other sites

@ shagstaphone, thanks for posting that. VERY helpful! Saves having to view them in individual script editor windows. Examining them on my laptop as I experiment with scripting routines on my big system.

 

Hey... does anyone know where to find a COMPLETE listing of all available MIDI javascript methods and arguments? I've been compiling one by examining each of the individual stock scripts and making notes. and it's been an excruciating exercise. Would love to see it all spelled out somewhere.

 

Thanx,

 

Peter

(ski)

Link to comment
Share on other sites

Related but not precisely on-topic: Does anyone know if LPX has better support for AppleScript/Automator? I'd love to be able to control the transport from a script outside of Logic,. e.g. play from, say, bar 13 to bar 17, then bar 5 to bar 7, etc.

 

Why use Automator when you can now use Arrange Markers to do what you just described? :)

 

I often use Logic when learning new songs and fiddle tunes from recordings. I've found that practicing small sections, e.g, a couple of bars at a time and in random order each works really well to counteract my tendency to learn the beginning and end far better than the middle. It also makes woodshedding a lot more fun for me.

 

It's trivial to write a program to generate a new practice sequence each time, but AFAICT it's not trivial, in prior versions of Logic, to use the program output to control the transport. I'm not familiar with Arrange Markers but I'm betting it's something I'd have to set up manually each time. Is that the case?

Link to comment
Share on other sites

Related but not precisely on-topic: Does anyone know if LPX has better support for AppleScript/Automator? I'd love to be able to control the transport from a script outside of Logic,. e.g. play from, say, bar 13 to bar 17, then bar 5 to bar 7, etc.

 

Something like that couldn't be any simpler by using the cycle bar.

Link to comment
Share on other sites

Thanks Eric,

 

Indeed, I've been studying that documentation for the past two days. But as I tear apart the stock scripts, I see lots of javascript "methods" which aren't described in the manual.

 

The Logic-specific stuff is the MIDI, Event and Timing objects, and some stuff for creating parameters on screen - everything else should be core javascript stuff. What sort of things are you seeing that you're unclear on?

 

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

 

Another thing that would be cool would be to be able to send events to MIDI ports directly. That would bypass the AU MIDI-out limitation and allow MIDI Script processed/generated events to be fed back into the environment (and also into other MIDI Scripter objects) but I don't think that is supported at the moment...

Link to comment
Share on other sites

Related but not precisely on-topic: Does anyone know if LPX has better support for AppleScript/Automator? I'd love to be able to control the transport from a script outside of Logic,. e.g. play from, say, bar 13 to bar 17, then bar 5 to bar 7, etc.

 

Something like that couldn't be any simpler by using the cycle bar.

 

Shiver, are you saying the cycle bar can be programmatically adjusted on the fly? I've already keymapped forward and backward cycle region movement and other transport/record operations into the the upper octave of my midi keyboard. That works pretty well for most things I do, but it's a real distraction to step back and forth by, say, 23 bars if I'm holding a violin and bow. That's why I want to control the transport from outside Logic.

Link to comment
Share on other sites

I am thinking of a foot controller. I can use the key commands for go to marker x and have the cycle bar turned on.

Step on pedal 1 and the playhead jumps to marker 1 and cycles until you select the next preset marker.

 

Thanks, Shiver. Your mention of a foot control clicked the light bulb for me. I realized there are scads of hardware controllers (Mackie, etc) that can manipulate Logic's transport with MIDI messages. I already have software that can send arbitrary midi to Logic, so now I just have to work out what messages to send to set the cycle locators to the desired start and end positions. If I get it working, I'll share the code so others can use it.

Link to comment
Share on other sites

The Logic-specific stuff is the MIDI, Event and Timing objects, and some stuff for creating parameters on screen - everything else should be core javascript stuff. What sort of things are you seeing that you're unclear on?

 

Thanks for replying Beej. I'll post back with some of the terms after I've made a little more headway compiling my list, but one thing that comes to mind...

 

In one of the stock MIDI plugins (snifolrn* so I don't recall which one), I saw a line that read:

var PluginParameters.push

 

It's the ".push" part that's unfamiliar to me.

 

(* = sorry, not in front of Logic right now)

Link to comment
Share on other sites

I am thinking of a foot controller. I can use the key commands for go to marker x and have the cycle bar turned on.

Step on pedal 1 and the playhead jumps to marker 1 and cycles until you select the next preset marker.

 

Thanks, Shiver. Your mention of a foot control clicked the light bulb for me. I realized there are scads of hardware controllers (Mackie, etc) that can manipulate Logic's transport with MIDI messages. I already have software that can send arbitrary midi to Logic, so now I just have to work out what messages to send to set the cycle locators to the desired start and end positions. If I get it working, I'll share the code so others can use it.

 

If you manage to get that working I'd love to see that. :D

Link to comment
Share on other sites

Thanks, Shiver. Your mention of a foot control clicked the light bulb for me.

 

You can use the Key command 'Go To Marker" and set up 20 markers. Those commands can be set up to be controlled by midi instead of the keyboard via Lear New Assignment. The cycle points follow whatever you have the marker length set to. Once Ski learns Java, maybe he can figure out how to 'on the fly' manipulate the marker length - kind of like a transformer meta event or something. :roll: (or program the meta goto right in the arrange window).

 

Any way, if you set your markers up ahead of time and you have a foot controller, then your worries are over.

533377352_ScreenShot2013-07-20at2_46_46PM.png.ff77c2237c602275f9dcfcffbbe0984e.png

816908103_ScreenShot2013-07-20at2_57_57PM.png.1b2630b470db32fa4dc8b759bafa5436.png

Link to comment
Share on other sites

It's the ".push" part that's unfamiliar to me.

push is usually used to add an object or element to the end of an array (in many scripting languages like Ruby and Javascript . . . ). But it always has an argument. So for example:

 

//create an array and add some strings to it

var parameters = new Array();

parameters.push("gain");

parameters.push("filter_frequency");

Link to comment
Share on other sites

Once Ski learns Java...

 

My javascript (eh, not java, different animal) is definitely a little rusty, but improving by the minute :mrgreen:

 

...maybe he can figure out how to 'on the fly' manipulate the marker length - kind of like a transformer meta event or something. :roll:

 

Thanks for having faith in me. I think. Um...... :shock:

 

Here's an idea :idea: though... Perhaps :?: some of these javascript properties could be used to manipulate looping:

 

TimingInfo.blockLength: A floating point number indicates the length of the process block in beats.

TimingInfo.cycling: Uses Boolean logic where “true” means the host transport is cycling.

TimingInfo.leftCycleBeat: A floating point number indicates the beat position at the start of the cycle range.

TimingInfo.rightCycleBeat: A floating point number indicates the beat position at the end of the cycle range.

 

In conjunction with those, the script could output MIDI data that then goes to Environment-based MIDI objects to generate the necessary Meta Events which -- in turn -- move the playhead to specific markers or whatever.

 

Just guessing here, but it seems, um, logical that some combo of the two might work.

Link to comment
Share on other sites

Just guessing here, but it seems, um, logical that some combo of the two might work.

Those properties may be read-only. The doc shows a GetTimingInfo() function to retrieve a timing object, which is likely to be a copy of the current timing properties. I would expect to see a corresponding SetTimingInfo(myInfo) function if changing the properties was supported. Maybe it's there but not documented. Good luck!

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.

Link to comment
Share on other sites

+1

 

Beej, another example of something I'd like to see explained in writing... Either in the manual or in one of the example scripts, there's an event type called "Note", as in:

 

if (e instanceof Note && e.velocity >64) {

 

While the manual lists event types of NoteOn and NoteOff (both self-explanatory), there is no mention of Note. So I'd like to read documentation as to what distinguishes Note from the other, similar event types.

 

On another subject, I'm finding that the Scripter doesn't seem to recognize global variables declared before "HandleMIDI". In one script I'm writing, I thought I had it working, but then it stopped. Anyone else experience this?

 

Cheers,

 

Peter

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.

 

That's weird about the global variables not being recognized when declared before HandleMIDI() function... I'm new to Javascript, but I would think that declaring a global variable earlier rather than later in the script, as long as it's declared globally (outside all functions), shouldn't be a problem. What do you mean exactly by failure to "recognize," are you getting an error message?

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...