Created
March 3, 2026 11:58
-
-
Save CIOSAI/dff8bb868db18ff39f08e0209be911cf to your computer and use it in GitHub Desktop.
wavenerd composition performed at stream for palestine, nov 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // find wavenerd at https://0b5vr.com/wavenerd/ | |
| // stream playback at https://archive.org/details/toplap-palestine-nov2025-ciosai-tw | |
| // CCBY | |
| #define BPM bpm | |
| #define B2T (60.0 / BPM) | |
| uniform vec4 param_knob0; | |
| uniform vec4 param_knob1; | |
| uniform vec4 param_knob2; | |
| uniform vec4 param_knob3; | |
| uniform vec4 param_knob4; | |
| uniform vec4 param_knob5; | |
| uniform vec4 param_knob6; | |
| uniform vec4 param_knob7; | |
| const float PI = acos(-1.0); | |
| const float TAU = 2.0 * PI; | |
| // easing style | |
| const int TW_LIN=0; | |
| const int TW_SIN=1; | |
| const int TW_EXP=2; | |
| const int TW_STP=3; | |
| // smooth on entrance or exit or both | |
| const int MD_INOUT=0; | |
| const int MD_IN=1; | |
| const int MD_OUT=2; | |
| float mtime=0.0; | |
| float[128] timers; | |
| uint timerPtr=0u; | |
| int twFun=TW_LIN; | |
| int twMode=MD_INOUT; | |
| uint currTimer=0u; | |
| float lslope(float lower, float upper, float index) { | |
| return clamp((index-lower)/(upper-lower),0.0,1.0); | |
| } | |
| // dont read this shit <3 | |
| float ease(float n) { | |
| float expCoeff=6.; | |
| if (twFun==TW_STP && twMode!=MD_INOUT) { | |
| return twMode==MD_IN?( | |
| n<=.999999?0.0:1.0 | |
| ):( | |
| n<=.000001?0.0:1.0 | |
| ); | |
| } | |
| else if (twFun==TW_SIN && twMode==MD_INOUT) { | |
| return cos(PI-n*PI)*.5+.5; | |
| } | |
| else if (twFun==TW_SIN && twMode==MD_IN) { | |
| return 1.-cos(n*PI/2.); | |
| } | |
| else if (twFun==TW_SIN && twMode==MD_OUT) { | |
| return sin(n*PI/2.); | |
| } | |
| else if (twFun==TW_EXP && twMode==MD_INOUT) { | |
| return (n<.5? | |
| exp((n*2.-1.)*expCoeff) | |
| :(2.-exp((1.-n*2.)*expCoeff) | |
| ))/2.; | |
| } | |
| else if (twFun==TW_EXP && twMode==MD_IN) { | |
| return exp((n-1.)*expCoeff); | |
| } | |
| else if (twFun==TW_EXP && twMode==MD_OUT) { | |
| return 1.-exp(-n*expCoeff); | |
| } | |
| return n; | |
| } | |
| uint getTimer() { | |
| timers[timerPtr] = 0.0; | |
| timerPtr++; | |
| return timerPtr-1u; | |
| } | |
| // (existing timeline, from what value, to what value, taking how long) | |
| // easing is configured by writing to twFun and twMode to avoid | |
| // having to pass it in consistently | |
| float tween(float orig, float from, float to, float duration) { | |
| float acc=timers[currTimer]; | |
| // accumulate duration so we dont have to manually calculate how long | |
| // each thing took | |
| timers[currTimer] = acc+duration; | |
| return mix(orig, mix( | |
| from, | |
| to, | |
| ease(lslope(acc, acc+duration, mtime)) | |
| ), step(acc,mtime)); | |
| } | |
| float tweenInto(float orig, float to, float duration) { | |
| return tween(orig, orig, to, duration); | |
| } | |
| float wait(float orig, float duration) { | |
| return tween(orig, orig, orig, duration); | |
| } | |
| // when you know when it should end but dont know how long | |
| // itll take to get to this time | |
| float timeUntil(float to) { | |
| return max(0.,to-timers[currTimer]); | |
| } | |
| mat2 rot_(float a) {return mat2(cos(a),-sin(a),sin(a),cos(a));} | |
| float expease(float n, float deg) { | |
| return n>0.0?1.0-exp(-n*deg):0.0; | |
| } | |
| vec3 cyclic(vec3 p, float pers, float lacu) { | |
| vec4 sum = vec4(0); | |
| for (int i = 0; i ++ < 5;) { | |
| //p *= rot; | |
| p.yz *= rot_(4.5); | |
| p.xy *= rot_(1.5); | |
| p += sin(p.zxy); | |
| sum += vec4(cross(cos(p), sin(p.yzx)), 1); | |
| sum /= pers; | |
| p *= lacu; | |
| } | |
| return sum.xyz / sum.w; | |
| } | |
| vec3 hash( uvec3 x ) | |
| { | |
| x = ((x>>8U)^x.yzx)*1103773245U; | |
| x = ((x>>8U)^x.yzx)*1103773245U; | |
| x = ((x>>8U)^x.yzx)*1103773245U; | |
| return vec3(x)*(1.0/float(0xffffffffU)); | |
| } | |
| vec3 hash3f( vec3 x ) | |
| { | |
| return hash(uvec3(x*66456.85725)); | |
| } | |
| uint hashi_( uint x) { | |
| x ^= x >> 16; | |
| x *= 0x7feb352dU; | |
| x ^= x >> 15; | |
| x *= 0x846ca68bU; | |
| x ^= x >> 16; | |
| return x; | |
| } | |
| vec2 spray( float t, float freq, float spread, float seed, float interval, int count) { | |
| float grainLength = float(count) * interval; | |
| vec2 sum = vec2(0); | |
| for(float i = 0.; i < float(count)+.5; i++) { | |
| vec3 dice = hash3f(vec3(i, floor((float(t) -interval * i) / grainLength), seed)); | |
| vec2 ph = 6.283 * vec2(freq * t * exp2(spread * sqrt(-2. * log(dice.x)) * vec2(cos(6.283*dice.y), sin(6.283*dice.y))) + dice.xy); | |
| sum += | |
| 2. * | |
| smoothstep(0., .5, mod(float(t) -interval * i, grainLength) / grainLength) * | |
| smoothstep(1., .5, mod(float(t) -interval * i, grainLength) / grainLength) * | |
| vec2(sin(ph.x),sin(ph.y)); | |
| } | |
| return sum / float(count); | |
| } | |
| float n2p(float n) { | |
| return 440.0*pow(2.,n/17.); | |
| } | |
| vec2 mainAudio(vec4 time) { | |
| vec2 dest = vec2(0.0); | |
| vec2 sidechain = vec2(0); | |
| vec2 kick=vec2(0); | |
| { // kick | |
| float env = exp(-time.x*4.) * smoothstep(0.0, 0.001, time.x) * smoothstep(0.0, 0.1, 1.-time.x); | |
| float wave = tanh(sin(70.*time.z-expease(time.x,16.)*70.)*mix(5.,2.,time.x)); | |
| float vol = 1.; | |
| kick = vec2(wave)*env*vol; | |
| } | |
| vec2 hats=vec2(0); | |
| { // hats | |
| float t = fract(time.y*4./B2T); float env = exp(-t*5.) * smoothstep(0.0, 0.001, t) * smoothstep(0.0, 0.1, 1.-t); | |
| vec2 wave = tanh(spray(time.x, 9900., .9, 4., 1., 64)*4.); | |
| float rand = sin(floor(time.z/B2T+0.5)*11.+.3); | |
| float pat = 0.; | |
| mtime = time.y*4./B2T; | |
| uint patTID = getTimer(); | |
| currTimer = patTID; | |
| twFun = TW_STP; twMode = MD_OUT; | |
| pat = tweenInto(pat, 0., 1.); | |
| pat = tweenInto(pat, 1., 3.); | |
| pat = tweenInto(pat, 0., 2.); | |
| pat = tweenInto(pat, 1., 1.); | |
| pat = tweenInto(pat, 0., 3.); | |
| pat = tweenInto(pat, 1., 1.); | |
| pat = tweenInto(pat, 0., 4.); | |
| pat = tweenInto(pat, 1., 1.); | |
| float vol = (rand*.6)*pat; | |
| hats=wave*env*vol*vec2(1.,.4); | |
| } | |
| vec2 snare=vec2(0); | |
| { // hats | |
| float env = exp(-time.x*15.) * smoothstep(0.0, 0.001, time.x) * smoothstep(0.0, 0.1, 1.-time.x); | |
| vec2 wave = spray(time.x, 5000., .2, 20., 1., 64) + | |
| tanh(sin(50.*time.z+expease(time.x,2.)*820.)*30.)*mix(.15,.001,expease(time.x,16.)); | |
| wave = tanh(wave*18.); | |
| float rand = sin(floor(time.z/B2T+0.5)*11.+.3); | |
| float pat = 0.; | |
| mtime = time.y/B2T; | |
| uint patTID = getTimer(); | |
| currTimer = patTID; | |
| twFun = TW_STP; twMode = MD_OUT; | |
| pat = tweenInto(pat, 0., 1.); | |
| pat = tweenInto(pat, 1., 1.); | |
| pat = tweenInto(pat, 0., 1.); | |
| pat = tweenInto(pat, 1., 1.); | |
| float vol = (rand*.6)*pat; | |
| snare=wave*env*vol*vec2(.7,1.); | |
| } | |
| vec2 bass=vec2(0); | |
| { // bass | |
| float env = exp(-time.x*6.) * smoothstep(0.0, 0.001, time.x) * smoothstep(0.0, 0.1, 1.-time.x); | |
| float note = 0.; | |
| { | |
| mtime = fract(time.z/(B2T*8.))*16.; | |
| uint patTID = getTimer(); | |
| currTimer = patTID; | |
| twFun = TW_STP; twMode = MD_OUT; | |
| for (int i=0; i<4; i++) { | |
| float possible[] = float[](-7., 0., 3., 4., 7.); | |
| note = tweenInto(note, possible[hashi_(uint(i+int(time.z/B2T)))%5u], 4.); | |
| } | |
| note = tweenInto(note, 0., timeUntil(16.)); | |
| } | |
| note -= 34.; | |
| float wave = tanh(sin(n2p(note)*TAU*time.y + sin(220.*time.z)*pow(sin(12.*time.z)*.5+.5,9.)*1.6)*12.); | |
| float pat = 1.; | |
| { | |
| mtime = fract(time.z/(B2T*8.))*16.; | |
| uint patTID = getTimer(); | |
| currTimer = patTID; | |
| twFun = TW_STP; twMode = MD_OUT; | |
| pat = tweenInto(pat, 1., 2.); | |
| pat = tweenInto(pat, 0., 1.); | |
| pat = tweenInto(pat, 1., 2.); | |
| pat = tweenInto(pat, 0., 3.); | |
| pat = tweenInto(pat, 1., 2.); | |
| pat = tweenInto(pat, 0., 1.); | |
| pat = tweenInto(pat, 1., 4.); | |
| pat = tweenInto(pat, 0., timeUntil(16.)); | |
| } | |
| bass = vec2(wave)*env*pat; | |
| } | |
| vec2 chord=vec2(0); | |
| { // chord | |
| vec4 save = time; | |
| time += sin(time)*.02; | |
| float env = smoothstep(0.0, | |
| mix(.01, .1, paramFetch(param_knob7)) | |
| , time.x) * smoothstep(0.0, | |
| mix(.5, .9, paramFetch(param_knob7)), | |
| mix(.4, 1.0, paramFetch(param_knob7))-time.x); | |
| vec2 offsets = vec2(15.,35.); | |
| vec2 wave = vec2(0.); | |
| for (int i=0; i<3; i++) { | |
| float note = 0.; | |
| { | |
| mtime = fract(time.z/(B2T*32.))*4.; | |
| uint patTID = getTimer(); | |
| currTimer = patTID; | |
| twFun = TW_STP; twMode = MD_OUT; | |
| note = tweenInto(note, float[3](0.,4.,10.)[i], 1.); | |
| note = tweenInto(note, float[3](-6.,0.,4.)[i], 1.); | |
| note = tweenInto(note, float[3](-3.,2.,7.)[i], 1.); | |
| note = tweenInto(note, float[3](-7.,0.,5.)[i], 1.); | |
| } | |
| wave.x += sin(n2p(note)*TAU*time.y + sin(120.*time.z)*pow(sin(offsets.x*time.z)*.5+.5,9.)*1.6); | |
| wave.y += sin(n2p(note)*TAU*time.y + sin(120.*time.z)*pow(sin(offsets.y*time.z)*.5+.5,9.)*1.6); | |
| offsets += 19.; | |
| } | |
| wave /= 3.; | |
| chord = wave*env; | |
| time = save; | |
| } | |
| dest += kick*paramFetch(param_knob0); | |
| sidechain+=exp(-time.x*18.)*paramFetch(param_knob0); | |
| dest += snare*paramFetch(param_knob1); | |
| dest += hats*paramFetch(param_knob2); | |
| dest += bass*(1.-sidechain)*paramFetch(param_knob3); | |
| dest += chord*paramFetch(param_knob4); | |
| return dest; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment