[READ-ONLY] Mirror of https://github.com/probablykasper/ferrum. Music library app for Mac, Linux and Windows ferrum.kasper.space
electron linux macos music music-library music-player napi windows
0

Configure Feed

Select the types of activity you want to include in your feed.

Working visualizer!!! thanks to @zachwinter

Kasper (Oct 2, 2025, 11:46 PM +0200) e2d1df8c f403f80e

+22 -5
+16
src/lib/visualizer/ShaderToyLite.js
··· 22 22 uniform sampler2D iChannel3; // input channel 3 23 23 uniform vec4 iDate; // (year, month, day, unixtime in seconds) 24 24 uniform float iSampleRate; // sound sample rate (i.e., 44100) 25 + uniform float iStream; // audio stream value 26 + uniform float iVolume; // audio volume value 25 27 out vec4 frag_out_color; 26 28 void mainImage( out vec4 c, in vec2 f ); 27 29 void main( void ) ··· 76 78 // uniforms 77 79 var iFrame = 0 78 80 var iMouse = { x: 0, y: 0, clickX: 0, clickY: 0 } 81 + var iStream = 0 82 + var iVolume = 0 79 83 80 84 // shader common source 81 85 var common = '' ··· 222 226 location[key]['iMouse'] = gl.getUniformLocation(program, 'iMouse') 223 227 location[key]['iDate'] = gl.getUniformLocation(program, 'iDate') 224 228 location[key]['iSampleRate'] = gl.getUniformLocation(program, 'iSampleRate') 229 + location[key]['iStream'] = gl.getUniformLocation(program, 'iStream') 230 + location[key]['iVolume'] = gl.getUniformLocation(program, 'iVolume') 225 231 location[key]['vertexInPosition'] = gl.getAttribLocation(program, 'vertexInPosition') 226 232 227 233 return program ··· 320 326 gl.uniform4f(location[key]['iMouse'], iMouse.x, iMouse.y, iMouse.clickX, iMouse.clickY) 321 327 gl.uniform4f(location[key]['iDate'], iDate[0], iDate[1], iDate[2], iDate[3]) 322 328 gl.uniform1f(location[key]['iSampleRate'], 44100) 329 + gl.uniform1f(location[key]['iStream'], iStream) 330 + gl.uniform1f(location[key]['iVolume'], iVolume) 323 331 324 332 // viewport 325 333 gl.viewport(0, 0, gl.canvas.width, gl.canvas.height) ··· 388 396 389 397 this.setOnDraw = (callback) => { 390 398 onDrawCallback = callback 399 + } 400 + 401 + this.setStream = (value) => { 402 + iStream = value 403 + } 404 + 405 + this.setVolume = (value) => { 406 + iVolume = value 391 407 } 392 408 393 409 this.addTexture = (texture, key) => {
+6 -5
src/lib/visualizer/Visualizer.svelte
··· 33 33 float dist = distance(uv, vec2(0.)); 34 34 uv = WARP ? uv * kale(uv, vec2(0.), 2.) : uv; 35 35 for (float i = 0.; i < BALLS; i++) { 36 - float t = iTime/2. - i * PI / BALLS * cos(iTime / max(i, 0.0001)); 37 - vec2 p = vec2(cos(t), sin(t)) / sin(i / BALLS * PI / dist + iTime); 38 - vec3 c = cos(vec3(0, 5, -5) * PI * 2. / PI + PI * (iTime / (i+1.) / 5.)) * (GLOW) + (GLOW); 39 - fragColor += vec4(vec3(dist * .35 / length(uv - p * ORB_SIZE) * c), 1.0); 36 + float t = iStream/2. - i * PI / BALLS * cos(iStream / max(i, 0.0001)); 37 + vec2 p = vec2(cos(t), sin(t)) / sin(i / BALLS * PI / dist + iStream); 38 + vec3 c = iVolume * cos(vec3(0, 5, -5) * PI * 2. / PI + PI * (iStream / (i+1.) / 5.)) * (GLOW) + (GLOW); 39 + fragColor += vec4(iVolume * vec3(dist * .35 / length(uv - p * ORB_SIZE) * c), 1.0); 40 40 } 41 41 fragColor.xyz = pow(fragColor.xyz, vec3(CONTRAST)); 42 42 } ··· 55 55 toy.play() 56 56 console.log('start') 57 57 const visualizer = start_visualizer(audioContext, mediaElementSource, (info) => { 58 - console.log('update', info.stream, info.volume) 58 + toy.setStream(info.stream) 59 + toy.setVolume(info.volume) 59 60 }) 60 61 61 62 return () => {