A technical support community for Apple Logic Pro users.

 
atmos74
Topic Author
Posts: 4
Joined: Sun Jun 13, 2021 4:24 am

Changing Mainstage patches automatically

Mon Jun 14, 2021 2:20 am

Hi

I am a keyboard player and am using mainstage for live performance. I am using the playback function to run some backing tracks for each song. I am trying to find a way to change my patches automatically so the correct one appears for verse, chorus etc and I do not need to trigger them from a footswitch or similar.

I have done some research on this forum and found suggestions on Bidule (which I had a look at but do not know how to use) and scripting (Dewdman42 seems to be the man on this) I tried the scripting route but there seemed to be some issues with looping as the playback was juttering and my keyboard layers disappeared for some reason.

Can anyone help, understand if it is not possible!. I do own logic as well so if there is an option to run the backing track in logic with midi triggers I am happy to do that but would need guidance. Sorry I am fairly new to the software......appreciate any help you can give.

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

Re: Changing Mainstage patches automatically

Mon Jun 14, 2021 8:36 am

I’m running out the door but search the forum I posted a solution for this before. You have to use IAC to send the pc message around to feed back into main stage. If you have something already post what you did and we can look for problems later tonight
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram
 
atmos74
Topic Author
Posts: 4
Joined: Sun Jun 13, 2021 4:24 am

Re: Changing Mainstage patches automatically

Mon Jun 14, 2021 9:05 am

Thanks, I think I found that one.....here is my attempt at it. Not sure what I maybe doing wrong!
Cheers
80's Band v3.zip
You do not have the required permissions to view the files attached to this post.
 
User avatar
Dewdman42
Posts: 3304
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Changing Mainstage patches automatically

Mon Jun 14, 2021 9:05 pm

A couple things I notice, some are relevant to your problems and some are just observations or suggestions you may find useful:

  1. Looks to me like you are attempting to use Bank Select to direct PC messages to the appropriate song and then PC# 2-n within each song. That's a perfectly fine way to handle it, but the current version of the script doesn't send bank select messages. Bank select messages are created using CC0 and CC32 messages. see this article: http://www.andrelouis.com/qws/art/art009.htm

    Here is a version of your script with bank select added:

    var NeedsTimingInfo = true;

    //========= EDIT THIS ARRAY ====================

    var programChanges = [
        {beatPos:4.99, channel:1,  number:1, msb:1, lsb:1}
       ,{beatPos:8.99, channel:1,  number:2, msb:1, lsb:1}
       ,{beatPos:12.99, channel:1, number:3, msb:1, lsb:1}
       ,{beatPos:16.99, channel:1, number:4, msb:1, lsb:1}   
       ,{beatPos:20.99, channel:1, number:5, msb:1, lsb:1}
       ,{beatPos:24.99, channel:1, number:6, msb:1, lsb:1}
       // copy the above line for more Program changes
    ];


    //========= DO NOT EDIT BELOW HERE =============

    var idx = 0;
    var pc = new ProgramChange;  //reuse in a loop
    var cc = new ControlChange;

    function ProcessMIDI() {
       /* Get current timing info */
       var info = GetTimingInfo();
     
       /* only do work if playing */
       if ( !info.playing ) {
           idx = 0;
           return;
       }
       
       if (idx < programChanges.length) {
       
          while ( idx < programChanges.length &&
                  info.blockStartBeat <= programChanges[idx].beatPos &&
                  info.blockEndBeat >= programChanges[idx].beatPos ) {
             cc.number = 0;
             cc.channel = programChanges[idx].channel;
             cc.value = programChanges[idx].msb-1;
             cc.send();
             
             cc.number = 32;
             cc.value = programChanges[idx].lsb-1;
             cc.send();
                   
             pc.number = programChanges[idx].number - 1;   
             pc.beatPos = programChanges[idx].beatPos;
             pc.channel = programChanges[idx].channel; 
             pc.send();
             // pc.trace();
             idx++;
          }             
       }
    }

    // ignore incoming midi - might not need this
    function HandleMIDI() {
    }


    Without the bank select message added to the script, then the song was jumping to the next song. The next song didn't even have a script, and also its possible that an endless midi feedback loop may have somehow ensued, which might explain all the flickering and erratic behavior. Not completely sure about that, it happened to me when I first started using your project, but once I added bank select, it stopped happening...but that is my guess.

  2. You are sending PC messages on channel 16. Why?

  3. Mainstage has two ways to consider PC messages, starting at zero or starting at 1, which is the so called "Standard" way. Scripter is hard coded to use the low level midi values, which means the first and lowest PC message you can send with Scripter is value=0. When that PC#0 goes over IAC and back into MainStage, if it is set in preferences to 1-128 as the PC range..which is normal...then that PC=0 will be treated as patch#1.

    I added a bit to the scripter script, see above, so that you can use the value of "1" in the array at the top...and it will convert that to an actual PC=0 message, so that when it comes back into MainStage that PC0 will be treated like patch #1. Hope that makes sense. The bank select messages are also handled in the same way. This way the script array you fill out should match the numbers you type into MainStage to define each patch's bank select and PC messages based on 1-128 range.

    Also notice that bank select is an MSB/LSB value. See the above article, hope that will make sense. You can literally have over 2 million separately identifiable patches this way.

    Side-note: You could simplify this script to only use MSB and skip the LSB. These are known as "course" and "fine" patch bank select, many synths and devices only use the MSB "course" to indicate a bank select...So anyway 128 banks for 128 songs is probably enough if you want to simplify things you can remove the LSB handling from the script and just use MSB. But the script has both for illustrative purposes.

  4. Another important point that I re-remembered while doing this, but you will want to think about...whenever you select a song, don't select the Set Folder, select the first patch of the song before hitting PLAY. I have found some weird things happen if you select the top folder...then press PLAY, the script works but somehow skips the first patch, I haven't been able to figure out why, but if you get any wierdness with that, that is why..make sure you always select the first patch of each song, then hit PLAY, don't choose the song set folder.

