mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 18:52:19 +00:00
extended MIDI support. Some new general purpose nodes like sequencer, string, cast to number.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
1011
build/litegraph.min.js
vendored
1011
build/litegraph.min.js
vendored
File diff suppressed because it is too large
Load Diff
1
demo/examples/midi_generation.json
Normal file
1
demo/examples/midi_generation.json
Normal file
File diff suppressed because one or more lines are too long
@@ -15,15 +15,17 @@
|
|||||||
|
|
||||||
<script type="text/javascript" src="../external/jquery-1.6.2.min.js"></script>
|
<script type="text/javascript" src="../external/jquery-1.6.2.min.js"></script>
|
||||||
<script type="text/javascript" src="http://tamats.com/projects/sillyserver/src/sillyclient.js"></script>
|
<script type="text/javascript" src="http://tamats.com/projects/sillyserver/src/sillyclient.js"></script>
|
||||||
|
<script type="text/javascript" src="js/libs/audiosynth.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="../src/litegraph.js"></script>
|
<script type="text/javascript" src="../src/litegraph.js"></script>
|
||||||
<script type="text/javascript" src="../src/litegraph-editor.js"></script>
|
<script type="text/javascript" src="../src/litegraph-editor.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="../src/nodes/base.js"></script>
|
<script type="text/javascript" src="../src/nodes/base.js"></script>
|
||||||
|
<script type="text/javascript" src="../src/nodes/logic.js"></script>
|
||||||
<script type="text/javascript" src="../src/nodes/events.js"></script>
|
<script type="text/javascript" src="../src/nodes/events.js"></script>
|
||||||
<script type="text/javascript" src="../src/nodes/math.js"></script>
|
<script type="text/javascript" src="../src/nodes/math.js"></script>
|
||||||
<script type="text/javascript" src="../src/nodes/interface.js"></script>
|
<script type="text/javascript" src="../src/nodes/interface.js"></script>
|
||||||
<script type="text/javascript" src="../src/nodes/image.js"></script>
|
<script type="text/javascript" src="../src/nodes/graphics.js"></script>
|
||||||
<script type="text/javascript" src="../src/nodes/input.js"></script>
|
<script type="text/javascript" src="../src/nodes/input.js"></script>
|
||||||
<script type="text/javascript" src="../src/nodes/midi.js"></script>
|
<script type="text/javascript" src="../src/nodes/midi.js"></script>
|
||||||
<script type="text/javascript" src="../src/nodes/audio.js"></script>
|
<script type="text/javascript" src="../src/nodes/audio.js"></script>
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ window.graphcanvas = editor.graphcanvas;
|
|||||||
window.graph = editor.graph;
|
window.graph = editor.graph;
|
||||||
window.addEventListener("resize", function() { editor.graphcanvas.resize(); } );
|
window.addEventListener("resize", function() { editor.graphcanvas.resize(); } );
|
||||||
window.addEventListener("keydown", editor.graphcanvas.processKey.bind(editor.graphcanvas) );
|
window.addEventListener("keydown", editor.graphcanvas.processKey.bind(editor.graphcanvas) );
|
||||||
|
window.onbeforeunload = function(){
|
||||||
|
var data = JSON.stringify( graph.serialize() );
|
||||||
|
localStorage.setItem("litegraphg demo backup", data );
|
||||||
|
}
|
||||||
|
|
||||||
//create scene selector
|
//create scene selector
|
||||||
var elem = document.createElement("span");
|
var elem = document.createElement("span");
|
||||||
@@ -18,6 +22,8 @@ select.addEventListener("change", function(e){
|
|||||||
|
|
||||||
if(url)
|
if(url)
|
||||||
graph.load( url );
|
graph.load( url );
|
||||||
|
else if(option.callback)
|
||||||
|
option.callback();
|
||||||
else
|
else
|
||||||
graph.clear();
|
graph.clear();
|
||||||
});
|
});
|
||||||
@@ -37,7 +43,10 @@ elem.querySelector("#load").addEventListener("click",function(){
|
|||||||
function addDemo( name, url )
|
function addDemo( name, url )
|
||||||
{
|
{
|
||||||
var option = document.createElement("option");
|
var option = document.createElement("option");
|
||||||
option.dataset["url"] = url;
|
if(url.constructor === String)
|
||||||
|
option.dataset["url"] = url;
|
||||||
|
else
|
||||||
|
option.callback = url;
|
||||||
option.innerHTML = name;
|
option.innerHTML = name;
|
||||||
select.appendChild( option );
|
select.appendChild( option );
|
||||||
}
|
}
|
||||||
@@ -48,6 +57,14 @@ addDemo("Benchmark", "examples/benchmark.json");
|
|||||||
addDemo("Audio", "examples/audio.json");
|
addDemo("Audio", "examples/audio.json");
|
||||||
addDemo("Audio Delay", "examples/audio_delay.json");
|
addDemo("Audio Delay", "examples/audio_delay.json");
|
||||||
addDemo("Audio Reverb", "examples/audio_reverb.json");
|
addDemo("Audio Reverb", "examples/audio_reverb.json");
|
||||||
|
addDemo("MIDI Generation", "examples/midi_generation.json");
|
||||||
|
addDemo("autobackup", function(){
|
||||||
|
var data = localStorage.getItem("litegraphg demo backup");
|
||||||
|
if(!data)
|
||||||
|
return;
|
||||||
|
var graph_data = JSON.parse(data);
|
||||||
|
graph.configure( graph_data );
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -191,7 +191,7 @@ function TestSlotsNode()
|
|||||||
this.addInput("C","number");
|
this.addInput("C","number");
|
||||||
this.addOutput("A","number");
|
this.addOutput("A","number");
|
||||||
this.addOutput("B","number");
|
this.addOutput("B","number");
|
||||||
this.flags = { horizontal: true };
|
this.horizontal = true;
|
||||||
this.size = [100,40];
|
this.size = [100,40];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
356
demo/js/libs/audiosynth.js
Normal file
356
demo/js/libs/audiosynth.js
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
var Synth, AudioSynth, AudioSynthInstrument;
|
||||||
|
!function(){
|
||||||
|
|
||||||
|
var URL = window.URL || window.webkitURL;
|
||||||
|
var Blob = window.Blob;
|
||||||
|
|
||||||
|
if(!URL || !Blob) {
|
||||||
|
throw new Error('This browser does not support AudioSynth');
|
||||||
|
}
|
||||||
|
|
||||||
|
var _encapsulated = false;
|
||||||
|
var AudioSynthInstance = null;
|
||||||
|
var pack = function(c,arg){ return [new Uint8Array([arg, arg >> 8]), new Uint8Array([arg, arg >> 8, arg >> 16, arg >> 24])][c]; };
|
||||||
|
var setPrivateVar = function(n,v,w,e){Object.defineProperty(this,n,{value:v,writable:!!w,enumerable:!!e});};
|
||||||
|
var setPublicVar = function(n,v,w){setPrivateVar.call(this,n,v,w,true);};
|
||||||
|
AudioSynthInstrument = function AudioSynthInstrument(){this.__init__.apply(this,arguments);};
|
||||||
|
var setPriv = setPrivateVar.bind(AudioSynthInstrument.prototype);
|
||||||
|
var setPub = setPublicVar.bind(AudioSynthInstrument.prototype);
|
||||||
|
setPriv('__init__', function(a,b,c) {
|
||||||
|
if(!_encapsulated) { throw new Error('AudioSynthInstrument can only be instantiated from the createInstrument method of the AudioSynth object.'); }
|
||||||
|
setPrivateVar.call(this, '_parent', a);
|
||||||
|
setPublicVar.call(this, 'name', b);
|
||||||
|
setPrivateVar.call(this, '_soundID', c);
|
||||||
|
});
|
||||||
|
setPub('play', function(note, octave, duration,volume) {
|
||||||
|
return this._parent.play(this._soundID, note, octave, duration, volume);
|
||||||
|
});
|
||||||
|
setPub('generate', function(note, octave, duration) {
|
||||||
|
return this._parent.generate(this._soundID, note, octave, duration);
|
||||||
|
});
|
||||||
|
AudioSynth = function AudioSynth(){if(AudioSynthInstance instanceof AudioSynth){return AudioSynthInstance;}else{ this.__init__(); return this; }};
|
||||||
|
setPriv = setPrivateVar.bind(AudioSynth.prototype);
|
||||||
|
setPub = setPublicVar.bind(AudioSynth.prototype);
|
||||||
|
setPriv('_debug',false,true);
|
||||||
|
setPriv('_bitsPerSample',16);
|
||||||
|
setPriv('_channels',1);
|
||||||
|
setPriv('_sampleRate',44100,true);
|
||||||
|
setPub('setSampleRate', function(v) {
|
||||||
|
this._sampleRate = Math.max(Math.min(v|0,44100), 4000);
|
||||||
|
this._clearCache();
|
||||||
|
return this._sampleRate;
|
||||||
|
});
|
||||||
|
setPub('getSampleRate', function() { return this._sampleRate; });
|
||||||
|
setPriv('_volume',32768,true);
|
||||||
|
setPub('setVolume', function(v) {
|
||||||
|
v = parseFloat(v); if(isNaN(v)) { v = 0; }
|
||||||
|
v = Math.round(v*32768);
|
||||||
|
this._volume = Math.max(Math.min(v|0,32768), 0);
|
||||||
|
this._clearCache();
|
||||||
|
return this._volume;
|
||||||
|
});
|
||||||
|
setPub('getVolume', function() { return Math.round(this._volume/32768*10000)/10000; });
|
||||||
|
setPriv('_notes',{'C':261.63,'C#':277.18,'D':293.66,'D#':311.13,'E':329.63,'F':346.23,'F#':369.99,'G':392.00,'G#':415.30,'A':440.00,'A#':466.16,'B':493.88});
|
||||||
|
setPriv('_fileCache',[],true);
|
||||||
|
setPriv('_temp',{},true);
|
||||||
|
setPriv('_sounds',[],true);
|
||||||
|
setPriv('_mod',[function(i,s,f,x){return Math.sin((2 * Math.PI)*(i/s)*f+x);}]);
|
||||||
|
setPriv('_resizeCache', function() {
|
||||||
|
var f = this._fileCache;
|
||||||
|
var l = this._sounds.length;
|
||||||
|
while(f.length<l) {
|
||||||
|
var octaveList = [];
|
||||||
|
for(var i = 0; i < 8; i++) {
|
||||||
|
var noteList = {};
|
||||||
|
for(var k in this._notes) {
|
||||||
|
noteList[k] = {};
|
||||||
|
}
|
||||||
|
octaveList.push(noteList);
|
||||||
|
}
|
||||||
|
f.push(octaveList);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setPriv('_clearCache', function() {
|
||||||
|
this._fileCache = [];
|
||||||
|
this._resizeCache();
|
||||||
|
});
|
||||||
|
setPub('generate', function(sound, note, octave, duration) {
|
||||||
|
var thisSound = this._sounds[sound];
|
||||||
|
if(!thisSound) {
|
||||||
|
for(var i=0;i<this._sounds.length;i++) {
|
||||||
|
if(this._sounds[i].name==sound) {
|
||||||
|
thisSound = this._sounds[i];
|
||||||
|
sound = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!thisSound) { throw new Error('Invalid sound or sound ID: ' + sound); }
|
||||||
|
var t = (new Date).valueOf();
|
||||||
|
this._temp = {};
|
||||||
|
octave |= 0;
|
||||||
|
octave = Math.min(8, Math.max(1, octave));
|
||||||
|
var time = !duration?2:parseFloat(duration);
|
||||||
|
if(typeof(this._notes[note])=='undefined') { throw new Error(note + ' is not a valid note.'); }
|
||||||
|
if(typeof(this._fileCache[sound][octave-1][note][time])!='undefined') {
|
||||||
|
if(this._debug) { console.log((new Date).valueOf() - t, 'ms to retrieve (cached)'); }
|
||||||
|
return this._fileCache[sound][octave-1][note][time];
|
||||||
|
} else {
|
||||||
|
var frequency = this._notes[note] * Math.pow(2,octave-4);
|
||||||
|
var sampleRate = this._sampleRate;
|
||||||
|
var volume = this._volume;
|
||||||
|
var channels = this._channels;
|
||||||
|
var bitsPerSample = this._bitsPerSample;
|
||||||
|
var attack = thisSound.attack(sampleRate, frequency, volume);
|
||||||
|
var dampen = thisSound.dampen(sampleRate, frequency, volume);
|
||||||
|
var waveFunc = thisSound.wave;
|
||||||
|
var waveBind = {modulate: this._mod, vars: this._temp};
|
||||||
|
var val = 0;
|
||||||
|
var curVol = 0;
|
||||||
|
|
||||||
|
var data = new Uint8Array(new ArrayBuffer(Math.ceil(sampleRate * time * 2)));
|
||||||
|
var attackLen = (sampleRate * attack) | 0;
|
||||||
|
var decayLen = (sampleRate * time) | 0;
|
||||||
|
|
||||||
|
for (var i = 0 | 0; i !== attackLen; i++) {
|
||||||
|
|
||||||
|
val = volume * (i/(sampleRate*attack)) * waveFunc.call(waveBind, i, sampleRate, frequency, volume);
|
||||||
|
|
||||||
|
data[i << 1] = val;
|
||||||
|
data[(i << 1) + 1] = val >> 8;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; i !== decayLen; i++) {
|
||||||
|
|
||||||
|
val = volume * Math.pow((1-((i-(sampleRate*attack))/(sampleRate*(time-attack)))),dampen) * waveFunc.call(waveBind, i, sampleRate, frequency, volume);
|
||||||
|
|
||||||
|
data[i << 1] = val;
|
||||||
|
data[(i << 1) + 1] = val >> 8;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var out = [
|
||||||
|
'RIFF',
|
||||||
|
pack(1, 4 + (8 + 24/* chunk 1 length */) + (8 + 8/* chunk 2 length */)), // Length
|
||||||
|
'WAVE',
|
||||||
|
// chunk 1
|
||||||
|
'fmt ', // Sub-chunk identifier
|
||||||
|
pack(1, 16), // Chunk length
|
||||||
|
pack(0, 1), // Audio format (1 is linear quantization)
|
||||||
|
pack(0, channels),
|
||||||
|
pack(1, sampleRate),
|
||||||
|
pack(1, sampleRate * channels * bitsPerSample / 8), // Byte rate
|
||||||
|
pack(0, channels * bitsPerSample / 8),
|
||||||
|
pack(0, bitsPerSample),
|
||||||
|
// chunk 2
|
||||||
|
'data', // Sub-chunk identifier
|
||||||
|
pack(1, data.length * channels * bitsPerSample / 8), // Chunk length
|
||||||
|
data
|
||||||
|
];
|
||||||
|
var blob = new Blob(out, {type: 'audio/wav'});
|
||||||
|
var dataURI = URL.createObjectURL(blob);
|
||||||
|
this._fileCache[sound][octave-1][note][time] = dataURI;
|
||||||
|
if(this._debug) { console.log((new Date).valueOf() - t, 'ms to generate'); }
|
||||||
|
return dataURI;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setPub('play', function(sound, note, octave, duration, volume) {
|
||||||
|
var src = this.generate( sound, note, octave, duration );
|
||||||
|
var audio = new Audio(src);
|
||||||
|
if(volume != null)
|
||||||
|
{
|
||||||
|
if(volume <= 0)
|
||||||
|
return true;
|
||||||
|
audio.volume = volume > 1 ? 1 : volume;
|
||||||
|
}
|
||||||
|
audio.play();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
setPub('debug', function() { this._debug = true; });
|
||||||
|
setPub('createInstrument', function(sound) {
|
||||||
|
var n = 0;
|
||||||
|
var found = false;
|
||||||
|
if(typeof(sound)=='string') {
|
||||||
|
for(var i=0;i<this._sounds.length;i++) {
|
||||||
|
if(this._sounds[i].name==sound) {
|
||||||
|
found = true;
|
||||||
|
n = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(this._sounds[sound]) {
|
||||||
|
n = sound;
|
||||||
|
sound = this._sounds[n].name;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found) { throw new Error('Invalid sound or sound ID: ' + sound); }
|
||||||
|
_encapsulated = true;
|
||||||
|
var ins = new AudioSynthInstrument(this, sound, n);
|
||||||
|
_encapsulated = false;
|
||||||
|
return ins;
|
||||||
|
});
|
||||||
|
setPub('listSounds', function() {
|
||||||
|
var r = [];
|
||||||
|
for(var i=0;i<this._sounds.length;i++) {
|
||||||
|
r.push(this._sounds[i].name);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
});
|
||||||
|
setPriv('__init__', function(){
|
||||||
|
this._resizeCache();
|
||||||
|
});
|
||||||
|
setPub('loadSoundProfile', function() {
|
||||||
|
for(var i=0,len=arguments.length;i<len;i++) {
|
||||||
|
o = arguments[i];
|
||||||
|
if(!(o instanceof Object)) { throw new Error('Invalid sound profile.'); }
|
||||||
|
this._sounds.push(o);
|
||||||
|
}
|
||||||
|
this._resizeCache();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
setPub('loadModulationFunction', function() {
|
||||||
|
for(var i=0,len=arguments.length;i<len;i++) {
|
||||||
|
f = arguments[i];
|
||||||
|
if(typeof(f)!='function') { throw new Error('Invalid modulation function.'); }
|
||||||
|
this._mod.push(f);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
AudioSynthInstance = new AudioSynth();
|
||||||
|
Synth = AudioSynthInstance;
|
||||||
|
}();
|
||||||
|
|
||||||
|
Synth.loadModulationFunction(
|
||||||
|
function(i, sampleRate, frequency, x) { return 1 * Math.sin(2 * Math.PI * ((i / sampleRate) * frequency) + x); },
|
||||||
|
function(i, sampleRate, frequency, x) { return 1 * Math.sin(4 * Math.PI * ((i / sampleRate) * frequency) + x); },
|
||||||
|
function(i, sampleRate, frequency, x) { return 1 * Math.sin(8 * Math.PI * ((i / sampleRate) * frequency) + x); },
|
||||||
|
function(i, sampleRate, frequency, x) { return 1 * Math.sin(0.5 * Math.PI * ((i / sampleRate) * frequency) + x); },
|
||||||
|
function(i, sampleRate, frequency, x) { return 1 * Math.sin(0.25 * Math.PI * ((i / sampleRate) * frequency) + x); },
|
||||||
|
function(i, sampleRate, frequency, x) { return 0.5 * Math.sin(2 * Math.PI * ((i / sampleRate) * frequency) + x); },
|
||||||
|
function(i, sampleRate, frequency, x) { return 0.5 * Math.sin(4 * Math.PI * ((i / sampleRate) * frequency) + x); },
|
||||||
|
function(i, sampleRate, frequency, x) { return 0.5 * Math.sin(8 * Math.PI * ((i / sampleRate) * frequency) + x); },
|
||||||
|
function(i, sampleRate, frequency, x) { return 0.5 * Math.sin(0.5 * Math.PI * ((i / sampleRate) * frequency) + x); },
|
||||||
|
function(i, sampleRate, frequency, x) { return 0.5 * Math.sin(0.25 * Math.PI * ((i / sampleRate) * frequency) + x); }
|
||||||
|
);
|
||||||
|
|
||||||
|
Synth.loadSoundProfile({
|
||||||
|
name: 'piano',
|
||||||
|
attack: function() { return 0.002; },
|
||||||
|
dampen: function(sampleRate, frequency, volume) {
|
||||||
|
return Math.pow(0.5*Math.log((frequency*volume)/sampleRate),2);
|
||||||
|
},
|
||||||
|
wave: function(i, sampleRate, frequency, volume) {
|
||||||
|
var base = this.modulate[0];
|
||||||
|
return this.modulate[1](
|
||||||
|
i,
|
||||||
|
sampleRate,
|
||||||
|
frequency,
|
||||||
|
Math.pow(base(i, sampleRate, frequency, 0), 2) +
|
||||||
|
(0.75 * base(i, sampleRate, frequency, 0.25)) +
|
||||||
|
(0.1 * base(i, sampleRate, frequency, 0.5))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'organ',
|
||||||
|
attack: function() { return 0.3 },
|
||||||
|
dampen: function(sampleRate, frequency) { return 1+(frequency * 0.01); },
|
||||||
|
wave: function(i, sampleRate, frequency) {
|
||||||
|
var base = this.modulate[0];
|
||||||
|
return this.modulate[1](
|
||||||
|
i,
|
||||||
|
sampleRate,
|
||||||
|
frequency,
|
||||||
|
base(i, sampleRate, frequency, 0) +
|
||||||
|
0.5*base(i, sampleRate, frequency, 0.25) +
|
||||||
|
0.25*base(i, sampleRate, frequency, 0.5)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'acoustic',
|
||||||
|
attack: function() { return 0.002; },
|
||||||
|
dampen: function() { return 1; },
|
||||||
|
wave: function(i, sampleRate, frequency) {
|
||||||
|
|
||||||
|
var vars = this.vars;
|
||||||
|
vars.valueTable = !vars.valueTable?[]:vars.valueTable;
|
||||||
|
if(typeof(vars.playVal)=='undefined') { vars.playVal = 0; }
|
||||||
|
if(typeof(vars.periodCount)=='undefined') { vars.periodCount = 0; }
|
||||||
|
|
||||||
|
var valueTable = vars.valueTable;
|
||||||
|
var playVal = vars.playVal;
|
||||||
|
var periodCount = vars.periodCount;
|
||||||
|
|
||||||
|
var period = sampleRate/frequency;
|
||||||
|
var p_hundredth = Math.floor((period-Math.floor(period))*100);
|
||||||
|
|
||||||
|
var resetPlay = false;
|
||||||
|
|
||||||
|
if(valueTable.length<=Math.ceil(period)) {
|
||||||
|
|
||||||
|
valueTable.push(Math.round(Math.random())*2-1);
|
||||||
|
|
||||||
|
return valueTable[valueTable.length-1];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
valueTable[playVal] = (valueTable[playVal>=(valueTable.length-1)?0:playVal+1] + valueTable[playVal]) * 0.5;
|
||||||
|
|
||||||
|
if(playVal>=Math.floor(period)) {
|
||||||
|
if(playVal<Math.ceil(period)) {
|
||||||
|
if((periodCount%100)>=p_hundredth) {
|
||||||
|
// Reset
|
||||||
|
resetPlay = true;
|
||||||
|
valueTable[playVal+1] = (valueTable[0] + valueTable[playVal+1]) * 0.5;
|
||||||
|
vars.periodCount++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resetPlay = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _return = valueTable[playVal];
|
||||||
|
if(resetPlay) { vars.playVal = 0; } else { vars.playVal++; }
|
||||||
|
|
||||||
|
return _return;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'edm',
|
||||||
|
attack: function() { return 0.002; },
|
||||||
|
dampen: function() { return 1; },
|
||||||
|
wave: function(i, sampleRate, frequency) {
|
||||||
|
var base = this.modulate[0];
|
||||||
|
var mod = this.modulate.slice(1);
|
||||||
|
return mod[0](
|
||||||
|
i,
|
||||||
|
sampleRate,
|
||||||
|
frequency,
|
||||||
|
mod[9](
|
||||||
|
i,
|
||||||
|
sampleRate,
|
||||||
|
frequency,
|
||||||
|
mod[2](
|
||||||
|
i,
|
||||||
|
sampleRate,
|
||||||
|
frequency,
|
||||||
|
Math.pow(base(i, sampleRate, frequency, 0), 3) +
|
||||||
|
Math.pow(base(i, sampleRate, frequency, 0.5), 5) +
|
||||||
|
Math.pow(base(i, sampleRate, frequency, 1), 7)
|
||||||
|
)
|
||||||
|
) +
|
||||||
|
mod[8](
|
||||||
|
i,
|
||||||
|
sampleRate,
|
||||||
|
frequency,
|
||||||
|
base(i, sampleRate, frequency, 1.75)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "litegraph.js",
|
"name": "litegraph.js",
|
||||||
"version": "0.6.0",
|
"version": "0.7.0",
|
||||||
"description": "A graph node editor similar to PD or UDK Blueprints, it works in a HTML5 Canvas and allow to exported graphs to be included in applications.",
|
"description": "A graph node editor similar to PD or UDK Blueprints, it works in a HTML5 Canvas and allow to exported graphs to be included in applications.",
|
||||||
"main": "build/litegraph.js",
|
"main": "build/litegraph.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
@@ -28,13 +28,13 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/kriffe/litegraph.js#readme",
|
"homepage": "https://github.com/kriffe/litegraph.js#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"express": "^4.16.2",
|
"express": "^4.16.4",
|
||||||
"google-closure-compiler": "^20171112.0.0",
|
"google-closure-compiler": "^20171112.0.0",
|
||||||
"grunt": "^1.0.1",
|
"grunt": "^1.0.3",
|
||||||
"grunt-cli": "^1.2.0",
|
"grunt-cli": "^1.2.0",
|
||||||
"grunt-closure-tools": "^1.0.0",
|
"grunt-closure-tools": "^1.0.0",
|
||||||
"grunt-contrib-concat": "^1.0.1",
|
"grunt-contrib-concat": "^1.0.1",
|
||||||
"nodemon": "^1.14.7",
|
"nodemon": "^1.18.9",
|
||||||
"rimraf": "^2.6.2"
|
"rimraf": "^2.6.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1719,11 +1719,16 @@ LGraph.prototype.onNodeTrace = function(node, msg, color)
|
|||||||
input|output: every connection
|
input|output: every connection
|
||||||
+ { name:string, type:string, pos: [x,y]=Optional, direction: "input"|"output", links: Array });
|
+ { name:string, type:string, pos: [x,y]=Optional, direction: "input"|"output", links: Array });
|
||||||
|
|
||||||
flags:
|
general properties:
|
||||||
+ clip_area: if you render outside the node, it will be cliped
|
+ clip_area: if you render outside the node, it will be cliped
|
||||||
+ unsafe_execution: not allowed for safe execution
|
+ unsafe_execution: not allowed for safe execution
|
||||||
+ skip_repeated_outputs: when adding new outputs, it wont show if there is one already connected
|
+ skip_repeated_outputs: when adding new outputs, it wont show if there is one already connected
|
||||||
+ resizable: if set to false it wont be resizable with the mouse
|
+ resizable: if set to false it wont be resizable with the mouse
|
||||||
|
+ horizontal: slots are distributed horizontally
|
||||||
|
+ widgets_up: widgets start from the top of the node
|
||||||
|
|
||||||
|
flags object:
|
||||||
|
+ collapsed: if it is collapsed
|
||||||
|
|
||||||
supported callbacks:
|
supported callbacks:
|
||||||
+ onAdded: when added to graph
|
+ onAdded: when added to graph
|
||||||
@@ -2168,13 +2173,16 @@ LGraphNode.prototype.getInputOrProperty = function( name )
|
|||||||
return this.properties ? this.properties[name] : null;
|
return this.properties ? this.properties[name] : null;
|
||||||
|
|
||||||
for(var i = 0, l = this.inputs.length; i < l; ++i)
|
for(var i = 0, l = this.inputs.length; i < l; ++i)
|
||||||
if(name == this.inputs[i].name)
|
{
|
||||||
|
var input_info = this.inputs[i];
|
||||||
|
if(name == input_info.name && input_info.link != null)
|
||||||
{
|
{
|
||||||
var link_id = this.inputs[i].link;
|
var link = this.graph.links[ input_info.link ];
|
||||||
var link = this.graph.links[ link_id ];
|
if(link)
|
||||||
return link ? link.data : null;
|
return link.data;
|
||||||
}
|
}
|
||||||
return this.properties[name];
|
}
|
||||||
|
return this.properties[ name ];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -3985,7 +3993,7 @@ LGraphCanvas.prototype.processMouseDown = function(e)
|
|||||||
if(!this.connecting_node && !node.flags.collapsed && !this.live_mode)
|
if(!this.connecting_node && !node.flags.collapsed && !this.live_mode)
|
||||||
{
|
{
|
||||||
//Search for corner for resize
|
//Search for corner for resize
|
||||||
if( !skip_action && node.flags.resizable !== false && isInsideRectangle( e.canvasX, e.canvasY, node.pos[0] + node.size[0] - 5, node.pos[1] + node.size[1] - 5 ,10,10 ))
|
if( !skip_action && node.resizable !== false && isInsideRectangle( e.canvasX, e.canvasY, node.pos[0] + node.size[0] - 5, node.pos[1] + node.size[1] - 5 ,10,10 ))
|
||||||
{
|
{
|
||||||
this.resizing_node = node;
|
this.resizing_node = node;
|
||||||
this.canvas.style.cursor = "se-resize";
|
this.canvas.style.cursor = "se-resize";
|
||||||
@@ -5535,6 +5543,8 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
|
|||||||
var shape = node._shape || LiteGraph.BOX_SHAPE;
|
var shape = node._shape || LiteGraph.BOX_SHAPE;
|
||||||
var size = temp_vec2;
|
var size = temp_vec2;
|
||||||
temp_vec2.set( node.size );
|
temp_vec2.set( node.size );
|
||||||
|
var horizontal = node.horizontal || node.flags.horizontal;
|
||||||
|
|
||||||
if( node.flags.collapsed )
|
if( node.flags.collapsed )
|
||||||
{
|
{
|
||||||
ctx.font = this.inner_text_font;
|
ctx.font = this.inner_text_font;
|
||||||
@@ -5544,7 +5554,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
|
|||||||
size[1] = 0;
|
size[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( node.flags.clip_area ) //Start clipping
|
if( node.clip_area ) //Start clipping
|
||||||
{
|
{
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
@@ -5562,7 +5572,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
|
|||||||
ctx.shadowColor = "transparent";
|
ctx.shadowColor = "transparent";
|
||||||
|
|
||||||
//connection slots
|
//connection slots
|
||||||
ctx.textAlign = node.flags.horizontal ? "center" : "left";
|
ctx.textAlign = horizontal ? "center" : "left";
|
||||||
ctx.font = this.inner_text_font;
|
ctx.font = this.inner_text_font;
|
||||||
|
|
||||||
var render_text = this.scale > 0.6;
|
var render_text = this.scale > 0.6;
|
||||||
@@ -5597,8 +5607,12 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
|
|||||||
|
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
|
|
||||||
if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE) {
|
if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE)
|
||||||
ctx.rect((pos[0] - 6) + 0.5, (pos[1] - 5) + 0.5, 14, 10);
|
{
|
||||||
|
if (horizontal)
|
||||||
|
ctx.rect((pos[0] - 5) + 0.5, (pos[1] - 8) + 0.5, 10, 14);
|
||||||
|
else
|
||||||
|
ctx.rect((pos[0] - 6) + 0.5, (pos[1] - 5) + 0.5, 14, 10);
|
||||||
} else if (slot.shape === LiteGraph.ARROW_SHAPE) {
|
} else if (slot.shape === LiteGraph.ARROW_SHAPE) {
|
||||||
ctx.moveTo(pos[0] + 8, pos[1] + 0.5);
|
ctx.moveTo(pos[0] + 8, pos[1] + 0.5);
|
||||||
ctx.lineTo(pos[0] - 4, (pos[1] + 6) + 0.5);
|
ctx.lineTo(pos[0] - 4, (pos[1] + 6) + 0.5);
|
||||||
@@ -5617,7 +5631,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
|
|||||||
if(text)
|
if(text)
|
||||||
{
|
{
|
||||||
ctx.fillStyle = LiteGraph.NODE_TEXT_COLOR;
|
ctx.fillStyle = LiteGraph.NODE_TEXT_COLOR;
|
||||||
if( node.flags.horizontal || slot.dir == LiteGraph.UP )
|
if( horizontal || slot.dir == LiteGraph.UP )
|
||||||
ctx.fillText(text,pos[0],pos[1] - 10);
|
ctx.fillText(text,pos[0],pos[1] - 10);
|
||||||
else
|
else
|
||||||
ctx.fillText(text,pos[0] + 10,pos[1] + 5);
|
ctx.fillText(text,pos[0] + 10,pos[1] + 5);
|
||||||
@@ -5629,7 +5643,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
|
|||||||
if(this.connecting_node)
|
if(this.connecting_node)
|
||||||
ctx.globalAlpha = 0.4 * editor_alpha;
|
ctx.globalAlpha = 0.4 * editor_alpha;
|
||||||
|
|
||||||
ctx.textAlign = node.flags.horizontal ? "center" : "right";
|
ctx.textAlign = horizontal ? "center" : "right";
|
||||||
ctx.strokeStyle = "black";
|
ctx.strokeStyle = "black";
|
||||||
if(node.outputs)
|
if(node.outputs)
|
||||||
for(var i = 0; i < node.outputs.length; i++)
|
for(var i = 0; i < node.outputs.length; i++)
|
||||||
@@ -5646,8 +5660,12 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
|
|||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
//ctx.rect( node.size[0] - 14,i*14,10,10);
|
//ctx.rect( node.size[0] - 14,i*14,10,10);
|
||||||
|
|
||||||
if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE) {
|
if (slot.type === LiteGraph.EVENT || slot.shape === LiteGraph.BOX_SHAPE)
|
||||||
ctx.rect((pos[0] - 6) + 0.5,(pos[1] - 5) + 0.5,14,10);
|
{
|
||||||
|
if( horizontal )
|
||||||
|
ctx.rect((pos[0] - 5) + 0.5,(pos[1] - 8) + 0.5,10,14);
|
||||||
|
else
|
||||||
|
ctx.rect((pos[0] - 6) + 0.5,(pos[1] - 5) + 0.5,14,10);
|
||||||
} else if (slot.shape === LiteGraph.ARROW_SHAPE) {
|
} else if (slot.shape === LiteGraph.ARROW_SHAPE) {
|
||||||
ctx.moveTo(pos[0] + 8, pos[1] + 0.5);
|
ctx.moveTo(pos[0] + 8, pos[1] + 0.5);
|
||||||
ctx.lineTo(pos[0] - 4, (pos[1] + 6) + 0.5);
|
ctx.lineTo(pos[0] - 4, (pos[1] + 6) + 0.5);
|
||||||
@@ -5672,7 +5690,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
|
|||||||
if(text)
|
if(text)
|
||||||
{
|
{
|
||||||
ctx.fillStyle = LiteGraph.NODE_TEXT_COLOR;
|
ctx.fillStyle = LiteGraph.NODE_TEXT_COLOR;
|
||||||
if( node.flags.horizontal || slot.dir == LiteGraph.DOWN )
|
if( horizontal || slot.dir == LiteGraph.DOWN )
|
||||||
ctx.fillText(text,pos[0],pos[1] - 8);
|
ctx.fillText(text,pos[0],pos[1] - 8);
|
||||||
else
|
else
|
||||||
ctx.fillText(text, pos[0] - 10,pos[1] + 5);
|
ctx.fillText(text, pos[0] - 10,pos[1] + 5);
|
||||||
@@ -5685,7 +5703,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
|
|||||||
|
|
||||||
if(node.widgets)
|
if(node.widgets)
|
||||||
{
|
{
|
||||||
if( node.flags.horizontal || node.flags.widgets_up )
|
if( horizontal || node.widgets_up )
|
||||||
max_y = 2;
|
max_y = 2;
|
||||||
this.drawNodeWidgets( node, max_y, ctx, (this.node_widget && this.node_widget[0] == node) ? this.node_widget[1] : null );
|
this.drawNodeWidgets( node, max_y, ctx, (this.node_widget && this.node_widget[0] == node) ? this.node_widget[1] : null );
|
||||||
}
|
}
|
||||||
@@ -5726,7 +5744,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
|
|||||||
{
|
{
|
||||||
var x = 0;
|
var x = 0;
|
||||||
var y = LiteGraph.NODE_TITLE_HEIGHT * -0.5; //center
|
var y = LiteGraph.NODE_TITLE_HEIGHT * -0.5; //center
|
||||||
if( node.flags.horizontal )
|
if( horizontal )
|
||||||
{
|
{
|
||||||
x = node._collapsed_width * 0.5;
|
x = node._collapsed_width * 0.5;
|
||||||
y = -LiteGraph.NODE_TITLE_HEIGHT;
|
y = -LiteGraph.NODE_TITLE_HEIGHT;
|
||||||
@@ -5750,7 +5768,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
|
|||||||
{
|
{
|
||||||
var x = node._collapsed_width;
|
var x = node._collapsed_width;
|
||||||
var y = LiteGraph.NODE_TITLE_HEIGHT * -0.5; //center
|
var y = LiteGraph.NODE_TITLE_HEIGHT * -0.5; //center
|
||||||
if( node.flags.horizontal )
|
if( horizontal )
|
||||||
{
|
{
|
||||||
x = node._collapsed_width * 0.5;
|
x = node._collapsed_width * 0.5;
|
||||||
y = 0;
|
y = 0;
|
||||||
@@ -5773,7 +5791,7 @@ LGraphCanvas.prototype.drawNode = function(node, ctx )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node.flags.clip_area)
|
if(node.clip_area)
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
|
|
||||||
ctx.globalAlpha = 1.0;
|
ctx.globalAlpha = 1.0;
|
||||||
@@ -5869,30 +5887,33 @@ LGraphCanvas.prototype.drawNodeShape = function( node, ctx, size, fgcolor, bgcol
|
|||||||
}
|
}
|
||||||
|
|
||||||
//title box
|
//title box
|
||||||
if (shape == LiteGraph.ROUND_SHAPE || shape == LiteGraph.CIRCLE_SHAPE || shape == LiteGraph.CARD_SHAPE)
|
if(node.flags.render_box !== false)
|
||||||
{
|
{
|
||||||
if( this.scale > 0.5 )
|
if (shape == LiteGraph.ROUND_SHAPE || shape == LiteGraph.CIRCLE_SHAPE || shape == LiteGraph.CARD_SHAPE)
|
||||||
{
|
{
|
||||||
ctx.fillStyle = "black";
|
if( this.scale > 0.5 )
|
||||||
|
{
|
||||||
|
ctx.fillStyle = "black";
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(title_height *0.5, title_height * -0.5, (title_height - 8) *0.5,0,Math.PI*2);
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR;
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(title_height *0.5, title_height * -0.5, (title_height - 8) *0.5,0,Math.PI*2);
|
ctx.arc(title_height *0.5, title_height * -0.5, (title_height - 8) *0.4,0,Math.PI*2);
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR;
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.arc(title_height *0.5, title_height * -0.5, (title_height - 8) *0.4,0,Math.PI*2);
|
|
||||||
ctx.fill();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( this.scale > 0.5 )
|
|
||||||
{
|
{
|
||||||
ctx.fillStyle = "black";
|
if( this.scale > 0.5 )
|
||||||
ctx.fillRect(4,-title_height + 4,title_height - 8,title_height - 8);
|
{
|
||||||
|
ctx.fillStyle = "black";
|
||||||
|
ctx.fillRect(4,-title_height + 4,title_height - 8,title_height - 8);
|
||||||
|
}
|
||||||
|
ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR;
|
||||||
|
ctx.fillRect(5,-title_height + 5,title_height - 10,title_height - 10);
|
||||||
}
|
}
|
||||||
ctx.fillStyle = node.boxcolor || LiteGraph.NODE_DEFAULT_BOXCOLOR;
|
|
||||||
ctx.fillRect(5,-title_height + 5,title_height - 10,title_height - 10);
|
|
||||||
}
|
}
|
||||||
ctx.globalAlpha = old_alpha;
|
ctx.globalAlpha = old_alpha;
|
||||||
|
|
||||||
@@ -6341,6 +6362,7 @@ LGraphCanvas.prototype.drawNodeWidgets = function( node, posY, ctx, active_widge
|
|||||||
ctx.fillText( w.value, width - 40, y + H*0.7 );
|
ctx.fillText( w.value, width - 40, y + H*0.7 );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "string":
|
||||||
case "text":
|
case "text":
|
||||||
ctx.textAlign = "left";
|
ctx.textAlign = "left";
|
||||||
ctx.strokeStyle = "#AAA";
|
ctx.strokeStyle = "#AAA";
|
||||||
@@ -6463,6 +6485,7 @@ LGraphCanvas.prototype.processNodeWidgets = function( node, pos, event, active_w
|
|||||||
setTimeout( function(){ w.callback( w.value, that, node, pos ); }, 20 );
|
setTimeout( function(){ w.callback( w.value, that, node, pos ); }, 20 );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "string":
|
||||||
case "text":
|
case "text":
|
||||||
if( event.type == "mousedown" )
|
if( event.type == "mousedown" )
|
||||||
this.prompt( "Value", w.value, (function(v){ this.value = v; if(w.callback) w.callback(v, that, node ); }).bind(w), event );
|
this.prompt( "Value", w.value, (function(v){ this.value = v; if(w.callback) w.callback(v, that, node ); }).bind(w), event );
|
||||||
|
|||||||
@@ -334,36 +334,55 @@ LiteGraph.registerNodeType("graph/output", GlobalOutput);
|
|||||||
|
|
||||||
|
|
||||||
//Constant
|
//Constant
|
||||||
function Constant()
|
function ConstantNumber()
|
||||||
{
|
{
|
||||||
this.addOutput("value","number");
|
this.addOutput("value","number");
|
||||||
this.addProperty( "value", 1.0 );
|
this.addProperty( "value", 1.0 );
|
||||||
this.editable = { property:"value", type:"number" };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant.title = "Const";
|
ConstantNumber.title = "Const Number";
|
||||||
Constant.desc = "Constant value";
|
ConstantNumber.desc = "Constant number";
|
||||||
|
|
||||||
|
ConstantNumber.prototype.onExecute = function()
|
||||||
Constant.prototype.setValue = function(v)
|
|
||||||
{
|
|
||||||
if( typeof(v) == "string") v = parseFloat(v);
|
|
||||||
this.properties["value"] = v;
|
|
||||||
this.setDirtyCanvas(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
Constant.prototype.onExecute = function()
|
|
||||||
{
|
{
|
||||||
this.setOutputData(0, parseFloat( this.properties["value"] ) );
|
this.setOutputData(0, parseFloat( this.properties["value"] ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant.prototype.onDrawBackground = function(ctx)
|
ConstantNumber.prototype.onDrawBackground = function(ctx)
|
||||||
{
|
{
|
||||||
//show the current value
|
//show the current value
|
||||||
this.outputs[0].label = this.properties["value"].toFixed(3);
|
this.outputs[0].label = this.properties["value"].toFixed(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
LiteGraph.registerNodeType("basic/const", Constant);
|
LiteGraph.registerNodeType("basic/const", ConstantNumber);
|
||||||
|
|
||||||
|
function ConstantString()
|
||||||
|
{
|
||||||
|
this.addOutput("","string");
|
||||||
|
this.addProperty( "value", "" );
|
||||||
|
this.widget = this.addWidget("text","value","", this.setValue.bind(this) );
|
||||||
|
this.widgets_up = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantString.title = "Const String";
|
||||||
|
ConstantString.desc = "Constant string";
|
||||||
|
|
||||||
|
ConstantString.prototype.setValue = function(v)
|
||||||
|
{
|
||||||
|
this.properties.value = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantString.prototype.onPropertyChanged = function(name,value)
|
||||||
|
{
|
||||||
|
this.widget.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantString.prototype.onExecute = function()
|
||||||
|
{
|
||||||
|
this.setOutputData(0, this.properties["value"] );
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType("basic/string", ConstantString );
|
||||||
|
|
||||||
|
|
||||||
//Watch a value in the editor
|
//Watch a value in the editor
|
||||||
|
|||||||
@@ -20,6 +20,39 @@ LogEvent.prototype.onAction = function( action, param )
|
|||||||
LiteGraph.registerNodeType("events/log", LogEvent );
|
LiteGraph.registerNodeType("events/log", LogEvent );
|
||||||
|
|
||||||
|
|
||||||
|
//Sequencer for events
|
||||||
|
function Sequencer()
|
||||||
|
{
|
||||||
|
this.addInput("", LiteGraph.ACTION);
|
||||||
|
this.addInput("", LiteGraph.ACTION);
|
||||||
|
this.addInput("", LiteGraph.ACTION);
|
||||||
|
this.addInput("", LiteGraph.ACTION);
|
||||||
|
this.addInput("", LiteGraph.ACTION);
|
||||||
|
this.addInput("", LiteGraph.ACTION);
|
||||||
|
this.addOutput("", LiteGraph.EVENT);
|
||||||
|
this.addOutput("", LiteGraph.EVENT);
|
||||||
|
this.addOutput("", LiteGraph.EVENT);
|
||||||
|
this.addOutput("", LiteGraph.EVENT);
|
||||||
|
this.addOutput("", LiteGraph.EVENT);
|
||||||
|
this.addOutput("", LiteGraph.EVENT);
|
||||||
|
this.size = [120,30];
|
||||||
|
this.flags = { horizontal: true, render_box: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
Sequencer.title = "Sequencer";
|
||||||
|
Sequencer.desc = "Trigger events when an event arrives";
|
||||||
|
|
||||||
|
Sequencer.prototype.getTitle = function() { return ""; }
|
||||||
|
|
||||||
|
Sequencer.prototype.onAction = function( action, param )
|
||||||
|
{
|
||||||
|
if(this.outputs)
|
||||||
|
for(var i = 0; i < this.outputs.length; ++i)
|
||||||
|
this.triggerSlot( i, param );
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType("events/sequencer", Sequencer );
|
||||||
|
|
||||||
//Filter events
|
//Filter events
|
||||||
function FilterEvent()
|
function FilterEvent()
|
||||||
{
|
{
|
||||||
@@ -59,6 +92,52 @@ FilterEvent.prototype.onAction = function( action, param )
|
|||||||
|
|
||||||
LiteGraph.registerNodeType("events/filter", FilterEvent );
|
LiteGraph.registerNodeType("events/filter", FilterEvent );
|
||||||
|
|
||||||
|
|
||||||
|
//Show value inside the debug console
|
||||||
|
function EventCounter()
|
||||||
|
{
|
||||||
|
this.addInput("inc", LiteGraph.ACTION);
|
||||||
|
this.addInput("dec", LiteGraph.ACTION);
|
||||||
|
this.addInput("reset", LiteGraph.ACTION);
|
||||||
|
this.addOutput("change", LiteGraph.EVENT);
|
||||||
|
this.addOutput("num", "number");
|
||||||
|
this.num = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EventCounter.title = "Counter";
|
||||||
|
EventCounter.desc = "Counts events";
|
||||||
|
|
||||||
|
EventCounter.prototype.onAction = function(action, param)
|
||||||
|
{
|
||||||
|
var v = this.num;
|
||||||
|
if(action == "inc")
|
||||||
|
this.num += 1;
|
||||||
|
else if(action == "dec")
|
||||||
|
this.num -= 1;
|
||||||
|
else if(action == "reset")
|
||||||
|
this.num = 0;
|
||||||
|
if(this.num != v)
|
||||||
|
this.trigger("change",this.num);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventCounter.prototype.onDrawBackground = function(ctx)
|
||||||
|
{
|
||||||
|
if(this.flags.collapsed)
|
||||||
|
return;
|
||||||
|
ctx.fillStyle = "#AAA";
|
||||||
|
ctx.font = "20px Arial";
|
||||||
|
ctx.textAlign = "center";
|
||||||
|
ctx.fillText( this.num, this.size[0] * 0.5, this.size[1] * 0.5 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EventCounter.prototype.onExecute = function()
|
||||||
|
{
|
||||||
|
this.setOutputData(1,this.num);
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType("events/counter", EventCounter );
|
||||||
|
|
||||||
//Show value inside the debug console
|
//Show value inside the debug console
|
||||||
function DelayEvent()
|
function DelayEvent()
|
||||||
{
|
{
|
||||||
@@ -142,15 +221,19 @@ TimerEvent.prototype.onDrawBackground = function()
|
|||||||
TimerEvent.prototype.onExecute = function()
|
TimerEvent.prototype.onExecute = function()
|
||||||
{
|
{
|
||||||
var dt = this.graph.elapsed_time * 1000; //in ms
|
var dt = this.graph.elapsed_time * 1000; //in ms
|
||||||
|
|
||||||
|
var trigger = this.time == 0;
|
||||||
|
|
||||||
this.time += dt;
|
this.time += dt;
|
||||||
this.last_interval = Math.max(1, this.getInputOrProperty("interval") | 0);
|
this.last_interval = Math.max(1, this.getInputOrProperty("interval") | 0);
|
||||||
|
|
||||||
if( this.time < this.last_interval || isNaN(this.last_interval) )
|
if( !trigger && ( this.time < this.last_interval || isNaN(this.last_interval)) )
|
||||||
{
|
{
|
||||||
if( this.inputs && this.inputs.length > 1 && this.inputs[1] )
|
if( this.inputs && this.inputs.length > 1 && this.inputs[1] )
|
||||||
this.setOutputData(1,false);
|
this.setOutputData(1,false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.triggered = true;
|
this.triggered = true;
|
||||||
this.time = this.time % this.last_interval;
|
this.time = this.time % this.last_interval;
|
||||||
this.trigger( "on_tick", this.properties.event );
|
this.trigger( "on_tick", this.properties.event );
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ GraphicsImage.prototype.onAdded = function()
|
|||||||
|
|
||||||
GraphicsImage.prototype.onDrawBackground = function(ctx)
|
GraphicsImage.prototype.onDrawBackground = function(ctx)
|
||||||
{
|
{
|
||||||
|
if(this.flags.collapsed)
|
||||||
|
return;
|
||||||
if(this.img && this.size[0] > 5 && this.size[1] > 5)
|
if(this.img && this.size[0] > 5 && this.size[1] > 5)
|
||||||
ctx.drawImage(this.img, 0,0,this.size[0],this.size[1]);
|
ctx.drawImage(this.img, 0,0,this.size[0],this.size[1]);
|
||||||
}
|
}
|
||||||
@@ -244,7 +246,7 @@ LiteGraph.registerNodeType("color/palette", ColorPalette );
|
|||||||
|
|
||||||
function ImageFrame()
|
function ImageFrame()
|
||||||
{
|
{
|
||||||
this.addInput("","image");
|
this.addInput("","image,canvas");
|
||||||
this.size = [200,200];
|
this.size = [200,200];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +257,7 @@ ImageFrame.widgets = [{name:"resize",text:"Resize box",type:"button"},{name:"vie
|
|||||||
|
|
||||||
ImageFrame.prototype.onDrawBackground = function(ctx)
|
ImageFrame.prototype.onDrawBackground = function(ctx)
|
||||||
{
|
{
|
||||||
if(this.frame)
|
if(this.frame && !this.flags.collapsed)
|
||||||
ctx.drawImage(this.frame, 0,0,this.size[0],this.size[1]);
|
ctx.drawImage(this.frame, 0,0,this.size[0],this.size[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,86 +300,6 @@ LiteGraph.registerNodeType("graphics/frame", ImageFrame );
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
LiteGraph.registerNodeType("visualization/graph", {
|
|
||||||
desc: "Shows a graph of the inputs",
|
|
||||||
|
|
||||||
inputs: [["",0],["",0],["",0],["",0]],
|
|
||||||
size: [200,200],
|
|
||||||
properties: {min:-1,max:1,bgColor:"#000"},
|
|
||||||
onDrawBackground: function(ctx)
|
|
||||||
{
|
|
||||||
var colors = ["#FFF","#FAA","#AFA","#AAF"];
|
|
||||||
|
|
||||||
if(this.properties.bgColor != null && this.properties.bgColor != "")
|
|
||||||
{
|
|
||||||
ctx.fillStyle="#000";
|
|
||||||
ctx.fillRect(2,2,this.size[0] - 4, this.size[1]-4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.data)
|
|
||||||
{
|
|
||||||
var min = this.properties["min"];
|
|
||||||
var max = this.properties["max"];
|
|
||||||
|
|
||||||
for(var i in this.data)
|
|
||||||
{
|
|
||||||
var data = this.data[i];
|
|
||||||
if(!data) continue;
|
|
||||||
|
|
||||||
if(this.getInputInfo(i) == null) continue;
|
|
||||||
|
|
||||||
ctx.strokeStyle = colors[i];
|
|
||||||
ctx.beginPath();
|
|
||||||
|
|
||||||
var d = data.length / this.size[0];
|
|
||||||
for(var j = 0; j < data.length; j += d)
|
|
||||||
{
|
|
||||||
var value = data[ Math.floor(j) ];
|
|
||||||
value = (value - min) / (max - min);
|
|
||||||
if (value > 1.0) value = 1.0;
|
|
||||||
else if(value < 0) value = 0;
|
|
||||||
|
|
||||||
if(j == 0)
|
|
||||||
ctx.moveTo( j / d, (this.size[1] - 5) - (this.size[1] - 10) * value);
|
|
||||||
else
|
|
||||||
ctx.lineTo( j / d, (this.size[1] - 5) - (this.size[1] - 10) * value);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//ctx.restore();
|
|
||||||
},
|
|
||||||
|
|
||||||
onExecute: function()
|
|
||||||
{
|
|
||||||
if(!this.data) this.data = [];
|
|
||||||
|
|
||||||
for(var i in this.inputs)
|
|
||||||
{
|
|
||||||
var value = this.getInputData(i);
|
|
||||||
|
|
||||||
if(typeof(value) == "number")
|
|
||||||
{
|
|
||||||
value = value ? value : 0;
|
|
||||||
if(!this.data[i])
|
|
||||||
this.data[i] = [];
|
|
||||||
this.data[i].push(value);
|
|
||||||
|
|
||||||
if(this.data[i].length > (this.size[1] - 4))
|
|
||||||
this.data[i] = this.data[i].slice(1,this.data[i].length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
this.data[i] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.data.length)
|
|
||||||
this.setDirtyCanvas(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
function ImageFade()
|
function ImageFade()
|
||||||
{
|
{
|
||||||
@@ -509,6 +431,105 @@ ImageCrop.prototype.onPropertyChanged = function(name,value)
|
|||||||
|
|
||||||
LiteGraph.registerNodeType("graphics/cropImage", ImageCrop );
|
LiteGraph.registerNodeType("graphics/cropImage", ImageCrop );
|
||||||
|
|
||||||
|
//CANVAS stuff
|
||||||
|
|
||||||
|
function CanvasNode()
|
||||||
|
{
|
||||||
|
this.addInput("clear", LiteGraph.ACTION );
|
||||||
|
this.addOutput("","canvas");
|
||||||
|
this.properties = {width:512,height:512,autoclear:true};
|
||||||
|
|
||||||
|
this.canvas = document.createElement("canvas");
|
||||||
|
this.ctx = this.canvas.getContext("2d");
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasNode.title = "Canvas";
|
||||||
|
CanvasNode.desc = "Canvas to render stuff";
|
||||||
|
|
||||||
|
CanvasNode.prototype.onExecute = function()
|
||||||
|
{
|
||||||
|
var canvas = this.canvas;
|
||||||
|
var w = (this.properties.width)|0;
|
||||||
|
var h = (this.properties.height)|0;
|
||||||
|
if( canvas.width != w )
|
||||||
|
canvas.width = w;
|
||||||
|
if( canvas.height != h )
|
||||||
|
canvas.height = h;
|
||||||
|
|
||||||
|
if(this.properties.autoclear)
|
||||||
|
this.ctx.clearRect(0,0,canvas.width,canvas.height);
|
||||||
|
this.setOutputData(0,canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasNode.prototype.onAction = function( action, param )
|
||||||
|
{
|
||||||
|
if(action == "clear")
|
||||||
|
this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType("graphics/canvas", CanvasNode );
|
||||||
|
|
||||||
|
function DrawImageNode()
|
||||||
|
{
|
||||||
|
this.addInput("canvas", "canvas" );
|
||||||
|
this.addInput("img", "image,canvas" );
|
||||||
|
this.addInput("x", "number" );
|
||||||
|
this.addInput("y", "number" );
|
||||||
|
this.properties = {x:0,y:0,opacity:1};
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawImageNode.title = "DrawImage";
|
||||||
|
DrawImageNode.desc = "Draws image into a canvas";
|
||||||
|
|
||||||
|
DrawImageNode.prototype.onExecute = function()
|
||||||
|
{
|
||||||
|
var canvas = this.getInputData(0);
|
||||||
|
if(!canvas)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var img = this.getInputOrProperty("img");
|
||||||
|
if(!img)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var x = this.getInputOrProperty("x");
|
||||||
|
var y = this.getInputOrProperty("y");
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
ctx.drawImage( img, x, y );
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType("graphics/drawImage", DrawImageNode );
|
||||||
|
|
||||||
|
|
||||||
|
function DrawRectangleNode()
|
||||||
|
{
|
||||||
|
this.addInput("canvas", "canvas" );
|
||||||
|
this.addInput("x", "number" );
|
||||||
|
this.addInput("y", "number" );
|
||||||
|
this.addInput("w", "number" );
|
||||||
|
this.addInput("h", "number" );
|
||||||
|
this.properties = { x:0,y:0,w:10,h:10,color:"white",opacity:1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawRectangleNode.title = "DrawRectangle";
|
||||||
|
DrawRectangleNode.desc = "Draws rectangle in canvas";
|
||||||
|
|
||||||
|
DrawRectangleNode.prototype.onExecute = function()
|
||||||
|
{
|
||||||
|
var canvas = this.getInputData(0);
|
||||||
|
if(!canvas)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var x = this.getInputOrProperty("x");
|
||||||
|
var y = this.getInputOrProperty("y");
|
||||||
|
var w = this.getInputOrProperty("w");
|
||||||
|
var h = this.getInputOrProperty("h");
|
||||||
|
var ctx = canvas.getContext("2d");
|
||||||
|
ctx.fillRect( x, y, w, h );
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType("graphics/drawRectangle", DrawRectangleNode );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function ImageVideo()
|
function ImageVideo()
|
||||||
{
|
{
|
||||||
@@ -3,39 +3,92 @@ var LiteGraph = global.LiteGraph;
|
|||||||
|
|
||||||
function Selector()
|
function Selector()
|
||||||
{
|
{
|
||||||
this.addInput("sel","boolean");
|
this.addInput("sel","number");
|
||||||
this.addOutput("value","number");
|
this.addInput("A");
|
||||||
this.properties = { A:0, B:1 };
|
this.addInput("B");
|
||||||
this.size = [60,20];
|
this.addInput("C");
|
||||||
|
this.addInput("D");
|
||||||
|
this.addOutput("out");
|
||||||
|
|
||||||
|
this.selected = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Selector.title = "Selector";
|
Selector.title = "Selector";
|
||||||
Selector.desc = "outputs A if selector is true, B if selector is false";
|
Selector.desc = "selects an output";
|
||||||
|
|
||||||
|
Selector.prototype.onDrawBackground = function(ctx)
|
||||||
|
{
|
||||||
|
if(this.flags.collapsed)
|
||||||
|
return;
|
||||||
|
ctx.fillStyle = "#AFB";
|
||||||
|
var y = (this.selected + 1) * LiteGraph.NODE_SLOT_HEIGHT + 2;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(30, y);
|
||||||
|
ctx.lineTo(30, y+LiteGraph.NODE_SLOT_HEIGHT);
|
||||||
|
ctx.lineTo(24, y+LiteGraph.NODE_SLOT_HEIGHT*0.5);
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
|
||||||
Selector.prototype.onExecute = function()
|
Selector.prototype.onExecute = function()
|
||||||
{
|
{
|
||||||
var cond = this.getInputData(0);
|
var sel = this.getInputData(0);
|
||||||
if(cond === undefined)
|
if(sel == null)
|
||||||
return;
|
sel = 0;
|
||||||
|
this.selected = sel = Math.round(sel) % (this.inputs.length - 1);
|
||||||
for(var i = 1; i < this.inputs.length; i++)
|
var v = this.getInputData(sel + 1);
|
||||||
{
|
if(v !== undefined)
|
||||||
var input = this.inputs[i];
|
this.setOutputData( 0, v );
|
||||||
var v = this.getInputData(i);
|
|
||||||
if(v === undefined)
|
|
||||||
continue;
|
|
||||||
this.properties[input.name] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
var A = this.properties.A;
|
|
||||||
var B = this.properties.B;
|
|
||||||
this.setOutputData(0, cond ? A : B );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Selector.prototype.onGetInputs = function() {
|
Selector.prototype.onGetInputs = function() {
|
||||||
return [["A",0],["B",0]];
|
return [["E",0],["F",0],["G",0],["H",0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
LiteGraph.registerNodeType("logic/selector", Selector);
|
LiteGraph.registerNodeType("logic/selector", Selector);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function Sequence()
|
||||||
|
{
|
||||||
|
this.properties = {
|
||||||
|
sequence: "A,B,C"
|
||||||
|
};
|
||||||
|
this.addInput("index","number");
|
||||||
|
this.addInput("seq");
|
||||||
|
this.addOutput("out");
|
||||||
|
|
||||||
|
this.index = 0;
|
||||||
|
this.values = this.properties.sequence.split(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
Sequence.title = "Sequence";
|
||||||
|
Sequence.desc = "select one element from a sequence from a string";
|
||||||
|
|
||||||
|
Sequence.prototype.onPropertyChanged = function(name,value)
|
||||||
|
{
|
||||||
|
if(name == "sequence")
|
||||||
|
{
|
||||||
|
this.values = value.split(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sequence.prototype.onExecute = function()
|
||||||
|
{
|
||||||
|
var seq = this.getInputData(1);
|
||||||
|
if(seq && seq != this.current_sequence)
|
||||||
|
{
|
||||||
|
this.values = seq.split(",");
|
||||||
|
this.current_sequence = seq;
|
||||||
|
}
|
||||||
|
var index = this.getInputData(0);
|
||||||
|
if(index == null)
|
||||||
|
index = 0;
|
||||||
|
this.index = index = Math.round(index) % this.values.length;
|
||||||
|
|
||||||
|
this.setOutputData( 0, this.values[ index ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType("logic/sequence", Sequence );
|
||||||
|
|
||||||
})(this);
|
})(this);
|
||||||
@@ -81,6 +81,23 @@ Bypass.prototype.onExecute = function()
|
|||||||
LiteGraph.registerNodeType("math/bypass", Bypass );
|
LiteGraph.registerNodeType("math/bypass", Bypass );
|
||||||
|
|
||||||
|
|
||||||
|
function ToNumber()
|
||||||
|
{
|
||||||
|
this.addInput("in");
|
||||||
|
this.addOutput("out");
|
||||||
|
}
|
||||||
|
|
||||||
|
ToNumber.title = "to Number";
|
||||||
|
ToNumber.desc = "Cast to number";
|
||||||
|
|
||||||
|
ToNumber.prototype.onExecute = function()
|
||||||
|
{
|
||||||
|
var v = this.getInputData(0);
|
||||||
|
this.setOutputData(0, Number(v) );
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType("math/to_number", ToNumber );
|
||||||
|
|
||||||
|
|
||||||
function MathRange()
|
function MathRange()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,16 +6,17 @@ function MIDIEvent( data )
|
|||||||
{
|
{
|
||||||
this.channel = 0;
|
this.channel = 0;
|
||||||
this.cmd = 0;
|
this.cmd = 0;
|
||||||
|
this.data = new Uint32Array(3);
|
||||||
|
|
||||||
if(data)
|
if(data)
|
||||||
this.setup(data)
|
this.setup(data)
|
||||||
else
|
|
||||||
this.data = [0,0,0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LiteGraph.MIDIEvent = MIDIEvent;
|
||||||
|
|
||||||
MIDIEvent.prototype.setup = function( raw_data )
|
MIDIEvent.prototype.setup = function( raw_data )
|
||||||
{
|
{
|
||||||
this.data = raw_data;
|
this.data.set(raw_data);
|
||||||
|
|
||||||
var midiStatus = raw_data[0];
|
var midiStatus = raw_data[0];
|
||||||
this.status = midiStatus;
|
this.status = midiStatus;
|
||||||
@@ -50,6 +51,32 @@ Object.defineProperty( MIDIEvent.prototype, "velocity", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
MIDIEvent.notes = ["A","A#","B","C","C#","D","D#","E","F","F#","G","G#"];
|
MIDIEvent.notes = ["A","A#","B","C","C#","D","D#","E","F","F#","G","G#"];
|
||||||
|
MIDIEvent.note_to_index = {"A":0,"A#":1,"B":2,"C":3,"C#":4,"D":5,"D#":6,"E":7,"F":8,"F#":9,"G":10,"G#":11};
|
||||||
|
|
||||||
|
Object.defineProperty( MIDIEvent.prototype, "note", {
|
||||||
|
get: function() {
|
||||||
|
if(this.cmd != MIDIEvent.NOTEON)
|
||||||
|
return -1;
|
||||||
|
return MIDIEvent.toNoteString( this.data[1], true );
|
||||||
|
},
|
||||||
|
set: function(v) {
|
||||||
|
throw("notes cannot be assigned this way, must modify the data[1]");
|
||||||
|
},
|
||||||
|
enumerable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
Object.defineProperty( MIDIEvent.prototype, "octave", {
|
||||||
|
get: function() {
|
||||||
|
if(this.cmd != MIDIEvent.NOTEON)
|
||||||
|
return -1;
|
||||||
|
var octave = this.data[1] - 24;
|
||||||
|
return Math.floor(octave / 12 + 1);
|
||||||
|
},
|
||||||
|
set: function(v) {
|
||||||
|
throw("octave cannot be assigned this way, must modify the data[1]");
|
||||||
|
},
|
||||||
|
enumerable: true
|
||||||
|
});
|
||||||
|
|
||||||
//returns HZs
|
//returns HZs
|
||||||
MIDIEvent.prototype.getPitch = function()
|
MIDIEvent.prototype.getPitch = function()
|
||||||
@@ -121,14 +148,39 @@ MIDIEvent.computeCommandFromString = function( str )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDIEvent.toNoteString = function(d)
|
//transform from a pitch number to string like "C4"
|
||||||
|
MIDIEvent.toNoteString = function( d, skip_octave )
|
||||||
{
|
{
|
||||||
|
d = Math.round(d); //in case it has decimals
|
||||||
var note = d - 21;
|
var note = d - 21;
|
||||||
var octave = d - 24;
|
var octave = Math.floor((d - 24) / 12 + 1);
|
||||||
note = note % 12;
|
note = note % 12;
|
||||||
if(note < 0)
|
if(note < 0)
|
||||||
note = 12 + note;
|
note = 12 + note;
|
||||||
return MIDIEvent.notes[ note ] + Math.floor(octave / 12 + 1);
|
return MIDIEvent.notes[ note ] + (skip_octave ? "" : octave);
|
||||||
|
}
|
||||||
|
|
||||||
|
MIDIEvent.NoteStringToPitch = function(str)
|
||||||
|
{
|
||||||
|
str = str.toUpperCase();
|
||||||
|
var note = str[0];
|
||||||
|
var octave = 4;
|
||||||
|
|
||||||
|
if(str[1] == "#")
|
||||||
|
{
|
||||||
|
note += "#";
|
||||||
|
if( str.length > 2 )
|
||||||
|
octave = Number( str[2] );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( str.length > 1 )
|
||||||
|
octave = Number( str[1] );
|
||||||
|
}
|
||||||
|
var pitch = MIDIEvent.note_to_index[note];
|
||||||
|
if(pitch == null)
|
||||||
|
return null;
|
||||||
|
return ((octave - 1) * 12) + pitch + 21;
|
||||||
}
|
}
|
||||||
|
|
||||||
MIDIEvent.prototype.toString = function()
|
MIDIEvent.prototype.toString = function()
|
||||||
@@ -482,7 +534,7 @@ LGMIDIOut.prototype.getPropertyInfo = function(name)
|
|||||||
|
|
||||||
LGMIDIOut.prototype.onAction = function(event, midi_event )
|
LGMIDIOut.prototype.onAction = function(event, midi_event )
|
||||||
{
|
{
|
||||||
console.log(midi_event);
|
//console.log(midi_event);
|
||||||
if(!this._midi)
|
if(!this._midi)
|
||||||
return;
|
return;
|
||||||
if(event == "send")
|
if(event == "send")
|
||||||
@@ -581,7 +633,7 @@ function LGMIDIEvent()
|
|||||||
{
|
{
|
||||||
this.properties = {
|
this.properties = {
|
||||||
channel: 0,
|
channel: 0,
|
||||||
cmd: "CC",
|
cmd: 144, //0x90
|
||||||
value1: 1,
|
value1: 1,
|
||||||
value2: 1
|
value2: 1
|
||||||
};
|
};
|
||||||
@@ -589,6 +641,8 @@ function LGMIDIEvent()
|
|||||||
this.addInput( "send", LiteGraph.EVENT );
|
this.addInput( "send", LiteGraph.EVENT );
|
||||||
this.addInput( "assign", LiteGraph.EVENT );
|
this.addInput( "assign", LiteGraph.EVENT );
|
||||||
this.addOutput( "on_midi", LiteGraph.EVENT );
|
this.addOutput( "on_midi", LiteGraph.EVENT );
|
||||||
|
|
||||||
|
this.midi_event = new MIDIEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
LGMIDIEvent.title = "MIDIEvent";
|
LGMIDIEvent.title = "MIDIEvent";
|
||||||
@@ -606,7 +660,7 @@ LGMIDIEvent.prototype.onAction = function( event, midi_event )
|
|||||||
}
|
}
|
||||||
|
|
||||||
//send
|
//send
|
||||||
var midi_event = new MIDIEvent();
|
var midi_event = this.midi_event;
|
||||||
midi_event.channel = this.properties.channel;
|
midi_event.channel = this.properties.channel;
|
||||||
if(this.properties.cmd && this.properties.cmd.constructor === String)
|
if(this.properties.cmd && this.properties.cmd.constructor === String)
|
||||||
midi_event.setCommandFromString( this.properties.cmd );
|
midi_event.setCommandFromString( this.properties.cmd );
|
||||||
@@ -615,6 +669,7 @@ LGMIDIEvent.prototype.onAction = function( event, midi_event )
|
|||||||
midi_event.data[0] = midi_event.cmd | midi_event.channel;
|
midi_event.data[0] = midi_event.cmd | midi_event.channel;
|
||||||
midi_event.data[1] = Number(this.properties.value1);
|
midi_event.data[1] = Number(this.properties.value1);
|
||||||
midi_event.data[2] = Number(this.properties.value2);
|
midi_event.data[2] = Number(this.properties.value2);
|
||||||
|
|
||||||
this.trigger("on_midi",midi_event);
|
this.trigger("on_midi",midi_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,6 +677,28 @@ LGMIDIEvent.prototype.onExecute = function()
|
|||||||
{
|
{
|
||||||
var props = this.properties;
|
var props = this.properties;
|
||||||
|
|
||||||
|
if(this.inputs)
|
||||||
|
{
|
||||||
|
for(var i = 0; i < this.inputs.length; ++i)
|
||||||
|
{
|
||||||
|
var input = this.inputs[i];
|
||||||
|
if(input.link == -1)
|
||||||
|
continue;
|
||||||
|
switch (input.name)
|
||||||
|
{
|
||||||
|
case "note":
|
||||||
|
var v = this.getInputData(i);
|
||||||
|
if(v != null)
|
||||||
|
{
|
||||||
|
if(v.constructor === String)
|
||||||
|
v = MIDIEvent.NoteStringToPitch(v);
|
||||||
|
this.properties.value1 = (v|0)%255;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(this.outputs)
|
if(this.outputs)
|
||||||
{
|
{
|
||||||
for(var i = 0; i < this.outputs.length; ++i)
|
for(var i = 0; i < this.outputs.length; ++i)
|
||||||
@@ -657,6 +734,9 @@ LGMIDIEvent.prototype.onPropertyChanged = function(name,value)
|
|||||||
this.properties.cmd = MIDIEvent.computeCommandFromString( value );
|
this.properties.cmd = MIDIEvent.computeCommandFromString( value );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LGMIDIEvent.prototype.onGetInputs = function() {
|
||||||
|
return [ ["note","number"] ];
|
||||||
|
}
|
||||||
|
|
||||||
LGMIDIEvent.prototype.onGetOutputs = function() {
|
LGMIDIEvent.prototype.onGetOutputs = function() {
|
||||||
return [
|
return [
|
||||||
@@ -701,6 +781,232 @@ LGMIDICC.prototype.onExecute = function()
|
|||||||
LiteGraph.registerNodeType("midi/cc", LGMIDICC);
|
LiteGraph.registerNodeType("midi/cc", LGMIDICC);
|
||||||
|
|
||||||
|
|
||||||
|
function LGMIDIGenerator()
|
||||||
|
{
|
||||||
|
this.addInput( "generate", LiteGraph.ACTION );
|
||||||
|
this.addInput( "scale", "string" );
|
||||||
|
this.addInput( "octave", "number" );
|
||||||
|
this.addOutput( "note", LiteGraph.EVENT );
|
||||||
|
this.properties = {
|
||||||
|
notes: "A,A#,B,C,C#,D,D#,E,F,F#,G,G#",
|
||||||
|
octave: 2,
|
||||||
|
mode: "sequence"
|
||||||
|
};
|
||||||
|
|
||||||
|
this.notes_pitches = LGMIDIGenerator.processScale( this.properties.notes );
|
||||||
|
this.sequence_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LGMIDIGenerator.title = "MIDI Generator";
|
||||||
|
LGMIDIGenerator.desc = "Generates a random MIDI note";
|
||||||
|
|
||||||
|
LGMIDIGenerator.processScale = function(scale)
|
||||||
|
{
|
||||||
|
var notes = scale.split(",");
|
||||||
|
for(var i = 0; i < notes.length; ++i)
|
||||||
|
notes[i] = MIDIEvent.note_to_index[ notes[i] ] || 0;
|
||||||
|
return notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
LGMIDIGenerator.prototype.onPropertyChanged = function(name,value)
|
||||||
|
{
|
||||||
|
if(name == "notes")
|
||||||
|
this.notes_pitches = LGMIDIGenerator.processScale( value );
|
||||||
|
}
|
||||||
|
|
||||||
|
LGMIDIGenerator.prototype.onExecute = function()
|
||||||
|
{
|
||||||
|
var octave = this.getInputData(2);
|
||||||
|
if(octave != null)
|
||||||
|
this.properties.octave = octave;
|
||||||
|
|
||||||
|
var scale = this.getInputData(1);
|
||||||
|
if(scale)
|
||||||
|
this.notes_pitches = LGMIDIGenerator.processScale( scale );
|
||||||
|
}
|
||||||
|
|
||||||
|
LGMIDIGenerator.prototype.onAction = function( event, midi_event )
|
||||||
|
{
|
||||||
|
//var range = this.properties.max - this.properties.min;
|
||||||
|
//var pitch = this.properties.min + ((Math.random() * range)|0);
|
||||||
|
var pitch = 0;
|
||||||
|
var range = this.notes_pitches.length;
|
||||||
|
|
||||||
|
if( this.properties.mode == "sequence" )
|
||||||
|
{
|
||||||
|
var index = this.sequence_index = (this.sequence_index + 1) % range;
|
||||||
|
pitch = this.notes_pitches[ index ] + ( (this.properties.octave-1) * 12) + 33;
|
||||||
|
}
|
||||||
|
else if( this.properties.mode == "random" )
|
||||||
|
{
|
||||||
|
var index = Math.floor(Math.random()*range);
|
||||||
|
pitch = this.notes_pitches[ index ] + ( (this.properties.octave-1) * 12) + 33;
|
||||||
|
}
|
||||||
|
var note = new MIDIEvent();
|
||||||
|
note.setup([ MIDIEvent.NOTEON, pitch, 10 ]);
|
||||||
|
this.trigger("note", note);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType("midi/generator", LGMIDIGenerator);
|
||||||
|
|
||||||
|
function LGMIDITranspose()
|
||||||
|
{
|
||||||
|
this.properties = {
|
||||||
|
amount: 0
|
||||||
|
};
|
||||||
|
this.addInput( "in", LiteGraph.ACTION );
|
||||||
|
this.addInput( "amount", "number" );
|
||||||
|
this.addOutput( "out", LiteGraph.EVENT );
|
||||||
|
|
||||||
|
this.midi_event = new MIDIEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
LGMIDITranspose.title = "MIDI Transpose";
|
||||||
|
LGMIDITranspose.desc = "Transpose a MIDI note";
|
||||||
|
|
||||||
|
LGMIDITranspose.prototype.onAction = function( event, midi_event )
|
||||||
|
{
|
||||||
|
this.midi_event.setup( midi_event.data );
|
||||||
|
this.midi_event.data[1] = Math.round( this.midi_event.data[1] + this.properties.amount );
|
||||||
|
this.trigger("out", this.midi_event );
|
||||||
|
}
|
||||||
|
|
||||||
|
LGMIDITranspose.prototype.onExecute = function()
|
||||||
|
{
|
||||||
|
var amount = this.getInputData(1);
|
||||||
|
if(amount!= null)
|
||||||
|
this.properties.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType("midi/transpose", LGMIDITranspose);
|
||||||
|
|
||||||
|
|
||||||
|
function LGMIDIQuantize()
|
||||||
|
{
|
||||||
|
this.properties = {
|
||||||
|
scale: "A,A#,B,C,C#,D,D#,E,F,F#,G,G#"
|
||||||
|
};
|
||||||
|
this.addInput( "note", LiteGraph.ACTION );
|
||||||
|
this.addInput( "scale", "string" );
|
||||||
|
this.addOutput( "out", LiteGraph.EVENT );
|
||||||
|
|
||||||
|
this.valid_notes = new Array(12);
|
||||||
|
this.offset_notes = new Array(12);
|
||||||
|
this.processScale( this.properties.scale );
|
||||||
|
this.midi_event = new MIDIEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
LGMIDIQuantize.title = "MIDI Quantize Pitch";
|
||||||
|
LGMIDIQuantize.desc = "Transpose a MIDI note tp fit an scale";
|
||||||
|
|
||||||
|
LGMIDIQuantize.prototype.onPropertyChanged = function(name,value)
|
||||||
|
{
|
||||||
|
if(name == "scale")
|
||||||
|
this.processScale( value );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LGMIDIQuantize.prototype.processScale = function( scale )
|
||||||
|
{
|
||||||
|
this._current_scale = scale;
|
||||||
|
this.notes_pitches = LGMIDIGenerator.processScale( scale );
|
||||||
|
for(var i = 0; i < 12; ++i)
|
||||||
|
this.valid_notes[i] = this.notes_pitches.indexOf(i) != -1;
|
||||||
|
for(var i = 0; i < 12; ++i)
|
||||||
|
{
|
||||||
|
if (this.valid_notes[ i ])
|
||||||
|
{
|
||||||
|
this.offset_notes[i] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for(var j = 1; j < 12; ++j)
|
||||||
|
{
|
||||||
|
if( this.valid_notes[ (i - j)%12 ] )
|
||||||
|
{
|
||||||
|
this.offset_notes[i] = -j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( this.valid_notes[ (i + j)%12 ] )
|
||||||
|
{
|
||||||
|
this.offset_notes[i] = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LGMIDIQuantize.prototype.onAction = function( event, midi_event )
|
||||||
|
{
|
||||||
|
this.midi_event.setup( midi_event.data );
|
||||||
|
var note = midi_event.note;
|
||||||
|
var index = MIDIEvent.note_to_index[ note ];
|
||||||
|
var offset = this.offset_notes[index];
|
||||||
|
this.midi_event.data[1] += offset;
|
||||||
|
this.trigger("out", this.midi_event );
|
||||||
|
}
|
||||||
|
|
||||||
|
LGMIDIQuantize.prototype.onExecute = function()
|
||||||
|
{
|
||||||
|
var scale = this.getInputData(1);
|
||||||
|
if(scale != null && scale != this._current_scale )
|
||||||
|
this.processScale( scale );
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType("midi/quantize", LGMIDIQuantize);
|
||||||
|
|
||||||
|
|
||||||
|
function LGMIDIPlay()
|
||||||
|
{
|
||||||
|
this.properties = {
|
||||||
|
volume: 0.5,
|
||||||
|
duration: 1
|
||||||
|
};
|
||||||
|
this.addInput( "note", LiteGraph.ACTION );
|
||||||
|
this.addInput( "volume", "number" );
|
||||||
|
this.addInput( "duration", "number" );
|
||||||
|
this.addOutput( "note", LiteGraph.EVENT );
|
||||||
|
|
||||||
|
if(typeof(AudioSynth) == "undefined")
|
||||||
|
{
|
||||||
|
console.error("Audiosynth.js not included, LGMidiPlay requires that library");
|
||||||
|
this.boxcolor = "red";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var Synth = this.synth = new AudioSynth();
|
||||||
|
this.instrument = Synth.createInstrument('piano');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LGMIDIPlay.title = "MIDI Play";
|
||||||
|
LGMIDIPlay.desc = "Plays a MIDI note";
|
||||||
|
|
||||||
|
LGMIDIPlay.prototype.onAction = function( event, midi_event )
|
||||||
|
{
|
||||||
|
if(!this.instrument)
|
||||||
|
return;
|
||||||
|
var note = midi_event.note; //C#
|
||||||
|
if( !note || note == "undefined" || note.constructor !== String )
|
||||||
|
return;
|
||||||
|
this.instrument.play( note, midi_event.octave, this.properties.duration, this.properties.volume );
|
||||||
|
this.trigger("note", midi_event );
|
||||||
|
}
|
||||||
|
|
||||||
|
LGMIDIPlay.prototype.onExecute = function()
|
||||||
|
{
|
||||||
|
var volume = this.getInputData(1);
|
||||||
|
if(volume != null)
|
||||||
|
this.properties.volume = volume;
|
||||||
|
|
||||||
|
var duration = this.getInputData(2);
|
||||||
|
if(duration != null)
|
||||||
|
this.properties.duration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteGraph.registerNodeType("midi/play", LGMIDIPlay);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function now() { return window.performance.now() }
|
function now() { return window.performance.now() }
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
../src/nodes/input.js
|
../src/nodes/input.js
|
||||||
../src/nodes/math.js
|
../src/nodes/math.js
|
||||||
../src/nodes/logic.js
|
../src/nodes/logic.js
|
||||||
../src/nodes/image.js
|
../src/nodes/graphics.js
|
||||||
../src/nodes/gltextures.js
|
../src/nodes/gltextures.js
|
||||||
../src/nodes/glfx.js
|
../src/nodes/glfx.js
|
||||||
../src/nodes/midi.js
|
../src/nodes/midi.js
|
||||||
|
|||||||
Reference in New Issue
Block a user