add function functionality for custom shape

This commit is contained in:
Eveline-97 2025-05-14 14:42:34 +02:00
parent 149d1a0b8d
commit dc2daade1b
4 changed files with 2255 additions and 65 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.DS_Store

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@ let lfos = [];
const MAXLFOS = 20; const MAXLFOS = 20;
const MAXENUMS = 20; const MAXENUMS = 20;
const MAXENUMPOINTS = 10; const MAXENUMPOINTS = 10;
const MAXUSERDEFINED = 4;
@ -81,11 +82,18 @@ function MasterLfoHandler(){
/// MODULATOR ARRAYS /// MODULATOR ARRAYS
let userDefinedWavesBase = []; let userDefinedWavesBase = [];
let userDefinedFunctionsBase = [];
let userDefinedTypesBase = [0, 0, 0, 0]; //0 = wave, 1 = function
for (let i=0; i<4; i++){ for (let i=0; i<MAXUSERDEFINED; i++){
userDefinedWavesBase.push(Array(50).fill(0)); userDefinedWavesBase.push(Array(50).fill(0));
//add
userDefinedFunctionsBase.push(Array(101).fill(0));
} }
const [userDefinedWaves, setUserDefinedWaves] = React.useState(userDefinedWavesBase); const [userDefinedWaves, setUserDefinedWaves] = React.useState(userDefinedWavesBase);
//add
const [userDefinedFunctions, setUserDefinedFunctions] = React.useState(userDefinedFunctionsBase);
const [userDefinedTypes, setUserDefinedTypes] = React.useState(userDefinedTypesBase);
const [modVisibleArr, setModVisibleArr] = React.useState(initVisArr); const [modVisibleArr, setModVisibleArr] = React.useState(initVisArr);
const [modTypeArr, setModTypeArr] = React.useState(Array(MAXLFOS).fill('LFO')); const [modTypeArr, setModTypeArr] = React.useState(Array(MAXLFOS).fill('LFO'));
const [modInstanceNumArr, setModInstanceNumArr] = React.useState(Array(MAXLFOS).fill('1')); const [modInstanceNumArr, setModInstanceNumArr] = React.useState(Array(MAXLFOS).fill('1'));
@ -244,7 +252,7 @@ function MasterLfoHandler(){
function handleTick(event) { function handleTick(event) {
let time = (Date.now() - firstUpdateTime) / 1000; let time = (Date.now() - firstUpdateTime) / 1000;
let noiseData = {lastPhaseArr, setLastPhaseArr, cachedNoiseValueArr1, setCachedNoiseValueArr1, cachedNoiseValueArr2, setCachedNoiseValueArr2, noiseTypeArr}; 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); operateModulators(modVisibleArr, modTypeArr, modInstanceNumArr, djParamArr, modCenterVals, freqArr, minArr, maxArr, shapeArr, initPhaseArr, noiseData, userDefinedWaves, userDefinedFunctions, userDefinedTypes, time, beatsInMeasure, ticks);
} }
function handleTimeSig(event) { function handleTimeSig(event) {
@ -256,6 +264,18 @@ function MasterLfoHandler(){
setUserDefinedWaves(userDefinedWaves); setUserDefinedWaves(userDefinedWaves);
} }
//add
function handleChangeUserFunction(event) {
userDefinedFunctions[event.detail.index] = event.detail.points;
setUserDefinedFunctions(userDefinedFunctions);
}
//add
function handleChangeUserDefinedType(event) {
userDefinedTypes[event.detail.index] = event.detail.type;
setUserDefinedTypes(userDefinedTypes);
}
function handleMaxTicks(event){ function handleMaxTicks(event){
setTicks(event.detail); setTicks(event.detail);
} }
@ -327,6 +347,10 @@ function MasterLfoHandler(){
window.addEventListener('enum', handleEnum); window.addEventListener('enum', handleEnum);
window.addEventListener('timesig', handleTimeSig); window.addEventListener('timesig', handleTimeSig);
window.addEventListener('userWave', handleChangeUserWave); window.addEventListener('userWave', handleChangeUserWave);
//add
window.addEventListener('userFunction', handleChangeUserFunction);
//add
window.addEventListener('userDefinedType', handleChangeUserDefinedType);
window.addEventListener('maxTicks', handleMaxTicks); window.addEventListener('maxTicks', handleMaxTicks);
return () => { return () => {
@ -339,9 +363,12 @@ function MasterLfoHandler(){
window.removeEventListener('enum', handleEnum); window.removeEventListener('enum', handleEnum);
window.removeEventListener('timesig', handleTimeSig); window.removeEventListener('timesig', handleTimeSig);
window.removeEventListener('userWave', handleChangeUserWave); window.removeEventListener('userWave', handleChangeUserWave);
//add
window.removeEventListener('userFunction', handleChangeUserFunction);
window.removeEventListener('userDefinedType', handleChangeUserDefinedType);
window.removeEventListener('maxTicks', handleMaxTicks); window.removeEventListener('maxTicks', handleMaxTicks);
}; };
}, [...allModArrays, ...allEnumArrays, ...allEnumMats, userDefinedWaves, modCenterVals, render, beatsInMeasure, ticks]); }, [...allModArrays, ...allEnumArrays, ...allEnumMats, userDefinedWaves, userDefinedFunctions, userDefinedTypes, modCenterVals, render, beatsInMeasure, ticks]);
function CheckLinked(inst, param, checkInstArr, checkParamArr){ function CheckLinked(inst, param, checkInstArr, checkParamArr){
@ -564,7 +591,6 @@ if (!DEBUG){
}); });
window.max.bindInlet("param", (inst, paramName, val) => { window.max.bindInlet("param", (inst, paramName, val) => {
window.dispatchEvent(new CustomEvent('param', {'detail' : [inst, paramName, val]})); window.dispatchEvent(new CustomEvent('param', {'detail' : [inst, paramName, val]}));
}); });
@ -580,6 +606,17 @@ if (!DEBUG){
let data = {points, index}; let data = {points, index};
window.dispatchEvent(new CustomEvent('userWave', {'detail' : data})); window.dispatchEvent(new CustomEvent('userWave', {'detail' : data}));
}); });
//add
window.max.bindInlet("userFunction", (index, ...points) => {
//list of 101 points between 0-100
let data = {points, index};
window.dispatchEvent(new CustomEvent('userFunction', {'detail': data}));
});
window.max.bindInlet("userDefinedType", (index, type) => {
let data = {index, type};
window.dispatchEvent(new CustomEvent('userDefinedType', {'detail': data}));
})
setInterval(() => { setInterval(() => {
window.dispatchEvent(new CustomEvent('tick')); window.dispatchEvent(new CustomEvent('tick'));

View File

@ -57,12 +57,17 @@ function LfoRow(props){
ListItem(e("div", {className:"linked"}, linkedText)), ListItem(e("div", {className:"linked"}, linkedText)),
); );
if (props.visible){ if (props.visible){
return content return content;
}; };
} }
function indexUserWave(phase, index, userDefinedWaves){ function indexUserWave(phase, index, userDefinedWaves){
return parseFloat(userDefinedWaves[index][Math.floor(phase * 50)]) / 127 return parseFloat(userDefinedWaves[index][Math.floor(phase * 50)]) / 127;
}
//add
function indexUserFunction(phase, index, userDefinedFunctions){
return parseFloat(userDefinedFunctions[index][Math.floor(phase * 110)]) / 127;
} }
function indexWave(type, phase, userDefinedWaves){ function indexWave(type, phase, userDefinedWaves){
@ -77,18 +82,19 @@ function indexWave(type, phase, userDefinedWaves){
return phase > 0.5? (1-phase) * 2 : phase * 2; return phase > 0.5? (1-phase) * 2 : phase * 2;
case "Square": case "Square":
return +(phase > 0.5); return +(phase > 0.5);
//TODO in Max, user chooses whether to use freedraw (wave, 0) or function (1)
case "Custom_1": case "Custom_1":
return indexUserWave(phase, 1, userDefinedWaves); return indexUserDefinedTypes[0] == 0 ? indexUserWave(phase, 1, userDefinedWaves) : indexUserFunction(phase, 1, userDefinedFunctions);
case "Custom_2": case "Custom_2":
return indexUserWave(phase, 2, userDefinedWaves); return indexUserDefinedTypes[1] == 0 ? indexUserWave(phase, 2, userDefinedWaves) : indexUserFunction(phase, 2, userDefinedFunctions);
case "Custom_3": case "Custom_3":
return indexUserWave(phase, 3, userDefinedWaves); return indexUserDefinedTypes[2] == 0 ? indexUserWave(phase, 3, userDefinedWaves) : indexUserFunction(phase, 3, userDefinedFunctions);
case "Custom_4": case "Custom_4":
return indexUserWave(phase, 4, userDefinedWaves); return indexUserDefinedTypes[3] == 0 ? indexUserWave(phase, 4, userDefinedWaves) : indexUserFunction(phase, 4, userDefinedFunctions);
} }
} }
function operateModulators(visibleArr, typeArr, instanceNumArr, paramNames, centers, freqs, mins, maxs, waveTypes, phaseArr, noiseData, userDefinedWaves, currTime, beatsInMeasure, ticks){ function operateModulators(visibleArr, typeArr, instanceNumArr, paramNames, centers, freqs, mins, maxs, waveTypes, phaseArr, noiseData, userDefinedWaves, userDefinedFunctions, userDefinedTypes, currTime, beatsInMeasure, ticks){
for (let i=0; i<paramNames.length; i++){ for (let i=0; i<paramNames.length; i++){
if (visibleArr[i]){ if (visibleArr[i]){
@ -102,7 +108,7 @@ function operateModulators(visibleArr, typeArr, instanceNumArr, paramNames, cent
let output = 0; let output = 0;
if (typeArr[i] == "LFO") if (typeArr[i] == "LFO")
output = operateLFO(center, inst, freqs[i], mins[i], maxs[i], waveTypes[i], phaseArr, i, userDefinedWaves, name, currTime, beatsInMeasure, ticks); output = operateLFO(center, inst, freqs[i], mins[i], maxs[i], waveTypes[i], phaseArr, i, userDefinedWaves, userDefinedFunctions, userDefinedTypes, name, currTime, beatsInMeasure, ticks);
else else
output = operateNoise(center, inst, freqs[i], mins[i], maxs[i], waveTypes[i], phaseArr, i, name, noiseData, currTime, beatsInMeasure, ticks); output = operateNoise(center, inst, freqs[i], mins[i], maxs[i], waveTypes[i], phaseArr, i, name, noiseData, currTime, beatsInMeasure, ticks);
if (name !== "NONE") if (name !== "NONE")
@ -111,7 +117,7 @@ function operateModulators(visibleArr, typeArr, instanceNumArr, paramNames, cent
} }
} }
function operateLFO(center, inst, timeBaseStr, min, max, waveType, phaseArr, phaseIndex, userDefinedWaves, name, currTime, beatsInMeasure, maxTicks){ function operateLFO(center, inst, timeBaseStr, min, max, waveType, phaseArr, phaseIndex, userDefinedWaves, userDefinedFunctions, userDefinedTypes, name, currTime, beatsInMeasure, maxTicks){
let amp = parseFloat(max) - parseFloat(min); let amp = parseFloat(max) - parseFloat(min);
let phaseType; let phaseType;
let timeBase; let timeBase;
@ -123,6 +129,7 @@ function operateLFO(center, inst, timeBaseStr, min, max, waveType, phaseArr, pha
phase = (currTime * timeBase + parseFloat(phaseArr[phaseIndex])) % 1.00; phase = (currTime * timeBase + parseFloat(phaseArr[phaseIndex])) % 1.00;
else if (phaseType === PhaseTypes.MUSICAL) else if (phaseType === PhaseTypes.MUSICAL)
phase = (maxTicks % timeBase) / timeBase; phase = (maxTicks % timeBase) / timeBase;
//TODO check if freedraw wave or function is used...
let unscaled = indexWave(waveType, phase, userDefinedWaves); let unscaled = indexWave(waveType, phase, userDefinedWaves);
syncDisplay(inst, name, unscaled); syncDisplay(inst, name, unscaled);