Compare commits
5 Commits
c8c410a38f
...
83cf801ec3
Author | SHA1 | Date | |
---|---|---|---|
83cf801ec3 | |||
![]() |
45e168ba11 | ||
37a65058bc | |||
![]() |
45847fbae4 | ||
![]() |
c794b5bc2f |
@ -10,7 +10,7 @@
|
|||||||
}
|
}
|
||||||
,
|
,
|
||||||
"classnamespace" : "box",
|
"classnamespace" : "box",
|
||||||
"rect" : [ 34.0, 76.0, 981.0, 763.0 ],
|
"rect" : [ 34.0, 76.0, 1155.0, 763.0 ],
|
||||||
"bglocked" : 0,
|
"bglocked" : 0,
|
||||||
"openinpresentation" : 0,
|
"openinpresentation" : 0,
|
||||||
"default_fontsize" : 12.0,
|
"default_fontsize" : 12.0,
|
||||||
@ -39,6 +39,44 @@
|
|||||||
"subpatcher_template" : "",
|
"subpatcher_template" : "",
|
||||||
"assistshowspatchername" : 0,
|
"assistshowspatchername" : 0,
|
||||||
"boxes" : [ {
|
"boxes" : [ {
|
||||||
|
"box" : {
|
||||||
|
"fontname" : "Arial",
|
||||||
|
"fontsize" : 13.0,
|
||||||
|
"id" : "obj-29",
|
||||||
|
"maxclass" : "newobj",
|
||||||
|
"numinlets" : 2,
|
||||||
|
"numoutlets" : 1,
|
||||||
|
"outlettype" : [ "bang" ],
|
||||||
|
"patching_rect" : [ 465.0, 141.0, 210.0, 23.0 ],
|
||||||
|
"text" : "metro @interval 40 ticks @active 1"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
, {
|
||||||
|
"box" : {
|
||||||
|
"id" : "obj-28",
|
||||||
|
"maxclass" : "button",
|
||||||
|
"numinlets" : 1,
|
||||||
|
"numoutlets" : 1,
|
||||||
|
"outlettype" : [ "bang" ],
|
||||||
|
"parameter_enable" : 0,
|
||||||
|
"patching_rect" : [ 826.0, 79.0, 24.0, 24.0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
, {
|
||||||
|
"box" : {
|
||||||
|
"id" : "obj-3",
|
||||||
|
"maxclass" : "newobj",
|
||||||
|
"numinlets" : 1,
|
||||||
|
"numoutlets" : 1,
|
||||||
|
"outlettype" : [ "" ],
|
||||||
|
"patching_rect" : [ 817.0, 147.0, 80.0, 22.0 ],
|
||||||
|
"text" : "prepend ticks"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
, {
|
||||||
"box" : {
|
"box" : {
|
||||||
"id" : "obj-54",
|
"id" : "obj-54",
|
||||||
"maxclass" : "newobj",
|
"maxclass" : "newobj",
|
||||||
@ -244,18 +282,6 @@
|
|||||||
"text" : "prepend timesig"
|
"text" : "prepend timesig"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
"box" : {
|
|
||||||
"id" : "obj-52",
|
|
||||||
"maxclass" : "newobj",
|
|
||||||
"numinlets" : 1,
|
|
||||||
"numoutlets" : 1,
|
|
||||||
"outlettype" : [ "" ],
|
|
||||||
"patching_rect" : [ 545.0, 135.0, 89.0, 22.0 ],
|
|
||||||
"text" : "prepend tempo"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
, {
|
, {
|
||||||
"box" : {
|
"box" : {
|
||||||
@ -299,8 +325,7 @@
|
|||||||
"numinlets" : 1,
|
"numinlets" : 1,
|
||||||
"numoutlets" : 5,
|
"numoutlets" : 5,
|
||||||
"outlettype" : [ "preset", "int", "preset", "int", "" ],
|
"outlettype" : [ "preset", "int", "preset", "int", "" ],
|
||||||
"patching_rect" : [ 934.0, 27.0, 100.0, 40.0 ],
|
"patching_rect" : [ 934.0, 27.0, 100.0, 40.0 ]
|
||||||
"pattrstorage" : "storage"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -784,6 +809,27 @@
|
|||||||
"source" : [ "obj-27", 1 ]
|
"source" : [ "obj-27", 1 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
, {
|
||||||
|
"patchline" : {
|
||||||
|
"destination" : [ "obj-47", 0 ],
|
||||||
|
"source" : [ "obj-28", 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
, {
|
||||||
|
"patchline" : {
|
||||||
|
"destination" : [ "obj-47", 0 ],
|
||||||
|
"source" : [ "obj-29", 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
, {
|
||||||
|
"patchline" : {
|
||||||
|
"destination" : [ "obj-2", 0 ],
|
||||||
|
"source" : [ "obj-3", 0 ]
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
, {
|
, {
|
||||||
"patchline" : {
|
"patchline" : {
|
||||||
@ -886,8 +932,8 @@
|
|||||||
}
|
}
|
||||||
, {
|
, {
|
||||||
"patchline" : {
|
"patchline" : {
|
||||||
"destination" : [ "obj-52", 0 ],
|
"destination" : [ "obj-3", 0 ],
|
||||||
"source" : [ "obj-47", 4 ]
|
"source" : [ "obj-47", 7 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -904,13 +950,6 @@
|
|||||||
"source" : [ "obj-5", 0 ]
|
"source" : [ "obj-5", 0 ]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
, {
|
|
||||||
"patchline" : {
|
|
||||||
"destination" : [ "obj-2", 0 ],
|
|
||||||
"source" : [ "obj-52", 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
, {
|
, {
|
||||||
"patchline" : {
|
"patchline" : {
|
||||||
|
27
lfogui.js
27
lfogui.js
@ -53,7 +53,7 @@ function MasterLfoHandler(){
|
|||||||
|
|
||||||
const [modCenterVals, setModCenterVals] = React.useState({'1':{}, '2':{}, '3':{}, '4':{}});
|
const [modCenterVals, setModCenterVals] = React.useState({'1':{}, '2':{}, '3':{}, '4':{}});
|
||||||
|
|
||||||
const [bpm, setBpm] = React.useState(100);
|
const [ticks, setTicks] = React.useState(0);
|
||||||
const [beatsInMeasure, setBeatsInMeasure] = React.useState(4);
|
const [beatsInMeasure, setBeatsInMeasure] = React.useState(4);
|
||||||
|
|
||||||
const [noiseTypeArr, setNoiseTypeArr] = React.useState(Array(MAXLFOS).fill('Sine Int.'));
|
const [noiseTypeArr, setNoiseTypeArr] = React.useState(Array(MAXLFOS).fill('Sine Int.'));
|
||||||
@ -202,11 +202,8 @@ function MasterLfoHandler(){
|
|||||||
|
|
||||||
function handleTick(event) {
|
function handleTick(event) {
|
||||||
let time = (Date.now() - firstUpdateTime) / 1000;
|
let time = (Date.now() - firstUpdateTime) / 1000;
|
||||||
operateModulators(modVisibleArr, modInstanceNumArr, djParamArr, modCenterVals, freqArr, minArr, maxArr, shapeArr, phaseArr, userDefinedWave, time, bpm, beatsInMeasure);
|
|
||||||
}
|
operateModulators(modVisibleArr, modInstanceNumArr, djParamArr, modCenterVals, freqArr, minArr, maxArr, shapeArr, phaseArr, userDefinedWave, time, beatsInMeasure, ticks);
|
||||||
|
|
||||||
function handleBpm(event) {
|
|
||||||
setBpm(event.detail);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTimeSig(event) {
|
function handleTimeSig(event) {
|
||||||
@ -217,15 +214,19 @@ function MasterLfoHandler(){
|
|||||||
setUserDefinedWave(event.detail);
|
setUserDefinedWave(event.detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleMaxTicks(event){
|
||||||
|
setTicks(event.detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
window.addEventListener('loadDict', handleLoad);
|
window.addEventListener('loadDict', handleLoad);
|
||||||
window.addEventListener('saveDict', handleSave);
|
window.addEventListener('saveDict', handleSave);
|
||||||
window.addEventListener('tick', handleTick);
|
window.addEventListener('tick', handleTick);
|
||||||
window.addEventListener('param', handleParam);
|
window.addEventListener('param', handleParam);
|
||||||
window.addEventListener('enum', handleEnum);
|
window.addEventListener('enum', handleEnum);
|
||||||
window.addEventListener('tempo', handleBpm);
|
|
||||||
window.addEventListener('timesig', handleTimeSig);
|
window.addEventListener('timesig', handleTimeSig);
|
||||||
window.addEventListener('userWave', handleChangeUserWave);
|
window.addEventListener('userWave', handleChangeUserWave);
|
||||||
|
window.addEventListener('maxTicks', handleMaxTicks);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('loadDict', handleLoad);
|
window.removeEventListener('loadDict', handleLoad);
|
||||||
@ -233,11 +234,11 @@ function MasterLfoHandler(){
|
|||||||
window.removeEventListener('tick', handleTick);
|
window.removeEventListener('tick', handleTick);
|
||||||
window.removeEventListener('param', handleParam);
|
window.removeEventListener('param', handleParam);
|
||||||
window.removeEventListener('enum', handleEnum);
|
window.removeEventListener('enum', handleEnum);
|
||||||
window.removeEventListener('tempo', handleBpm);
|
|
||||||
window.removeEventListener('timesig', handleTimeSig);
|
window.removeEventListener('timesig', handleTimeSig);
|
||||||
window.removeEventListener('userWave', handleChangeUserWave);
|
window.removeEventListener('userWave', handleChangeUserWave);
|
||||||
|
window.removeEventListener('maxTicks', handleMaxTicks);
|
||||||
};
|
};
|
||||||
}, [...allModArrays, ...allEnumArrays, ...allEnumMats, modCenterVals, render, bpm, beatsInMeasure]);
|
}, [...allModArrays, ...allEnumArrays, ...allEnumMats, modCenterVals, render, beatsInMeasure, ticks]);
|
||||||
|
|
||||||
|
|
||||||
function CheckLinked(inst, param, checkInstArr, checkParamArr){
|
function CheckLinked(inst, param, checkInstArr, checkParamArr){
|
||||||
@ -440,14 +441,14 @@ if (!DEBUG){
|
|||||||
window.dispatchEvent(new CustomEvent('param', {'detail' : [inst, paramName, val]}));
|
window.dispatchEvent(new CustomEvent('param', {'detail' : [inst, paramName, val]}));
|
||||||
});
|
});
|
||||||
|
|
||||||
window.max.bindInlet("tempo", (val) => {
|
|
||||||
window.dispatchEvent(new CustomEvent('tempo', {'detail' : val}));
|
|
||||||
});
|
|
||||||
|
|
||||||
window.max.bindInlet("timesig", (top, bottom) => {
|
window.max.bindInlet("timesig", (top, bottom) => {
|
||||||
window.dispatchEvent(new CustomEvent('timesig', {'detail' : [top, bottom]}));
|
window.dispatchEvent(new CustomEvent('timesig', {'detail' : [top, bottom]}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window.max.bindInlet("ticks", (val) => {
|
||||||
|
window.dispatchEvent(new CustomEvent('maxTicks', {'detail' : val}));
|
||||||
|
});
|
||||||
|
|
||||||
window.max.bindInlet("userWave", (...points) => {
|
window.max.bindInlet("userWave", (...points) => {
|
||||||
window.dispatchEvent(new CustomEvent('userWave', {'detail' : points}));
|
window.dispatchEvent(new CustomEvent('userWave', {'detail' : points}));
|
||||||
});
|
});
|
||||||
|
@ -13,6 +13,16 @@ const MODPARAMOPTIONS = ["NONE", "stream", "pulse_length", "eventfulness", "even
|
|||||||
"harmoniclarity", "melodic_cohesion", "melody_scope", "tonic_pitch", "pitch_center", "pitch_range", "dynamics",
|
"harmoniclarity", "melodic_cohesion", "melody_scope", "tonic_pitch", "pitch_center", "pitch_range", "dynamics",
|
||||||
"attenuation", "chordal_weight", "tonality-profile", "ostinato-buffer", "ostinato", "meter", "scale"];
|
"attenuation", "chordal_weight", "tonality-profile", "ostinato-buffer", "ostinato", "meter", "scale"];
|
||||||
|
|
||||||
|
const PhaseTypes = Object.freeze({
|
||||||
|
MUSICAL: Symbol("musical"),
|
||||||
|
TIME: Symbol("time")
|
||||||
|
});
|
||||||
|
|
||||||
|
function ControlType(){
|
||||||
|
return e('select', {className: 'control-type'}, Option("LFO"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function LfoRow(props){
|
function LfoRow(props){
|
||||||
|
|
||||||
@ -68,7 +78,7 @@ function indexWave(type, phase, userDefinedWave){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function operateModulators(visibleArr, instanceNumArr, paramNames, centers, freqs, mins, maxs, waveTypes, phaseArr, userDefinedWave, currTime, bpm, beatsInMeasure){
|
function operateModulators(visibleArr, instanceNumArr, paramNames, centers, freqs, mins, maxs, waveTypes, phaseArr, userDefinedWave, 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]){
|
||||||
|
|
||||||
@ -78,18 +88,26 @@ function operateModulators(visibleArr, instanceNumArr, paramNames, centers, freq
|
|||||||
if (centers[inst].hasOwnProperty(name)){
|
if (centers[inst].hasOwnProperty(name)){
|
||||||
center = centers[inst][name];
|
center = centers[inst][name];
|
||||||
}
|
}
|
||||||
let output = operateModulator(center, inst, freqs[i], mins[i], maxs[i], waveTypes[i], phaseArr, i, userDefinedWave, name, currTime, bpm, beatsInMeasure);
|
let output = operateModulator(center, inst, freqs[i], mins[i], maxs[i], waveTypes[i], phaseArr, i, userDefinedWave, name, currTime, beatsInMeasure, ticks);
|
||||||
if (name !== "NONE")
|
if (name !== "NONE")
|
||||||
window.dispatchEvent(new CustomEvent('enum', {'detail' : [inst, name, output]}));
|
window.dispatchEvent(new CustomEvent('enum', {'detail' : [inst, name, output]}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function operateModulator(center, inst, freq, min, max, waveType, phaseArr, phaseI, userDefinedWave, name, currTime, bpm, beatsInMeasure){
|
function operateModulator(center, inst, timeBaseStr, min, max, waveType, phaseArr, phaseI, userDefinedWave, name, currTime, beatsInMeasure, maxTicks){
|
||||||
let amp = parseFloat(max) - parseFloat(min);
|
|
||||||
|
|
||||||
freq = parseLfoTime(freq, bpm, beatsInMeasure);
|
let amp = parseFloat(max) - parseFloat(min);
|
||||||
let phase = (currTime * freq + parseFloat(phaseArr[phaseI])) % 1.00;
|
let phaseType;
|
||||||
|
let timeBase;
|
||||||
|
|
||||||
|
[timeBase, phaseType] = parseLfoTime(timeBaseStr, beatsInMeasure);
|
||||||
|
let phase;
|
||||||
|
|
||||||
|
if (phaseType === PhaseTypes.TIME)
|
||||||
|
phase = (currTime * timeBase + parseFloat(phaseArr[phaseI])) % 1.00;
|
||||||
|
else if (phaseType === PhaseTypes.MUSICAL)
|
||||||
|
phase = (maxTicks % timeBase) / timeBase;
|
||||||
let unscaled = indexWave(waveType, phase, userDefinedWave);
|
let unscaled = indexWave(waveType, phase, userDefinedWave);
|
||||||
let el = document.getElementById(`slider-${inst}-${name}`);
|
let el = document.getElementById(`slider-${inst}-${name}`);
|
||||||
|
|
||||||
@ -99,33 +117,30 @@ function operateModulator(center, inst, freq, min, max, waveType, phaseArr, phas
|
|||||||
return unscaled * amp + center + parseFloat(min);
|
return unscaled * amp + center + parseFloat(min);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// actual returns the period for musical timing, to avoid floating point errors
|
||||||
function parseLfoTime(lfoTime, bpm, beatsInMeasure){
|
function parseLfoTime(lfoTime, beatsInMeasure){
|
||||||
if (lfoTime.slice(-2) == "hz"){
|
if (lfoTime.slice(-2) == "hz"){
|
||||||
return parseFloat(lfoTime.slice(0, -2));
|
return [parseFloat(lfoTime.slice(0, -2)), PhaseTypes.TIME];
|
||||||
}
|
}
|
||||||
else if (lfoTime.slice(-2) == "ms"){
|
else if (lfoTime.slice(-2) == "ms"){
|
||||||
return 1000 / parseFloat(lfoTime.slice(0, -2));
|
return [1000 / parseFloat(lfoTime.slice(0, -2)), PhaseTypes.TIME];
|
||||||
}
|
}
|
||||||
else if (lfoTime.slice(-1) == "s"){
|
else if (lfoTime.slice(-1) == "s"){
|
||||||
return 1 / parseFloat(lfoTime.slice(0, -1));
|
return [1 / parseFloat(lfoTime.slice(0, -1)), PhaseTypes.TIME];
|
||||||
}
|
}
|
||||||
else if ((lfoTime.match(/:/g) || []).length == 2){
|
else if ((lfoTime.match(/:/g) || []).length == 2){
|
||||||
return 1 / moment.duration(lfoTime).asSeconds();
|
return [1 / moment.duration(lfoTime).asSeconds(), PhaseTypes.TIME];
|
||||||
}
|
}
|
||||||
else if ((lfoTime.match(/\./g) || []).length == 2){
|
else if ((lfoTime.match(/\./g) || []).length == 2){
|
||||||
return musicalTimingToFreq(...lfoTime.split('.'), bpm, beatsInMeasure)
|
return [musicalTimingToFreq(...lfoTime.split('.'), beatsInMeasure), PhaseTypes.MUSICAL];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return 0;
|
return [0, PhaseTypes.TIME];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function musicalTimingToFreq(bars, beats, ticks, bpm, beatsInMeasure){
|
function musicalTimingToFreq(bars, beats, ticks, beatsInMeasure){
|
||||||
let totalTicks = (parseFloat(bars) * parseFloat(beatsInMeasure) + beats) * 480 + parseFloat(ticks);
|
let totalTicks = (parseFloat(bars) * parseFloat(beatsInMeasure) + parseFloat(beats)) * 480 + parseFloat(ticks);
|
||||||
let tpm = bpm * 480;
|
return totalTicks;
|
||||||
let cyclesPerMinute = tpm / totalTicks;
|
|
||||||
let hz = cyclesPerMinute / 60;
|
|
||||||
return hz;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user