Derek Chan

Making a Melody Harmonizer in Logic Pro X

The Logic Pro X Scripter tool, specifically for manipulating incoming MIDI data, is an often overlooked one. If used correctly, it can make it easier to work with MIDI in general, especially with complex sequences. I myself make a niche electronic dance music genre called hardstyle. You can check out my stuff here, but I will say it is not the best stuff.

Now the reason I bring this specific genre up is because in order to maintain a massive, epic feeling and atmosphere, every element needs to sound a certain way. While I will acknowledge that the kick is probably the most obvious and noticeable element, the lead melody needs to sound huge as well. This feeling can be achieved using reverb and delay plugins, but there's a little more to it than that.

In order to make the lead sound huge, synth layering comes into play most of the time, not only of the same melody on different synth patches, but also harmonies of the melody.

Initially what I would do to make harmonies is to duplicate the melody pattern and adjust each note accordingly. This can take up time, especially when you have a secondary melody later in the track. Upon discovering the Scripter tool in Logic Pro X, I decided to make a harmonizer script. I can honestly say it has made things much easier.

Code

// Declare parameters
// Begin from 0 = C major or A minor
var PluginParameters = [{ name: "Key", type: 'lin', minValue: 0, maxValue: 11, numberOfSteps: 11, defaultValue: 0 }];

function scaleNotes(key) {
  // Major scale with key as root note
  var array = [key, key + 2, key + 4, key + 5, key + 7, key + 9, key + 11].map(function(n) {
    return n >= 12 ? n % 12 : n;
  });
  return array;
}

// Checks if note exists in scale
function noteInScale(note, key) {
  var normNote = note % 12;
  return scaleNotes(key).indexOf(normNote) > -1;
}

function roundUpCalc(note, key) {
  if (noteInScale(note + 4, key)) {
    return 4;
  }
  else return 3;
}

function HandleMIDI(event) {
  if (event instanceof Note) {
    event.pitch += roundUpCalc(event.pitch, GetParameter('Key') );
  }
  event.send();
}

The only thing to remember is to set the key parameter accordingly. I hope this helps!