Jump to content

Script for Microtuning via Pitch Bend?


DjStiky

Recommended Posts

Hi Guys,

 

Was wondering if anyone could create a script where you could do the following:

 

- Select 1 or many notes from C to B (Would affect said notes on all octaves)

- Set a pitch bend value for each of the selected notes

- Send the note plus pitch bend value whenever that note(s) is/are played on a keyboard and then reset pitch bend when note is released.

 

If it's simpler, you could also just list all the notes from C to B and then a pitchbend value next to each

 

The reason I'm asking this is so I can have microtuning with legato or portamento instruments in Kontakt. Right now, combining both the built in portamento and microtuning scripts in Kontakt together doesn't work, conflict with each other and sounds weird.

 

Thanks!

Link to comment
Share on other sites

  • 4 weeks later...

I had making a microtuner on my to do list for a while, so I thought this would be a good opportunity to get it done. I'll be using it for middle eastern style quarter tones. I have the code below. 

 

CAVEAT: The only thing that I can't figure out is how to manipulate the time it takes for the bend to complete. Smaller values seem to be usable but the further away the value gets from zero, the longer it takes for the bend to complete. Maybe somebody can chime in and let me know if there is a property some other value to adjust. 

 

 

var pitches = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];
var detuned = [0,0,0,0,0,0,0,0,0,0,0,0]
function findPitch(midiNote){
    var mod = midiNote % 12;
    var result = pitches[mod]
    return result;
}

var PluginParameters = [
  {
    name:"Bend Value",
    type:"lin",
    defaultValue:-1450,
    minValue:-4000,
    maxValue:0,
    numberOfSteps:80,
    currentValue:-1450,
    callBack: function(value){
      this.currentValue = value;
      /*
      NOTE: Play with the ranges. Valid pitch bend value range is 
      a 14-bit pitch bend value from -8192–8191. A value of 0 is center.
      BEWARE: The further away you get from center (0), 
      the longer it takes for the bends to complete. I need to find a way to
      make the bends instant.
      */ 
    }
  },
  {
    name:"NOTES TO DETUNE",
    type:"text",
    callBack: function(value){
      // Do nothing. This is just a label!
    }
  },
  {
    name:"C",
    type:"menu",
    valueStrings:["Off", "On"],
    defaultValue:0,
    numberOfSteps:2,
    callBack: function(value){
      //Trace("Setting detuned note to " + value);
      detuned[0] = value;
    }
  },
  {
    name:"C#",
    type:"menu",
    valueStrings:["Off", "On"],
    defaultValue:0,
    numberOfSteps:2,
    callBack: function(value){
      //Trace("Setting detuned note to " + value);
      detuned[1] = value;
    }
  },
  {
    name:"D",
    type:"menu",
    valueStrings:["Off", "On"],
    defaultValue:0,
    numberOfSteps:2,
    callBack: function(value){
      //Trace("Setting detuned note to " + value);
      detuned[2] = value;
    }
  },
  {
    name:"D#",
    type:"menu",
    valueStrings:["Off", "On"],
    defaultValue:0,
    numberOfSteps:2,
    callBack: function(value){
      //Trace("Setting detuned note to " + value);
      detuned[3] = value;
    }
  },
  {
    name:"E",
    type:"menu",
    valueStrings:["Off", "On"],
    defaultValue:0,
    numberOfSteps:2,
    callBack: function(value){
      //Trace("Setting detuned note to " + value);
      detuned[4] = value;
    }
  },
  {
    name:"F",
    type:"menu",
    valueStrings:["Off", "On"],
    defaultValue:0,
    numberOfSteps:2,
    callBack: function(value){
      //Trace("Setting detuned note to " + value);
      detuned[5] = value;
    }
  },
  {
    name:"F#",
    type:"menu",
    valueStrings:["Off", "On"],
    defaultValue:0,
    numberOfSteps:2,
    callBack: function(value){
      //Trace("Setting detuned note to " + value);
      detuned[6] = value;
    }
  },
  {
    name:"G",
    type:"menu",
    valueStrings:["Off", "On"],
    defaultValue:0,
    numberOfSteps:2,
    callBack: function(value){
      //Trace("Setting detuned note to " + value);
      detuned[7] = value;
    }
  },
  {
    name:"G#",
    type:"menu",
    valueStrings:["Off", "On"],
    defaultValue:0,
    numberOfSteps:2,
    callBack: function(value){
      //Trace("Setting detuned note to " + value);
      detuned[8] = value;
    }
  },
  {
    name:"A",
    type:"menu",
    valueStrings:["Off", "On"],
    defaultValue:0,
    numberOfSteps:2,
    callBack: function(value){
      //Trace("Setting detuned note to " + value);
      detuned[9] = value;
    }
  },
  {
    name:"A#",
    type:"menu",
    valueStrings:["Off", "On"],
    defaultValue:0,
    numberOfSteps:2,
    callBack: function(value){
      //Trace("Setting detuned note to " + value);
      detuned[10] = value;
    }
  },
  {
    name:"B",
    type:"menu",
    valueStrings:["Off", "On"],
    defaultValue:0,
    numberOfSteps:2,
    callBack: function(value){
      //Trace("Setting detuned note to " + value);
      detuned[11] = value;
    }
  }
]

