`//`

// EventGamma

// Version 0.4

//

// This script will provide a non-linear accleration to CC, Pitchbend and

// aftertouch midi events. The factor value establishes the amount of curve

// above or below the linear line. A factor of zero will be the linear line

//

// TODO, generate a lookup table to avoid using math during PLAY

var NeedsTimingInfo = true;

var PluginParameters = [];

function HandleMIDI(event) {

var gamma = GuiParameter(0);

// if the gamma is 1 then just forward the event.

if (gamma==1) {

event.send();

return;

}

// if CC events are being included, then range is 0-127

if (event instanceof ControlChange && GuiParameter(3) == 1) {

event.value = scale(event.value, 127, gamma);

}

// if Pitch Bend events, the range is -8291 to 8192

else if (event instanceof PitchBend && GuiParameter(4) == 1) {

// if event.value is not zero, then accelerate it. use offset to

// force positive range

if (event.value!=0) {

const OFFSET = 8192;

var temp = event.value+OFFSET;

var maxPitch = OFFSET+OFFSET;

event.value = scale(event.value, maxPitch, gamma)-OFFSET;

}

}

// if aftertouch, then range is 0-127

else if (event instanceof ChannelPressure && GuiParameter(5) == 1) {

event.value = scale(event.value, 127, gamma);

}

else if (event instanceof PolyPressure && GuiParameter(6) == 1) {

event.value = scale(event.value, 127, gamma);

}

// send event

event.send();

}

//============================================

// couple of globals related to the graphing

//============================================

var gGraphFlush = false;

var gGraph = [];

const MAXFLUSH = 10;

//======================================================

// Scales the value based on gamma and range

//

function scale(value, range, gamma) {

// off means off, no matter what. Should we do this?

if(value == 0) {

return 0;

}

// calculate scaled value

var out = Math.round(range * Math.pow((value/range),gamma));

// for incoming value over 1, always scale to at least 1

if(out == 0) {

out = 1;

}

return out;

}

//===================================================================

// function that will send to console a graph if the selected curve

//

function plotCurve(gamma) {

// if flush in progress then ignore this

if (gGraphFlush) {

return;

}

var graph = new Array(64);

for (var x=0;x<64;x++) {

graph[x] = new Array(32);

for (var y=0;y<32;y++) {

graph[x][y] = 0;

}

}

// calculate Y values, cut X size in half and cut Y value in half again to shrink height of graph

for (var x=0;x<64;x++) {

var y = scale(x*2, 127, gamma)/4;

graph[x][Math.round(y)] = 1;

}

// build output strings,

for(var y=31;y>=0;y--) {

var str = "|";

for (var x=0;x<64;x++) {

if (graph[x][y] == 1) {

str = str + "x";

}

else if (x/2==y) {

str = str + ".";

}

else {

str = str + " ";

}

}

gGraph.push(str);

}

// add x axis

var xaxis = "+";

for(var x=0;x<64;x++) {

xaxis = xaxis + "-";

}

gGraph.push(xaxis);

gGraphFlush = true;

}

//=============================================

// handle when they hit the show graph button

//

function ParameterChanged(idx, val) {

PluginParameters[idx].data = val;

if (idx == 1) {

plotCurve(GuiParameter(0));

}

}

//=========================================================

// use Idle() function to flush graph to console

//

function Idle() {

if(gGraphFlush) {

// Trace("printing graph");

var i = 0;

while( gGraph.length > 0 && i < MAXFLUSH) {

Trace(gGraph.shift());

i++

}

if (gGraph.length <= 0) {

gGraphFlush = false;

}

}

}

PluginParameters.push({

name: "Gamma",

type: "log",

defaultValue: 1,

minValue: .1,

maxValue: 7.9,

numberOfSteps: 100,

hidden: false,

disableAutomation: false

});

PluginParameters.push({

name: "Show Graph",

type: "momentary",

hidden: false,

disableAutomation: true

});

PluginParameters.push({

name: "-------- Filter -------",

type: "text",

hidden: false,

disableAutomation: true

});

PluginParameters.push({

name: "Control Change",

type: "checkbox",

defaultValue: 1,

hidden: false,

disableAutomation: true

});

PluginParameters.push({

name: "Pitch Bend",

type: "checkbox",

defaultValue: 0,

hidden: false,

disableAutomation: true

});

PluginParameters.push({

name: "Channel Pressure",

type: "checkbox",

defaultValue: 0,

hidden: false,

disableAutomation: true

});

PluginParameters.push({

name: "Poly Pressure",

type: "checkbox",

defaultValue: 0,

hidden: false,

disableAutomation: true

});

function GuiParameter(id) {

// if script was recently initialized, reload GUI value

if(PluginParameters[id].data == undefined) {

PluginParameters[id].data = GetParameter(id);

}

if(id < PluginParameters.length) {

return PluginParameters[id].data;

}

}

function Reset() {

}

Reset();