mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-07 16:40:05 +00:00
images
This commit is contained in:
@@ -2512,6 +2512,7 @@ function LGraphCanvas( canvas, graph, options )
|
||||
this.show_info = true;
|
||||
this.allow_dragcanvas = true;
|
||||
this.allow_dragnodes = true;
|
||||
this.allow_interaction = true; //allow to control widgets, buttons, collapse, etc
|
||||
|
||||
this.always_render_background = false;
|
||||
this.render_connections_shadows = false; //too much cpu
|
||||
@@ -2987,7 +2988,7 @@ LGraphCanvas.prototype.processMouseDown = function(e)
|
||||
|
||||
//when clicked on top of a node
|
||||
//and it is not interactive
|
||||
if(n)
|
||||
if(n && this.allow_interaction )
|
||||
{
|
||||
if(!this.live_mode && !n.flags.pinned)
|
||||
this.bringToFront(n); //if it wasnt selected?
|
||||
@@ -3150,7 +3151,7 @@ LGraphCanvas.prototype.processMouseMove = function(e)
|
||||
this.dirty_canvas = true;
|
||||
this.dirty_bgcanvas = true;
|
||||
}
|
||||
else
|
||||
else if(this.allow_interaction)
|
||||
{
|
||||
if(this.connecting_node)
|
||||
this.dirty_canvas = true;
|
||||
@@ -3514,7 +3515,7 @@ LGraphCanvas.prototype.processDrop = function(e)
|
||||
return;
|
||||
}
|
||||
|
||||
if(node.onDropFile)
|
||||
if( node.onDropFile || node.onDropData )
|
||||
{
|
||||
var files = e.dataTransfer.files;
|
||||
if(files && files.length)
|
||||
@@ -3526,22 +3527,28 @@ LGraphCanvas.prototype.processDrop = function(e)
|
||||
var ext = LGraphCanvas.getFileExtension( filename );
|
||||
//console.log(file);
|
||||
|
||||
//prepare reader
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
//console.log(event.target);
|
||||
var data = event.target.result;
|
||||
node.onDropFile( data, filename, file );
|
||||
};
|
||||
if(node.onDropFile)
|
||||
node.onDropFile(file);
|
||||
|
||||
//read data
|
||||
var type = file.type.split("/")[0];
|
||||
if(type == "text" || type == "")
|
||||
reader.readAsText(file);
|
||||
else if (type == "image")
|
||||
reader.readAsDataURL(file);
|
||||
else
|
||||
reader.readAsArrayBuffer(file);
|
||||
if(node.onDropData)
|
||||
{
|
||||
//prepare reader
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
//console.log(event.target);
|
||||
var data = event.target.result;
|
||||
node.onDropData( data, filename, file );
|
||||
};
|
||||
|
||||
//read data
|
||||
var type = file.type.split("/")[0];
|
||||
if(type == "text" || type == "")
|
||||
reader.readAsText(file);
|
||||
else if (type == "image")
|
||||
reader.readAsDataURL(file);
|
||||
else
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3992,7 +3999,7 @@ LGraphCanvas.prototype.drawBackCanvas = function()
|
||||
if(this.background_image && this.scale > 0.5)
|
||||
{
|
||||
ctx.globalAlpha = (1.0 - 0.5 / this.scale) * this.editor_alpha;
|
||||
ctx.webkitImageSmoothingEnabled = ctx.mozImageSmoothingEnabled = ctx.imageSmoothingEnabled = false;
|
||||
ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = ctx.imageSmoothingEnabled = false;
|
||||
if(!this._bg_img || this._bg_img.name != this.background_image)
|
||||
{
|
||||
this._bg_img = new Image();
|
||||
@@ -4021,7 +4028,7 @@ LGraphCanvas.prototype.drawBackCanvas = function()
|
||||
}
|
||||
|
||||
ctx.globalAlpha = 1.0;
|
||||
ctx.webkitImageSmoothingEnabled = ctx.mozImageSmoothingEnabled = ctx.imageSmoothingEnabled = true;
|
||||
ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = ctx.imageSmoothingEnabled = true;
|
||||
}
|
||||
|
||||
if(this.onBackgroundRender)
|
||||
@@ -4862,12 +4869,14 @@ LGraphCanvas.onShowMenuNodeProperties = function(node,e, prev_menu)
|
||||
for (var i in node.properties)
|
||||
{
|
||||
var value = node.properties[i] !== undefined ? node.properties[i] : " ";
|
||||
//value could contain invalid html characters, clean that
|
||||
value = LGraphCanvas.decodeHTML(value);
|
||||
entries.push({content: "<span class='property_name'>" + i + "</span>" + "<span class='property_value'>" + value + "</span>", value: i});
|
||||
}
|
||||
if(!entries.length)
|
||||
return;
|
||||
|
||||
var menu = LiteGraph.createContextMenu(entries, {event: e, callback: inner_clicked, from: prev_menu},ref_window);
|
||||
var menu = LiteGraph.createContextMenu(entries, {event: e, callback: inner_clicked, from: prev_menu, allow_html: true },ref_window);
|
||||
|
||||
function inner_clicked( v, e, prev )
|
||||
{
|
||||
@@ -4879,6 +4888,70 @@ LGraphCanvas.onShowMenuNodeProperties = function(node,e, prev_menu)
|
||||
return false;
|
||||
}
|
||||
|
||||
LGraphCanvas.decodeHTML = function( str )
|
||||
{
|
||||
var e = document.createElement("div");
|
||||
e.innerText = str;
|
||||
return e.innerHTML;
|
||||
}
|
||||
|
||||
LGraphCanvas.onShowTitleEditor = function( node, event )
|
||||
{
|
||||
var input_html = "";
|
||||
|
||||
var dialog = document.createElement("div");
|
||||
dialog.className = "graphdialog";
|
||||
dialog.innerHTML = "<span class='name'>Title</span><input autofocus type='text' class='value'/><button>OK</button>";
|
||||
var input = dialog.querySelector("input");
|
||||
if(input)
|
||||
{
|
||||
input.value = node.title;
|
||||
input.addEventListener("keydown", function(e){
|
||||
if(e.keyCode != 13)
|
||||
return;
|
||||
inner();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
var rect = this.canvas.getClientRects()[0];
|
||||
var offsetx = -20;
|
||||
var offsety = -20;
|
||||
if(rect)
|
||||
{
|
||||
offsetx -= rect.left;
|
||||
offsety -= rect.top;
|
||||
}
|
||||
|
||||
if( event )
|
||||
{
|
||||
dialog.style.left = (event.pageX + offsetx) + "px";
|
||||
dialog.style.top = (event.pageY + offsety)+ "px";
|
||||
}
|
||||
else
|
||||
{
|
||||
dialog.style.left = (this.canvas.width * 0.5 + offsetx) + "px";
|
||||
dialog.style.top = (this.canvas.height * 0.5 + offsety) + "px";
|
||||
}
|
||||
|
||||
var button = dialog.querySelector("button");
|
||||
button.addEventListener("click", inner );
|
||||
this.canvas.parentNode.appendChild( dialog );
|
||||
|
||||
function inner()
|
||||
{
|
||||
setValue( input.value );
|
||||
}
|
||||
|
||||
function setValue(value)
|
||||
{
|
||||
node.title = value;
|
||||
dialog.parentNode.removeChild( dialog );
|
||||
node.setDirtyCanvas(true,true);
|
||||
}
|
||||
}
|
||||
|
||||
LGraphCanvas.prototype.showEditPropertyValue = function( node, property, options )
|
||||
{
|
||||
if(!node || node.properties[ property ] === undefined )
|
||||
@@ -5148,6 +5221,7 @@ LGraphCanvas.prototype.getNodeMenuOptions = function(node)
|
||||
null,
|
||||
{content:"Properties", is_menu: true, callback: LGraphCanvas.onShowMenuNodeProperties },
|
||||
null,
|
||||
{content:"Title", callback: LGraphCanvas.onShowTitleEditor },
|
||||
{content:"Mode", is_menu: true, callback: LGraphCanvas.onMenuNodeMode },
|
||||
{content:"Collapse", callback: LGraphCanvas.onMenuNodeCollapse },
|
||||
{content:"Pin", callback: LGraphCanvas.onMenuNodePin },
|
||||
@@ -5362,7 +5436,7 @@ function num2hex(triplet) {
|
||||
|
||||
/* LiteGraph GUI elements *************************************/
|
||||
|
||||
LiteGraph.createContextMenu = function(values,options, ref_window)
|
||||
LiteGraph.createContextMenu = function(values, options, ref_window)
|
||||
{
|
||||
options = options || {};
|
||||
this.options = options;
|
||||
@@ -5435,10 +5509,16 @@ LiteGraph.createContextMenu = function(values,options, ref_window)
|
||||
element.style.cursor = "pointer";
|
||||
element.dataset["value"] = typeof(item) == "string" ? item : item.value;
|
||||
element.data = item;
|
||||
|
||||
var content = "";
|
||||
if(typeof(item) == "string")
|
||||
element.innerHTML = values.constructor == Array ? values[i] : i;
|
||||
content = values.constructor == Array ? values[i] : i;
|
||||
else
|
||||
element.innerHTML = item.content ? item.content : i;
|
||||
content = item.content ? item.content : i;
|
||||
if(options.allow_html)
|
||||
element.innerHTML = content;
|
||||
else
|
||||
element.innerText = content;
|
||||
|
||||
element.addEventListener("click", on_click );
|
||||
root.appendChild(element);
|
||||
@@ -7205,6 +7285,47 @@ MathClamp.prototype.getCode = function(lang)
|
||||
LiteGraph.registerNodeType("math/clamp", MathClamp );
|
||||
|
||||
|
||||
|
||||
//Math ABS
|
||||
function MathLerp()
|
||||
{
|
||||
this.properties = { f: 0.5 };
|
||||
this.addInput("A","number");
|
||||
this.addInput("B","number");
|
||||
|
||||
this.addOutput("out","number");
|
||||
}
|
||||
|
||||
MathLerp.title = "Lerp";
|
||||
MathLerp.desc = "Linear Interpolation";
|
||||
|
||||
MathLerp.prototype.onExecute = function()
|
||||
{
|
||||
var v1 = this.getInputData(0);
|
||||
if(v1 == null)
|
||||
v1 = 0;
|
||||
var v2 = this.getInputData(1);
|
||||
if(v2 == null)
|
||||
v2 = 0;
|
||||
|
||||
var f = this.properties.f;
|
||||
|
||||
var _f = this.getInputData(2);
|
||||
if(_f !== undefined)
|
||||
f = _f;
|
||||
|
||||
this.setOutputData(0, v1 * (1-f) + v2 * f );
|
||||
}
|
||||
|
||||
MathLerp.prototype.onGetInputs = function()
|
||||
{
|
||||
return [["f","number"]];
|
||||
}
|
||||
|
||||
LiteGraph.registerNodeType("math/lerp", MathLerp);
|
||||
|
||||
|
||||
|
||||
//Math ABS
|
||||
function MathAbs()
|
||||
{
|
||||
@@ -12153,13 +12274,74 @@ LGAudio.onConnectionsChange = function( connection, slot, connected, link_info )
|
||||
LGAudio.disconnect( local_audionode, target_audionode );
|
||||
}
|
||||
|
||||
//this function helps creating wrappers to existing classes
|
||||
LGAudio.createAudioNodeWrapper = function( class_object )
|
||||
{
|
||||
class_object.prototype.onPropertyChanged = function(name, value)
|
||||
{
|
||||
if(!this.audionode)
|
||||
return;
|
||||
|
||||
if( this.audionode[ name ] === undefined )
|
||||
return;
|
||||
|
||||
if( this.audionode[ name ].value !== undefined )
|
||||
this.audionode[ name ].value = value;
|
||||
else
|
||||
this.audionode[ name ] = value;
|
||||
}
|
||||
|
||||
class_object.prototype.onConnectionsChange = LGAudio.onConnectionsChange;
|
||||
}
|
||||
|
||||
|
||||
LGAudio.cached_audios = {};
|
||||
|
||||
LGAudio.loadSound = function( url, on_complete, on_error )
|
||||
{
|
||||
if( LGAudio.cached_audios[ url ] && url.indexOf("blob:") == -1 )
|
||||
{
|
||||
if(on_complete)
|
||||
on_complete( LGAudio.cached_audios[ url ] );
|
||||
return;
|
||||
}
|
||||
|
||||
//load new sample
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', url, true);
|
||||
request.responseType = 'arraybuffer';
|
||||
|
||||
var context = LGAudio.getAudioContext();
|
||||
|
||||
// Decode asynchronously
|
||||
request.onload = function() {
|
||||
console.log("AudioSource loaded");
|
||||
context.decodeAudioData( request.response, function( buffer ) {
|
||||
console.log("AudioSource decoded");
|
||||
LGAudio.cached_audios[ url ] = buffer;
|
||||
if(on_complete)
|
||||
on_complete( buffer );
|
||||
}, onError);
|
||||
}
|
||||
request.send();
|
||||
|
||||
function onError(err)
|
||||
{
|
||||
console.log("Audio loading sample error:",err);
|
||||
if(on_error)
|
||||
on_error(err);
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************
|
||||
|
||||
function LGAudioSource()
|
||||
{
|
||||
this.properties = {
|
||||
src: "demodata/audio.wav",
|
||||
src: "",
|
||||
gain: 0.5,
|
||||
loop: true,
|
||||
autoplay: true,
|
||||
@@ -12212,6 +12394,8 @@ LGAudioSource.prototype.onStop = function()
|
||||
LGAudioSource.prototype.onRemoved = function()
|
||||
{
|
||||
this.stopAllSounds();
|
||||
if(this._dropped_url)
|
||||
URL.revokeObjectURL( this._url );
|
||||
}
|
||||
|
||||
LGAudioSource.prototype.stopAllSounds = function()
|
||||
@@ -12235,7 +12419,6 @@ LGAudioSource.prototype.onExecute = function()
|
||||
var input = this.inputs[i];
|
||||
if(!input.link)
|
||||
continue;
|
||||
|
||||
var v = this.getInputData(i);
|
||||
if( v === undefined )
|
||||
continue;
|
||||
@@ -12311,36 +12494,19 @@ LGAudioSource.prototype.loadSound = function( url )
|
||||
if(!url)
|
||||
return;
|
||||
|
||||
//load new sample
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', url, true);
|
||||
request.responseType = 'arraybuffer';
|
||||
this._request = LGAudio.loadSound( url, inner );
|
||||
|
||||
this._loading_audio = true;
|
||||
this._request = request;
|
||||
this.boxcolor = "#AA4";
|
||||
|
||||
var context = LGAudio.getAudioContext();
|
||||
|
||||
// Decode asynchronously
|
||||
request.onload = function() {
|
||||
context.decodeAudioData( request.response, function(buffer) {
|
||||
that._audio_buffer = buffer;
|
||||
if(that._url)
|
||||
{
|
||||
URL.revokeObjectURL( that._url );
|
||||
that._url = null;
|
||||
}
|
||||
|
||||
that._loading_audio = false;
|
||||
//if is playing, then play it
|
||||
if(that.graph && that.graph.status === LGraph.STATUS_RUNNING)
|
||||
that.onStart();
|
||||
}, onError);
|
||||
}
|
||||
request.send();
|
||||
|
||||
function onError(err)
|
||||
function inner( buffer )
|
||||
{
|
||||
console.log("Audio loading sample error:",err);
|
||||
this.boxcolor = LiteGraph.NODE_DEFAULT_BOXCOLOR;
|
||||
that._audio_buffer = buffer;
|
||||
that._loading_audio = false;
|
||||
//if is playing, then play it
|
||||
if(that.graph && that.graph.status === LGraph.STATUS_RUNNING)
|
||||
that.onStart(); //this controls the autoplay already
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12359,11 +12525,12 @@ LGAudioSource.prototype.onGetOutputs = function()
|
||||
|
||||
LGAudioSource.prototype.onDropFile = function(file)
|
||||
{
|
||||
if(this._url)
|
||||
URL.revokeObjectURL( this._url );
|
||||
this._url = URL.createObjectURL( file );
|
||||
this.properties.src = this._url;
|
||||
this.loadSound( this._url );
|
||||
if(this._dropped_url)
|
||||
URL.revokeObjectURL( this._dropped_url );
|
||||
var url = URL.createObjectURL( file );
|
||||
this.properties.src = url;
|
||||
this.loadSound( url );
|
||||
this._dropped_url = url;
|
||||
}
|
||||
|
||||
|
||||
@@ -12417,15 +12584,24 @@ LGAudioAnalyser.prototype.onExecute = function()
|
||||
this.setOutputData(0,this._freq_bin);
|
||||
}
|
||||
|
||||
//send analyzer
|
||||
if(this.isOutputConnected(1))
|
||||
this.setOutputData(1,this.audionode);
|
||||
|
||||
|
||||
//properties
|
||||
for(var i = 1; i < this.inputs.length; ++i)
|
||||
{
|
||||
var input = this.inputs[i];
|
||||
if(!input.link)
|
||||
continue;
|
||||
var v = this.getInputData(i);
|
||||
if (v !== undefined)
|
||||
this.audionode[ input.name ].value = v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//time domain
|
||||
//this.audionode.getFloatTimeDomainData( dataArray );
|
||||
}
|
||||
@@ -12435,33 +12611,17 @@ LGAudioAnalyser.prototype.onGetInputs = function()
|
||||
return [["minDecibels","number"],["maxDecibels","number"],["smoothingTimeConstant","number"]];
|
||||
}
|
||||
|
||||
/*
|
||||
LGAudioAnalyser.prototype.onGetOutputs = function()
|
||||
{
|
||||
return [["Analyzer","analyzer"]];
|
||||
}
|
||||
*/
|
||||
|
||||
LGAudioAnalyser.title = "Analyser";
|
||||
LGAudioAnalyser.desc = "Audio Analyser";
|
||||
LiteGraph.registerNodeType( "audio/analyser", LGAudioAnalyser );
|
||||
|
||||
|
||||
|
||||
//*****************************************************
|
||||
|
||||
//this function helps creating wrappers to existing classes
|
||||
function createAudioNodeWrapper( class_object )
|
||||
{
|
||||
class_object.prototype.onPropertyChanged = function(name, value)
|
||||
{
|
||||
if( this.audionode[ name ] === undefined )
|
||||
return;
|
||||
|
||||
if( this.audionode[ name ].value !== undefined )
|
||||
this.audionode[ name ].value = value;
|
||||
else
|
||||
this.audionode[ name ] = value;
|
||||
}
|
||||
|
||||
class_object.prototype.onConnectionsChange = LGAudio.onConnectionsChange;
|
||||
}
|
||||
|
||||
|
||||
//*****************************************************
|
||||
|
||||
function LGAudioGain()
|
||||
@@ -12491,14 +12651,128 @@ LGAudioGain.prototype.onExecute = function()
|
||||
}
|
||||
}
|
||||
|
||||
createAudioNodeWrapper( LGAudioGain );
|
||||
LGAudio.createAudioNodeWrapper( LGAudioGain );
|
||||
|
||||
LGAudioGain.title = "Gain";
|
||||
LGAudioGain.desc = "Audio gain";
|
||||
LiteGraph.registerNodeType("audio/gain", LGAudioGain);
|
||||
|
||||
|
||||
function LGAudioConvolver()
|
||||
{
|
||||
//default
|
||||
this.properties = {
|
||||
impulse_src:"",
|
||||
normalize: true
|
||||
};
|
||||
|
||||
this.audionode = LGAudio.getAudioContext().createConvolver();
|
||||
this.addInput("in","audio");
|
||||
this.addOutput("out","audio");
|
||||
}
|
||||
|
||||
LGAudio.createAudioNodeWrapper( LGAudioConvolver );
|
||||
|
||||
LGAudioConvolver.prototype.onRemove = function()
|
||||
{
|
||||
if(this._dropped_url)
|
||||
URL.revokeObjectURL( this._dropped_url );
|
||||
}
|
||||
|
||||
LGAudioConvolver.prototype.onPropertyChanged = function( name, value )
|
||||
{
|
||||
if( name == "impulse_src" )
|
||||
this.loadImpulse( value );
|
||||
else if( name == "normalize" )
|
||||
this.audionode.normalize = value;
|
||||
}
|
||||
|
||||
LGAudioConvolver.prototype.onDropFile = function(file)
|
||||
{
|
||||
if(this._dropped_url)
|
||||
URL.revokeObjectURL( this._dropped_url );
|
||||
this._dropped_url = URL.createObjectURL( file );
|
||||
this.properties.impulse_src = this._dropped_url;
|
||||
this.loadImpulse( this._dropped_url );
|
||||
}
|
||||
|
||||
LGAudioConvolver.prototype.loadImpulse = function( url )
|
||||
{
|
||||
var that = this;
|
||||
|
||||
//kill previous load
|
||||
if(this._request)
|
||||
{
|
||||
this._request.abort();
|
||||
this._request = null;
|
||||
}
|
||||
|
||||
this._impulse_buffer = null;
|
||||
this._loading_impulse = false;
|
||||
|
||||
if(!url)
|
||||
return;
|
||||
|
||||
//load new sample
|
||||
this._request = LGAudio.loadSound( url, inner );
|
||||
this._loading_impulse = true;
|
||||
|
||||
// Decode asynchronously
|
||||
function inner( buffer ) {
|
||||
that._impulse_buffer = buffer;
|
||||
that.audionode.buffer = buffer;
|
||||
console.log("Impulse signal set");
|
||||
that._loading_impulse = false;
|
||||
}
|
||||
}
|
||||
|
||||
LGAudioConvolver.title = "Convolver";
|
||||
LGAudioConvolver.desc = "Convolves the signal (used for reverb)";
|
||||
LiteGraph.registerNodeType("audio/convolver", LGAudioConvolver);
|
||||
|
||||
|
||||
function LGAudioDynamicsCompressor()
|
||||
{
|
||||
//default
|
||||
this.properties = {
|
||||
threshold: -50,
|
||||
knee: 40,
|
||||
ratio: 12,
|
||||
reduction: -20,
|
||||
attack: 0,
|
||||
release: 0.25
|
||||
};
|
||||
|
||||
this.audionode = LGAudio.getAudioContext().createDynamicsCompressor();
|
||||
this.addInput("in","audio");
|
||||
this.addOutput("out","audio");
|
||||
}
|
||||
|
||||
LGAudio.createAudioNodeWrapper( LGAudioDynamicsCompressor );
|
||||
|
||||
LGAudioDynamicsCompressor.prototype.onExecute = function()
|
||||
{
|
||||
if(!this.inputs || !this.inputs.length)
|
||||
return;
|
||||
for(var i = 1; i < this.inputs.length; ++i)
|
||||
{
|
||||
var input = this.inputs[i];
|
||||
if(!input.link)
|
||||
continue;
|
||||
var v = this.getInputData(i);
|
||||
if(v !== undefined)
|
||||
this.audionode[ input.name ].value = v;
|
||||
}
|
||||
}
|
||||
|
||||
LGAudioDynamicsCompressor.prototype.onGetInputs = function()
|
||||
{
|
||||
return [["threshold","number"],["knee","number"],["ratio","number"],["reduction","number"],["attack","number"],["release","number"]];
|
||||
}
|
||||
|
||||
LGAudioDynamicsCompressor.title = "DynamicsCompressor";
|
||||
LGAudioDynamicsCompressor.desc = "Dynamics Compressor";
|
||||
LiteGraph.registerNodeType("audio/dynamicsCompressor", LGAudioDynamicsCompressor);
|
||||
|
||||
|
||||
function LGAudioWaveShaper()
|
||||
@@ -12528,7 +12802,7 @@ LGAudioWaveShaper.prototype.setWaveShape = function(shape)
|
||||
this.audionode.curve = shape;
|
||||
}
|
||||
|
||||
createAudioNodeWrapper( LGAudioWaveShaper );
|
||||
LGAudio.createAudioNodeWrapper( LGAudioWaveShaper );
|
||||
|
||||
/* disabled till I dont find a way to do a wave shape
|
||||
LGAudioWaveShaper.title = "WaveShaper";
|
||||
@@ -12578,7 +12852,8 @@ LGAudioMixer.prototype.onExecute = function()
|
||||
for(var i = 1; i < this.inputs.length; ++i)
|
||||
{
|
||||
var input = this.inputs[i];
|
||||
if(input.type == "audio")
|
||||
|
||||
if(!input.link || input.type == "audio")
|
||||
continue;
|
||||
|
||||
var v = this.getInputData(i);
|
||||
@@ -12592,7 +12867,7 @@ LGAudioMixer.prototype.onExecute = function()
|
||||
}
|
||||
}
|
||||
|
||||
createAudioNodeWrapper( LGAudioMixer );
|
||||
LGAudio.createAudioNodeWrapper( LGAudioMixer );
|
||||
|
||||
LGAudioMixer.title = "Mixer";
|
||||
LGAudioMixer.desc = "Audio mixer";
|
||||
@@ -12613,7 +12888,7 @@ function LGAudioDelay()
|
||||
this.addOutput("out","audio");
|
||||
}
|
||||
|
||||
createAudioNodeWrapper( LGAudioDelay );
|
||||
LGAudio.createAudioNodeWrapper( LGAudioDelay );
|
||||
|
||||
LGAudioDelay.prototype.onExecute = function()
|
||||
{
|
||||
@@ -12653,6 +12928,8 @@ LGAudioBiquadFilter.prototype.onExecute = function()
|
||||
for(var i = 1; i < this.inputs.length; ++i)
|
||||
{
|
||||
var input = this.inputs[i];
|
||||
if(!input.link)
|
||||
continue;
|
||||
var v = this.getInputData(i);
|
||||
if(v !== undefined)
|
||||
this.audionode[ input.name ].value = v;
|
||||
@@ -12664,7 +12941,7 @@ LGAudioBiquadFilter.prototype.onGetInputs = function()
|
||||
return [["frequency","number"],["detune","number"],["Q","number"]];
|
||||
}
|
||||
|
||||
createAudioNodeWrapper( LGAudioBiquadFilter );
|
||||
LGAudio.createAudioNodeWrapper( LGAudioBiquadFilter );
|
||||
|
||||
LGAudioBiquadFilter.title = "BiquadFilter";
|
||||
LGAudioBiquadFilter.desc = "Audio filter";
|
||||
@@ -12679,10 +12956,12 @@ LiteGraph.registerNodeType("audio/biquadfilter", LGAudioBiquadFilter);
|
||||
function LGAudioVisualization()
|
||||
{
|
||||
this.properties = {
|
||||
continuous: true
|
||||
continuous: true,
|
||||
mark: -1
|
||||
};
|
||||
|
||||
this.addInput("freqs","array");
|
||||
this.addInput("mark","number");
|
||||
this.size = [300,200];
|
||||
this._last_buffer = null;
|
||||
}
|
||||
@@ -12690,6 +12969,10 @@ function LGAudioVisualization()
|
||||
LGAudioVisualization.prototype.onExecute = function()
|
||||
{
|
||||
this._last_buffer = this.getInputData(0);
|
||||
var v = this.getInputData(1);
|
||||
if(v !== undefined)
|
||||
this.properties.mark = v;
|
||||
this.setDirtyCanvas(true,false);
|
||||
}
|
||||
|
||||
LGAudioVisualization.prototype.onDrawForeground = function(ctx)
|
||||
@@ -12699,6 +12982,7 @@ LGAudioVisualization.prototype.onDrawForeground = function(ctx)
|
||||
|
||||
var buffer = this._last_buffer;
|
||||
|
||||
//delta represents how many samples we advance per pixel
|
||||
var delta = buffer.length / this.size[0];
|
||||
var h = this.size[1];
|
||||
|
||||
@@ -12721,12 +13005,26 @@ LGAudioVisualization.prototype.onDrawForeground = function(ctx)
|
||||
{
|
||||
for(var i = 0; i < buffer.length; i+= delta)
|
||||
{
|
||||
ctx.moveTo(x,h);
|
||||
ctx.lineTo(x,h - (buffer[i|0]/255) * h);
|
||||
ctx.moveTo(x+0.5,h);
|
||||
ctx.lineTo(x+0.5,h - (buffer[i|0]/255) * h);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
ctx.stroke();
|
||||
|
||||
if(this.properties.mark >= 0)
|
||||
{
|
||||
var samplerate = LGAudio.getAudioContext().sampleRate;
|
||||
var binfreq = samplerate / buffer.length;
|
||||
var x = 2 * (this.properties.mark / binfreq) / delta;
|
||||
if(x >= this.size[0])
|
||||
x = this.size[0]-1;
|
||||
ctx.strokeStyle = "red";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x,h);
|
||||
ctx.lineTo(x,0);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
LGAudioVisualization.title = "Visualization";
|
||||
@@ -12734,6 +13032,59 @@ LGAudioVisualization.desc = "Audio Visualization";
|
||||
LiteGraph.registerNodeType("audio/visualization", LGAudioVisualization);
|
||||
|
||||
|
||||
function LGAudioBandSignal()
|
||||
{
|
||||
//default
|
||||
this.properties = {
|
||||
band: 440,
|
||||
amplitude: 1
|
||||
};
|
||||
|
||||
this.addInput("freqs","array");
|
||||
this.addOutput("signal","number");
|
||||
}
|
||||
|
||||
LGAudioBandSignal.prototype.onExecute = function()
|
||||
{
|
||||
this._freqs = this.getInputData(0);
|
||||
if( !this._freqs )
|
||||
return;
|
||||
|
||||
var band = this.properties.band;
|
||||
var v = this.getInputData(1);
|
||||
if(v !== undefined)
|
||||
band = v;
|
||||
|
||||
var samplerate = LGAudio.getAudioContext().sampleRate;
|
||||
var binfreq = samplerate / this._freqs.length;
|
||||
var index = 2 * (band / binfreq);
|
||||
var v = 0;
|
||||
if( index < 0 )
|
||||
v = this._freqs[ 0 ];
|
||||
if( index >= this._freqs.length )
|
||||
v = this._freqs[ this._freqs.length - 1];
|
||||
else
|
||||
{
|
||||
var pos = index|0;
|
||||
var v0 = this._freqs[ pos ];
|
||||
var v1 = this._freqs[ pos+1 ];
|
||||
var f = index - pos;
|
||||
v = v0 * (1-f) + v1 * f;
|
||||
}
|
||||
|
||||
this.setOutputData( 0, (v/255) * this.properties.amplitude );
|
||||
}
|
||||
|
||||
LGAudioBandSignal.prototype.onGetInputs = function()
|
||||
{
|
||||
return [["band","number"]];
|
||||
}
|
||||
|
||||
LGAudioBandSignal.title = "Signal";
|
||||
LGAudioBandSignal.desc = "extract the signal of some frequency";
|
||||
LiteGraph.registerNodeType("audio/signal", LGAudioBandSignal);
|
||||
|
||||
|
||||
|
||||
function LGAudioDestination()
|
||||
{
|
||||
|
||||
@@ -33,5 +33,6 @@ function addDemo( name, url )
|
||||
//some examples
|
||||
addDemo("Audio", "examples/audio.json");
|
||||
addDemo("Audio Delay", "examples/audio_delay.json");
|
||||
addDemo("Audio Reverb", "examples/audio_reverb.json");
|
||||
|
||||
|
||||
|
||||
BIN
demo/demodata/impulse.wav
Normal file
BIN
demo/demodata/impulse.wav
Normal file
Binary file not shown.
@@ -1 +1,689 @@
|
||||
{"iteration":55277,"last_node_id":11,"last_link_id":10,"links":{"0":{"id":0,"origin_id":0,"origin_slot":0,"target_id":2,"target_slot":0,"data":null},"1":{"id":1,"origin_id":2,"origin_slot":0,"target_id":1,"target_slot":0,"data":null},"2":{"id":2,"origin_id":2,"origin_slot":0,"target_id":3,"target_slot":0,"data":null},"3":{"id":3,"origin_id":3,"origin_slot":0,"target_id":4,"target_slot":0,"data":null},"4":{"id":4,"origin_id":5,"origin_slot":0,"target_id":2,"target_slot":1,"data":null},"5":{"id":5,"origin_id":6,"origin_slot":0,"target_id":0,"target_slot":0,"data":null},"6":{"id":6,"origin_id":7,"origin_slot":0,"target_id":0,"target_slot":1,"data":null},"7":{"id":7,"origin_id":8,"origin_slot":0,"target_id":0,"target_slot":2,"data":null},"8":{"id":8,"origin_id":9,"origin_slot":0,"target_id":0,"target_slot":3,"data":null},"9":{"id":9,"origin_id":9,"origin_slot":0,"target_id":10,"target_slot":0,"data":null}},"config":{},"nodes":[{"id":1,"title":"Destination","type":"audio/destination","pos":[673,171],"size":{"0":140,"1":20},"flags":{},"inputs":[{"name":"in","type":"audio","link":1}],"mode":0,"properties":{}},{"id":2,"title":"BiquadFilter","type":"audio/biquadfilter","pos":[437,251],"size":{"0":140,"1":34},"flags":{},"inputs":[{"name":"in","type":"audio","link":0},{"name":"frequency","type":"number","link":4}],"outputs":[{"name":"out","type":"audio","links":[1,2]}],"mode":0,"properties":{"frequency":350,"detune":0,"Q":1,"type":"lowpass"}},{"id":3,"title":"Analyser","type":"audio/analyser","pos":[672,306],"size":{"0":140,"1":20},"flags":{},"inputs":[{"name":"in","type":"audio","link":2}],"outputs":[{"name":"freqs","type":"array","links":[3]}],"mode":0,"properties":{"fftSize":2048,"minDecibels":-100,"maxDecibels":-10,"smoothingTimeConstant":0.5}},{"id":6,"title":"Knob","type":"widget/knob","pos":[120,183],"size":[54,74],"flags":{},"outputs":[{"name":"","type":"number","links":[5]}],"mode":0,"properties":{"min":0,"max":1,"value":0.5099999999999996,"wcolor":"#7AF","size":50},"boxcolor":"rgba(128,128,128,1.0)"},{"id":0,"title":"Source","type":"audio/source","pos":[251,196],"size":{"0":140,"1":62},"flags":{},"inputs":[{"name":"gain","type":"number","link":5},{"name":"Play","type":-1,"link":6},{"name":"Stop","type":-1,"link":7},{"name":"playbackRate","type":"number","link":8}],"outputs":[{"name":"out","type":"audio","links":[0]}],"mode":0,"properties":{"src":"demodata/audio.wav","gain":0.5,"loop":false,"autoplay":true,"playbackRate":1.0000000000000002}},{"id":8,"title":"Button","type":"widget/button","pos":[274,106],"size":[128,43],"flags":{},"outputs":[{"name":"clicked","type":-1,"links":[7]}],"mode":0,"properties":{"text":"Stop","font":"40px Arial","message":""}},{"id":5,"title":"Knob","type":"widget/knob","pos":[125,293],"size":[54,74],"flags":{},"outputs":[{"name":"","type":"number","links":[4]}],"mode":0,"properties":{"min":0,"max":20000,"value":14800.00000000001,"wcolor":"#7AF","size":50},"boxcolor":"rgba(189,189,189,1.0)"},{"id":10,"title":"Watch","type":"basic/watch","pos":[516,123],"size":{"0":140,"1":20},"flags":{},"inputs":[{"name":"value","type":0,"link":9,"label":"1.000"}],"outputs":[{"name":"value","type":0,"links":null,"label":""}],"mode":0,"properties":{"value":1.0000000000000002}},{"id":9,"title":"Knob","type":"widget/knob","pos":[429,119],"size":[64,84],"flags":{},"outputs":[{"name":"","type":"number","links":[8,9]}],"mode":0,"properties":{"min":0,"max":4,"value":1.0000000000000002,"wcolor":"#7AF","size":50},"boxcolor":"rgba(64,64,64,1.0)"},{"id":7,"title":"Button","type":"widget/button","pos":[114,103],"size":[128,43],"flags":{},"outputs":[{"name":"clicked","type":-1,"links":[6]}],"mode":0,"properties":{"text":"Play","font":"40px Arial","message":""}},{"id":4,"title":"Visualization","type":"audio/visualization","pos":[132,394],"size":[662,180],"flags":{},"inputs":[{"name":"freqs","type":"array","link":3}],"mode":0,"properties":{"continuous":true}}]}
|
||||
{
|
||||
"iteration": 139049,
|
||||
"last_node_id": 16,
|
||||
"last_link_id": 16,
|
||||
"links": {
|
||||
"0": {
|
||||
"id": 0,
|
||||
"origin_id": 0,
|
||||
"origin_slot": 0,
|
||||
"target_id": 2,
|
||||
"target_slot": 0,
|
||||
"data": null
|
||||
},
|
||||
"1": {
|
||||
"id": 1,
|
||||
"origin_id": 2,
|
||||
"origin_slot": 0,
|
||||
"target_id": 1,
|
||||
"target_slot": 0,
|
||||
"data": null
|
||||
},
|
||||
"2": {
|
||||
"id": 2,
|
||||
"origin_id": 2,
|
||||
"origin_slot": 0,
|
||||
"target_id": 3,
|
||||
"target_slot": 0,
|
||||
"data": null
|
||||
},
|
||||
"3": {
|
||||
"id": 3,
|
||||
"origin_id": 3,
|
||||
"origin_slot": 0,
|
||||
"target_id": 4,
|
||||
"target_slot": 0,
|
||||
"data": null
|
||||
},
|
||||
"4": {
|
||||
"id": 4,
|
||||
"origin_id": 5,
|
||||
"origin_slot": 0,
|
||||
"target_id": 2,
|
||||
"target_slot": 1,
|
||||
"data": null
|
||||
},
|
||||
"5": {
|
||||
"id": 5,
|
||||
"origin_id": 6,
|
||||
"origin_slot": 0,
|
||||
"target_id": 0,
|
||||
"target_slot": 0,
|
||||
"data": null
|
||||
},
|
||||
"6": {
|
||||
"id": 6,
|
||||
"origin_id": 7,
|
||||
"origin_slot": 0,
|
||||
"target_id": 0,
|
||||
"target_slot": 1,
|
||||
"data": null
|
||||
},
|
||||
"7": {
|
||||
"id": 7,
|
||||
"origin_id": 8,
|
||||
"origin_slot": 0,
|
||||
"target_id": 0,
|
||||
"target_slot": 2,
|
||||
"data": null
|
||||
},
|
||||
"8": {
|
||||
"id": 8,
|
||||
"origin_id": 9,
|
||||
"origin_slot": 0,
|
||||
"target_id": 0,
|
||||
"target_slot": 3,
|
||||
"data": null
|
||||
},
|
||||
"9": {
|
||||
"id": 9,
|
||||
"origin_id": 9,
|
||||
"origin_slot": 0,
|
||||
"target_id": 10,
|
||||
"target_slot": 0,
|
||||
"data": null
|
||||
},
|
||||
"10": {
|
||||
"id": 10,
|
||||
"origin_id": 3,
|
||||
"origin_slot": 0,
|
||||
"target_id": 11,
|
||||
"target_slot": 0,
|
||||
"data": null
|
||||
},
|
||||
"11": {
|
||||
"id": 11,
|
||||
"origin_id": 12,
|
||||
"origin_slot": 0,
|
||||
"target_id": 11,
|
||||
"target_slot": 1,
|
||||
"data": null
|
||||
},
|
||||
"12": {
|
||||
"id": 12,
|
||||
"origin_id": 11,
|
||||
"origin_slot": 0,
|
||||
"target_id": 13,
|
||||
"target_slot": 0,
|
||||
"data": null
|
||||
},
|
||||
"13": {
|
||||
"id": 13,
|
||||
"origin_id": 12,
|
||||
"origin_slot": 0,
|
||||
"target_id": 4,
|
||||
"target_slot": 1,
|
||||
"data": null
|
||||
},
|
||||
"14": {
|
||||
"id": 14,
|
||||
"origin_id": 13,
|
||||
"origin_slot": 0,
|
||||
"target_id": 14,
|
||||
"target_slot": 0,
|
||||
"data": null
|
||||
},
|
||||
"15": {
|
||||
"id": 15,
|
||||
"origin_id": 12,
|
||||
"origin_slot": 0,
|
||||
"target_id": 15,
|
||||
"target_slot": 0,
|
||||
"data": null
|
||||
}
|
||||
},
|
||||
"config": {},
|
||||
"nodes": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Destination",
|
||||
"type": "audio/destination",
|
||||
"pos": [
|
||||
673,
|
||||
171
|
||||
],
|
||||
"size": {
|
||||
"0": 140,
|
||||
"1": 20
|
||||
},
|
||||
"flags": {},
|
||||
"inputs": [
|
||||
{
|
||||
"name": "in",
|
||||
"type": "audio",
|
||||
"link": 1
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"title": "BiquadFilter",
|
||||
"type": "audio/biquadfilter",
|
||||
"pos": [
|
||||
437,
|
||||
251
|
||||
],
|
||||
"size": {
|
||||
"0": 140,
|
||||
"1": 34
|
||||
},
|
||||
"flags": {},
|
||||
"inputs": [
|
||||
{
|
||||
"name": "in",
|
||||
"type": "audio",
|
||||
"link": 0
|
||||
},
|
||||
{
|
||||
"name": "frequency",
|
||||
"type": "number",
|
||||
"link": 4
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "out",
|
||||
"type": "audio",
|
||||
"links": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"frequency": 350,
|
||||
"detune": 0,
|
||||
"Q": 1,
|
||||
"type": "lowpass"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"title": "Knob",
|
||||
"type": "widget/knob",
|
||||
"pos": [
|
||||
120,
|
||||
183
|
||||
],
|
||||
"size": [
|
||||
54,
|
||||
74
|
||||
],
|
||||
"flags": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "number",
|
||||
"links": [
|
||||
5
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"min": 0,
|
||||
"max": 1,
|
||||
"value": 0.5099999999999996,
|
||||
"wcolor": "#7AF",
|
||||
"size": 50
|
||||
},
|
||||
"boxcolor": "rgba(128,128,128,1.0)"
|
||||
},
|
||||
{
|
||||
"id": 0,
|
||||
"title": "Source",
|
||||
"type": "audio/source",
|
||||
"pos": [
|
||||
251,
|
||||
196
|
||||
],
|
||||
"size": {
|
||||
"0": 140,
|
||||
"1": 62
|
||||
},
|
||||
"flags": {},
|
||||
"inputs": [
|
||||
{
|
||||
"name": "gain",
|
||||
"type": "number",
|
||||
"link": 5
|
||||
},
|
||||
{
|
||||
"name": "Play",
|
||||
"type": -1,
|
||||
"link": 6
|
||||
},
|
||||
{
|
||||
"name": "Stop",
|
||||
"type": -1,
|
||||
"link": 7
|
||||
},
|
||||
{
|
||||
"name": "playbackRate",
|
||||
"type": "number",
|
||||
"link": 8
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "out",
|
||||
"type": "audio",
|
||||
"links": [
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"src": "demodata/audio.wav",
|
||||
"gain": 0.5,
|
||||
"loop": true,
|
||||
"autoplay": true,
|
||||
"playbackRate": 0.24000000000000002
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"title": "Knob",
|
||||
"type": "widget/knob",
|
||||
"pos": [
|
||||
125,
|
||||
293
|
||||
],
|
||||
"size": [
|
||||
54,
|
||||
74
|
||||
],
|
||||
"flags": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "number",
|
||||
"links": [
|
||||
4
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"min": 0,
|
||||
"max": 20000,
|
||||
"value": 14800.00000000001,
|
||||
"wcolor": "#7AF",
|
||||
"size": 50
|
||||
},
|
||||
"boxcolor": "rgba(128,128,128,1.0)"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"title": "Watch",
|
||||
"type": "basic/watch",
|
||||
"pos": [
|
||||
516,
|
||||
123
|
||||
],
|
||||
"size": {
|
||||
"0": 140,
|
||||
"1": 20
|
||||
},
|
||||
"flags": {},
|
||||
"inputs": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": 0,
|
||||
"link": 9,
|
||||
"label": "0.240"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": 0,
|
||||
"links": null,
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"value": 0.24000000000000002
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"title": "Button",
|
||||
"type": "widget/button",
|
||||
"pos": [
|
||||
274,
|
||||
106
|
||||
],
|
||||
"size": [
|
||||
128,
|
||||
43
|
||||
],
|
||||
"flags": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "clicked",
|
||||
"type": -1,
|
||||
"links": [
|
||||
7
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"text": "Stop",
|
||||
"font": "40px Arial",
|
||||
"message": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"title": "Knob",
|
||||
"type": "widget/knob",
|
||||
"pos": [
|
||||
429,
|
||||
119
|
||||
],
|
||||
"size": [
|
||||
54,
|
||||
74
|
||||
],
|
||||
"flags": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "number",
|
||||
"links": [
|
||||
8,
|
||||
9
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"min": 0,
|
||||
"max": 4,
|
||||
"value": 0.24000000000000002,
|
||||
"wcolor": "#7AF",
|
||||
"size": 50
|
||||
},
|
||||
"boxcolor": "rgba(128,128,128,1.0)"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"title": "Button",
|
||||
"type": "widget/button",
|
||||
"pos": [
|
||||
114,
|
||||
103
|
||||
],
|
||||
"size": [
|
||||
128,
|
||||
43
|
||||
],
|
||||
"flags": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "clicked",
|
||||
"type": -1,
|
||||
"links": [
|
||||
6
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"text": "Play",
|
||||
"font": "40px Arial",
|
||||
"message": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title": "Analyser",
|
||||
"type": "audio/analyser",
|
||||
"pos": [
|
||||
672,
|
||||
306
|
||||
],
|
||||
"size": {
|
||||
"0": 140,
|
||||
"1": 20
|
||||
},
|
||||
"flags": {},
|
||||
"inputs": [
|
||||
{
|
||||
"name": "in",
|
||||
"type": "audio",
|
||||
"link": 2
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "freqs",
|
||||
"type": "array",
|
||||
"links": [
|
||||
3,
|
||||
10
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"fftSize": 2048,
|
||||
"minDecibels": -100,
|
||||
"maxDecibels": -10,
|
||||
"smoothingTimeConstant": 0.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"title": "Signal",
|
||||
"type": "audio/signal",
|
||||
"pos": [
|
||||
241,
|
||||
391
|
||||
],
|
||||
"size": {
|
||||
"0": 140,
|
||||
"1": 34
|
||||
},
|
||||
"flags": {},
|
||||
"inputs": [
|
||||
{
|
||||
"name": "freqs",
|
||||
"type": "array",
|
||||
"link": 10
|
||||
},
|
||||
{
|
||||
"name": "band",
|
||||
"type": "number",
|
||||
"link": 11
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "signal",
|
||||
"type": "number",
|
||||
"links": [
|
||||
12
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"band": 440,
|
||||
"amplitude": 1,
|
||||
"samplerate": 44100
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"title": "Progress",
|
||||
"type": "widget/progress",
|
||||
"pos": [
|
||||
91,
|
||||
568
|
||||
],
|
||||
"size": {
|
||||
"0": 140,
|
||||
"1": 20
|
||||
},
|
||||
"flags": {},
|
||||
"inputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "number",
|
||||
"link": 14
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"min": 0,
|
||||
"max": 1,
|
||||
"value": 0.3843137254901945,
|
||||
"wcolor": "#AAF"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"title": "Max. Signal",
|
||||
"type": "basic/watch",
|
||||
"pos": [
|
||||
92,
|
||||
527
|
||||
],
|
||||
"size": {
|
||||
"0": 140,
|
||||
"1": 20
|
||||
},
|
||||
"flags": {},
|
||||
"inputs": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": 0,
|
||||
"link": 12,
|
||||
"label": "0.396"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": 0,
|
||||
"links": [
|
||||
14
|
||||
],
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"value": 0.3843137254901945
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"title": "Visualization",
|
||||
"type": "audio/visualization",
|
||||
"pos": [
|
||||
253,
|
||||
497
|
||||
],
|
||||
"size": [
|
||||
662,
|
||||
180
|
||||
],
|
||||
"flags": {},
|
||||
"inputs": [
|
||||
{
|
||||
"name": "freqs",
|
||||
"type": "array",
|
||||
"link": 3
|
||||
},
|
||||
{
|
||||
"name": "mark",
|
||||
"type": "number",
|
||||
"link": 13
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"continuous": true,
|
||||
"mark": 12000.000000000005,
|
||||
"samplerate": 44100
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"title": "Watch",
|
||||
"type": "basic/watch",
|
||||
"pos": [
|
||||
93,
|
||||
398
|
||||
],
|
||||
"size": {
|
||||
"0": 87,
|
||||
"1": 20
|
||||
},
|
||||
"flags": {},
|
||||
"inputs": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": 0,
|
||||
"link": 15,
|
||||
"label": "12000.000"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"name": "value",
|
||||
"type": 0,
|
||||
"links": null,
|
||||
"label": ""
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"value": 12000.000000000005
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"title": "Knob",
|
||||
"type": "widget/knob",
|
||||
"pos": [
|
||||
92,
|
||||
435
|
||||
],
|
||||
"size": [
|
||||
54,
|
||||
74
|
||||
],
|
||||
"flags": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "",
|
||||
"type": "number",
|
||||
"links": [
|
||||
11,
|
||||
13,
|
||||
15
|
||||
]
|
||||
}
|
||||
],
|
||||
"mode": 0,
|
||||
"properties": {
|
||||
"min": 0,
|
||||
"max": 24000,
|
||||
"value": 12000.000000000005,
|
||||
"wcolor": "#7AF",
|
||||
"size": 50
|
||||
},
|
||||
"boxcolor": "rgba(128,128,128,1.0)"
|
||||
}
|
||||
]
|
||||
}
|
||||
1
demo/examples/audio_reverb.json
Normal file
1
demo/examples/audio_reverb.json
Normal file
@@ -0,0 +1 @@
|
||||
{"iteration":48488,"last_node_id":8,"last_link_id":9,"links":{"0":{"id":0,"origin_id":0,"origin_slot":0,"target_id":1,"target_slot":0,"data":null},"1":{"id":1,"origin_id":0,"origin_slot":0,"target_id":2,"target_slot":0,"data":null},"3":{"id":3,"origin_id":1,"origin_slot":0,"target_id":3,"target_slot":0,"data":null},"4":{"id":4,"origin_id":4,"origin_slot":0,"target_id":1,"target_slot":1,"data":null},"5":{"id":5,"origin_id":5,"origin_slot":0,"target_id":1,"target_slot":3,"data":null},"6":{"id":6,"origin_id":6,"origin_slot":0,"target_id":2,"target_slot":1,"data":null},"7":{"id":7,"origin_id":0,"origin_slot":0,"target_id":7,"target_slot":0,"data":null},"8":{"id":8,"origin_id":7,"origin_slot":0,"target_id":1,"target_slot":2,"data":null}},"config":{},"nodes":[{"id":1,"title":"Mixer","type":"audio/mixer","pos":[655,183],"size":{"0":140,"1":62},"flags":{},"inputs":[{"name":"in1","type":"audio","link":0},{"name":"in1 gain","type":"number","link":4},{"name":"in2","type":"audio","link":8},{"name":"in2 gain","type":"number","link":5}],"outputs":[{"name":"out","type":"audio","links":[3]}],"mode":0,"properties":{"gain1":0.5,"gain2":0.8}},{"id":3,"title":"Destination","type":"audio/destination","pos":[911,180],"size":{"0":140,"1":20},"flags":{},"inputs":[{"name":"in","type":"audio","link":3}],"mode":0,"properties":{}},{"id":0,"title":"Source","type":"audio/source","pos":[195,187],"size":{"0":140,"1":20},"flags":{},"inputs":[{"name":"gain","type":"number","link":null}],"outputs":[{"name":"out","type":"audio","links":[0,7]}],"mode":0,"properties":{"src":"demodata/audio.wav","gain":0.5,"loop":true,"autoplay":true,"playbackRate":1}},{"id":7,"title":"Convolver","type":"audio/convolver","pos":[421,253],"size":{"0":140,"1":20},"flags":{},"inputs":[{"name":"in","type":"audio","link":7}],"outputs":[{"name":"out","type":"audio","links":[8]}],"mode":0,"properties":{"impulse_src":"demodata/impulse.wav","normalize":true}},{"id":5,"title":"Reverb","type":"widget/knob","pos":[398,311],"size":[84,100],"flags":{},"outputs":[{"name":"","type":"number","links":[5]}],"mode":0,"properties":{"min":0,"max":1,"value":0.4099999999999999,"wcolor":"#7AF","size":50},"boxcolor":"rgba(128,128,128,1.0)"},{"id":4,"title":"Main","type":"widget/knob","pos":[408,59],"size":[81,93],"flags":{},"outputs":[{"name":"","type":"number","links":[4]}],"mode":0,"properties":{"min":0,"max":1,"value":0.21000000000000002,"wcolor":"#7AF","size":50},"boxcolor":"rgba(128,128,128,1.0)"}]}
|
||||
BIN
imgs/elephant.gif
Normal file
BIN
imgs/elephant.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
BIN
imgs/webglstudio.gif
Normal file
BIN
imgs/webglstudio.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 MiB |
@@ -22,8 +22,8 @@ function Editor( container_id, options )
|
||||
graph.onAfterExecute = function() { graphcanvas.draw(true) };
|
||||
|
||||
//add stuff
|
||||
this.addToolsButton("loadsession_button","Load","imgs/icon-load.png", this.onLoadButton.bind(this), ".tools-left" );
|
||||
this.addToolsButton("savesession_button","Save","imgs/icon-save.png", this.onSaveButton.bind(this), ".tools-left" );
|
||||
//this.addToolsButton("loadsession_button","Load","imgs/icon-load.png", this.onLoadButton.bind(this), ".tools-left" );
|
||||
//this.addToolsButton("savesession_button","Save","imgs/icon-save.png", this.onSaveButton.bind(this), ".tools-left" );
|
||||
this.addLoadCounter();
|
||||
this.addToolsButton("playnode_button","Play","imgs/icon-play.png", this.onPlayButton.bind(this), ".tools-right" );
|
||||
this.addToolsButton("playstepnode_button","Step","imgs/icon-playstep.png", this.onPlayStepButton.bind(this), ".tools-right" );
|
||||
@@ -186,8 +186,14 @@ Editor.prototype.addMiniWindow = function(w,h)
|
||||
var graphcanvas = new LGraphCanvas(canvas, this.graph);
|
||||
graphcanvas.background_image = "imgs/grid.png";
|
||||
graphcanvas.scale = 0.25;
|
||||
graphcanvas.allow_dragnodes = false;
|
||||
graphcanvas.allow_interaction = false;
|
||||
this.miniwindow_graphcanvas = graphcanvas;
|
||||
graphcanvas.onClear = function() { graphcanvas.scale = 0.25; };
|
||||
graphcanvas.onClear = function() {
|
||||
graphcanvas.scale = 0.25;
|
||||
graphcanvas.allow_dragnodes = false;
|
||||
graphcanvas.allow_interaction = false;
|
||||
};
|
||||
|
||||
miniwindow.style.position = "absolute";
|
||||
miniwindow.style.top = "4px";
|
||||
|
||||
128
src/litegraph.js
128
src/litegraph.js
@@ -2511,6 +2511,7 @@ function LGraphCanvas( canvas, graph, options )
|
||||
this.show_info = true;
|
||||
this.allow_dragcanvas = true;
|
||||
this.allow_dragnodes = true;
|
||||
this.allow_interaction = true; //allow to control widgets, buttons, collapse, etc
|
||||
|
||||
this.always_render_background = false;
|
||||
this.render_connections_shadows = false; //too much cpu
|
||||
@@ -2986,7 +2987,7 @@ LGraphCanvas.prototype.processMouseDown = function(e)
|
||||
|
||||
//when clicked on top of a node
|
||||
//and it is not interactive
|
||||
if(n)
|
||||
if(n && this.allow_interaction )
|
||||
{
|
||||
if(!this.live_mode && !n.flags.pinned)
|
||||
this.bringToFront(n); //if it wasnt selected?
|
||||
@@ -3149,7 +3150,7 @@ LGraphCanvas.prototype.processMouseMove = function(e)
|
||||
this.dirty_canvas = true;
|
||||
this.dirty_bgcanvas = true;
|
||||
}
|
||||
else
|
||||
else if(this.allow_interaction)
|
||||
{
|
||||
if(this.connecting_node)
|
||||
this.dirty_canvas = true;
|
||||
@@ -3513,7 +3514,7 @@ LGraphCanvas.prototype.processDrop = function(e)
|
||||
return;
|
||||
}
|
||||
|
||||
if(node.onDropFile)
|
||||
if( node.onDropFile || node.onDropData )
|
||||
{
|
||||
var files = e.dataTransfer.files;
|
||||
if(files && files.length)
|
||||
@@ -3525,22 +3526,28 @@ LGraphCanvas.prototype.processDrop = function(e)
|
||||
var ext = LGraphCanvas.getFileExtension( filename );
|
||||
//console.log(file);
|
||||
|
||||
//prepare reader
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
//console.log(event.target);
|
||||
var data = event.target.result;
|
||||
node.onDropFile( data, filename, file );
|
||||
};
|
||||
if(node.onDropFile)
|
||||
node.onDropFile(file);
|
||||
|
||||
//read data
|
||||
var type = file.type.split("/")[0];
|
||||
if(type == "text" || type == "")
|
||||
reader.readAsText(file);
|
||||
else if (type == "image")
|
||||
reader.readAsDataURL(file);
|
||||
else
|
||||
reader.readAsArrayBuffer(file);
|
||||
if(node.onDropData)
|
||||
{
|
||||
//prepare reader
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (event) {
|
||||
//console.log(event.target);
|
||||
var data = event.target.result;
|
||||
node.onDropData( data, filename, file );
|
||||
};
|
||||
|
||||
//read data
|
||||
var type = file.type.split("/")[0];
|
||||
if(type == "text" || type == "")
|
||||
reader.readAsText(file);
|
||||
else if (type == "image")
|
||||
reader.readAsDataURL(file);
|
||||
else
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3991,7 +3998,7 @@ LGraphCanvas.prototype.drawBackCanvas = function()
|
||||
if(this.background_image && this.scale > 0.5)
|
||||
{
|
||||
ctx.globalAlpha = (1.0 - 0.5 / this.scale) * this.editor_alpha;
|
||||
ctx.webkitImageSmoothingEnabled = ctx.mozImageSmoothingEnabled = ctx.imageSmoothingEnabled = false;
|
||||
ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = ctx.imageSmoothingEnabled = false;
|
||||
if(!this._bg_img || this._bg_img.name != this.background_image)
|
||||
{
|
||||
this._bg_img = new Image();
|
||||
@@ -4020,7 +4027,7 @@ LGraphCanvas.prototype.drawBackCanvas = function()
|
||||
}
|
||||
|
||||
ctx.globalAlpha = 1.0;
|
||||
ctx.webkitImageSmoothingEnabled = ctx.mozImageSmoothingEnabled = ctx.imageSmoothingEnabled = true;
|
||||
ctx.imageSmoothingEnabled = ctx.mozImageSmoothingEnabled = ctx.imageSmoothingEnabled = true;
|
||||
}
|
||||
|
||||
if(this.onBackgroundRender)
|
||||
@@ -4861,12 +4868,14 @@ LGraphCanvas.onShowMenuNodeProperties = function(node,e, prev_menu)
|
||||
for (var i in node.properties)
|
||||
{
|
||||
var value = node.properties[i] !== undefined ? node.properties[i] : " ";
|
||||
//value could contain invalid html characters, clean that
|
||||
value = LGraphCanvas.decodeHTML(value);
|
||||
entries.push({content: "<span class='property_name'>" + i + "</span>" + "<span class='property_value'>" + value + "</span>", value: i});
|
||||
}
|
||||
if(!entries.length)
|
||||
return;
|
||||
|
||||
var menu = LiteGraph.createContextMenu(entries, {event: e, callback: inner_clicked, from: prev_menu},ref_window);
|
||||
var menu = LiteGraph.createContextMenu(entries, {event: e, callback: inner_clicked, from: prev_menu, allow_html: true },ref_window);
|
||||
|
||||
function inner_clicked( v, e, prev )
|
||||
{
|
||||
@@ -4878,6 +4887,70 @@ LGraphCanvas.onShowMenuNodeProperties = function(node,e, prev_menu)
|
||||
return false;
|
||||
}
|
||||
|
||||
LGraphCanvas.decodeHTML = function( str )
|
||||
{
|
||||
var e = document.createElement("div");
|
||||
e.innerText = str;
|
||||
return e.innerHTML;
|
||||
}
|
||||
|
||||
LGraphCanvas.onShowTitleEditor = function( node, event )
|
||||
{
|
||||
var input_html = "";
|
||||
|
||||
var dialog = document.createElement("div");
|
||||
dialog.className = "graphdialog";
|
||||
dialog.innerHTML = "<span class='name'>Title</span><input autofocus type='text' class='value'/><button>OK</button>";
|
||||
var input = dialog.querySelector("input");
|
||||
if(input)
|
||||
{
|
||||
input.value = node.title;
|
||||
input.addEventListener("keydown", function(e){
|
||||
if(e.keyCode != 13)
|
||||
return;
|
||||
inner();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
var rect = this.canvas.getClientRects()[0];
|
||||
var offsetx = -20;
|
||||
var offsety = -20;
|
||||
if(rect)
|
||||
{
|
||||
offsetx -= rect.left;
|
||||
offsety -= rect.top;
|
||||
}
|
||||
|
||||
if( event )
|
||||
{
|
||||
dialog.style.left = (event.pageX + offsetx) + "px";
|
||||
dialog.style.top = (event.pageY + offsety)+ "px";
|
||||
}
|
||||
else
|
||||
{
|
||||
dialog.style.left = (this.canvas.width * 0.5 + offsetx) + "px";
|
||||
dialog.style.top = (this.canvas.height * 0.5 + offsety) + "px";
|
||||
}
|
||||
|
||||
var button = dialog.querySelector("button");
|
||||
button.addEventListener("click", inner );
|
||||
this.canvas.parentNode.appendChild( dialog );
|
||||
|
||||
function inner()
|
||||
{
|
||||
setValue( input.value );
|
||||
}
|
||||
|
||||
function setValue(value)
|
||||
{
|
||||
node.title = value;
|
||||
dialog.parentNode.removeChild( dialog );
|
||||
node.setDirtyCanvas(true,true);
|
||||
}
|
||||
}
|
||||
|
||||
LGraphCanvas.prototype.showEditPropertyValue = function( node, property, options )
|
||||
{
|
||||
if(!node || node.properties[ property ] === undefined )
|
||||
@@ -5147,6 +5220,7 @@ LGraphCanvas.prototype.getNodeMenuOptions = function(node)
|
||||
null,
|
||||
{content:"Properties", is_menu: true, callback: LGraphCanvas.onShowMenuNodeProperties },
|
||||
null,
|
||||
{content:"Title", callback: LGraphCanvas.onShowTitleEditor },
|
||||
{content:"Mode", is_menu: true, callback: LGraphCanvas.onMenuNodeMode },
|
||||
{content:"Collapse", callback: LGraphCanvas.onMenuNodeCollapse },
|
||||
{content:"Pin", callback: LGraphCanvas.onMenuNodePin },
|
||||
@@ -5361,7 +5435,7 @@ function num2hex(triplet) {
|
||||
|
||||
/* LiteGraph GUI elements *************************************/
|
||||
|
||||
LiteGraph.createContextMenu = function(values,options, ref_window)
|
||||
LiteGraph.createContextMenu = function(values, options, ref_window)
|
||||
{
|
||||
options = options || {};
|
||||
this.options = options;
|
||||
@@ -5434,10 +5508,16 @@ LiteGraph.createContextMenu = function(values,options, ref_window)
|
||||
element.style.cursor = "pointer";
|
||||
element.dataset["value"] = typeof(item) == "string" ? item : item.value;
|
||||
element.data = item;
|
||||
|
||||
var content = "";
|
||||
if(typeof(item) == "string")
|
||||
element.innerHTML = values.constructor == Array ? values[i] : i;
|
||||
content = values.constructor == Array ? values[i] : i;
|
||||
else
|
||||
element.innerHTML = item.content ? item.content : i;
|
||||
content = item.content ? item.content : i;
|
||||
if(options.allow_html)
|
||||
element.innerHTML = content;
|
||||
else
|
||||
element.innerText = content;
|
||||
|
||||
element.addEventListener("click", on_click );
|
||||
root.appendChild(element);
|
||||
|
||||
@@ -151,13 +151,74 @@ LGAudio.onConnectionsChange = function( connection, slot, connected, link_info )
|
||||
LGAudio.disconnect( local_audionode, target_audionode );
|
||||
}
|
||||
|
||||
//this function helps creating wrappers to existing classes
|
||||
LGAudio.createAudioNodeWrapper = function( class_object )
|
||||
{
|
||||
class_object.prototype.onPropertyChanged = function(name, value)
|
||||
{
|
||||
if(!this.audionode)
|
||||
return;
|
||||
|
||||
if( this.audionode[ name ] === undefined )
|
||||
return;
|
||||
|
||||
if( this.audionode[ name ].value !== undefined )
|
||||
this.audionode[ name ].value = value;
|
||||
else
|
||||
this.audionode[ name ] = value;
|
||||
}
|
||||
|
||||
class_object.prototype.onConnectionsChange = LGAudio.onConnectionsChange;
|
||||
}
|
||||
|
||||
|
||||
LGAudio.cached_audios = {};
|
||||
|
||||
LGAudio.loadSound = function( url, on_complete, on_error )
|
||||
{
|
||||
if( LGAudio.cached_audios[ url ] && url.indexOf("blob:") == -1 )
|
||||
{
|
||||
if(on_complete)
|
||||
on_complete( LGAudio.cached_audios[ url ] );
|
||||
return;
|
||||
}
|
||||
|
||||
//load new sample
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', url, true);
|
||||
request.responseType = 'arraybuffer';
|
||||
|
||||
var context = LGAudio.getAudioContext();
|
||||
|
||||
// Decode asynchronously
|
||||
request.onload = function() {
|
||||
console.log("AudioSource loaded");
|
||||
context.decodeAudioData( request.response, function( buffer ) {
|
||||
console.log("AudioSource decoded");
|
||||
LGAudio.cached_audios[ url ] = buffer;
|
||||
if(on_complete)
|
||||
on_complete( buffer );
|
||||
}, onError);
|
||||
}
|
||||
request.send();
|
||||
|
||||
function onError(err)
|
||||
{
|
||||
console.log("Audio loading sample error:",err);
|
||||
if(on_error)
|
||||
on_error(err);
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
//****************************************************
|
||||
|
||||
function LGAudioSource()
|
||||
{
|
||||
this.properties = {
|
||||
src: "demodata/audio.wav",
|
||||
src: "",
|
||||
gain: 0.5,
|
||||
loop: true,
|
||||
autoplay: true,
|
||||
@@ -210,6 +271,8 @@ LGAudioSource.prototype.onStop = function()
|
||||
LGAudioSource.prototype.onRemoved = function()
|
||||
{
|
||||
this.stopAllSounds();
|
||||
if(this._dropped_url)
|
||||
URL.revokeObjectURL( this._url );
|
||||
}
|
||||
|
||||
LGAudioSource.prototype.stopAllSounds = function()
|
||||
@@ -233,7 +296,6 @@ LGAudioSource.prototype.onExecute = function()
|
||||
var input = this.inputs[i];
|
||||
if(!input.link)
|
||||
continue;
|
||||
|
||||
var v = this.getInputData(i);
|
||||
if( v === undefined )
|
||||
continue;
|
||||
@@ -309,36 +371,19 @@ LGAudioSource.prototype.loadSound = function( url )
|
||||
if(!url)
|
||||
return;
|
||||
|
||||
//load new sample
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', url, true);
|
||||
request.responseType = 'arraybuffer';
|
||||
this._request = LGAudio.loadSound( url, inner );
|
||||
|
||||
this._loading_audio = true;
|
||||
this._request = request;
|
||||
this.boxcolor = "#AA4";
|
||||
|
||||
var context = LGAudio.getAudioContext();
|
||||
|
||||
// Decode asynchronously
|
||||
request.onload = function() {
|
||||
context.decodeAudioData( request.response, function(buffer) {
|
||||
that._audio_buffer = buffer;
|
||||
if(that._url)
|
||||
{
|
||||
URL.revokeObjectURL( that._url );
|
||||
that._url = null;
|
||||
}
|
||||
|
||||
that._loading_audio = false;
|
||||
//if is playing, then play it
|
||||
if(that.graph && that.graph.status === LGraph.STATUS_RUNNING)
|
||||
that.onStart();
|
||||
}, onError);
|
||||
}
|
||||
request.send();
|
||||
|
||||
function onError(err)
|
||||
function inner( buffer )
|
||||
{
|
||||
console.log("Audio loading sample error:",err);
|
||||
this.boxcolor = LiteGraph.NODE_DEFAULT_BOXCOLOR;
|
||||
that._audio_buffer = buffer;
|
||||
that._loading_audio = false;
|
||||
//if is playing, then play it
|
||||
if(that.graph && that.graph.status === LGraph.STATUS_RUNNING)
|
||||
that.onStart(); //this controls the autoplay already
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,11 +402,12 @@ LGAudioSource.prototype.onGetOutputs = function()
|
||||
|
||||
LGAudioSource.prototype.onDropFile = function(file)
|
||||
{
|
||||
if(this._url)
|
||||
URL.revokeObjectURL( this._url );
|
||||
this._url = URL.createObjectURL( file );
|
||||
this.properties.src = this._url;
|
||||
this.loadSound( this._url );
|
||||
if(this._dropped_url)
|
||||
URL.revokeObjectURL( this._dropped_url );
|
||||
var url = URL.createObjectURL( file );
|
||||
this.properties.src = url;
|
||||
this.loadSound( url );
|
||||
this._dropped_url = url;
|
||||
}
|
||||
|
||||
|
||||
@@ -415,15 +461,24 @@ LGAudioAnalyser.prototype.onExecute = function()
|
||||
this.setOutputData(0,this._freq_bin);
|
||||
}
|
||||
|
||||
//send analyzer
|
||||
if(this.isOutputConnected(1))
|
||||
this.setOutputData(1,this.audionode);
|
||||
|
||||
|
||||
//properties
|
||||
for(var i = 1; i < this.inputs.length; ++i)
|
||||
{
|
||||
var input = this.inputs[i];
|
||||
if(!input.link)
|
||||
continue;
|
||||
var v = this.getInputData(i);
|
||||
if (v !== undefined)
|
||||
this.audionode[ input.name ].value = v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//time domain
|
||||
//this.audionode.getFloatTimeDomainData( dataArray );
|
||||
}
|
||||
@@ -433,33 +488,17 @@ LGAudioAnalyser.prototype.onGetInputs = function()
|
||||
return [["minDecibels","number"],["maxDecibels","number"],["smoothingTimeConstant","number"]];
|
||||
}
|
||||
|
||||
/*
|
||||
LGAudioAnalyser.prototype.onGetOutputs = function()
|
||||
{
|
||||
return [["Analyzer","analyzer"]];
|
||||
}
|
||||
*/
|
||||
|
||||
LGAudioAnalyser.title = "Analyser";
|
||||
LGAudioAnalyser.desc = "Audio Analyser";
|
||||
LiteGraph.registerNodeType( "audio/analyser", LGAudioAnalyser );
|
||||
|
||||
|
||||
|
||||
//*****************************************************
|
||||
|
||||
//this function helps creating wrappers to existing classes
|
||||
function createAudioNodeWrapper( class_object )
|
||||
{
|
||||
class_object.prototype.onPropertyChanged = function(name, value)
|
||||
{
|
||||
if( this.audionode[ name ] === undefined )
|
||||
return;
|
||||
|
||||
if( this.audionode[ name ].value !== undefined )
|
||||
this.audionode[ name ].value = value;
|
||||
else
|
||||
this.audionode[ name ] = value;
|
||||
}
|
||||
|
||||
class_object.prototype.onConnectionsChange = LGAudio.onConnectionsChange;
|
||||
}
|
||||
|
||||
|
||||
//*****************************************************
|
||||
|
||||
function LGAudioGain()
|
||||
@@ -489,14 +528,128 @@ LGAudioGain.prototype.onExecute = function()
|
||||
}
|
||||
}
|
||||
|
||||
createAudioNodeWrapper( LGAudioGain );
|
||||
LGAudio.createAudioNodeWrapper( LGAudioGain );
|
||||
|
||||
LGAudioGain.title = "Gain";
|
||||
LGAudioGain.desc = "Audio gain";
|
||||
LiteGraph.registerNodeType("audio/gain", LGAudioGain);
|
||||
|
||||
|
||||
function LGAudioConvolver()
|
||||
{
|
||||
//default
|
||||
this.properties = {
|
||||
impulse_src:"",
|
||||
normalize: true
|
||||
};
|
||||
|
||||
this.audionode = LGAudio.getAudioContext().createConvolver();
|
||||
this.addInput("in","audio");
|
||||
this.addOutput("out","audio");
|
||||
}
|
||||
|
||||
LGAudio.createAudioNodeWrapper( LGAudioConvolver );
|
||||
|
||||
LGAudioConvolver.prototype.onRemove = function()
|
||||
{
|
||||
if(this._dropped_url)
|
||||
URL.revokeObjectURL( this._dropped_url );
|
||||
}
|
||||
|
||||
LGAudioConvolver.prototype.onPropertyChanged = function( name, value )
|
||||
{
|
||||
if( name == "impulse_src" )
|
||||
this.loadImpulse( value );
|
||||
else if( name == "normalize" )
|
||||
this.audionode.normalize = value;
|
||||
}
|
||||
|
||||
LGAudioConvolver.prototype.onDropFile = function(file)
|
||||
{
|
||||
if(this._dropped_url)
|
||||
URL.revokeObjectURL( this._dropped_url );
|
||||
this._dropped_url = URL.createObjectURL( file );
|
||||
this.properties.impulse_src = this._dropped_url;
|
||||
this.loadImpulse( this._dropped_url );
|
||||
}
|
||||
|
||||
LGAudioConvolver.prototype.loadImpulse = function( url )
|
||||
{
|
||||
var that = this;
|
||||
|
||||
//kill previous load
|
||||
if(this._request)
|
||||
{
|
||||
this._request.abort();
|
||||
this._request = null;
|
||||
}
|
||||
|
||||
this._impulse_buffer = null;
|
||||
this._loading_impulse = false;
|
||||
|
||||
if(!url)
|
||||
return;
|
||||
|
||||
//load new sample
|
||||
this._request = LGAudio.loadSound( url, inner );
|
||||
this._loading_impulse = true;
|
||||
|
||||
// Decode asynchronously
|
||||
function inner( buffer ) {
|
||||
that._impulse_buffer = buffer;
|
||||
that.audionode.buffer = buffer;
|
||||
console.log("Impulse signal set");
|
||||
that._loading_impulse = false;
|
||||
}
|
||||
}
|
||||
|
||||
LGAudioConvolver.title = "Convolver";
|
||||
LGAudioConvolver.desc = "Convolves the signal (used for reverb)";
|
||||
LiteGraph.registerNodeType("audio/convolver", LGAudioConvolver);
|
||||
|
||||
|
||||
function LGAudioDynamicsCompressor()
|
||||
{
|
||||
//default
|
||||
this.properties = {
|
||||
threshold: -50,
|
||||
knee: 40,
|
||||
ratio: 12,
|
||||
reduction: -20,
|
||||
attack: 0,
|
||||
release: 0.25
|
||||
};
|
||||
|
||||
this.audionode = LGAudio.getAudioContext().createDynamicsCompressor();
|
||||
this.addInput("in","audio");
|
||||
this.addOutput("out","audio");
|
||||
}
|
||||
|
||||
LGAudio.createAudioNodeWrapper( LGAudioDynamicsCompressor );
|
||||
|
||||
LGAudioDynamicsCompressor.prototype.onExecute = function()
|
||||
{
|
||||
if(!this.inputs || !this.inputs.length)
|
||||
return;
|
||||
for(var i = 1; i < this.inputs.length; ++i)
|
||||
{
|
||||
var input = this.inputs[i];
|
||||
if(!input.link)
|
||||
continue;
|
||||
var v = this.getInputData(i);
|
||||
if(v !== undefined)
|
||||
this.audionode[ input.name ].value = v;
|
||||
}
|
||||
}
|
||||
|
||||
LGAudioDynamicsCompressor.prototype.onGetInputs = function()
|
||||
{
|
||||
return [["threshold","number"],["knee","number"],["ratio","number"],["reduction","number"],["attack","number"],["release","number"]];
|
||||
}
|
||||
|
||||
LGAudioDynamicsCompressor.title = "DynamicsCompressor";
|
||||
LGAudioDynamicsCompressor.desc = "Dynamics Compressor";
|
||||
LiteGraph.registerNodeType("audio/dynamicsCompressor", LGAudioDynamicsCompressor);
|
||||
|
||||
|
||||
function LGAudioWaveShaper()
|
||||
@@ -526,7 +679,7 @@ LGAudioWaveShaper.prototype.setWaveShape = function(shape)
|
||||
this.audionode.curve = shape;
|
||||
}
|
||||
|
||||
createAudioNodeWrapper( LGAudioWaveShaper );
|
||||
LGAudio.createAudioNodeWrapper( LGAudioWaveShaper );
|
||||
|
||||
/* disabled till I dont find a way to do a wave shape
|
||||
LGAudioWaveShaper.title = "WaveShaper";
|
||||
@@ -576,7 +729,8 @@ LGAudioMixer.prototype.onExecute = function()
|
||||
for(var i = 1; i < this.inputs.length; ++i)
|
||||
{
|
||||
var input = this.inputs[i];
|
||||
if(input.type == "audio")
|
||||
|
||||
if(!input.link || input.type == "audio")
|
||||
continue;
|
||||
|
||||
var v = this.getInputData(i);
|
||||
@@ -590,7 +744,7 @@ LGAudioMixer.prototype.onExecute = function()
|
||||
}
|
||||
}
|
||||
|
||||
createAudioNodeWrapper( LGAudioMixer );
|
||||
LGAudio.createAudioNodeWrapper( LGAudioMixer );
|
||||
|
||||
LGAudioMixer.title = "Mixer";
|
||||
LGAudioMixer.desc = "Audio mixer";
|
||||
@@ -611,7 +765,7 @@ function LGAudioDelay()
|
||||
this.addOutput("out","audio");
|
||||
}
|
||||
|
||||
createAudioNodeWrapper( LGAudioDelay );
|
||||
LGAudio.createAudioNodeWrapper( LGAudioDelay );
|
||||
|
||||
LGAudioDelay.prototype.onExecute = function()
|
||||
{
|
||||
@@ -651,6 +805,8 @@ LGAudioBiquadFilter.prototype.onExecute = function()
|
||||
for(var i = 1; i < this.inputs.length; ++i)
|
||||
{
|
||||
var input = this.inputs[i];
|
||||
if(!input.link)
|
||||
continue;
|
||||
var v = this.getInputData(i);
|
||||
if(v !== undefined)
|
||||
this.audionode[ input.name ].value = v;
|
||||
@@ -662,7 +818,7 @@ LGAudioBiquadFilter.prototype.onGetInputs = function()
|
||||
return [["frequency","number"],["detune","number"],["Q","number"]];
|
||||
}
|
||||
|
||||
createAudioNodeWrapper( LGAudioBiquadFilter );
|
||||
LGAudio.createAudioNodeWrapper( LGAudioBiquadFilter );
|
||||
|
||||
LGAudioBiquadFilter.title = "BiquadFilter";
|
||||
LGAudioBiquadFilter.desc = "Audio filter";
|
||||
@@ -677,10 +833,12 @@ LiteGraph.registerNodeType("audio/biquadfilter", LGAudioBiquadFilter);
|
||||
function LGAudioVisualization()
|
||||
{
|
||||
this.properties = {
|
||||
continuous: true
|
||||
continuous: true,
|
||||
mark: -1
|
||||
};
|
||||
|
||||
this.addInput("freqs","array");
|
||||
this.addInput("mark","number");
|
||||
this.size = [300,200];
|
||||
this._last_buffer = null;
|
||||
}
|
||||
@@ -688,6 +846,10 @@ function LGAudioVisualization()
|
||||
LGAudioVisualization.prototype.onExecute = function()
|
||||
{
|
||||
this._last_buffer = this.getInputData(0);
|
||||
var v = this.getInputData(1);
|
||||
if(v !== undefined)
|
||||
this.properties.mark = v;
|
||||
this.setDirtyCanvas(true,false);
|
||||
}
|
||||
|
||||
LGAudioVisualization.prototype.onDrawForeground = function(ctx)
|
||||
@@ -697,6 +859,7 @@ LGAudioVisualization.prototype.onDrawForeground = function(ctx)
|
||||
|
||||
var buffer = this._last_buffer;
|
||||
|
||||
//delta represents how many samples we advance per pixel
|
||||
var delta = buffer.length / this.size[0];
|
||||
var h = this.size[1];
|
||||
|
||||
@@ -719,12 +882,26 @@ LGAudioVisualization.prototype.onDrawForeground = function(ctx)
|
||||
{
|
||||
for(var i = 0; i < buffer.length; i+= delta)
|
||||
{
|
||||
ctx.moveTo(x,h);
|
||||
ctx.lineTo(x,h - (buffer[i|0]/255) * h);
|
||||
ctx.moveTo(x+0.5,h);
|
||||
ctx.lineTo(x+0.5,h - (buffer[i|0]/255) * h);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
ctx.stroke();
|
||||
|
||||
if(this.properties.mark >= 0)
|
||||
{
|
||||
var samplerate = LGAudio.getAudioContext().sampleRate;
|
||||
var binfreq = samplerate / buffer.length;
|
||||
var x = 2 * (this.properties.mark / binfreq) / delta;
|
||||
if(x >= this.size[0])
|
||||
x = this.size[0]-1;
|
||||
ctx.strokeStyle = "red";
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x,h);
|
||||
ctx.lineTo(x,0);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
LGAudioVisualization.title = "Visualization";
|
||||
@@ -732,6 +909,59 @@ LGAudioVisualization.desc = "Audio Visualization";
|
||||
LiteGraph.registerNodeType("audio/visualization", LGAudioVisualization);
|
||||
|
||||
|
||||
function LGAudioBandSignal()
|
||||
{
|
||||
//default
|
||||
this.properties = {
|
||||
band: 440,
|
||||
amplitude: 1
|
||||
};
|
||||
|
||||
this.addInput("freqs","array");
|
||||
this.addOutput("signal","number");
|
||||
}
|
||||
|
||||
LGAudioBandSignal.prototype.onExecute = function()
|
||||
{
|
||||
this._freqs = this.getInputData(0);
|
||||
if( !this._freqs )
|
||||
return;
|
||||
|
||||
var band = this.properties.band;
|
||||
var v = this.getInputData(1);
|
||||
if(v !== undefined)
|
||||
band = v;
|
||||
|
||||
var samplerate = LGAudio.getAudioContext().sampleRate;
|
||||
var binfreq = samplerate / this._freqs.length;
|
||||
var index = 2 * (band / binfreq);
|
||||
var v = 0;
|
||||
if( index < 0 )
|
||||
v = this._freqs[ 0 ];
|
||||
if( index >= this._freqs.length )
|
||||
v = this._freqs[ this._freqs.length - 1];
|
||||
else
|
||||
{
|
||||
var pos = index|0;
|
||||
var v0 = this._freqs[ pos ];
|
||||
var v1 = this._freqs[ pos+1 ];
|
||||
var f = index - pos;
|
||||
v = v0 * (1-f) + v1 * f;
|
||||
}
|
||||
|
||||
this.setOutputData( 0, (v/255) * this.properties.amplitude );
|
||||
}
|
||||
|
||||
LGAudioBandSignal.prototype.onGetInputs = function()
|
||||
{
|
||||
return [["band","number"]];
|
||||
}
|
||||
|
||||
LGAudioBandSignal.title = "Signal";
|
||||
LGAudioBandSignal.desc = "extract the signal of some frequency";
|
||||
LiteGraph.registerNodeType("audio/signal", LGAudioBandSignal);
|
||||
|
||||
|
||||
|
||||
function LGAudioDestination()
|
||||
{
|
||||
|
||||
@@ -216,6 +216,47 @@ MathClamp.prototype.getCode = function(lang)
|
||||
LiteGraph.registerNodeType("math/clamp", MathClamp );
|
||||
|
||||
|
||||
|
||||
//Math ABS
|
||||
function MathLerp()
|
||||
{
|
||||
this.properties = { f: 0.5 };
|
||||
this.addInput("A","number");
|
||||
this.addInput("B","number");
|
||||
|
||||
this.addOutput("out","number");
|
||||
}
|
||||
|
||||
MathLerp.title = "Lerp";
|
||||
MathLerp.desc = "Linear Interpolation";
|
||||
|
||||
MathLerp.prototype.onExecute = function()
|
||||
{
|
||||
var v1 = this.getInputData(0);
|
||||
if(v1 == null)
|
||||
v1 = 0;
|
||||
var v2 = this.getInputData(1);
|
||||
if(v2 == null)
|
||||
v2 = 0;
|
||||
|
||||
var f = this.properties.f;
|
||||
|
||||
var _f = this.getInputData(2);
|
||||
if(_f !== undefined)
|
||||
f = _f;
|
||||
|
||||
this.setOutputData(0, v1 * (1-f) + v2 * f );
|
||||
}
|
||||
|
||||
MathLerp.prototype.onGetInputs = function()
|
||||
{
|
||||
return [["f","number"]];
|
||||
}
|
||||
|
||||
LiteGraph.registerNodeType("math/lerp", MathLerp);
|
||||
|
||||
|
||||
|
||||
//Math ABS
|
||||
function MathAbs()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user