var TransformParameter = function(instr, tDefinition, parent, transform, twist, onChange) { var self = this; var refreshable = false; var changeFunc; var initval = true; var definition = {}; var randomiseAllowed = true; var visible = true; if (parent) { Object.assign(definition, tDefinition); } else { definition = tDefinition; } if (definition.channel == "applymode") { randomiseAllowed = false; } if (definition.hasOwnProperty("preset")) { var save = {}; for (var s of ["dfault", "name", "channel", "automatable", "description"]) { if (definition.hasOwnProperty(s)) { save[s] = definition[s]; } } if (definition.preset == "amp") { Object.assign(definition, {name: "Amplitude", channel: "amp", description: "Amplitude", dfault: 1, min: 0, max: 1}); } else if (definition.preset == "pvslock") { Object.assign(definition, {name: "Peak lock", channel: "pvslock", description: "Lock frequencies around peaks", step: 1, dfault: 0}); } else if (definition.preset == "fftsize") { Object.assign(definition, {name: "FFT size", channel: "fftsize", description: "FFT size", options: [256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65535], dfault: 2, asvalue: true, automatable: false, lagHint: -1}); } else if (definition.preset == "wave") { Object.assign(definition, {name: "Wave", description: "Wave shape to use", options: ["Sine", "Square", "Saw", "Pulse", "Triangle"], dfault: 0, channel: "wave"}); } else if (definition.preset == "wintype") { Object.assign(definition, {name: "Window type", channel: "wintype", description: "Window shape", options: ["Hanning", "Hamming", "Half sine"], dfault: 0, automatable: false}); } else if (definition.preset == "instanceloop") { Object.assign(definition, {name: "Cross instance loop type", channel: "otlooptype", description: "Loop type of other instance", options: ["None", "Forward", "Backward", "Ping-pong"], dfault: 0}); } else if (definition.preset == "applymode") { Object.assign(definition, {name: "Apply mode", channel: "applymode", absolutechannel: true, description: "Apply mode", automatable: false, options: ["Replace", "Mix", "Modulate", "Demodulate"], dfault: 0}); } else if (definition.preset == "note") { var notes = {}; for (var i = 21; i < 128; i++) { var v = twist.noteData.data.notes[i]; notes[v[0]] = v[1]; } Object.assign(definition, {name: "Note", channel: "note", description: "Note to use", options: notes, dfault: 69, automatable: true}); } else if (definition.preset == "instance") { var c = (!definition.channel) ? "ot" : definition.channel; initval = false; if (transform) transform.refreshable = true; refreshable = true; Object.assign(definition, { name: "Instance", description: "Other wave to use", channel: instr + "_" + "instance", options: twist.otherInstanceNames, automatable: false }); changeFunc = function(index) { var s = twist.waveforms[index].selected; app.setControlChannel(instr + "_" + "inststart", s[0]); app.setControlChannel(instr + "_" + "instend", s[1]); app.setControlChannel(instr + "_" + "instchan", s[2]); }; } if (save) { Object.assign(definition, save); } } // if preset var type; if (definition.hasOwnProperty("conditions") && !parent) { refreshable = true; if (transform) transform.refreshable = refreshable; } var channel = ""; if (!definition.hasOwnProperty("absolutechannel")) { channel = (parent) ? parent.channel : instr + "_"; } if (definition.hasOwnProperty("channel")) { channel += definition.channel; } else { channel += definition.name.toLowerCase(); } var elContainer = $("
"); var elValueLabel = $("
"); var elValueInput; var elModulations; var elInput; var elRow; var elModSelect; var automation = []; this.definition = definition; this.modulation = null; this.automation = null; this.channel = channel; this.modulationParameters = null; this.setPlaying = async function(state) { if (definition.automatable || definition.hidden) return; if (elValueInput) { elValueInput.prop("disabled", state); elValueInput.css("opacity", (state) ? 0.8 : 1); } if (elInput) { elInput.prop("disabled", state); elInput.css("opacity", (state) ? 0.8 : 1); } }; if (!definition.hasOwnProperty("hidden")) { definition.hidden = false; } if (!definition.hasOwnProperty("step")) { definition.step = 0.0000001; } if (!definition.hasOwnProperty("min")) { definition.min = 0; } if (!definition.hasOwnProperty("max")) { definition.max = 1; } if (!definition.hasOwnProperty("fireChanges")) { definition.fireChanges = true; } if (!definition.hasOwnProperty("dfault")) { definition.dfault = 1; } if (parent) { if (definition.hostrange) { var items = ["step", "min", "max", "options", "conditions", "hostrange"]; if (definition.dfault == "hostrangemin") { definition.dfault = parent.definition.min; } else if (definition.dfault == "hostrangemax") { definition.dfault = parent.definition.max; } else { items.push("dfault"); } for (let o of items) { if (parent.definition.hasOwnProperty(o)) { definition[o] = parent.definition[o]; } } } else if (definition.preset == "hostrangemin") { definition.min = definition.max = definition.dfault = parent.definition.min; } else if (definition.preset == "hostrangemax") { definition.min = definition.max = definition.dfault = parent.definition.max; } } if (definition.hasOwnProperty("options")) { type = "select"; } else if (definition.hasOwnProperty("type")) { type = definition.type; } else if (definition.min == 0 && definition.max == 1 && definition.step == 1) { type = "checkbox"; } else { type = "range"; } if (!definition.hasOwnProperty("automatable")) { definition.automatable = ((type == "range" || type == "checkbox") && !parent); } this.getLagHint = function() { if (!definition.lagHint || !visible) return; var lagHint; if (typeof(definition.lagHint) == "object") { lagHint = "setting " + definition.name + " to " + definition.options[definition.lagHint.option] + ""; } else { lagHint = ((definition.lagHint < 0) ? "reducing" : "increasing") + " " + definition.name + ""; } return lagHint; }; this.setRawValue = function(val) { if (type == "checkbox") { elInput[0].checked = (val == 0) ? false : true; } else { elInput.val(val); } elInput.trigger("change"); } this.getRawValue = function() { return elInput.val(); } this.getValue = function() { var val; if (type == "range" || type == "string") { val = elInput.val(); } else if (type == "select") { val = (definition.asvalue) ? elInput.find("option:selected").text() : elInput.val(); } else if (type == "checkbox") { val = (elInput[0].checked) ? 1 : 0; } return val; }; this.reset = function() { self.setRawValue(definition.dfault); if (automationActive) disableAutomation(); if (self.automation) { delete self.automation; self.automation = null; } if (elSpline) { elSpline.remove(); delete elSpline; } if (modulationShown) hideModulations(); }; this.randomise = function() { if (!randomiseAllowed) return; var val; if (definition.automatable) { if (Math.random() >= 0.5) { modButton.el.click(); } } if (type == "select") { val = Math.round(Math.random() * (definition.options.length - 1)); } else if (type == "range") { val = (Math.random() * (definition.max - definition.min)) + definition.min; if (definition.step == 1) { val = Math.round(val); } else { val = Math.ceil((val - definition.min) / definition.step) * definition.step + definition.min; } } else if (type = "checkbox") { val = (Math.round(Math.random())); } self.setRawValue(val); if (self.modulationParameters) { // 4 = just the non-crossadaptive ones elModSelect.val(Math.round(Math.random() * 4)).trigger("change"); for (let mp in self.modulationParameters) { self.modulationParameters[mp].randomise(); } } }; this.refresh = function() { if (!refreshable || !transform) { return; } if (definition.preset == "instance") { createSelectOptions(elInput, twist.otherInstanceNames); } for (var k in definition.conditions) { var c = definition.conditions[k]; var val = transform.parameters[transform.instr + "_" + c.channel].getValue(); if ( (c.operator == "eq" && val != c.value) || (c.operator == "neq" && val == c.value) || (c.operator == "lt" && val >= c.value) || (c.operator == "gt" && val <= c.value) || (c.operator == "le" && val > c.value) || (c.operator == "ge" && val < c.value) ) { visible = false; return elRow.hide(); } } visible = true; elRow.show(); }; function createSelectOptions(elSelect, options) { var selected = elInput.val(); elSelect.empty(); for (var x in options) { var opt = $("