chataigne
This is an old revision of the document!
Table of Contents
Chataigne
GrandMa2 fader automation
module.json
{
"name":"GrandMa2Msc",
"type":"MIDI",
"path":"Hardware",
"version":"0.0.1",
"description":"Chataigne script to record and play grandma2/dot2 msc events",
"url":"https://github.com/ssm2017/chataigne_grandma2msc",
"downloadURL":"Chataigne script to record and play grandma2 msc events",
"hasInput":true,
"hasOutput":true,
"hideDefaultCommands":true,
"parameters":
{
"Module parameters":
{
"type":"Container",
"collapsed":false,
"LogSysex":{"type":"Boolean", "description":"Choose if you want to see a translation of the sysex.\nThe script logs must be activated.", "default":false}
}
},
"defaults":
{
"autoAdd":false
},
"hideDefaultParameters":
[
"autoAdd",
"autoFeedback",
"infos",
"tempo",
"MTC"
],
"scripts":
[
"grandma2msc.js"
],
"commands":
{
"Move GrandMa2 fader":
{
"menu":"",
"callback": "sendFaderSysex",
"parameters":
{
"Page":
{
"type": "Integer",
"default": 1,
"min": 1,
"max": 4
},
"Exec":
{
"type": "Integer",
"default": 0,
"min": 0,
"max": 130
},
"Value":
{
"type": "Float",
"default": 0,
"min": 0,
"max": 100
}
}
}
}
}
}
module script
/**
* Vanilla JUCE JS doesn't support the toFixed() function for rounding numbers to decimal places.
* So we need to make our own to get around the floating point math errors causing glitches
* @author : DJSTech + ssm2017 (convert to float)
* @link : https://discord.com/channels/697400442027769998/1058493819877851136/1059853940818198629
* @param {int} precision
* @param {float} value
* @returns {float}
*/
function fixedIt(value, precision) {
var num = "" + (Math.round(value * Math.pow(10, precision)));
return parseFloat(num.substring(0, num.length - precision) + "." + num.substring(num.length - precision, num.length));
}
/**
* Convert the hex values sent by the desk to 0 thru 100 level
* @param {*} coarse (coarse value (byte 8))
* @param {*} fine (fine value (byte 7))
* @returns {float} (the fader level)
*/
function hex2FaderLevel(coarse, fine) {
return fixedIt((((fine / 128) + coarse) / 1.28), 2);
//return (((fine / 128) + coarse) / 1.28);
}
/**
* Set the fader level if the param exists or create the param if not exists.
* @param {int} exec_page (the fader page id (byte 6))
* @param {int} exec_id (the fader id in the page (byte 5))
* @param {float} fader_level (the level of the fader (see: hex2FaderLevel function))
*/
function setFaderParamLevel(exec_page, exec_id, fader_level) {
var param_name = "faderPage"+ exec_page+ "Exec"+ exec_id;
//var param = script.params.getChild(param_name);
//var param = local.parameters.getChild(param_name);
var param = local.values.getChild(param_name);
if (typeof param === "void") {
//script.addFloatParameter(param_name,"Value of the fader Exec ", fader_level, 0, 100);
//local.parameters.addFloatParameter(param_name,"Value of the fader Exec ", fader_level, 0, 100);
local.values.addFloatParameter(param_name,"Value of the fader Exec ", fader_level, 0, 100);
}
else {
param.set(fader_level);
}
}
/**
* Display the sysex data with translation in the log
* @param {array} data (the sysex message as array of bytes)
*/
function logSysex(data) {
script.log("-------- sysex message start ---------");
script.log("0 universal_sysex > "+ data[0]);
script.log("1 device_id > "+ data[1]);
script.log("2 msc > "+ data[2]);
script.log("3 command_format > "+ data[3]);
script.log("4 command > "+ data[4]);
// if this is a goto message (go)
if (data[4] == 1) {
script.log("go");
}
// if this is a pause message (stop)
if (data[4] == 2) {
script.log("stop");
}
// if this is a un-pause message (resume)
if (data[4] == 3) {
script.log("resume");
}
// if this is a timed go message (timed_go)
if (data[4] == 4) {
script.log("timed go");
}
// if this is a fader level (set)
if (data[4] == 6) {
script.log("5 exec > "+ data[5]);
script.log("6 exec page > "+ data[6]);
script.log("7 fine value > "+ data[7]);
script.log("8 coarse value > "+ data[8]);
}
// if this is a macro trigger message (fire)
if (data[4] == 7) {
script.log("timed go");
}
// if this is a off message (go_off)
if (data[4] == 10 || data[4] == 11) {
script.log("go off");
}
script.log("-------- sysex message end ---------");
}
/**
* Parse received data and fill parameters
* @param {array} data (sysex data received knowing that the first (f0) and the last one (f7) are truncated)
*/
function parseSysex(data) {
// check if data is a fader move
if (data[4] == 6) {
var fader_level = hex2FaderLevel(data[8], data[7]);
setFaderParamLevel(data[6], data[5], fader_level);
}
}
/**
* Get the page and exec id from parameter name
* @param {string} param_name
* @returns {array} 0=page / 1=fader
*/
function getFaderIdFromParamName(param_name) {
var strings = param_name.replace("faderPage", "").replace("Exec", "-").split("-");
return [parseInt(strings[0]), parseInt(strings[1])];
}
/**
* Get coarse and fine values to be sent to sysex
* @param {float} fader_value
* @returns {array} 0=coarse / 1=fine
*/
function parseFaderValueToCoarseFine(fader_value) {
var temp_coarse = fader_value * 1.28;
var coarse = parseInt(Math.floor(temp_coarse));
var coarse_decimals = parseFloat(fixedIt(2,temp_coarse %2));
var temp_fine = coarse_decimals * 128;
var fine = parseInt(Math.floor(temp_fine));
return [coarse, fine];
}
/**
* Build the sysex output and send it to move the selected fader
* @param {int} execId
* @param {int} pageId
* @param {float} fader_value
*/
function sendFaderSysex(execId, pageId, fader_value) {
// workaround for an error when loading the module without parameter defined ? no, need to find something
script.log("===== "+ typeof fader_value);
if (typeof fader_value === array) return;
// send sysex
var sysex = [127,112,2,1,6];
sysex[5] = execId;
sysex[6] = pageId;
var coarse_fine = parseFaderValueToCoarseFine(fader_value);
sysex[7] = coarse_fine[1];
sysex[8] = coarse_fine[0];
local.sendSysex(sysex[0], sysex[1], sysex[2], sysex[3], sysex[4], sysex[5], sysex[6], sysex[7], sysex[8]);
}
/**
* Chataigne event triggered when receiving sysex data
* @param {array} data (sysex data received)
*/
function sysExEvent(data) {
if (local.parameters.moduleParameters.logSysex.get())logSysex(data);
parseSysex(data);
}
/**
* Chataigne event triggered when a script parameter value has changed
* @param {object} param
*/
function moduleParameterChanged(param) {
var index = getFaderIdFromParamName(param.name);
sendFaderSysex(index[1], index[0], param.get());
}
chataigne.1675477845.txt.gz · Last modified: by ssm2017
