Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save CIOSAI/dff8bb868db18ff39f08e0209be911cf to your computer and use it in GitHub Desktop.

Select an option

Save CIOSAI/dff8bb868db18ff39f08e0209be911cf to your computer and use it in GitHub Desktop.
wavenerd composition performed at stream for palestine, nov 2025
// 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