ModScripter Scripts

A classical ADSR triggered via MIDI Input:

//-----------------------------------------------------------
getDescription = function () {
	return "ADSR";
}

//-----------------------------------------------------------
makeParameter = function (name) {
	var value = 0;
	var listeners = [];
	return {
		name: name, 
		units: "",
		stepCount: 0,
		toString: function (val) { return val; },
		fromString: function (str) { return parseFloat (str); },
		addListener: function (obj) { listeners.push (obj); },
		getValue: function () { return value; },
		getPlain: function () { return value; },
		setValue: function (val) {
			value = val;
			for (i = 0; i < listeners.length; ++i)
				listeners[i] (this);
		},
	};
}

//-----------------------------------------------------------
makeBoolParameter = function (name) {
	param = makeParameter (name);
	param.stepCount = 1;
	param.toString = function (value) { return value >= 0.5 ? "On" : "Off"; };
	param.fromString = function (str) { if (str == "On") return 1.; if (str == "Off") return 0.; };
	return param;
};

//-----------------------------------------------------------
makeRangeParameter = function (name, min, max, units, precision) {
	if (precision == undefined)
		precision = 2;
	var precision = Math.pow (10, precision);
	param = makeParameter (name);
	param.units = units;
	param.toString = function (value) {
		value = normalizedToPlain (min, max, value);
		value = Math.round (value * precision) / precision;
		return value + (this.units ? " " + this.units : "");
	};
	param.fromString = function (str) { 
		var v = parseFloat (str);
		if (!isNaN (v))
			return plainToNormalized (min, max, v);
	};
	param.getPlain = function () { return normalizedToPlain (min, max, this.getValue ()); };
	return param;
};

//-----------------------------------------------------------
makeADSR = function () {
	const Phase = { Attack: 1, Decay: 2, Hold: 3, Release: 4 };
	var attack = 0;
	var decay = 0;
	var sustain = 0;
	var release = 0;
	var phase = Phase.Attack;
	var value = 0;
	var time = -1;
	var doHold = 0;
	var doRetrigger = 0;
	obj = {
		setAttack: function (newValue) { attack = newValue;},
		setDecay: function (newValue) { decay = newValue; },
		setSustain: function (newValue) { sustain = newValue; },
		setRelease: function (newValue) { release = newValue; },
		setRetrigger: function (newValue) { doRetrigger = newValue > 0.5; },
		trigger: function () {
			if (doRetrigger)
			{
				time = 0;
			}
			else
			{
				time = value * attack;
			}
			phase = Phase.Attack; 
		},
		setHold: function (hold) { doHold = hold; },
		release: function () { 
			doHold = 0;
			if (phase == Phase.Hold)
			{
				phase = Phase.Release;
				time = 0;
			}
		},
		process: function (numSamples) {
			if (time < 0)
				return 0;
 			time += numSamples;
			if (phase == Phase.Attack)
			{
				if (time > attack)
				{
					phase = Phase.Decay;
					value = 1.;
					time -= attack;
				}
				else
				{
					value = time / attack;
				}
			}
			if (phase == Phase.Decay)
			{
				if (time > decay)
				{
					phase = Phase.Hold;
					time -= decay;
					value = sustain;
				}
				else
				{
					value = 1. - (1. - sustain) * time / decay;
				}
			}
			if (phase == Phase.Hold)
			{
				if (doHold == 0)
				{
					phase = Phase.Release;
				}
			}
			if (phase == Phase.Release)
			{
				if (time > release)
				{
					phase = Phase.Attack;
					time = -1;
					value = 0;
				}
				else
				{
					value = sustain * (1 - (time / release));
				}
			}
			return value;
		}
	};
	return obj;
};


const AttackIndex = 1;
const DecayIndex = 2;
const SustainIndex = 3;
const ReleaseIndex = 4;
const VelocityIndex = 5;
const RetriggerIndex = 6;

parameter = [];
parameter[AttackIndex]		= makeRangeParameter ("Attack", 0, 3000, "ms", 0);
parameter[DecayIndex]		= makeRangeParameter ("Decay", 0, 3000, "ms", 0);
parameter[SustainIndex]		= makeRangeParameter ("Sustain", 0, 100, "%", 0);
parameter[ReleaseIndex]		= makeRangeParameter ("Release", 0, 3000, "ms", 0);
parameter[VelocityIndex]	= makeRangeParameter ("Velocity", 0, 100, "%", 0);
parameter[RetriggerIndex]	= makeBoolParameter  ("Retrigger");

adsr = makeADSR ();

sr = getSampleRate () / 1000;

parameter[AttackIndex].addListener (function (param) { adsr.setAttack (param.getPlain () * sr); });
parameter[DecayIndex].addListener (function (param) { adsr.setDecay (param.getPlain () * sr); });
parameter[SustainIndex].addListener (function (param) { adsr.setSustain (param.getValue ()); });
parameter[ReleaseIndex].addListener (function (param) { adsr.setRelease (param.getPlain () * sr); });
parameter[RetriggerIndex].addListener (function (param) { adsr.setRetrigger (param.getPlain ()); });

key = {noteID: -1, velocity: 0};

//-----------------------------------------------------------
processModulation = function (inputValue, numSamples) {
	return adsr.process (numSamples) * key.velocity;
}

pressedNote = -1;
//-----------------------------------------------------------
onNoteOnEvent = function (channel, pitch, velocity, tuning, noteID) {
	if (key.noteID == -1)
	{
		
		key.noteID = noteID;
		velAmount = parameter[VelocityIndex].getValue ();
		key.velocity = 1. + (velocity * velAmount) - 1. * velAmount;
		adsr.trigger ();
		adsr.setHold (1);
	}
}

//-----------------------------------------------------------
onNoteOffEvent = function (channel, pitch, velocity, tuning, noteID) {
	if (key.noteID == noteID)
	{
		key.noteID = -1;
		adsr.release ();
	}
}

//-----------------------------------------------------------
onParamChange = function (paramIndex, newValue) {
	if (parameter[paramIndex])
		parameter[paramIndex].setValue (newValue);
}

//-----------------------------------------------------------
paramValueToString = function (paramIndex, paramValue) {
	if (parameter[paramIndex])
		return parameter[paramIndex].toString (paramValue);
}

//-----------------------------------------------------------
stringToParamValue = function (paramIndex, string) {
	if (parameter[paramIndex])
		return parameter[paramIndex].fromString (string);
}

//-----------------------------------------------------------
getParamTitle = function (paramIndex) {
	if (parameter[paramIndex])
		return parameter[paramIndex].name;
}

//-----------------------------------------------------------
getParamStepCount = function (paramIndex) {
	if (parameter[paramIndex])
		return parameter[paramIndex].stepCount;
}

4 Likes