Jump to content

Help with ProcessMIDI() Hello World!


Recommended Posts

Hi everybody. While I'm not new to programming, I am new to developing for midi/Scripter. I've been trying to get a proof of concept with ProcessMIDI(). What I want to do is simply print a Trace() message in the console on every beat. I was trying some things out based on the tutorial scripts but it crashed Logic and I lost my work in the process too. So now that I'm back to square one, if somebody could be kind enough to provide a simple js code snippet that illustrates how I could get a Trace() on every beat I would really appreciate it.

 

 

Thanks!

Link to comment
Share on other sites

BTW: Wow, not a lot of traffic in this section :(

 

I guess there's not that many Logic users that happen to be into coding too.

 

Still, most people that come here looking for help with a script usually get it.

 

Never mind, I figured it out.

Since you figured out your own problem, how about sharing your solution with the rest of us?

I for one would appreciate reading it and that's the point of these forums anyway, to share knowledge.

 

J.

Link to comment
Share on other sites

I guess there's not that many Logic users that happen to be into coding too. 

 

Still, most people that come here looking for help with a script usually get it.

J.

 

My apologies if I seemed like I was trying to slam the site (I wasn't I was just disappointed). I was getting a bit frustrated after trying to deal with ProcessMIDI() and failing at every turn. Going to the only online Logic community I knew of only to find crickets was disheartening, but I digress. In the end, I did find a way to get a hello world type application. Here is the code...

 

// ProcessMIDI Hello Downbeat!

var currentBeat = 0;
NeedsTimingInfo = true;
function ProcessMIDI()
{
  var info = GetTimingInfo();
//calculate all values
var currentDiv = 4; // Divisions
var beat = Math.ceil(info.blockStartBeat * currentDiv) / currentDiv;

// Filter duplicates and detect downbeat
var wholeNumber = beat.toString().indexOf(".")==-1; // boolean
if(info.playing && beat !== currentBeat){
 currentBeat = beat;
 if(wholeNumber === true){
   Trace("DOWNBEAT: " + beat);
 } else {
   Trace("Beat: " + beat);
 }
}
}

 

I have abandoned this approach for two reasons. The first is that the timing is off. This code will output what you want to see in the console but it is approximate and not in sync with the sequencer's click. After noticing that the timing was not on the beat, I quickly skimmed through the "Sequencer" named Scripter plugin factory preset. I noticed that there are functions in there to calculate probability and at that point I started looking for another method. The second reason is that by simply setting NeedsTimingInfo = true; that API call maxes out an entire CPU core. That's without any other code running or even the transport turned on in a practically empty Logic project. 

 

Anyway, my purpose for this whole exercise is to build a functioning step sequencer. With any other programming environment, the first thing you would want to do when trying to create a sequencer is to create a metronome type object. So with that in mind, I used Logic's midi click in the environment as a replacement for ProcessMIDI(). I also send MTC through a separate IAC bus to detect playhead position. Once these are being fed to Scripter, it is easy to call custom functions from HandleMIDI() and manipulate things. 

Link to comment
Share on other sites

Here is my understanding of the issue with the code I posted. The property GetTimingInfo.blockStartBeat gets the starting point of a "process block". The starting point is measured in relation to the bars/beats ruler in the timeline. Think of two trains on two different tracks going the same direction but at different speeds and with different car lengths. The cars simply don't line up and you'll have to do a lot of calculations to figure out when they will line up. 

 

I don't understand why the Logic team thought this would be useful in any way. I'm not clear on exactly what they are referring to by a "process block" (ticks maybe?), but it seems something way too low level to be trying to manipulate via an interpreted language like javascript. Especially in an application where timing is crucial. This also might have something to do with why this particular API call is so non-performant. 

 

Most importantly, unless blocks are ticks, end users probably don't care about them. Even if blocks are ticks, users are way more likely to want timing info in terms of bars, beats and divisions. The midi click provides all of these, so that's what I used for my workaround. I set the metronome to send midi only and created a dedicated click instrument track. I set the metronome to send the bars beats and divisions on separate midi channels. This allows me to control the click track in the mixer and I get all the midi info via a dedicated IAC bus I labelled "Transport". I also send MTC to the same IAC bus and this will give me playhead position when a transport button is pressed.

 

Personally, I think they should do away with ProcessMIDI() and implement a bridge to let Scripter tap into Logic's OSC interface. Almost everything you'd want for timing info and more has already been implemented there. You'd be able to control anything that the LogicRemote app can control.

Link to comment
Share on other sites

I have abandoned this approach for two reasons. The first is that the timing is off. This code will output what you want to see in the console but it is approximate and not in sync with the sequencer's click.

 

Apparently they were aware of that:

 

Timing for the ProcessMIDI() function in the Scripter plug-in has been improved.

 

J.

Link to comment
Share on other sites

  • 1 month later...

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...