From 354256812d8ce06c7a59129a4697b939ee8ae1c0 Mon Sep 17 00:00:00 2001 From: Alex Sz Date: Thu, 8 Feb 2024 20:55:17 +0100 Subject: [PATCH] add features: duplicate, save to exec, comment line. Add utilities: cull, createLFO --- bundle.min.js | 40 +++++++++++++++- hydrakit.js | 114 ++++++++++++++++++++++++++++++++++++---------- package-lock.json | 6 +++ 3 files changed, 134 insertions(+), 26 deletions(-) create mode 100644 package-lock.json diff --git a/bundle.min.js b/bundle.min.js index e0a6543..5850881 100644 --- a/bundle.min.js +++ b/bundle.min.js @@ -47242,6 +47242,41 @@ } }); + emitter.on('editor:commentLine', () => { + const editor = state.editor.editor + const cursorPosition = editor.cm.getCursor(); + const content = editor.getValue().split('\n').map((line, i) => { + if (i === editor.cm.getCursor().line) { + return line.trim().startsWith('//') ? line.replace('//', '') : line.startsWith(' ') ? line.replace(' ', '//') : `// ${line}` + } else { + return line + }; + }).join('\n'); + editor.setValue(content); + repl.eval(content); + editor.cm.getCursor().line = cursorPosition.line; + }); + + emitter.on('editor:duplicateLine', () => { + const editor = state.editor.editor + const cursorPosition = editor.cm.getCursor(); + const content = editor.getValue().split('\n').map((line, i) => { + if (i === editor.cm.getCursor().line) { + return `${line}\n${line}` + } else { + return line + }; + }).join('\n'); + editor.setValue(content); + }) + + function getCurrentCursorPosition(editor) { + const cursor = editor.cm.getCursor(); + const line = cursor.line; + const ch = cursor.ch; + return { line, ch }; + } + function clearAll() { const editor = state.editor.editor hush() @@ -47836,7 +47871,10 @@ 'Shift-Ctrl-H': 'hideAll', 'Shift-Ctrl-S': 'screencap', 'Shift-Ctrl-X': 'editor:toggleAutomutate', - 'Shift-Ctrl-C': 'gallery:search' + 'Shift-Ctrl-C': 'gallery:search', + 'Shift-Ctrl-K': 'editor:commentLine', + 'Cmd-D': 'editor:duplicateLine', + 'Cmd-S': 'editor:evalAll', } },{}],266:[function(require,module,exports){ var logElement diff --git a/hydrakit.js b/hydrakit.js index cd2916e..d18aeda 100644 --- a/hydrakit.js +++ b/hydrakit.js @@ -4,20 +4,20 @@ console.log("Hydrakit already loaded"); return; } - + navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure); - + function onMIDISuccess(midiAccess) { console.log(midiAccess); for (var input of midiAccess.inputs.values()) { input.onmidimessage = getMIDIMessage; } } - + function onMIDIFailure() { console.log('Could not access your MIDI devices.'); } - + //create an array to hold our cc values and init to a normalized value window.cc = Array(128).fill(0.5); window.ccc = Array(16).fill(1).map(() => Array(128).fill(0.5)); @@ -32,8 +32,8 @@ hydrakit.js:31 Midi received on cc#88 value:0.7890625, channel: 5 FEL hydrakit.js:31 Midi received on cc#86 value:0.7890625, channel: 5 LE */ - - getMIDIMessage = function(midiMessage) { + + getMIDIMessage = function (midiMessage) { const [kind, ccIndex, value] = midiMessage.data; const channel = kind & 0b00001111; var valNormalized = (value > 64 ? value + 1 : value) / 128.0; @@ -48,7 +48,7 @@ hydrakit.js:31 Midi received on cc#86 value:0.7890625, channel: 5 LE } if (ccIndex === 86) { - window.xemitter.emit("gallery:nextSketch", {backwards:true}); + window.xemitter.emit("gallery:nextSketch", { backwards: true }); } } @@ -57,7 +57,7 @@ hydrakit.js:31 Midi received on cc#86 value:0.7890625, channel: 5 LE ', channel: ' + channel); // uncomment to monitor incoming Midi cc[ccIndex] = valNormalized; ccc[channel][ccIndex] = valNormalized; - + if (!ccbind.includes(ccIndex)) { console.log(`${ccIndex} bound to b${ccbind.length}`); ccbind.push(ccIndex) @@ -66,7 +66,7 @@ hydrakit.js:31 Midi received on cc#86 value:0.7890625, channel: 5 LE }; var kp = []; - window.onkeypress = (a) => {"Space" == a.code && a.altKey && (a.preventDefault(), 4 === kp.push(a.timeStamp) && (window.bpm = Math.floor(6E4 / ((kp[3] - kp[0]) / 3)), kp.length = 0));} + window.onkeypress = (a) => { "Space" == a.code && a.altKey && (a.preventDefault(), 4 === kp.push(a.timeStamp) && (window.bpm = Math.floor(6E4 / ((kp[3] - kp[0]) / 3)), kp.length = 0)); } console.log("Hydrakit loaded"); window.hydrakitReady = true; @@ -78,9 +78,9 @@ function midi(ccIndex, options = {}) { "green": 1, "blue": 2, "yellow": 3, - "red":4, + "red": 4, }; - const {min=0, max=1, channel, transform} = options + const { min = 0, max = 1, channel, transform } = options return () => { let localIndex = ccIndex @@ -103,19 +103,83 @@ function midi(ccIndex, options = {}) { } const saw = ({ - min = 0, - max = 1, - x = 1, - t + min = 0, + max = 1, + x = 1, + t } = {}) => ({ - time + time }) => { - const spb = 60 / bpm * x; - const p = (time % spb) / spb * (max - min) + min; - - if (t) { - return t(p); - } else { - return p; - } -} \ No newline at end of file + const spb = 60 / bpm * x; + const p = (time % spb) / spb * (max - min) + min; + + if (t) { + return t(p); + } else { + return p; + } + } + +function createLFO({ + frequency = 1, // Frequency in Hz + amplitude = 1, // Amplitude of the oscillation + phase = 0, // Phase offset in radians + waveform = 'sine', // 'sine', 'square', 'sawtooth', 'triangle' + bpm = undefined, + trans = undefined, +} = {}) { + if (bpm) { + frequency = bpm / 60 * frequency; + } + const omega = 2 * Math.PI * frequency; // Angular frequency + + return ({ time: t }) => { + let theta = omega * t + phase; // Phase of the oscillator at time t + let value; + + switch (waveform) { + case 'sine': + value = Math.sin(theta); + break; + case 'square': + value = Math.sign(Math.sin(theta)); + break; + case 'sawtooth': + value = 2 * (theta / (2 * Math.PI) - Math.floor(1 / 2 + theta / (2 * Math.PI))); + break; + case 'triangle': + value = 2 * Math.abs(2 * (theta / (2 * Math.PI) - Math.floor(1 / 2 + theta / (2 * Math.PI)))) - 1; + break; + case 'random': + value = Math.random() * 2 - 1; // Generates a random value between -1 and 1 + break; + default: + throw new Error('Unsupported waveform'); + } + + if (trans) { + return trans(value*amplitude); + } + return value * amplitude; + }; +} + +function cull(value, cullRate, x = 1) { + const v = typeof value === "function" ? value() : value; + const arr = new Array(cullRate).fill(0); + for (let i = 0; i < x;) { + const randomIndex = Math.floor(Math.random() * cullRate); + if (arr[randomIndex] === v) { + continue; + } else { + arr[randomIndex] = v; + i++; + } + } + return arr; +} + +function randInt(from, to) { + return Math.floor(Math.random() * (to - from + 1) + from); +} + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..4420a5d --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "hydralisk", + "lockfileVersion": 3, + "requires": true, + "packages": {} +}