Here is an updated version of your MainStage project to check it out.

80's Band v3-1.zip
You do not have the required permissions to view the files attached to this post.
Last edited by Dewdman42 on Mon Jun 14, 2021 9:44 pm, edited 4 times in total.
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: 3304
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Changing Mainstage patches automatically

Mon Jun 14, 2021 9:19 pm

As an advanced alternative, here is a version of the script which uses global values for bank select for the whole script, since each song will basically have its own script...you can just choose one bank select MSB/LSB for the whole song which would handle up to 128 patches within that bank. That keeps the script array smaller and simpler to edit:

check it out:

var NeedsTimingInfo = true;

//========= EDIT THIS ARRAY ====================

var MSB = 1;
var LSB = 1;

var programChanges = [
    {beatPos:4.99, channel:1,  number:1}
   ,{beatPos:8.99, channel:1,  number:2}
   ,{beatPos:12.99, channel:1, number:3}
   ,{beatPos:16.99, channel:1, number:4}   
   ,{beatPos:20.99, channel:1, number:5}
   ,{beatPos:24.99, channel:1, number:6}
   // copy the above line for more Program changes
];


//========= DO NOT EDIT BELOW HERE =============

var idx = 0;
var pc = new ProgramChange;  //reuse in a loop
var cc = new ControlChange;

function ProcessMIDI() {
   /* Get current timing info */
   var info = GetTimingInfo();
 
   /* only do work if playing */
   if ( !info.playing ) {
       idx = 0;
       return;
   }

   if (idx < programChanges.length) {
   
      while ( idx < programChanges.length &&
              info.blockStartBeat <= programChanges[idx].beatPos &&
              info.blockEndBeat >= programChanges[idx].beatPos ) {
         cc.number = 0;
         cc.channel = programChanges[idx].channel;
         cc.value = MSB-1;
         cc.send();
         
         cc.number = 32;
         cc.value = LSB-1;
         cc.send();
               
         pc.number = programChanges[idx].number-1;   
         pc.beatPos = programChanges[idx].beatPos;
         pc.channel = programChanges[idx].channel; 
         pc.send();
         // pc.trace();
         idx++;
      }             
   }
}

// ignore incoming midi - might not need this
function HandleMIDI() {
}
Last edited by Dewdman42 on Mon Jun 14, 2021 9:46 pm, edited 3 times in total.
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: 3304
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Changing Mainstage patches automatically

