15 Commits

Author SHA1 Message Date
149d1a0b8d save on every UI change 2025-05-13 11:24:39 +02:00
4ee8a93791 four user defined waves 2025-02-12 11:02:51 +01:00
c706461443 Merge pull request 'nn-communication' (#8) from nn-communication into main
Reviewed-on: #8
2024-11-29 14:21:11 +01:00
081e33dd07 modulator noise function previous val bug 2024-11-29 14:20:29 +01:00
eb02657b4a center vals included in NN data 2024-10-22 13:27:07 +02:00
d670aefcbd enums start with NONE 2024-10-22 12:32:42 +02:00
68baa3c8de Merge pull request 'nn-communication' (#7) from nn-communication into main
Reviewed-on: #7
2024-10-22 11:00:25 +02:00
a35fecafae NN data receiving 2024-10-22 10:58:46 +02:00
b3ba9b0f2d cachedNoise no longer an array 2024-10-18 15:34:53 +02:00
102a88b242 bugfix - modulators not properly initializing 2024-10-15 14:54:37 +02:00
aebfbe5277 Merge pull request 'main' (#6) from main into nn-communication
Reviewed-on: #6
2024-10-15 12:27:53 +02:00
2d81a832af Merge branch 'nn-communication' into main 2024-10-15 12:27:08 +02:00
cdbcf24dfc Merge pull request 'fixed userwave update' (#5) from lock into main
Reviewed-on: #5
2024-10-15 12:21:08 +02:00
trian-gles
a855d254cd non musical timing to ms value for input from neural net 2024-10-11 15:34:37 +02:00
09a1b5f20f Merge pull request 'lock mode' (#4) from lock into main
Reviewed-on: #4
2024-10-11 13:36:54 +02:00
4 changed files with 686 additions and 326 deletions

View File

@@ -49,6 +49,10 @@ function CreateParamChanger(arr, setArr, index, postCB=() => {}, preCB=(val) =>
newArr[index] = preCB(event.target.value);
setArr(newArr);
postCB();
setTimeout(() => {
window.dispatchEvent(new CustomEvent('saveDict', {'detail' : "localStorage"}));
}, 50)
log(`${index} ${event.target.value}`);
}
}
@@ -60,6 +64,9 @@ function CreateMatrixParamChanger(matrix, setMatrix, i, j){
});
newMatrix[i][j] = event.target.value;
setMatrix(newMatrix);
setTimeout(() => {
window.dispatchEvent(new CustomEvent('saveDict', {'detail' : "localStorage"}));
}, 50)
log(`${i}, ${j} ${event.target.value}`);
}

File diff suppressed because it is too large Load Diff

147
lfogui.js
View File

@@ -33,10 +33,33 @@ const MODULATORLABELS = ["inst", "-type-", "---shape---", "-------param-------",
const ENUMERATORLABELS = ["inst", "---parameter---", "-# points-"];
function parseLfoTimeNonMusical(lfoTime){
if (lfoTime.slice(-2) == "hz"){
return parseFloat(lfoTime.slice(0, -2));
}
else if (lfoTime.slice(-2) == "ms"){
return 1000 / parseFloat(lfoTime.slice(0, -2));
}
else if (lfoTime.slice(-1) == "s"){
return 1 / parseFloat(lfoTime.slice(0, -1));
}
else if ((lfoTime.match(/:/g) || []).length == 2){
return 1 / moment.duration(lfoTime).asSeconds();
}
else if ((lfoTime.match(/\./g) || []).length == 2){
return 0; // ignore musical timings
}
else {
return 0;
}
}
function nnFreqToHzString(num){
return `${num}hz`;
}
function MasterLfoHandler(){
let initVisArr = Array(MAXLFOS).fill(false);
initVisArr[0] = true;
@@ -57,9 +80,12 @@ function MasterLfoHandler(){
};
/// MODULATOR ARRAYS
const [userDefinedWave, setUserDefinedWave] = React.useState(Array(50).fill(0));
let userDefinedWavesBase = [];
for (let i=0; i<4; i++){
userDefinedWavesBase.push(Array(50).fill(0));
}
const [userDefinedWaves, setUserDefinedWaves] = React.useState(userDefinedWavesBase);
const [modVisibleArr, setModVisibleArr] = React.useState(initVisArr);
const [modTypeArr, setModTypeArr] = React.useState(Array(MAXLFOS).fill('LFO'));
const [modInstanceNumArr, setModInstanceNumArr] = React.useState(Array(MAXLFOS).fill('1'));
@@ -81,25 +107,26 @@ function MasterLfoHandler(){
const [initPhaseArr, setInitPhaseArr] = React.useState(Array(MAXLFOS).fill('0'));
const [lastPhaseArr, setLastPhaseArr] = React.useState(Array(MAXLFOS).fill(0));
const [cachedNoiseValueArr, setCachedNoiseValueArr] = React.useState(Array(MAXLFOS).fill([0, 0]));
const [cachedNoiseValueArr1, setCachedNoiseValueArr1] = React.useState(Array(MAXLFOS).fill(0));
const [cachedNoiseValueArr2, setCachedNoiseValueArr2] = React.useState(Array(MAXLFOS).fill(0));
const allModArrays = [modVisibleArr, modTypeArr, modInstanceNumArr, shapeArr, noiseTypeArr, djParamArr, freqArr, minArr, maxArr, initPhaseArr, lastPhaseArr, cachedNoiseValueArr];
const allModSetters = [setModVisibleArr, setModTypeArr, setModInstanceNumArr, setShapeArr, setNoiseTypeArr, setDjParamArr, setFreqArr, setMinArr, setMaxArr, setInitPhaseArr, lastPhaseArr, cachedNoiseValueArr];
const modBlankVals = [true, 'LFO', '1', SHAPETYPES[0], MODPARAMOPTIONS[0], "Sine Int.", '1hz', '0', '1', '0', 0, [0, 0]];
const allModArrays = [modVisibleArr, modTypeArr, modInstanceNumArr, shapeArr, noiseTypeArr, djParamArr, freqArr, minArr, maxArr, initPhaseArr, lastPhaseArr, cachedNoiseValueArr1, cachedNoiseValueArr2];
const allModSetters = [setModVisibleArr, setModTypeArr, setModInstanceNumArr, setShapeArr, setNoiseTypeArr, setDjParamArr, setFreqArr, setMinArr, setMaxArr, setInitPhaseArr, setLastPhaseArr, setCachedNoiseValueArr1, setCachedNoiseValueArr2];
const modBlankVals = [true, 'LFO', '1', SHAPETYPES[0], NOISETYPES[0], MODPARAMOPTIONS[0], '1hz', '0', '1', '0', 0, 0, 0];
/// ENUMERATOR ARRAYS
const [enumVisibleArr, setEnumVisibleArr] = React.useState(initVisArr);
const [enumInstanceNumArr, setEnumInstanceNumArr] = React.useState(Array(MAXLFOS).fill('1'));
const [enumItemCounts, setEnumItemCounts] = React.useState(Array(MAXENUMPOINTS).fill('2'));
const [enumDjParamArr, setEnumDjParamArr] = React.useState(Array(MAXENUMPOINTS).fill('attenuation'));
const [enumDjParamArr, setEnumDjParamArr] = React.useState(Array(MAXENUMPOINTS).fill('NONE'));
let baseEnumBreakpoints = Array(MAXENUMS).fill(0).map(x => Array(MAXENUMPOINTS+ 1).fill(0));
for (let i = 0; i < MAXENUMS; i++){
for (let j=0; j < MAXENUMPOINTS + 1; j++){
baseEnumBreakpoints[i][j] = j;
baseEnumBreakpoints[i][j] = j - 0.5;
}
}
const [enumBreakPoints, setEnumBreakPoints] = React.useState(baseEnumBreakpoints);
@@ -107,7 +134,7 @@ function MasterLfoHandler(){
const getBlankEnumBreakPointRow = () => {
let arr = []
for (let i=0; i< MAXENUMPOINTS + 1; i++)
arr.push(i)
arr.push(i - 0.5)
return arr;
}
@@ -133,14 +160,12 @@ function MasterLfoHandler(){
function handleLoad(event) {
window.max.getDict(event.detail, (dict) => {
for (let i = 0; i<allModArrays.length; i++) {
for (let i = 0; i<dict.data.modArrays.length; i++) {
allModSetters[i](dict.data.modArrays[i]);
}
for (let i = 0; i<allEnumArrays.length; i++) {
allEnumArrSetters[i](dict.data.enumArrays[i]);
}
for (let i = 0; i<allEnumMats.length; i++) {
allEnumMatSetters[i](dict.data.enumMats[i]);
}
@@ -218,8 +243,8 @@ function MasterLfoHandler(){
function handleTick(event) {
let time = (Date.now() - firstUpdateTime) / 1000;
let noiseData = {lastPhaseArr, setLastPhaseArr, cachedNoiseValueArr, setCachedNoiseValueArr, noiseTypeArr};
operateModulators(modVisibleArr, modTypeArr, modInstanceNumArr, djParamArr, modCenterVals, freqArr, minArr, maxArr, shapeArr, initPhaseArr, noiseData, userDefinedWave, time, beatsInMeasure, ticks);
let noiseData = {lastPhaseArr, setLastPhaseArr, cachedNoiseValueArr1, setCachedNoiseValueArr1, cachedNoiseValueArr2, setCachedNoiseValueArr2, noiseTypeArr};
operateModulators(modVisibleArr, modTypeArr, modInstanceNumArr, djParamArr, modCenterVals, freqArr, minArr, maxArr, shapeArr, initPhaseArr, noiseData, userDefinedWaves, time, beatsInMeasure, ticks);
}
function handleTimeSig(event) {
@@ -227,16 +252,76 @@ function MasterLfoHandler(){
}
function handleChangeUserWave(event){
setUserDefinedWave(event.detail);
userDefinedWaves[event.detail.index] = event.detail.points;
setUserDefinedWaves(userDefinedWaves);
}
function handleMaxTicks(event){
setTicks(event.detail);
}
function setNN(event){
for (let i=0; i<MAXLFOS; i++){
freqArr[i] = nnFreqToHzString(event.detail[i]);
}
setFreqArr(freqArr)
for (let i=MAXLFOS; i<MAXLFOS * 2; i++){
minArr[i - MAXLFOS] = event.detail[i];
}
setMinArr(minArr);
for (let i=MAXLFOS*2; i<MAXLFOS * 3; i++){
maxArr[i - MAXLFOS*2] = event.detail[i];
}
setMaxArr(maxArr);
for (let i=MAXLFOS*3; i<MAXLFOS * 4; i++){
initPhaseArr[i - MAXLFOS*3] = parseFloat(event.detail[i]);
}
setInitPhaseArr(initPhaseArr);
for (let i=MAXLFOS*4; i<MAXLFOS * 5; i++){
let index = i - MAXLFOS*4;
let inst = modInstanceNumArr[index];
let param = djParamArr[index];
modCenterVals[inst][param] = parseFloat(event.detail[i]);
}
setModCenterVals(modCenterVals);
rerender(!render); // BAD! SHOULD NOT BE DOING THIS!
}
function dumpNN(event){
let allNNData = [];
freqArr.forEach(element => {
allNNData.push(parseLfoTimeNonMusical(element));
});
allNNData = allNNData.concat(minArr);
allNNData = allNNData.concat(maxArr);
allNNData = allNNData.concat(initPhaseArr);
let lfoMatchedCenterVals = [];
for (let i=0; i<MAXLFOS; i++){
let inst = modInstanceNumArr[i];
let param = djParamArr[i];
lfoMatchedCenterVals.push(modCenterVals[inst][param]);
if (!lfoMatchedCenterVals[i])
lfoMatchedCenterVals[i] = 0
}
allNNData = allNNData.concat(lfoMatchedCenterVals);
window.max.outlet("NNdata " + allNNData.join(" "));
}
window.addEventListener('loadDict', handleLoad);
window.addEventListener('saveDict', handleSave);
window.addEventListener('dumpNN', dumpNN);
window.addEventListener('setNN', setNN);
window.addEventListener('tick', handleTick);
window.addEventListener('param', handleParam);
window.addEventListener('enum', handleEnum);
@@ -247,6 +332,8 @@ function MasterLfoHandler(){
return () => {
window.removeEventListener('loadDict', handleLoad);
window.removeEventListener('saveDict', handleSave);
window.removeEventListener('dumpNN', dumpNN);
window.removeEventListener('setNN', setNN);
window.removeEventListener('tick', handleTick);
window.removeEventListener('param', handleParam);
window.removeEventListener('enum', handleEnum);
@@ -254,7 +341,7 @@ function MasterLfoHandler(){
window.removeEventListener('userWave', handleChangeUserWave);
window.removeEventListener('maxTicks', handleMaxTicks);
};
}, [...allModArrays, ...allEnumArrays, ...allEnumMats, userDefinedWave, modCenterVals, render, beatsInMeasure, ticks]);
}, [...allModArrays, ...allEnumArrays, ...allEnumMats, userDefinedWaves, modCenterVals, render, beatsInMeasure, ticks]);
function CheckLinked(inst, param, checkInstArr, checkParamArr){
@@ -325,7 +412,7 @@ function MasterLfoHandler(){
}
}
else {
log("adding lfo");
for (var j = 0; j < allModArrays.length; j++){ // no space below, easy.
let array = allModArrays[j];
array[id + 1] = modBlankVals[j];
@@ -333,6 +420,7 @@ function MasterLfoHandler(){
}
}
rerender(!render);
}
},
removeLfo: () => {
@@ -467,6 +555,14 @@ if (!DEBUG){
window.dispatchEvent(new CustomEvent('saveDict', {'detail' : dictId}));
});
window.max.bindInlet("dumpNN", () => {
window.dispatchEvent(new CustomEvent('dumpNN'));
});
window.max.bindInlet("setNN", (...data) => {
window.dispatchEvent(new CustomEvent('setNN', {'detail' : data}));
});
window.max.bindInlet("param", (inst, paramName, val) => {
window.dispatchEvent(new CustomEvent('param', {'detail' : [inst, paramName, val]}));
@@ -480,16 +576,11 @@ if (!DEBUG){
window.dispatchEvent(new CustomEvent('maxTicks', {'detail' : val}));
});
window.max.bindInlet("userWave", (...points) => {
window.dispatchEvent(new CustomEvent('userWave', {'detail' : points}));
window.max.bindInlet("userWave", (index, ...points) => {
let data = {points, index};
window.dispatchEvent(new CustomEvent('userWave', {'detail' : data}));
});
/* window.max.binInlet("userWave", (...points) => {
window.dispatchEvent(new CustomEvent('userWave', {'detail' : [points]}));
log("received user points");
}); */
setInterval(() => {
window.dispatchEvent(new CustomEvent('tick'));
}, 200);
@@ -497,4 +588,4 @@ if (!DEBUG){
const root = ReactDOM.createRoot(document.getElementById('lfo-container'));
root.render(e(MasterLfoHandler, null, null));
root.render(e(MasterLfoHandler, null, null));

View File

@@ -4,7 +4,7 @@
var TYPEOPTIONS = ["LFO", "Noise"];
var SHAPETYPES = ["Sine", "SawUp", "SawDown", "Tri", "Square", "Custom"];
var SHAPETYPES = ["Sine", "SawUp", "SawDown", "Tri", "Square", "Custom_1", "Custom_2", "Custom_3", "Custom_4"];
var NOISETYPES = ["Rand", "Line Int.", "Sine Int."]
var INSTANCEOPTIONS = ["1", "2", "3", "4"];
@@ -61,7 +61,11 @@ function LfoRow(props){
};
}
function indexWave(type, phase, userDefinedWave){
function indexUserWave(phase, index, userDefinedWaves){
return parseFloat(userDefinedWaves[index][Math.floor(phase * 50)]) / 127
}
function indexWave(type, phase, userDefinedWaves){
switch (type){
case "Sine":
return (Math.sin(phase * Math.PI * 2) / 2) + 0.5;
@@ -73,12 +77,18 @@ function indexWave(type, phase, userDefinedWave){
return phase > 0.5? (1-phase) * 2 : phase * 2;
case "Square":
return +(phase > 0.5);
case "Custom":
return parseFloat(userDefinedWave[Math.floor(phase * 50)]) / 127
case "Custom_1":
return indexUserWave(phase, 1, userDefinedWaves);
case "Custom_2":
return indexUserWave(phase, 2, userDefinedWaves);
case "Custom_3":
return indexUserWave(phase, 3, userDefinedWaves);
case "Custom_4":
return indexUserWave(phase, 4, userDefinedWaves);
}
}
function operateModulators(visibleArr, typeArr, instanceNumArr, paramNames, centers, freqs, mins, maxs, waveTypes, phaseArr, noiseData, userDefinedWave, currTime, beatsInMeasure, ticks){
function operateModulators(visibleArr, typeArr, instanceNumArr, paramNames, centers, freqs, mins, maxs, waveTypes, phaseArr, noiseData, userDefinedWaves, currTime, beatsInMeasure, ticks){
for (let i=0; i<paramNames.length; i++){
if (visibleArr[i]){
@@ -92,7 +102,7 @@ function operateModulators(visibleArr, typeArr, instanceNumArr, paramNames, cent
let output = 0;
if (typeArr[i] == "LFO")
output = operateLFO(center, inst, freqs[i], mins[i], maxs[i], waveTypes[i], phaseArr, i, userDefinedWave, name, currTime, beatsInMeasure, ticks);
output = operateLFO(center, inst, freqs[i], mins[i], maxs[i], waveTypes[i], phaseArr, i, userDefinedWaves, name, currTime, beatsInMeasure, ticks);
else
output = operateNoise(center, inst, freqs[i], mins[i], maxs[i], waveTypes[i], phaseArr, i, name, noiseData, currTime, beatsInMeasure, ticks);
if (name !== "NONE")
@@ -101,7 +111,7 @@ function operateModulators(visibleArr, typeArr, instanceNumArr, paramNames, cent
}
}
function operateLFO(center, inst, timeBaseStr, min, max, waveType, phaseArr, phaseIndex, userDefinedWave, name, currTime, beatsInMeasure, maxTicks){
function operateLFO(center, inst, timeBaseStr, min, max, waveType, phaseArr, phaseIndex, userDefinedWaves, name, currTime, beatsInMeasure, maxTicks){
let amp = parseFloat(max) - parseFloat(min);
let phaseType;
let timeBase;
@@ -113,7 +123,7 @@ function operateLFO(center, inst, timeBaseStr, min, max, waveType, phaseArr, pha
phase = (currTime * timeBase + parseFloat(phaseArr[phaseIndex])) % 1.00;
else if (phaseType === PhaseTypes.MUSICAL)
phase = (maxTicks % timeBase) / timeBase;
let unscaled = indexWave(waveType, phase, userDefinedWave);
let unscaled = indexWave(waveType, phase, userDefinedWaves);
syncDisplay(inst, name, unscaled);
return unscaled * amp + center + parseFloat(min);
@@ -143,22 +153,24 @@ function operateNoise(center, inst, timeBaseStr, min, max, waveType, phaseArr, i
phase = (maxTicks % timeBase) / timeBase;
if (noiseData.cachedNoiseValueArr[index][0] == 0 || noiseData.lastPhaseArr[index] > phase){ // occurs if the phase reset to 0 or at the very start
noiseData.cachedNoiseValueArr[index][0] = noiseData.cachedNoiseValueArr[index][1];
if (noiseData.cachedNoiseValueArr[index][0] == 0)
noiseData.cachedNoiseValueArr[index][0] = center;
if (noiseData.cachedNoiseValueArr1[index] == 0 || noiseData.lastPhaseArr[index] > phase){ // occurs if the phase reset to 0 or at the very start
noiseData.cachedNoiseValueArr[index][1] = Math.random();
noiseData.setCachedNoiseValueArr(noiseData.cachedNoiseValueArr);
noiseData.cachedNoiseValueArr2[index] = noiseData.cachedNoiseValueArr1[index];
if (noiseData.cachedNoiseValueArr1[index] == 0)
noiseData.cachedNoiseValueArr2[index] = center;
noiseData.cachedNoiseValueArr1[index] = Math.random();
noiseData.setCachedNoiseValueArr1(noiseData.cachedNoiseValueArr1);
noiseData.setCachedNoiseValueArr2(noiseData.cachedNoiseValueArr2);
}
noiseData.lastPhaseArr[index] = phase;
noiseData.setLastPhaseArr(noiseData.lastPhaseArr);
let sinePhase = (Math.sin(Math.PI + Math.PI * phase) + 1) / 2
//let unscaled = (noiseData.cachedNoiseValueArr[index][1] - noiseData.cachedNoiseValueArr[index][0]) * sinePhase + noiseData.cachedNoiseValueArr[index][0];
let unscaled = interpolateNoise(noiseData.noiseTypeArr[index], noiseData.cachedNoiseValueArr[index][0], noiseData.cachedNoiseValueArr[index][1], phase);
let unscaled = interpolateNoise(noiseType, noiseData.cachedNoiseValueArr1[index], noiseData.cachedNoiseValueArr2[index], phase);
syncDisplay(inst, name, unscaled);
return unscaled * amp + center + parseFloat(min);