added more verbose error

This commit is contained in:
tamat
2017-10-30 13:44:16 +01:00
parent 0e52737808
commit 16f10e292f
8 changed files with 3143 additions and 1119 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -23,8 +23,8 @@ LGAudio.getAudioContext = function()
}
//in case it crashes
if(this._audio_context.state == "suspended")
this._audio_context.resume();
//if(this._audio_context.state == "suspended")
// this._audio_context.resume();
return this._audio_context;
}
@@ -154,8 +154,13 @@ LGAudio.onConnectionsChange = function( connection, slot, connected, link_info )
//this function helps creating wrappers to existing classes
LGAudio.createAudioNodeWrapper = function( class_object )
{
var old_func = class_object.prototype.onPropertyChanged;
class_object.prototype.onPropertyChanged = function(name, value)
{
if(old_func)
old_func.call(this,name,value);
if(!this.audionode)
return;
@@ -171,7 +176,7 @@ LGAudio.createAudioNodeWrapper = function( class_object )
class_object.prototype.onConnectionsChange = LGAudio.onConnectionsChange;
}
//contains the samples decoded of the loaded audios in AudioBuffer format
LGAudio.cached_audios = {};
LGAudio.loadSound = function( url, on_complete, on_error )
@@ -183,6 +188,9 @@ LGAudio.loadSound = function( url, on_complete, on_error )
return;
}
if( LGAudio.onProcessAudioURL )
url = LGAudio.onProcessAudioURL( url );
//load new sample
var request = new XMLHttpRequest();
request.open('GET', url, true);
@@ -226,8 +234,9 @@ function LGAudioSource()
};
this._loading_audio = false;
this._audio_buffer = null;
this._audiobuffer = null; //points to AudioBuffer with the audio samples decoded
this._audionodes = [];
this._last_sourcenode = null; //the last AudioBufferSourceNode (there could be more if there are several sounds playing)
this.addOutput( "out", "audio" );
this.addInput( "gain", "number" );
@@ -235,7 +244,7 @@ function LGAudioSource()
//init context
var context = LGAudio.getAudioContext();
//create gain node
//create gain node to control volume
this.audionode = context.createGain();
this.audionode.graphnode = this;
this.audionode.gain.value = this.properties.gain;
@@ -245,6 +254,7 @@ function LGAudioSource()
this.loadSound( this.properties.src );
}
LGAudioSource["@src"] = { widget: "resource" };
LGAudioSource.supported_extensions = ["wav","ogg","mp3"];
@@ -256,11 +266,11 @@ LGAudioSource.prototype.onAdded = function(graph)
LGAudioSource.prototype.onStart = function()
{
if(!this._audio_buffer)
if(!this._audiobuffer)
return;
if(this.properties.autoplay)
this.playBuffer( this._audio_buffer );
this.playBuffer( this._audiobuffer );
}
LGAudioSource.prototype.onStop = function()
@@ -268,6 +278,18 @@ LGAudioSource.prototype.onStop = function()
this.stopAllSounds();
}
LGAudioSource.prototype.onPause = function()
{
this.pauseAllSounds();
}
LGAudioSource.prototype.onUnpause = function()
{
this.unpauseAllSounds();
//this.onStart();
}
LGAudioSource.prototype.onRemoved = function()
{
this.stopAllSounds();
@@ -280,38 +302,62 @@ LGAudioSource.prototype.stopAllSounds = function()
//iterate and stop
for(var i = 0; i < this._audionodes.length; ++i )
{
this._audionodes[i].stop();
if(this._audionodes[i].started)
{
this._audionodes[i].started = false;
this._audionodes[i].stop();
}
//this._audionodes[i].disconnect( this.audionode );
}
this._audionodes.length = 0;
}
LGAudioSource.prototype.pauseAllSounds = function()
{
LGAudio.getAudioContext().suspend();
}
LGAudioSource.prototype.unpauseAllSounds = function()
{
LGAudio.getAudioContext().resume();
}
LGAudioSource.prototype.onExecute = function()
{
if(!this.inputs)
return;
if(this.inputs)
for(var i = 0; i < this.inputs.length; ++i)
{
var input = this.inputs[i];
if(input.link == null)
continue;
var v = this.getInputData(i);
if( v === undefined )
continue;
if( input.name == "gain" )
this.audionode.gain.value = v;
else if( input.name == "playbackRate" )
{
this.properties.playbackRate = v;
for(var j = 0; j < this._audionodes.length; ++j)
this._audionodes[j].playbackRate.value = v;
}
}
for(var i = 0; i < this.inputs.length; ++i)
{
var input = this.inputs[i];
if(!input.link)
continue;
var v = this.getInputData(i);
if( v === undefined )
continue;
if( input.name == "gain" )
this.audionode.gain.value = v;
else if( input.name == "playbackRate" )
this.properties.playbackRate = v;
}
if(this.outputs)
for(var i = 0; i < this.outputs.length; ++i)
{
var output = this.outputs[i];
if( output.name == "buffer" && this._audiobuffer )
this.setOutputData( i, this._audiobuffer );
}
}
LGAudioSource.prototype.onAction = function(event)
{
if(this._audio_buffer)
if(this._audiobuffer)
{
if(event == "Play")
this.playBuffer(this._audio_buffer);
this.playBuffer(this._audiobuffer);
else if(event == "Stop")
this.stopAllSounds();
}
@@ -323,6 +369,11 @@ LGAudioSource.prototype.onPropertyChanged = function( name, value )
this.loadSound( value );
else if(name == "gain")
this.audionode.gain.value = value;
else if(name == "playbackRate")
{
for(var j = 0; j < this._audionodes.length; ++j)
this._audionodes[j].playbackRate.value = value;
}
}
LGAudioSource.prototype.playBuffer = function( buffer )
@@ -332,6 +383,7 @@ LGAudioSource.prototype.playBuffer = function( buffer )
//create a new audionode (this is mandatory, AudioAPI doesnt like to reuse old ones)
var audionode = context.createBufferSource(); //create a AudioBufferSourceNode
this._last_sourcenode = audionode;
audionode.graphnode = this;
audionode.buffer = buffer;
audionode.loop = this.properties.loop;
@@ -350,7 +402,11 @@ LGAudioSource.prototype.playBuffer = function( buffer )
that._audionodes.splice(index,1);
}
audionode.start();
if(!audionode.started)
{
audionode.started = true;
audionode.start();
}
return audionode;
}
@@ -365,7 +421,7 @@ LGAudioSource.prototype.loadSound = function( url )
this._request = null;
}
this._audio_buffer = null;
this._audiobuffer = null; //points to the audiobuffer once the audio is loaded
this._loading_audio = false;
if(!url)
@@ -379,7 +435,7 @@ LGAudioSource.prototype.loadSound = function( url )
function inner( buffer )
{
this.boxcolor = LiteGraph.NODE_DEFAULT_BOXCOLOR;
that._audio_buffer = buffer;
that._audiobuffer = buffer;
that._loading_audio = false;
//if is playing, then play it
if(that.graph && that.graph.status === LGraph.STATUS_RUNNING)
@@ -397,7 +453,7 @@ LGAudioSource.prototype.onGetInputs = function()
LGAudioSource.prototype.onGetOutputs = function()
{
return [["ended",LiteGraph.EVENT]];
return [["buffer","audiobuffer"],["ended",LiteGraph.EVENT]];
}
LGAudioSource.prototype.onDropFile = function(file)
@@ -438,7 +494,7 @@ function LGAudioAnalyser()
this.addInput("in","audio");
this.addOutput("freqs","array");
//this.addOutput("time","freq");
this.addOutput("samples","array");
this._freq_bin = null;
this._time_bin = null;
@@ -463,14 +519,21 @@ LGAudioAnalyser.prototype.onExecute = function()
//send analyzer
if(this.isOutputConnected(1))
this.setOutputData(1,this.audionode);
{
//send Samples
var bufferLength = this.audionode.frequencyBinCount;
if( !this._time_bin || this._time_bin.length != bufferLength )
this._time_bin = new Uint8Array( bufferLength );
this.audionode.getByteTimeDomainData( this._time_bin );
this.setOutputData(1,this._time_bin);
}
//properties
for(var i = 1; i < this.inputs.length; ++i)
{
var input = this.inputs[i];
if(!input.link)
if(input.link == null)
continue;
var v = this.getInputData(i);
if (v !== undefined)
@@ -488,12 +551,11 @@ LGAudioAnalyser.prototype.onGetInputs = function()
return [["minDecibels","number"],["maxDecibels","number"],["smoothingTimeConstant","number"]];
}
/*
LGAudioAnalyser.prototype.onGetOutputs = function()
{
return [["Analyzer","analyzer"]];
return [["freqs","array"],["samples","array"]];
}
*/
LGAudioAnalyser.title = "Analyser";
LGAudioAnalyser.desc = "Audio Analyser";
@@ -634,7 +696,7 @@ LGAudioDynamicsCompressor.prototype.onExecute = function()
for(var i = 1; i < this.inputs.length; ++i)
{
var input = this.inputs[i];
if(!input.link)
if(input.link == null)
continue;
var v = this.getInputData(i);
if(v !== undefined)
@@ -721,6 +783,15 @@ LGAudioMixer.prototype.getAudioNodeInInputSlot = function( slot )
return this.audionode2;
}
LGAudioMixer.prototype.onPropertyChanged = function( name, value )
{
if( name == "gain1" )
this.audionode1.gain.value = value;
else if( name == "gain2" )
this.audionode2.gain.value = value;
}
LGAudioMixer.prototype.onExecute = function()
{
if(!this.inputs || !this.inputs.length)
@@ -730,7 +801,7 @@ LGAudioMixer.prototype.onExecute = function()
{
var input = this.inputs[i];
if(!input.link || input.type == "audio")
if(input.link == null || input.type == "audio")
continue;
var v = this.getInputData(i);
@@ -805,7 +876,7 @@ LGAudioBiquadFilter.prototype.onExecute = function()
for(var i = 1; i < this.inputs.length; ++i)
{
var input = this.inputs[i];
if(!input.link)
if(input.link == null)
continue;
var v = this.getInputData(i);
if(v !== undefined)
@@ -825,6 +896,81 @@ LGAudioBiquadFilter.desc = "Audio filter";
LiteGraph.registerNodeType("audio/biquadfilter", LGAudioBiquadFilter);
function LGAudioOscillatorNode()
{
//default
this.properties = {
frequency: 440,
detune: 0,
type: "sine"
};
this.addProperty("type","sine","enum",{values:["sine","square","sawtooth","triangle","custom"]});
//create node
this.audionode = LGAudio.getAudioContext().createOscillator();
//slots
this.addOutput("out","audio");
}
LGAudioOscillatorNode.prototype.onStart = function()
{
if(!this.audionode.started)
{
this.audionode.started = true;
this.audionode.start();
}
}
LGAudioOscillatorNode.prototype.onStop = function()
{
if(this.audionode.started)
{
this.audionode.started = false;
this.audionode.stop();
}
}
LGAudioOscillatorNode.prototype.onPause = function()
{
this.onStop();
}
LGAudioOscillatorNode.prototype.onUnpause = function()
{
this.onStart();
}
LGAudioOscillatorNode.prototype.onExecute = function()
{
if(!this.inputs || !this.inputs.length)
return;
for(var i = 0; i < this.inputs.length; ++i)
{
var input = this.inputs[i];
if(input.link == null)
continue;
var v = this.getInputData(i);
if(v !== undefined)
this.audionode[ input.name ].value = v;
}
}
LGAudioOscillatorNode.prototype.onGetInputs = function()
{
return [["frequency","number"],["detune","number"],["type","string"]];
}
LGAudio.createAudioNodeWrapper( LGAudioOscillatorNode );
LGAudioOscillatorNode.title = "Oscillator";
LGAudioOscillatorNode.desc = "Oscillator";
LiteGraph.registerNodeType("audio/oscillator", LGAudioOscillatorNode);
//*****************************************************
//EXTRA
@@ -837,7 +983,7 @@ function LGAudioVisualization()
mark: -1
};
this.addInput("freqs","array");
this.addInput("data","array");
this.addInput("mark","number");
this.size = [300,200];
this._last_buffer = null;
@@ -962,6 +1108,137 @@ LGAudioBandSignal.desc = "extract the signal of some frequency";
LiteGraph.registerNodeType("audio/signal", LGAudioBandSignal);
function LGAudioScript()
{
if(!LGAudioScript.default_code)
{
var code = LGAudioScript.default_function.toString();
var index = code.indexOf("{")+1;
var index2 = code.lastIndexOf("}");
LGAudioScript.default_code = code.substr(index, index2 - index);
}
//default
this.properties = {
code: LGAudioScript.default_code
};
//create node
var ctx = LGAudio.getAudioContext();
if(ctx.createScriptProcessor)
this.audionode = ctx.createScriptProcessor(4096,1,1); //buffer size, input channels, output channels
else
{
console.warn("ScriptProcessorNode deprecated");
this.audionode = ctx.createGain(); //bypass audio
}
this.processCode();
if(!LGAudioScript._bypass_function)
LGAudioScript._bypass_function = this.audionode.onaudioprocess;
//slots
this.addInput("in","audio");
this.addOutput("out","audio");
}
LGAudioScript.prototype.onAdded = function( graph )
{
if(graph.status == LGraph.STATUS_RUNNING)
this.audionode.onaudioprocess = this._callback;
}
LGAudioScript["@code"] = { widget: "code" };
LGAudioScript.prototype.onStart = function()
{
this.audionode.onaudioprocess = this._callback;
}
LGAudioScript.prototype.onStop = function()
{
this.audionode.onaudioprocess = LGAudioScript._bypass_function;
}
LGAudioScript.prototype.onPause = function()
{
this.audionode.onaudioprocess = LGAudioScript._bypass_function;
}
LGAudioScript.prototype.onUnpause = function()
{
this.audionode.onaudioprocess = this._callback;
}
LGAudioScript.prototype.onExecute = function()
{
//nothing! because we need an onExecute to receive onStart... fix that
}
LGAudioScript.prototype.onRemoved = function()
{
this.audionode.onaudioprocess = LGAudioScript._bypass_function;
}
LGAudioScript.prototype.processCode = function()
{
try
{
var func = new Function( "properties", this.properties.code );
this._script = new func( this.properties );
this._old_code = this.properties.code;
this._callback = this._script.onaudioprocess;
}
catch (err)
{
console.error("Error in onaudioprocess code",err);
this._callback = LGAudioScript._bypass_function;
this.audionode.onaudioprocess = this._callback;
}
}
LGAudioScript.prototype.onPropertyChanged = function( name, value )
{
if(name == "code")
{
this.properties.code = value;
this.processCode();
if(this.graph && this.graph.status == LGraph.STATUS_RUNNING)
this.audionode.onaudioprocess = this._callback;
}
}
LGAudioScript.default_function = function()
{
this.onaudioprocess = function(audioProcessingEvent) {
// The input buffer is the song we loaded earlier
var inputBuffer = audioProcessingEvent.inputBuffer;
// The output buffer contains the samples that will be modified and played
var outputBuffer = audioProcessingEvent.outputBuffer;
// Loop through the output channels (in this case there is only one)
for (var channel = 0; channel < outputBuffer.numberOfChannels; channel++) {
var inputData = inputBuffer.getChannelData(channel);
var outputData = outputBuffer.getChannelData(channel);
// Loop through the 4096 samples
for (var sample = 0; sample < inputBuffer.length; sample++) {
// make output equal to the same as the input
outputData[sample] = inputData[sample];
}
}
}
}
LGAudio.createAudioNodeWrapper( LGAudioScript );
LGAudioScript.title = "Script";
LGAudioScript.desc = "apply script to signal";
LiteGraph.registerNodeType("audio/script", LGAudioScript);
function LGAudioDestination()
{

View File

@@ -389,7 +389,7 @@ Console.prototype.onAction = function(action, param)
Console.prototype.onExecute = function()
{
var msg = this.getInputData(0);
var msg = this.getInputData(1);
if(msg !== null)
this.properties.msg = msg;
console.log(msg);
@@ -403,4 +403,62 @@ Console.prototype.onGetInputs = function()
LiteGraph.registerNodeType("basic/console", Console );
//Show value inside the debug console
function NodeScript()
{
this.size = [60,20];
this.addProperty( "onExecute", "" );
this.addInput("in", "");
this.addInput("in2", "");
this.addOutput("out", "");
this.addOutput("out2", "");
this._func = null;
}
NodeScript.title = "Script";
NodeScript.desc = "executes a code";
NodeScript.widgets_info = {
"onExecute": { type:"code" }
};
NodeScript.prototype.onPropertyChanged = function(name,value)
{
if(name == "onExecute" && LiteGraph.allow_scripts )
{
this._func = null;
try
{
this._func = new Function( value );
}
catch (err)
{
console.error("Error parsing script");
console.error(err);
}
}
}
NodeScript.prototype.onExecute = function()
{
if(!this._func)
return;
try
{
this._func.call(this);
}
catch (err)
{
console.error("Error in script");
console.error(err);
}
}
LiteGraph.registerNodeType("basic/script", NodeScript );
})();

View File

@@ -306,17 +306,19 @@ if(typeof(LiteGraph) != "undefined")
LGraphTexturePreview.title = "Preview";
LGraphTexturePreview.desc = "Show a texture in the graph canvas";
LGraphTexturePreview.allow_preview = false;
LGraphTexturePreview.prototype.onDrawBackground = function(ctx)
{
if(this.flags.collapsed)
return;
if(!ctx.webgl)
if(!ctx.webgl && !LGraphTexturePreview.allow_preview)
return; //not working well
var tex = this.getInputData(0);
if(!tex) return;
if(!tex)
return;
var tex_canvas = null;
@@ -353,12 +355,19 @@ if(typeof(LiteGraph) != "undefined")
LGraphTextureSave.prototype.onExecute = function()
{
var tex = this.getInputData(0);
if(!tex) return;
if(!tex)
return;
if(this.properties.name)
{
var container = LGraphTexture.getTexturesContainer();
container[ this.properties.name ] = tex;
//for cases where we want to perform something when storing it
if( LGraphTexture.storeTexture )
LGraphTexture.storeTexture( this.properties.name, tex );
else
{
var container = LGraphTexture.getTexturesContainer();
container[ this.properties.name ] = tex;
}
}
this.setOutputData(0, tex);
@@ -564,7 +573,7 @@ if(typeof(LiteGraph) != "undefined")
this.addOutput("Texture","Texture");
this.properties = {code:"", width: 512, height: 512};
this.properties.code = "\nvoid main() {\n vec2 uv = coord;\n vec3 color = vec3(0.0);\n//your code here\n\ngl_FragColor = vec4(color, 1.0);\n}\n";
this.properties.code = "\nvoid main() {\n vec2 uv = v_coord;\n vec3 color = vec3(0.0);\n//your code here\n\ngl_FragColor = vec4(color, 1.0);\n}\n";
}
LGraphTextureShader.title = "Shader";
@@ -574,65 +583,133 @@ if(typeof(LiteGraph) != "undefined")
"precision": { widget:"combo", values: LGraphTexture.MODE_VALUES }
};
LGraphTextureShader.prototype.onPropertyChanged = function(name, value)
{
if(name != "code")
return;
var shader = this.getShader();
if(!shader)
return;
//update connections
var uniforms = shader.uniformInfo;
//remove deprecated slots
if(this.inputs)
{
var already = {};
for(var i = 0; i < this.inputs.length; ++i)
{
var info = this.getInputInfo(i);
if(!info)
continue;
if( uniforms[ info.name ] && !already[ info.name ] )
{
already[ info.name ] = true;
continue;
}
this.removeInput(i);
i--;
}
}
//update existing ones
for(var i in uniforms)
{
var info = shader.uniformInfo[i];
if(info.loc === null)
continue; //is an attribute, not a uniform
if(i == "time") //default one
continue;
var type = "number";
if( this._shader.samplers[i] )
type = "texture";
else
{
switch(info.size)
{
case 1: type = "number"; break;
case 2: type = "vec2"; break;
case 3: type = "vec3"; break;
case 4: type = "vec4"; break;
case 9: type = "mat3"; break;
case 16: type = "mat4"; break;
default: continue;
}
}
var slot = this.findInputSlot(i);
if(slot == -1)
{
this.addInput(i,type);
continue;
}
var input_info = this.getInputInfo(slot);
if(!input_info)
this.addInput(i,type);
else
{
if(input_info.type == type)
continue;
this.removeInput(slot,type);
this.addInput(i,type);
}
}
}
LGraphTextureShader.prototype.getShader = function()
{
//replug
if(this._shader && this._shader_code == this.properties.code)
return this._shader;
this._shader_code = this.properties.code;
this._shader = new GL.Shader(Shader.SCREEN_VERTEX_SHADER, LGraphTextureShader.pixel_shader + this.properties.code );
if(!this._shader) {
this.boxcolor = "red";
return null;
}
else
this.boxcolor = "green";
return this._shader;
}
LGraphTextureShader.prototype.onExecute = function()
{
if(!this.isOutputConnected(0))
return; //saves work
//replug
if(this._shader_code != this.properties.code)
{
this._shader_code = this.properties.code;
this._shader = new GL.Shader(Shader.SCREEN_VERTEX_SHADER, LGraphTextureShader.pixel_shader + this.properties.code );
if(!this._shader) {
this.boxcolor = "red";
return;
}
else
this.boxcolor = "green";
/*
var uniforms = this._shader.uniformLocations;
//disconnect inputs
if(this.inputs)
for(var i = 0; i < this.inputs.length; i++)
{
var slot = this.inputs[i];
if(slot.link != null)
this.disconnectInput(i);
}
var shader = this.getShader();
if(!shader)
return;
for(var i = 0; i < uniforms.length; i++)
var tex_slot = 0;
//set uniforms
for(var i = 0; i < this.inputs.length; ++i)
{
var info = this.getInputInfo(i);
var data = this.getInputData(i);
if(data == null)
continue;
if(data.constructor === GL.Texture)
{
var type = "number";
if( this._shader.isSampler[i] )
type = "texture";
else
{
var v = gl.getUniform(this._shader.program, i);
type = typeof(v);
if(type == "object" && v.length)
{
switch(v.length)
{
case 1: type = "number"; break;
case 2: type = "vec2"; break;
case 3: type = "vec3"; break;
case 4: type = "vec4"; break;
case 9: type = "mat3"; break;
case 16: type = "mat4"; break;
default: continue;
}
}
}
this.addInput(i,type);
data.bind(slot);
data = slot;
slot++;
}
*/
shader.setUniform( info.name, data );
}
//render to texture
if(!this._tex || this._tex.width != this.properties.width || this._tex.height != this.properties.height )
this._tex = new GL.Texture( this.properties.width, this.properties.height, { format: gl.RGBA, filter: gl.LINEAR });
var tex = this._tex;
var shader = this._shader;
var time = this.graph.getTime();
tex.drawTo(function() {
shader.uniforms({texSize: [tex.width, tex.height], time: time}).draw( Mesh.getScreenQuad() );
@@ -830,7 +907,7 @@ if(typeof(LiteGraph) != "undefined")
\n\
void main() {\n\
vec2 uv = v_coord;\n\
uv += texture2D(u_textureB, uv).rg * u_factor;\n\
uv += ( texture2D(u_textureB, uv).rg - vec2(0.5)) * u_factor;\n\
gl_FragColor = texture2D(u_texture, uv);\n\
}\n\
";
@@ -1046,16 +1123,127 @@ if(typeof(LiteGraph) != "undefined")
LiteGraph.registerNodeType("texture/copy", LGraphTextureCopy );
// Texture Downsample *****************************************
function LGraphTextureDownsample()
{
this.addInput("Texture","Texture");
this.addOutput("","Texture");
this.properties = { iterations: 1, generate_mipmaps: false, precision: LGraphTexture.DEFAULT };
}
LGraphTextureDownsample.title = "Downsample";
LGraphTextureDownsample.desc = "Downsample Texture";
LGraphTextureDownsample.widgets_info = {
iterations: { type:"number", step: 1, precision: 0, min: 1 },
precision: { widget:"combo", values: LGraphTexture.MODE_VALUES }
};
LGraphTextureDownsample.prototype.onExecute = function()
{
var tex = this.getInputData(0);
if(!tex && !this._temp_texture)
return;
if(!this.isOutputConnected(0))
return; //saves work
//we do not allow any texture different than texture 2D
if(!tex || tex.texture_type !== GL.TEXTURE_2D )
return;
var shader = LGraphTextureDownsample._shader;
if(!shader)
LGraphTextureDownsample._shader = shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTextureDownsample.pixel_shader );
var width = tex.width|0;
var height = tex.height|0;
var type = tex.type;
if(this.properties.precision === LGraphTexture.LOW)
type = gl.UNSIGNED_BYTE;
else if(this.properties.precision === LGraphTexture.HIGH)
type = gl.HIGH_PRECISION_FORMAT;
var iterations = this.properties.iterations || 1;
var origin = tex;
var target = null;
var temp = [];
var options = {
type: type,
format: tex.format
};
var offset = vec2.create();
var uniforms = {
u_offset: offset
};
if( this._texture )
GL.Texture.releaseTemporary( this._texture );
for(var i = 0; i < iterations; ++i)
{
offset[0] = 1/width;
offset[1] = 1/height;
width = width>>1 || 0;
height = height>>1 || 0;
target = GL.Texture.getTemporary( width, height, options );
temp.push( target );
origin.setParameter( GL.TEXTURE_MAG_FILTER, GL.NEAREST );
origin.copyTo( target, shader, uniforms );
if(width == 1 && height == 1)
break; //nothing else to do
origin = target;
}
//keep the last texture used
this._texture = temp.pop();
//free the rest
for(var i = 0; i < temp.length; ++i)
GL.Texture.releaseTemporary( temp[i] );
if(this.properties.generate_mipmaps)
{
this._texture.bind(0);
gl.generateMipmap(this._texture.texture_type);
this._texture.unbind(0);
}
this.setOutputData(0,this._texture);
}
LGraphTextureDownsample.pixel_shader = "precision highp float;\n\
precision highp float;\n\
uniform sampler2D u_texture;\n\
uniform vec2 u_offset;\n\
varying vec2 v_coord;\n\
\n\
void main() {\n\
vec4 color = texture2D(u_texture, v_coord );\n\
color += texture2D(u_texture, v_coord + vec2( u_offset.x, 0.0 ) );\n\
color += texture2D(u_texture, v_coord + vec2( 0.0, u_offset.y ) );\n\
color += texture2D(u_texture, v_coord + vec2( u_offset.x, u_offset.y ) );\n\
gl_FragColor = color * 0.25;\n\
}\n\
";
LiteGraph.registerNodeType("texture/downsample", LGraphTextureDownsample );
// Texture Copy *****************************************
function LGraphTextureAverage()
{
this.addInput("Texture","Texture");
this.addOutput("","Texture");
this.properties = { low_precision: false };
this.properties = { mipmap_offset: 0, low_precision: false };
this._uniforms = { u_texture: 0, u_mipmap_offset: this.properties.mipmap_offset };
}
LGraphTextureAverage.title = "Average";
LGraphTextureAverage.desc = "Compute the total average of a texture and stores it as a 1x1 pixel texture";
LGraphTextureAverage.desc = "Compute a partial average (32 random samples) of a texture and stores it as a 1x1 pixel texture";
LGraphTextureAverage.prototype.onExecute = function()
{
@@ -1068,7 +1256,8 @@ if(typeof(LiteGraph) != "undefined")
if(!LGraphTextureAverage._shader)
{
LGraphTextureAverage._shader = new GL.Shader(Shader.SCREEN_VERTEX_SHADER, LGraphTextureAverage.pixel_shader);
LGraphTextureAverage._shader = new GL.Shader( GL.Shader.SCREEN_VERTEX_SHADER, LGraphTextureAverage.pixel_shader);
//creates 32 random numbers and stores the, in two mat4
var samples = new Float32Array(32);
for(var i = 0; i < 32; ++i)
samples[i] = Math.random();
@@ -1081,8 +1270,10 @@ if(typeof(LiteGraph) != "undefined")
this._temp_texture = new GL.Texture( 1, 1, { type: type, format: gl.RGBA, filter: gl.NEAREST });
var shader = LGraphTextureAverage._shader;
var uniforms = this._uniforms;
uniforms.u_mipmap_offset = this.properties.mipmap_offset;
this._temp_texture.drawTo(function(){
tex.toViewport(shader,{u_texture:0});
tex.toViewport( shader, uniforms );
});
this.setOutputData(0,this._temp_texture);
@@ -1093,6 +1284,7 @@ if(typeof(LiteGraph) != "undefined")
uniform mat4 u_samples_a;\n\
uniform mat4 u_samples_b;\n\
uniform sampler2D u_texture;\n\
uniform float u_mipmap_offset;\n\
varying vec2 v_coord;\n\
\n\
void main() {\n\
@@ -1100,8 +1292,8 @@ if(typeof(LiteGraph) != "undefined")
for(int i = 0; i < 4; ++i)\n\
for(int j = 0; j < 4; ++j)\n\
{\n\
color += texture2D(u_texture, vec2( u_samples_a[i][j], u_samples_b[i][j] ) );\n\
color += texture2D(u_texture, vec2( 1.0 - u_samples_a[i][j], u_samples_b[i][j] ) );\n\
color += texture2D(u_texture, vec2( u_samples_a[i][j], u_samples_b[i][j] ), u_mipmap_offset );\n\
color += texture2D(u_texture, vec2( 1.0 - u_samples_a[i][j], 1.0 - u_samples_b[i][j] ), u_mipmap_offset );\n\
}\n\
gl_FragColor = color * 0.03125;\n\
}\n\
@@ -2193,6 +2385,8 @@ LGraphTextureKuwaharaFilter.pixel_shader = "\n\
this.size = [LGraphTexture.image_preview_size, LGraphTexture.image_preview_size];
}
LGraphCubemap.title = "Cubemap";
LGraphCubemap.prototype.onDropFile = function(data, filename, file)
{
if(!data)

View File

@@ -61,6 +61,15 @@ MIDIEvent.computePitch = function( note )
return Math.pow(2, (note - 69) / 12 ) * 440;
}
MIDIEvent.prototype.getCC = function()
{
return this.data[1];
}
MIDIEvent.prototype.getCCValue = function()
{
return this.data[2];
}
//not tested, there is a formula missing here
MIDIEvent.prototype.getPitchBend = function()
@@ -188,9 +197,18 @@ function MIDIInterface( on_ready, on_error )
this.on_ready = on_ready;
this.state = {
note: [],
cc: []
};
navigator.requestMIDIAccess().then( this.onMIDISuccess.bind(this), this.onMIDIFailure.bind(this) );
}
MIDIInterface.input = null;
MIDIInterface.MIDIEvent = MIDIEvent;
MIDIInterface.prototype.onMIDISuccess = function(midiAccess)
@@ -209,8 +227,41 @@ MIDIInterface.prototype.updatePorts = function()
var midi = this.midi;
this.input_ports = midi.inputs;
var num = 0;
var it = this.input_ports.values();
var it_value = it.next();
while( it_value && it_value.done === false )
{
var port_info = it_value.value;
console.log( "Input port [type:'" + port_info.type + "'] id:'" + port_info.id +
"' manufacturer:'" + port_info.manufacturer + "' name:'" + port_info.name +
"' version:'" + port_info.version + "'" );
num++;
it_value = it.next();
}
this.num_input_ports = num;
num = 0;
this.output_ports = midi.outputs;
var it = this.output_ports.values();
var it_value = it.next();
while( it_value && it_value.done === false )
{
var port_info = it_value.value;
console.log( "Output port [type:'" + port_info.type + "'] id:'" + port_info.id +
"' manufacturer:'" + port_info.manufacturer + "' name:'" + port_info.name +
"' version:'" + port_info.version + "'" );
num++;
it_value = it.next();
}
this.num_output_ports = num;
/* OLD WAY
for (var i = 0; i < this.input_ports.size; ++i) {
var input = this.input_ports.get(i);
if(!input)
continue; //sometimes it is null?!
console.log( "Input port [type:'" + input.type + "'] id:'" + input.id +
"' manufacturer:'" + input.manufacturer + "' name:'" + input.name +
"' version:'" + input.version + "'" );
@@ -223,12 +274,15 @@ MIDIInterface.prototype.updatePorts = function()
this.output_ports = midi.outputs;
for (var i = 0; i < this.output_ports.size; ++i) {
var output = this.output_ports.get(i);
if(!output)
continue;
console.log( "Output port [type:'" + output.type + "'] id:'" + output.id +
"' manufacturer:'" + output.manufacturer + "' name:'" + output.name +
"' version:'" + output.version + "'" );
num++;
}
this.num_output_ports = num;
*/
}
MIDIInterface.prototype.onMIDIFailure = function(msg)
@@ -236,14 +290,17 @@ MIDIInterface.prototype.onMIDIFailure = function(msg)
console.error( "Failed to get MIDI access - " + msg );
}
MIDIInterface.prototype.openInputPort = function( port, callback)
MIDIInterface.prototype.openInputPort = function( port, callback )
{
var input_port = this.input_ports.get( port );
var input_port = this.input_ports.get( "input-" + port );
if(!input_port)
return false;
MIDIInterface.input = this;
var that = this;
input_port.onmidimessage = function(a) {
var midi_event = new MIDIEvent(a.data);
that.updateState( midi_event );
if(callback)
callback(a.data, midi_event );
if(MIDIInterface.on_message)
@@ -258,15 +315,27 @@ MIDIInterface.parseMsg = function(data)
}
MIDIInterface.prototype.updateState = function( midi_event )
{
switch( midi_event.cmd )
{
case MIDIEvent.NOTEON: this.state.note[ midi_event.value1|0 ] = midi_event.value2; break;
case MIDIEvent.NOTEOFF: this.state.note[ midi_event.value1|0 ] = 0; break;
case MIDIEvent.CONTROLLERCHANGE: this.state.cc[ midi_event.getCC() ] = midi_event.getCCValue(); break;
}
}
MIDIInterface.prototype.sendMIDI = function( port, midi_data )
{
if( !midi_data )
return;
var output_port = this.output_ports.get(port);
var output_port = this.output_ports.get( "output-" + port );
if(!output_port)
return;
MIDIInterface.output = this;
if( midi_data.constructor === MIDIEvent)
output_port.send( midi_data.data );
else
@@ -308,7 +377,7 @@ LGMIDIIn.prototype.getPropertyInfo = function(name)
var values = {};
for (var i = 0; i < this._midi.input_ports.size; ++i)
{
var input = this._midi.input_ports.get(i);
var input = this._midi.input_ports.get( "input-" + i);
values[i] = i + ".- " + input.name + " version:" + input.version;
}
return { type: "enum", values: values };
@@ -351,6 +420,7 @@ LGMIDIIn.prototype.onExecute = function()
var v = null;
switch (output.name)
{
case "midi": v = this._midi; break;
case "last_midi": v = last; break;
default:
continue;
@@ -565,8 +635,10 @@ LGMIDIEvent.prototype.onExecute = function()
v.channel = props.channel;
break;
case "command": v = props.cmd; break;
case "note": v = (props.cmd == MIDIEvent.NOTEON || props.cmd == MIDIEvent.NOTEOFF) ? props.value1 : NULL; break;
case "velocity": v = props.cmd == MIDIEvent.NOTEON ? props.value2 : NULL; break;
case "cc": v = props.value1; break;
case "cc_value": v = props.value2; break;
case "note": v = (props.cmd == MIDIEvent.NOTEON || props.cmd == MIDIEvent.NOTEOFF) ? props.value1 : null; break;
case "velocity": v = props.cmd == MIDIEvent.NOTEON ? props.value2 : null; break;
case "pitch": v = props.cmd == MIDIEvent.NOTEON ? MIDIEvent.computePitch( props.value1 ) : null; break;
case "pitchbend": v = props.cmd == MIDIEvent.PITCHBEND ? MIDIEvent.computePitchBend( props.value1, props.value2 ) : null; break;
default:
@@ -592,6 +664,8 @@ LGMIDIEvent.prototype.onGetOutputs = function() {
["command","number"],
["note","number"],
["velocity","number"],
["cc","number"],
["cc_value","number"],
["pitch","number"],
["pitchbend","number"]
];
@@ -601,6 +675,31 @@ LGMIDIEvent.prototype.onGetOutputs = function() {
LiteGraph.registerNodeType("midi/event", LGMIDIEvent);
function LGMIDICC()
{
this.properties = {
// channel: 0,
cc: 1,
value: 0
};
this.addOutput( "value", "number" );
}
LGMIDICC.title = "MIDICC";
LGMIDICC.desc = "gets a Controller Change";
LGMIDICC.prototype.onExecute = function()
{
var props = this.properties;
if( MIDIInterface.input )
this.properties.value = MIDIInterface.input.state.cc[ this.properties.cc ];
this.setOutputData( 0, this.properties.value );
}
LiteGraph.registerNodeType("midi/cc", LGMIDICC);
function now() { return window.performance.now() }