Mon Jun 14, 2021 9:37 pm

An even more advanced version could probably just assume a global midi channel also, to remove it from that script array, to make it easier to edit. You could also reduce that script array to something like the following structure for easy editing in a less-verbose structure. This should make it easier to edit each script for each song.

//Global values for this script
var CHANNEL = 1;
var MSB = 1;  //bank select MSB course
var LSB = 1;   // bank select LSB fine

var programChanges = [
    [ 4.99,   1]
   ,[ 8.99,   2]
   ,[ 12.99,  3]
   ,[ 16.99,  4] 
   ,[ 20.99,  5]
   ,[ 24.99,  6]
   // copy the above line for more Program changes
];


So the full script using the above would be this in order to make that simpler array work:

var NeedsTimingInfo = true;

//========= EDIT THIS ARRAY ====================

//Global values for this script
var CHANNEL = 1;
var MSB = 1;  //bank select MSB course
var LSB = 1;   // bank select LSB fine

var programChanges = [
    [ 4.99,   1]
   ,[ 8.99,   2]
   ,[ 12.99,  3]
   ,[ 16.99,  4] 
   ,[ 20.99,  5]
   ,[ 24.99,  6]
   
   // copy the above line for more Program changes
];

//========= DO NOT EDIT BELOW HERE =============

var idx = 0;
var pc = new ProgramChange;  //reuse in a loop
var cc = new ControlChange;

function ProcessMIDI() {
   /* Get current timing info */
   var info = GetTimingInfo();
 
   /* only do work if playing */
   if ( !info.playing ) {
       idx = 0;
       return;
   }

   if (idx < programChanges.length) {
   
      while ( idx < programChanges.length &&
              info.blockStartBeat <= programChanges[idx][0] &&
              info.blockEndBeat >= programChanges[idx][0] ) {
         cc.number = 0;
         cc.channel = CHANNEL;
         cc.value = MSB-1;
         cc.send();
         
         cc.number = 32;
         cc.value = LSB-1;
         cc.send();
               
         pc.number = programChanges[idx][1]-1;   
         pc.beatPos = programChanges[idx][0];
         pc.channel = CHANNEL; 
         pc.send();
         // pc.trace();
         idx++;
      }             
   }
}

// ignore incoming midi - might not need this
function HandleMIDI() {
}
Last edited by Dewdman42 on Mon Jun 14, 2021 9:47 pm, edited 1 time in total.
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: 3304
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Changing Mainstage patches automatically

Mon Jun 14, 2021 9:41 pm

anyway, that's enough scripting for one night. good luck. If you're gonna use this for gigging, I recommend you become intimately familiar with how these scripts actually work just in case.
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram
 
atmos74
Topic Author
Posts: 4
Joined: Sun Jun 13, 2021 4:24 am

Re: Changing Mainstage patches automatically

Tue Jun 15, 2021 1:25 am

Thanks so much for all of your help with this. Am at work currently but will give this a try when I get home.
Cheers
 
atmos74
Topic Author
Posts: 4
Joined: Sun Jun 13, 2021 4:24 am

Re: Changing Mainstage patches automatically

Tue Jun 15, 2021 2:07 pm

Hi, just gave this a try tonight.....should the patches be changing automatically when I hit the play button? Nothing was changing as far as I could tell this end. Apologies if I'm missing something obvious.
I have checked my IAS bus is online. I am using a midi keyboard to add live keys to the track. What midi channel should this be on?
Thanks
 
User avatar
Dewdman42
Posts: 3304
Joined: Tue Sep 09, 2014 3:01 pm
Location: Salt Lake City, UT

Re: Changing Mainstage patches automatically

Tue Jun 15, 2021 2:11 pm

Yea, they will change according to the script. Make sure you choose the first patch of the song set and hit the play button. If its not changing...then check your IAC connections... I made a lot of comments already you will have to troubleshoot from there.
OSX 10.15 (Catalina) on OpenCore - Logic Pro 10.6.1, VePro7, Mainstage3
5,1 MacPro 3.46ghz x 12 96gb ram