float adsr(float t, vec4 v, float s) { v.xyw = max(vec3(2.2e-05), v.xyw); // attack term float ta = t/v.x; // decay / sustain amplitude term float td = max(s, 1.0-(t-v.x)*(1.0-s)/v.y); // length / release term float tr = (1.0 - max(0.0,t-(v.x+v.y+v.z))/v.w); return max(0.0, min(ta, tr*td)); } void main () { float l = 0.; float r = 0.; vec2 uv = gl_FragCoord.xy / resolution; vec4 t = texture(iInput0, vec2(globalTime * 16. + uv.x, uv.y)); vec4 f = texture(pFrame, vec2(uv.x, uv.y+(sin(globalTime * 64.)/3.1415/6644.))); float attenuation_constant = 1.95; const float harmonics = 62.; vec4 arr[8] = vec4[8](vec4(0.75, 0.25, 0., 0.), vec4(0.75, 0.5, 0., 0.), vec4(0.2, 0.72, 0., 0.), vec4(0.2, 0.75, 0., 0.), vec4(0.57, 0.2, 0., 0.), vec4(0., 0.75, 0., 0.), vec4(0.25, 0.5, 0., 0.), vec4(0.25, 0.5, 0., 0.)); for (int k = 0; k < 8; k += 1) { vec4 data = keyboard[k]; float kfrq = data.x; float kvel = data.y; float ktim = data.z; float kchn = data.w; vec3 pdata = pKey[0]; float pkfrq = pdata.x; float pkvel = pdata.y; float pktim = pdata.z; if (kfrq == 0.) { break; } if (kchn == 0. && uv.x < 0.5) { vec4 t = texture(iInput0, vec2(ktim/8.,uv.y)); float kktim = abs(mod(ktim*8., 2.) - 1.); kfrq = mix(pkfrq, kfrq, min(ktim *49. + sin(ktim)*16., 1.)); float u = abs((tanh(ktim * 62.) * (cos(ktim * 64.) / 3.1415)) * .75); for (float i = 1.; i < harmonics; i += (2.)) { float a = 1. / pow(i - u, attenuation_constant * 0.805); float a2 = 1. / (pow(i, attenuation_constant * (0.06555+ abs(sin(kktim*8./i/(sin(globalTime / 180.))))*10.5)) / tan(kktim * ((i/(abs(sin(globalTime / 64.)) / 100.)) / 2.))); float mix_f = 0.5 * (1. - abs(tan(kktim/8.+1.4/cos((i*8.) - i / 18.) - 1.))); vec4 lc = arr[int(i+7. + globalTime * 64.) % 8]; float attack = .25 + abs(sin(i * mix_f) / 8.); float decay = 1. / mix_f * i/8.; float sustain = 0.; float release = 8.25; float decay_amp = 0.35; float env = kvel * adsr(ktim, vec4(attack, decay, sustain, release), decay_amp); float al = mix(a, a2, mix_f); l += fline(kfrq * i) * (al * env)*a*lc.r; r += fline(kfrq * i) * (al * env)*a*lc.g; } } else if (kchn == 1. && uv.x > 0.5) { vec4 t = texture(iInput0, vec2(ktim/ 4.,uv.y)); float kktim = abs(mod(ktim*20., 2.) - 1.); kfrq = mix(pkfrq, kfrq, min(ktim * 19. + sin(ktim)*16., 1.)); float u = abs((tanh(ktim / 4.) * (cos(ktim * 8.) / 3.1415)) * 10.18); for (float i = 1.; i < harmonics; i += (1.+u)) { float a = 1. / pow(i, attenuation_constant * 0.905); float a2 = 1. / (pow(i, attenuation_constant * (0.86555 * u)) / (sin(kktim / (i / 64.)))); float mix_f = 0.5 * (1. - abs(sin(kktim*8.+1.8*cos(i * a * 18.) - 1.))); vec4 lc = arr[int(i+7. + globalTime * 2.) % 8]; float attack = .25 * mix_f* (harmonics-i*2.+kktim/8.) / 8.; float decay = 1. * mix_f / -i*2.; float sustain = 0.; float release = 8.25; float decay_amp = 0.35; float env = kvel * adsr(kktim, vec4(attack, decay, sustain, release), decay_amp); float al = mix(a, a2, mix_f); l += fline(kfrq * i) * (al * env)*a*lc.r; r += fline(kfrq * i) * (al * env)*a*lc.g; } } } vec4 fo = max(f - 0.005, 0.); gl_FragColor = vec4(l, r, l + r, 1.) + fo; synthOutput = vec4(l, r, (l + r) / 2., 0.) + fo; // WebGL 2.0 only }