function ParameterChanged(param,value){
    PluginParameters[param].callBack(value);
}

function HandleMIDI(event)
{
var bend = new PitchBend();
if(event.status === 144){
 var note = findPitch(event.pitch);
    var index = pitches.indexOf(note);
    if(detuned[index] === 1){
      bend.value = PluginParameters[0].currentValue; // Set in UI
      bend.inStartFrame = 1;
      bend.send();
      event.send
    } else {
      bend.value = 0;
      bend.inStartFrame = 1;
      bend.send();
      event.send
    }
}

event.send();
}

Link to comment
Share on other sites

  • 2 months later...
  • 3 weeks later...
  • 3 years later...

I rewritten your script so that it allows tuning of each note via sliders

 

logic-microtuning-script.png.7dbc1327e9768e177b5f933ef340eab3.png

 

var pitches = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];
var detuned = [0,0,0,0,0,0,0,0,0,0,0,0]
function findPitch(midiNote){
   var mod = midiNote % 12;
   var result = pitches[mod]
   return result;
}

var PluginParameters = [
 {
   name:"C",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"C#",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"D",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"D#",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"E",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"F",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"F#",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"G",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"G#",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"A",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"A#",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"B",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
]

function ParameterChanged(param,value){
   PluginParameters[param].callBack(value);
}

function HandleMIDI(event)
{
var bend = new PitchBend();
if(event.status === 144){
 var note = findPitch(event.pitch);
 var index = pitches.indexOf(note);
 Trace(index)
 bend.value = PluginParameters[index].currentValue; // Set in UI
 bend.inStartFrame = 1;
 bend.send();
}

event.send();
}

Link to comment
Share on other sites

  • 2 years later...
On 4/21/2020 at 1:51 AM, maciejsaw said:

I rewritten your script so that it allows tuning of each note via sliders

logic-microtuning-script.png.7dbc1327e9768e177b5f933ef340eab3.png

var pitches = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"];
var detuned = [0,0,0,0,0,0,0,0,0,0,0,0]
function findPitch(midiNote){
   var mod = midiNote % 12;
   var result = pitches[mod]
   return result;
}

var PluginParameters = [
 {
   name:"C",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"C#",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"D",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"D#",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"E",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"F",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"F#",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"G",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"G#",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"A",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"A#",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
 {
   name:"B",
   type:"lin",
   defaultValue:0,
   minValue:-4000,
   maxValue:4000,
   numberOfSteps:80,
   currentValue:-1450,
   callBack: function(value){
     this.currentValue = value;
   }
 },
]

function ParameterChanged(param,value){
   PluginParameters[param].callBack(value);
}

function HandleMIDI(event)
{
var bend = new PitchBend();
if(event.status === 144){
 var note = findPitch(event.pitch);
 var index = pitches.indexOf(note);
 Trace(index)
 bend.value = PluginParameters[index].currentValue; // Set in UI
 bend.inStartFrame = 1;
 bend.send();
}

event.send();
}
 

Thanks for the script! I also want to use it for Kontakt legato instruments. I have no experience with the scripter, so I have some questions:

  • What does the values (-4000, 4000) and the steps (80) stand for? Are these values in cent?
  • Is it possible to have all keys of an 88 keyboard shown in the GUI, so that I can manipulate the tuning of each key and not only octaves?

Thanks in advance.

Edited by Pixelpoet1985
Link to comment
Share on other sites

  • 6 months later...
  • 4 months later...
  • 3 weeks later...

This script is very good, thank you for sharing. But he resends the pitch bend information with each new note played. That is, he can't keep the tuning of the previous note. This is because all the notes are being sent to the same MIDI channel. I wanted to know if anyone knows how to send each new note to a new unoccupied midi channel. From 1 to 6, in loop.

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