Added support for midi

This commit is contained in:
RodZill4 2020-04-01 06:04:22 +02:00
parent 76e3e66a60
commit e8ff548ad6
11 changed files with 2335 additions and 76 deletions

View File

@ -29,3 +29,5 @@ vec3 hsv2rgb(vec3 c) {
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
uniform float envelope_time = 1.0;

View File

@ -88,6 +88,15 @@
"params":"t",
"slot_type":4,
"color":{ "r":1.0, "g":1.0, "b":0.0, "a":1.0 }
},
{
"name":"control",
"label":"Control",
"type":"float",
"paramdefs":"float t",
"params":"t",
"slot_type":5,
"color":{ "r":0.5, "g":1.0, "b":0.0, "a":1.0 }
},
{
"name":"any",

View File

@ -0,0 +1,17 @@
float __control(vec3 uv) {
$(code)
return $(value);
}
vec4 preview_2d(vec2 uv) {
float cmin = 1.0;
float cmax = -1.0;
for (int i = -5; i <=5; ++i) {
float c = 0.1*__control(vec3(uv.x+float(i)/5.0/preview_size));
cmin = min(c, cmin);
cmax = max(c, cmax);
}
vec2 y = vec2((0.5-uv.y)*2.1);
vec2 color = step(cmin, y+1.0/preview_size)*step(y-1.0/preview_size, smax);
return vec4(color, max(color.x, color.y), 1.0);
}

View File

@ -3,16 +3,15 @@ vec2 __sound(vec3 uv) {
return $(value);
}
void fragment() {
vec3 uv = UV.xxx;
vec4 preview_2d(vec2 uv) {
vec2 smin = vec2(1.0);
vec2 smax = vec2(-1.0);
for (int i = -5; i <=5; ++i) {
vec2 s = __sound(vec3(UV.x+float(i)/5.0/preview_size));
vec2 s = __sound(vec3(uv.x+float(i)/10.0/preview_size));
smin = min(s, smin);
smax = max(s, smax);
}
vec2 y = vec2((0.5-UV.y)*2.1);
vec2 color = step(smin, y+4.0/preview_size)*step(y-4.0/preview_size, smax);
COLOR = vec4(color, max(color.x, color.y), 1.0);
vec2 y = vec2((0.5-uv.y)*2.1);
vec2 color = step(smin, y+1.0/preview_size)*step(y-1.0/preview_size, smax);
return vec4(color, max(color.x, color.y), 1.0);
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,865 @@
{
"lib": [
{
"collapsed": false,
"tree_item": "Audio"
},
{
"collapsed": true,
"name": "audio",
"parameters": {
},
"seed_value": 57148,
"tree_item": "Audio/Out",
"type": "audio"
},
{
"collapsed": true,
"name": "206_2",
"parameters": {
"frequency": 440,
"type": 0
},
"shader_model": {
"code": "",
"global": "",
"inputs": [
],
"instance": "",
"name": "Oscillator",
"outputs": [
{
"sound": "vec2($type)",
"type": "sound"
}
],
"parameters": [
{
"default": 4,
"label": "Type",
"name": "type",
"type": "enum",
"values": [
{
"name": "Sine",
"value": "sin($frequency*$uv.x*6.28)"
},
{
"name": "Rect",
"value": "2.0*step(fract($frequency*$uv.x), 0.5)-1.0"
},
{
"name": "Sawtooth",
"value": "2.0*fract($frequency*$uv.x)-1.0"
},
{
"name": "Triangle",
"value": "4.0*abs(fract($frequency*$uv.x)-0.5)-1.0"
},
{
"name": "Noise",
"value": "2.0*fract(rand(vec2($uv.x)))-1.0"
}
]
},
{
"control": "None",
"default": 440,
"label": "Frequency",
"max": 22000,
"min": 0,
"name": "frequency",
"step": 0.1,
"type": "float"
}
]
},
"tree_item": "Audio/Oscillator",
"type": "shader"
},
{
"collapsed": true,
"name": "206_2_2_2_2_2_2",
"parameters": {
"v": 0.23
},
"shader_model": {
"code": "",
"global": "",
"inputs": [
{
"default": "vec2(0.0)",
"label": "",
"name": "in",
"type": "sound"
},
{
"default": "1.0",
"label": "",
"name": "control",
"type": "control"
}
],
"instance": "",
"name": "Volume",
"outputs": [
{
"sound": "$in($uv)*$v*$control($uv.z)",
"type": "sound"
}
],
"parameters": [
{
"control": "None",
"default": 1,
"label": "",
"max": 3,
"min": 0,
"name": "v",
"step": 0.01,
"type": "float"
}
]
},
"tree_item": "Audio/Volume",
"type": "shader"
},
{
"collapsed": true,
"name": "206_2_2_2_2_2_4_3",
"parameters": {
"b": 0
},
"seed_value": 61757,
"shader_model": {
"code": "",
"global": "",
"inputs": [
{
"default": "vec2(0.0)",
"label": "",
"name": "in",
"type": "sound"
},
{
"default": "0.0",
"label": "",
"name": "control",
"type": "control"
}
],
"instance": "",
"name": "Balance",
"outputs": [
{
"sound": "$in($uv)*clamp(vec2(1.0)-($b+$control($uv.z))*vec2(1.0, -1.0), vec2(0.0), vec2(1.0))",
"type": "sound"
}
],
"parameters": [
{
"control": "None",
"default": 0,
"label": "",
"max": 1,
"min": -1,
"name": "b",
"step": 0.01,
"type": "float"
}
]
},
"tree_item": "Audio/Balance",
"type": "shader"
},
{
"collapsed": true,
"name": "206",
"parameters": {
"attack": 0.19,
"decay": 0.7,
"release": 0.25,
"sustain": 0
},
"shader_model": {
"code": "",
"global": "float enveloppe(float time, float attack, float decay, float sustain, float release) {\n\tfloat rv = 0.0;\n\tif (time < attack) {\n\t\trv = time/attack;\n\t} else if (time < attack+decay) {\n\t\trv = 1.0-(1.0-sustain)*(time-attack)/(decay);\n\t} else if (time < envelope_time) {\n\t\trv = sustain;\n\t} else {\n\t\trv = sustain-sustain*(time-envelope_time)/(release);\n\t}\n\treturn clamp(rv, 0.0, 1.0);\n}",
"inputs": [
{
"default": "vec2(0.0)",
"label": "",
"name": "in",
"type": "sound"
}
],
"instance": "",
"name": "Envelope",
"outputs": [
{
"sound": "$in($uv)*enveloppe($uv.y, $attack, $decay, $sustain, $release)",
"type": "sound"
}
],
"parameters": [
{
"control": "None",
"default": 0.2,
"label": "Attack",
"max": 10,
"min": 0,
"name": "attack",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 0.5,
"label": "Decay",
"max": 10,
"min": 0,
"name": "decay",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 0.5,
"label": "Sustain",
"max": 1,
"min": 0,
"name": "sustain",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 2,
"label": "Release",
"max": 10,
"min": 0,
"name": "release",
"step": 0.01,
"type": "float"
}
]
},
"tree_item": "Audio/Envelope",
"type": "shader"
},
{
"collapsed": true,
"name": "206_2_2_2_2_2_4_2_3",
"parameters": {
"v1": 0.25,
"v2": 0.25,
"v3": 0.25,
"v4": 0.25
},
"seed_value": 61757,
"shader_model": {
"code": "",
"global": "",
"inputs": [
{
"default": "vec2(0.0)",
"label": "",
"name": "in1",
"type": "sound"
},
{
"default": "vec2(0.0)",
"label": "",
"name": "in2",
"type": "sound"
},
{
"default": "vec2(0.0)",
"label": "",
"name": "in3",
"type": "sound"
},
{
"default": "vec2(0.0)",
"label": "",
"name": "in4",
"type": "sound"
}
],
"instance": "",
"name": "Mix",
"outputs": [
{
"sound": " $v1*$in1($uv)+$v2*$in2($uv)+$v3*$in3($uv)+$v4*$in4($uv)",
"type": "sound"
}
],
"parameters": [
{
"control": "None",
"default": 1,
"label": "",
"max": 1,
"min": 0,
"name": "v1",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 1,
"label": "",
"max": 1,
"min": 0,
"name": "v2",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 1,
"label": "",
"max": 1,
"min": 0,
"name": "v3",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 1,
"label": "",
"max": 1,
"min": 0,
"name": "v4",
"step": 0.01,
"type": "float"
}
]
},
"tree_item": "Audio/Mix",
"type": "shader"
},
{
"collapsed": true,
"name": "206_2_2_2_2_2_4_2_2",
"parameters": {
"t": 0
},
"seed_value": 61757,
"shader_model": {
"code": "",
"global": "",
"inputs": [
{
"default": "vec2(0.0)",
"label": "",
"name": "in",
"type": "sound"
}
],
"instance": "",
"name": "Transpose",
"outputs": [
{
"sound": " $in(vec3($uv.x*pow(1.05946309436, $t), $uv.yz))",
"type": "sound"
}
],
"parameters": [
{
"control": "None",
"default": 0,
"label": "",
"max": 64,
"min": -64,
"name": "t",
"step": 1,
"type": "float"
}
]
},
"tree_item": "Audio/Transpose",
"type": "shader"
},
{
"collapsed": true,
"name": "206_2_2_2_2",
"parameters": {
"amplitude": 0.053,
"speed": 1.65
},
"shader_model": {
"code": "",
"global": "",
"inputs": [
{
"default": "vec2(0.0)",
"label": "",
"name": "in",
"type": "sound"
}
],
"instance": "",
"name": "Vibrato",
"outputs": [
{
"sound": "$in(vec3($uv.x*(1.0+0.1*$amplitude*sin($uv.y*$speed*6.28318530718)/$uv.x/$speed), $uv.yz))",
"type": "sound"
}
],
"parameters": [
{
"control": "None",
"default": 0.1,
"label": "Amplitude",
"max": 0.5,
"min": 0,
"name": "amplitude",
"step": 0.001,
"type": "float"
},
{
"control": "None",
"default": 2,
"label": "Speed",
"max": 20,
"min": 0,
"name": "speed",
"step": 0.01,
"type": "float"
}
]
},
"tree_item": "Audio/Vibrato",
"type": "shader"
},
{
"collapsed": true,
"name": "206_2_2_2_3",
"parameters": {
"detune": 0.06,
"voices": 4
},
"shader_model": {
"code": "",
"global": "",
"inputs": [
{
"default": "vec2(0.0)",
"function": true,
"label": "",
"name": "in",
"type": "sound"
}
],
"instance": "vec2 chorus_$(name)(vec3 t, int voices, float detune, float seed) {\n\tvec2 result = vec2(0.0);\n\tfor (int i = 0; i < voices; ++i) {\n\t\tseed = rand(vec2(seed, seed));\n\t\tresult += $in(vec3(t.x*(1.0+detune*(fract(seed)-0.5)), t.yz))/float(voices);\n\t}\n\treturn result;\n}",
"name": "Chorus",
"outputs": [
{
"sound": "chorus_$(name)($uv, int($voices), $detune, float($seed))",
"type": "sound"
}
],
"parameters": [
{
"control": "None",
"default": 3,
"label": "Voices",
"max": 10,
"min": 1,
"name": "voices",
"step": 1,
"type": "float"
},
{
"control": "None",
"default": 0.2,
"label": "Detune",
"max": 2,
"min": 0,
"name": "detune",
"step": 0.01,
"type": "float"
}
]
},
"tree_item": "Audio/Chorus",
"type": "shader"
},
{
"collapsed": true,
"name": "206_2_2_2_2_2_2_2_2",
"parameters": {
},
"seed_value": 47451,
"shader_model": {
"code": "",
"global": "vec2 overdrive(vec2 x) {\n\tvec2 ax = abs(x);\n\tvec2 sx = sign(x);\n\tvec2 absx3 = 3.0*ax;\n\treturn sx*mix(mix(2.0*ax, 1.0-((2.0-absx3)*(2.0-absx3))/3.0, step(vec2(1.0), absx3)), vec2(1.0), step(vec2(2.0), absx3));\n}",
"inputs": [
{
"default": "vec2(0.0)",
"label": "",
"name": "in",
"type": "sound"
}
],
"instance": "",
"name": "Overdrive",
"outputs": [
{
"sound": "overdrive($in($uv))",
"type": "sound"
}
],
"parameters": [
]
},
"tree_item": "Audio/Overdrive",
"type": "shader"
},
{
"collapsed": true,
"name": "206_2_2_2_2_2_2_2_3",
"parameters": {
"a": 0.8
},
"seed_value": 47451,
"shader_model": {
"code": "",
"global": "vec2 distorsion(vec2 x, float a) {\n\treturn sign(x)*(vec2(1.0)-pow(vec2(2.71828182846), (a*abs(x))));\n}",
"inputs": [
{
"default": "vec2(0.0)",
"label": "",
"name": "in",
"type": "sound"
},
{
"default": "1.0",
"label": "",
"name": "control",
"type": "control"
}
],
"instance": "",
"name": "Distorsion",
"outputs": [
{
"sound": "distorsion($in($uv), $control($uv.z)*$a)",
"type": "sound"
}
],
"parameters": [
{
"control": "None",
"default": 1,
"label": "",
"max": 3,
"min": 0,
"name": "a",
"step": 0.01,
"type": "float"
}
]
},
"tree_item": "Audio/Distorsion",
"type": "shader"
},
{
"collapsed": true,
"name": "206_2_2_2_2_2_4_2",
"parameters": {
"v1": 0.98,
"v2": 0.54,
"v3": 0.83,
"v4": 0.47,
"v5": 0.57,
"v6": 0.26,
"v7": 0.58,
"v8": 0.13
},
"shader_model": {
"code": "",
"global": "",
"inputs": [
{
"default": "vec2(0.0)",
"label": "",
"name": "in",
"type": "sound"
}
],
"instance": "",
"name": "Harmonics",
"outputs": [
{
"sound": " $v1*$in($uv)+$v2*$in(vec3($uv.x*2.0, $uv.yz))+$v3*$in(vec3($uv.x*3.0, $uv.yz))+$v4*$in(vec3($uv.x*4.0, $uv.yz))+$v5*$in(vec3($uv.x*5.0, $uv.yz))+$v6*$in(vec3($uv.x*6.0, $uv.yz))+$v7*$in(vec3($uv.x*7.0, $uv.yz))+$v8*$in(vec3($uv.x*8.0, $uv.yz))",
"type": "sound"
}
],
"parameters": [
{
"control": "None",
"default": 1,
"label": "1",
"max": 1,
"min": 0,
"name": "v1",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 1,
"label": "2",
"max": 1,
"min": 0,
"name": "v2",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 1,
"label": "3",
"max": 1,
"min": 0,
"name": "v3",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 1,
"label": "4",
"max": 1,
"min": 0,
"name": "v4",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 1,
"label": "5",
"max": 1,
"min": 0,
"name": "v5",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 1,
"label": "6",
"max": 1,
"min": 0,
"name": "v6",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 1,
"label": "7",
"max": 1,
"min": 0,
"name": "v7",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 1,
"label": "8",
"max": 1,
"min": 0,
"name": "v8",
"step": 0.01,
"type": "float"
}
]
},
"tree_item": "Audio/Harmonics",
"type": "shader"
},
{
"collapsed": true,
"name": "206_2_2_2_2_2_4_2_2_2_2_2_2",
"parameters": {
"a": 24,
"t": 0.15
},
"seed_value": 61757,
"shader_model": {
"code": "",
"global": "",
"inputs": [
{
"default": "vec2(0.0)",
"label": "",
"name": "in",
"type": "sound"
}
],
"instance": "",
"name": "Random notes",
"outputs": [
{
"sound": "$in(vec3($uv.x*pow(1.05946309436, floor($a*(rand(vec2(floor($uv.z/$t)))-0.5))), mod($uv.z, $t), $uv.z))",
"type": "sound"
}
],
"parameters": [
{
"control": "None",
"default": 0.5,
"label": "Note duration",
"max": 1,
"min": 0,
"name": "t",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 12,
"label": "Amplitude",
"max": 24,
"min": 0,
"name": "a",
"step": 1,
"type": "float"
}
]
},
"tree_item": "Audio/Random notes",
"type": "shader"
},
{
"collapsed": true,
"name": "1289_2",
"parameters": {
"value": 0
},
"seed_value": 26490,
"shader_model": {
"code": "",
"global": "",
"inputs": [
],
"instance": "",
"name": "Control",
"outputs": [
{
"control": "$value",
"type": "control"
}
],
"parameters": [
{
"control": "None",
"default": 0,
"label": "",
"max": 64,
"min": -64,
"name": "value",
"step": 1,
"type": "float"
}
]
},
"tree_item": "Audio/Control",
"type": "shader"
},
{
"collapsed": true,
"name": "206_2_3_2",
"parameters": {
"amplitude": 0.94,
"center": 0,
"frequency": 1,
"type": 0
},
"shader_model": {
"code": "",
"global": "",
"inputs": [
],
"instance": "",
"name": "Wave control",
"outputs": [
{
"control": "$center+$amplitude*$type",
"type": "control"
}
],
"parameters": [
{
"default": 1,
"label": "Type",
"name": "type",
"type": "enum",
"values": [
{
"name": "Sine",
"value": "sin($frequency*$uv*6.28)"
},
{
"name": "Rect",
"value": "clamp(10.0*sin($frequency*$uv*6.28), -1.0, 1.0)"
},
{
"name": "Sawtooth",
"value": "2.0*fract($frequency*$uv)-1.0"
},
{
"name": "Triangle",
"value": "4.0*abs(fract($frequency*$uv)-0.5)-1.0"
}
]
},
{
"control": "None",
"default": 1,
"label": "Frequency",
"max": 20,
"min": 0,
"name": "frequency",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 0,
"label": "Center",
"max": 10,
"min": -10,
"name": "center",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 0.5,
"label": "Amplitude",
"max": 10,
"min": 0,
"name": "amplitude",
"step": 0.01,
"type": "float"
}
]
},
"tree_item": "Audio/Control/Wave",
"type": "shader"
},
{
"collapsed": false,
"tree_item": "Simple"

View File

@ -1,11 +1,19 @@
extends MMGraphNodeBase
onready var playback = $AudioStreamPlayer.get_stream_playback()
onready var shader_material = $ViewportContainer/Viewport/ColorRect.material
var samples_played = 0
var samples_played : int
var mutex = Mutex.new()
const MIDI_VOICES = 32
func _ready():
set_process(false)
OS.open_midi_inputs()
if OS.get_connected_midi_inputs().empty():
$Midi.disabled = true
$Keyboard.visible = false
func set_generator(g) -> void:
.set_generator(g)
@ -17,28 +25,57 @@ func on_parameter_changed(p, v):
func update_shader():
var src = generator.get_source(0)
var result = { code="", sound="vec2(0.0)", globals=[] }
var result = { code="", defs="", sound="vec2(0.0)", globals=[] }
if src != null:
var context : MMGenContext = MMGenContext.new()
result = src.generator.get_shader_code("vec3(s2ttime(UV))", src.output_index, context)
result = src.generator.get_shader_code("t", src.output_index, context)
while result is GDScriptFunctionState:
result = yield(result, "completed")
var code : String = "shader_type canvas_item;\n"
code += "render_mode blend_disabled;\n"
code += mm_renderer.common_shader
code += "uniform float start_time = 0.0;\n"
code += "const float buffer_size = 64.0;\n"
code += "float s2ttime(vec2 uv) {\nreturn start_time+(floor(uv.x*buffer_size)+buffer_size*floor(uv.y*buffer_size))/44100.0;\n}\n"
code += "float s2ttime(vec2 uv, float t) {\nreturn t+(floor(uv.x*buffer_size)+buffer_size*floor(uv.y*buffer_size))/44100.0;\n}\n"
#code += "vec4 au2tex(vec2 s) {\nvec2 v = floor((0.5+0.5*s)*65536.0);\nvec2 vl = mod(v, 256.0)/255.0;\nvec2 vh = floor(v/256.0)/255.0;\nreturn vec4(vh.x, vl.x, vh.y, vl.y);\n}\n"
code += "vec4 au2tex(vec2 s) {\nreturn vec4(s.x, s.y, 0.0, 0.0);\n}\n"
code += "vec4 au2tex(vec2 s) {\nreturn vec4(s.x, s.y, 1.0, 1.0);\n}\n"
for g in result.globals:
code += g
code += "void fragment() {\n"
code += result.defs;
code += "vec2 sound(vec3 t) {\n"
code += result.code;
code += "COLOR = au2tex("+result.sound+");"
code += "return "+result.sound+";"
code += "}"
$ViewportContainer/Viewport/ColorRect.material.shader.code = code
if $Midi.pressed:
for v in range(MIDI_VOICES):
code += "uniform float voice_"+str(v)+"_velocity = 0.0;\n"
code += "uniform float voice_"+str(v)+"_time_scale = 1.0;\n"
code += "uniform float voice_"+str(v)+"_current_time = 0.0;\n"
code += "uniform float voice_"+str(v)+"_envelope_time = 0.0;\n"
code += "void fragment() {\n"
if $Midi.pressed:
code += "vec2 s = vec2(0.0);\n"
for v in range(MIDI_VOICES):
code += "s += voice_"+str(v)+"_velocity*sound(vec3(voice_"+str(v)+"_time_scale*s2ttime(UV, voice_"+str(v)+"_current_time), s2ttime(UV, voice_"+str(v)+"_envelope_time), s2ttime(UV, voice_"+str(v)+"_current_time)));"
code += "COLOR = au2tex(s);\n"
else:
code += "COLOR = au2tex(sound(vec3(s2ttime(UV, start_time))));"
code += "}"
shader_material.shader.code = code
samples_played = 0
$ViewportContainer/Viewport/ColorRect.material.set_shader_param("start_time", 0.0)
shader_material.set_shader_param("start_time", 0.0)
if $Midi.pressed:
shader_material.set_shader_param("envelope_time", 100.0)
else:
shader_material.set_shader_param("envelope_time", 1.0)
func on_float_parameters_changed(parameter_changes : Dictionary) -> void:
for n in parameter_changes.keys():
for p in VisualServer.shader_get_param_list(shader_material.shader.get_rid()):
if p.name == n:
shader_material.set_shader_param(n, parameter_changes[n])
break
func _on_Button_pressed():
if $AudioStreamPlayer.playing:
@ -48,11 +85,15 @@ func _on_Button_pressed():
else:
update_shader()
samples_played = 0
$ViewportContainer/Viewport/ColorRect.material.set_shader_param("start_time", 0.0)
shader_material.set_shader_param("start_time", 0.0)
$AudioStreamPlayer.play()
set_process(true)
$Button.text = "Stop"
func _on_Midi_toggled(button_pressed):
$Keyboard.visible = button_pressed
update_shader()
func _process(delta):
var image = $ViewportContainer/Viewport.get_texture().get_data()
var to_fill = min(playback.get_frames_available(), image.data.width*image.data.height)
@ -66,5 +107,42 @@ func _process(delta):
i += 4
samples_played += to_fill
image.unlock()
$ViewportContainer/Viewport/ColorRect.material.set_shader_param("start_time", samples_played/44100.0)
shader_material.set_shader_param("start_time", samples_played/44100.0)
var release = 0
if $Midi.pressed:
var source = generator.get_source(0)
if source != null:
if source.generator.parameters.has("release"):
release = source.generator.parameters.release
mutex.lock()
var notes = $Keyboard.notes.keys()
for v in notes:
if $Keyboard.notes[v].has("released") and $Keyboard.notes[v].envelope > 100+release:
$Keyboard.notes.erase(v)
$Keyboard.update()
notes = $Keyboard.notes.keys()
var note = 0
for v in notes:
if !$Keyboard.notes[v].has("current"):
$Keyboard.notes[v].current = 0
$Keyboard.notes[v].envelope = 0
else:
$Keyboard.notes[v].current += to_fill/44100.0
$Keyboard.notes[v].envelope += to_fill/44100.0
if $Keyboard.notes[v].has("released") and $Keyboard.notes[v].envelope == $Keyboard.notes[v].current:
$Keyboard.notes[v].envelope = 100.0
shader_material.set_shader_param("voice_"+str(note)+"_velocity", $Keyboard.notes[v].velocity/127.0)
shader_material.set_shader_param("voice_"+str(note)+"_current_time", $Keyboard.notes[v].current)
shader_material.set_shader_param("voice_"+str(note)+"_envelope_time", $Keyboard.notes[v].envelope)
shader_material.set_shader_param("voice_"+str(note)+"_time_scale", pow(1.05946309436, v-69))
note += 1
while note < MIDI_VOICES:
shader_material.set_shader_param("voice_"+str(note)+"_velocity", 0.0)
note += 1
mutex.unlock()
func _unhandled_input(event):
if event is InputEventMIDI and $AudioStreamPlayer.playing and $Midi.pressed:
mutex.lock()
$Keyboard.process_midi_event(event)
mutex.unlock()

View File

@ -1,9 +1,10 @@
[gd_scene load_steps=5 format=2]
[gd_scene load_steps=6 format=2]
[ext_resource path="res://material_maker/nodes/audio.gd" type="Script" id=1]
[ext_resource path="res://material_maker/nodes/audio_keyboard.gd" type="Script" id=2]
[sub_resource type="AudioStreamGenerator" id=1]
buffer_length = 0.1
buffer_length = 0.05
[sub_resource type="Shader" id=2]
resource_local_to_scene = true
@ -12,7 +13,9 @@ resource_local_to_scene = true
resource_local_to_scene = true
shader = SubResource( 2 )
[node name="Audio" type="GraphNode"]
[node name="Audio" type="GraphNode" groups=[
"preview",
]]
margin_right = 96.0
margin_bottom = 115.0
title = "Audio"
@ -29,6 +32,12 @@ slot/1/left_color = Color( 1, 1, 1, 1 )
slot/1/right_enabled = false
slot/1/right_type = 0
slot/1/right_color = Color( 1, 1, 1, 1 )
slot/2/left_enabled = false
slot/2/left_type = 0
slot/2/left_color = Color( 1, 1, 1, 1 )
slot/2/right_enabled = false
slot/2/right_type = 0
slot/2/right_color = Color( 1, 1, 1, 1 )
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false,
@ -42,14 +51,21 @@ margin_right = 80.0
margin_bottom = 44.0
text = "Play"
[node name="Midi" type="CheckBox" parent="."]
margin_left = 16.0
margin_top = 45.0
margin_right = 80.0
margin_bottom = 69.0
text = "MIDI"
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."]
stream = SubResource( 1 )
[node name="ViewportContainer" type="ViewportContainer" parent="."]
margin_left = 16.0
margin_top = 45.0
margin_top = 70.0
margin_right = 80.0
margin_bottom = 109.0
margin_bottom = 134.0
rect_min_size = Vector2( 64, 64 )
mouse_filter = 2
@ -70,5 +86,11 @@ rect_min_size = Vector2( 64, 64 )
[node name="Timer" type="Timer" parent="."]
wait_time = 0.1
one_shot = true
[node name="Keyboard" type="Node2D" parent="."]
visible = false
position = Vector2( -174.468, 146.693 )
script = ExtResource( 2 )
[connection signal="pressed" from="Button" to="." method="_on_Button_pressed"]
[connection signal="toggled" from="Midi" to="." method="_on_Midi_toggled"]
[connection signal="timeout" from="Timer" to="." method="update_shader"]

View File

@ -0,0 +1,29 @@
extends Node2D
var notes : Dictionary = {}
const WHITE = [0, 2, 4, 5, 7, 9, 11]
const BLACK = [1, 3, -1, 6, 8, 10, -1]
func _draw():
for i in range(52):
var color : Color = Color(1.0, 1.0, 1.0)
var index : int = WHITE[(i+5)%7]+12*((i+5)/7)
if notes.has(index):
color = Color(0.8, 0.8, 1.0)
draw_rect(Rect2(i*9, 0, 8, 30), color)
for i in range(51):
if BLACK[(i-2)%7] >= 0:
var color : Color = Color(0.0, 0.0, 0.0)
var index : int = BLACK[(i+5)%7]+12*((i+5)/7)
if notes.has(index):
color = Color(0.0, 0.0, 1.0)
draw_rect(Rect2(i*9+6, 0, 5, 15), color)
func process_midi_event(event):
match event.message:
9:
notes[event.pitch] = { velocity=event.velocity, start=OS.get_ticks_usec() }
update()
8:
notes[event.pitch].released = true

View File

@ -186,7 +186,7 @@ boot_splash/fullsize=false
boot_splash/bg_color=Color( 0.0901961, 0.0941176, 0.141176, 1 )
config/icon="res://icon.png"
config/windows_native_icon="res://icon.ico"
config/release="0.9"
config/release="0.91"
[autoload]
@ -205,6 +205,7 @@ gdscript/warnings/unsafe_call_argument=true
window/size/width=1280
window/size/height=720
window/dpi/allow_hidpi=true
window/vsync/use_vsync=false
[editor_plugins]