From 9fbf91db06a6d4f4b5cd8bb45389a731bb86bf22 Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 13 Apr 2025 18:48:02 +0100 Subject: initial --- site/app/twist/_unlive/transform.js | 1024 +++++++++++++++++++++++++++++++++++ 1 file changed, 1024 insertions(+) create mode 100644 site/app/twist/_unlive/transform.js (limited to 'site/app/twist/_unlive/transform.js') diff --git a/site/app/twist/_unlive/transform.js b/site/app/twist/_unlive/transform.js new file mode 100644 index 0000000..3810359 --- /dev/null +++ b/site/app/twist/_unlive/transform.js @@ -0,0 +1,1024 @@ +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 = $("