mirror of
				https://github.com/9001/copyparty.git
				synced 2025-10-30 20:22:20 -06:00 
			
		
		
		
	
		
			
				
	
	
		
			209 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			209 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* untz untz untz untz */
 | |
| 
 | |
| (function () {
 | |
| 
 | |
|     var can, ctx, W, H, fft, buf, bars, barw, pv,
 | |
|         hue = 0,
 | |
|         ibeat = 0,
 | |
|         beats = [9001],
 | |
|         beats_url = '',
 | |
|         uofs = 0,
 | |
|         ops = ebi('ops'),
 | |
|         raving = false,
 | |
|         recalc = 0,
 | |
|         cdown = 0,
 | |
|         FC = 0.9,
 | |
|         css = `<style>
 | |
| 
 | |
| #fft {
 | |
|     position: fixed;
 | |
|     top: 0;
 | |
|     left: 0;
 | |
|     z-index: -1;
 | |
| }
 | |
| body {
 | |
|     box-shadow: inset 0 0 0 white;
 | |
| }
 | |
| #ops>a,
 | |
| #path>a {
 | |
|     display: inline-block;
 | |
| }
 | |
| /*
 | |
| body.untz {
 | |
|     animation: untz-body 200ms ease-out;
 | |
| }
 | |
| @keyframes untz-body {
 | |
| 	0% {inset 0 0 20em white}
 | |
| 	100% {inset 0 0 0 white}
 | |
| }
 | |
| */
 | |
| :root, html.a, html.b, html.c, html.d, html.e {
 | |
|     --row-alt: rgba(48,52,78,0.2);
 | |
| }
 | |
| #files td {
 | |
|     background: none;
 | |
| }
 | |
| 
 | |
| </style>`;
 | |
| 
 | |
|     QS('body').appendChild(mknod('div', null, css));
 | |
| 
 | |
|     function rave_load() {
 | |
|         console.log('rave_load');
 | |
|         can = mknod('canvas', 'fft');
 | |
|         QS('body').appendChild(can);
 | |
|         ctx = can.getContext('2d');
 | |
| 
 | |
|         fft = new AnalyserNode(actx, {
 | |
|             "fftSize": 2048,
 | |
|             "maxDecibels": 0,
 | |
|             "smoothingTimeConstant": 0.7,
 | |
|         });
 | |
|         ibeat = 0;
 | |
|         beats = [9001];
 | |
|         buf = new Uint8Array(fft.frequencyBinCount);
 | |
|         bars = buf.length * FC;
 | |
|         afilt.filters.push(fft);
 | |
|         if (!raving) {
 | |
|             raving = true;
 | |
|             raver();
 | |
|         }
 | |
|         beats_url = mp.au.src.split('?')[0].replace(/(.*\/)(.*)/, '$1.beats/$2.txt');
 | |
|         console.log("reading beats from", beats_url);
 | |
|         var xhr = new XHR();
 | |
|         xhr.open('GET', beats_url, true);
 | |
|         xhr.onload = readbeats;
 | |
|         xhr.url = beats_url;
 | |
|         xhr.send();
 | |
|     }
 | |
| 
 | |
|     function rave_unload() {
 | |
|         qsr('#fft');
 | |
|         can = null;
 | |
|     }
 | |
| 
 | |
|     function readbeats() {
 | |
|         if (this.url != beats_url)
 | |
|             return console.log('old beats??', this.url, beats_url);
 | |
| 
 | |
|         var sbeats = this.responseText.replace(/\r/g, '').split(/\n/g);
 | |
|         if (sbeats.length < 3)
 | |
|             return;
 | |
| 
 | |
|         beats = [];
 | |
|         for (var a = 0; a < sbeats.length; a++)
 | |
|             beats.push(parseFloat(sbeats[a]));
 | |
| 
 | |
|         var end = beats.slice(-2),
 | |
|             t = end[1],
 | |
|             d = t - end[0];
 | |
| 
 | |
|         while (d > 0.1 && t < 1200)
 | |
|             beats.push(t += d);
 | |
|     }
 | |
| 
 | |
|     function hrand() {
 | |
|         return Math.random() - 0.5;
 | |
|     }
 | |
| 
 | |
|     function raver() {
 | |
|         if (!can) {
 | |
|             raving = false;
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         requestAnimationFrame(raver);
 | |
|         if (!mp || !mp.au || mp.au.paused)
 | |
|             return;
 | |
| 
 | |
|         if (--uofs >= 0) {
 | |
|             document.body.style.marginLeft = hrand() * uofs + 'px';
 | |
|             ebi('tree').style.marginLeft = hrand() * uofs + 'px';
 | |
|             for (var a of QSA('#ops>a, #path>a, #pctl>a'))
 | |
|                 a.style.transform = 'translate(' + hrand() * uofs * 1 + 'px, ' + hrand() * uofs * 0.7 + 'px) rotate(' + Math.random() * uofs * 0.7 + 'deg)'
 | |
|         }
 | |
| 
 | |
|         if (--recalc < 0) {
 | |
|             recalc = 60;
 | |
|             var tree = ebi('tree'),
 | |
|                 x = tree.style.display == 'none' ? 0 : tree.offsetWidth;
 | |
| 
 | |
|             //W = can.width = window.innerWidth - x;
 | |
|             //H = can.height = window.innerHeight;
 | |
|             //H = ebi('widget').offsetTop;
 | |
|             W = can.width = bars;
 | |
|             H = can.height = 512;
 | |
|             barw = 1; //parseInt(0.8 + W / bars);
 | |
|             can.style.left = x + 'px';
 | |
|             can.style.width = (window.innerWidth - x) + 'px';
 | |
|             can.style.height = ebi('widget').offsetTop + 'px';
 | |
|         }
 | |
| 
 | |
|         //if (--cdown == 1)
 | |
|         //    clmod(ops, 'untz');
 | |
| 
 | |
|         fft.getByteFrequencyData(buf);
 | |
| 
 | |
|         var imax = 0, vmax = 0;
 | |
|         for (var a = 10; a < 50; a++)
 | |
|             if (vmax < buf[a]) {
 | |
|                 vmax = buf[a];
 | |
|                 imax = a;
 | |
|             }
 | |
| 
 | |
|         hue = hue * 0.93 + imax * 0.07;
 | |
| 
 | |
|         ctx.fillStyle = 'rgba(0,0,0,0)';
 | |
|         ctx.fillRect(0, 0, W, H);
 | |
|         ctx.clearRect(0, 0, W, H);
 | |
|         ctx.fillStyle = 'hsla(' + (hue * 2.5) + ',100%,50%,0.7)';
 | |
| 
 | |
|         var x = 0, mul = (H / 256) * 0.5;
 | |
|         for (var a = 0; a < buf.length * FC; a++) {
 | |
|             var v = buf[a] * mul * (1 + 0.69 * a / buf.length);
 | |
|             ctx.fillRect(x, H - v, barw, v);
 | |
|             x += barw;
 | |
|         }
 | |
| 
 | |
|         var t = mp.au.currentTime + 0.05;
 | |
| 
 | |
|         if (ibeat >= beats.length || beats[ibeat] > t)
 | |
|             return;
 | |
| 
 | |
|         while (ibeat < beats.length && beats[ibeat++] < t)
 | |
|             continue;
 | |
| 
 | |
|         return untz();
 | |
| 
 | |
|         var cv = 0;
 | |
|         for (var a = 0; a < 128; a++)
 | |
|             cv += buf[a];
 | |
| 
 | |
|         if (cv - pv > 1000) {
 | |
|             console.log(pv, cv, cv - pv);
 | |
|             if (cdown < 0) {
 | |
|                 clmod(ops, 'untz', 1);
 | |
|                 cdown = 20;
 | |
|             }
 | |
|         }
 | |
|         pv = cv;
 | |
|     }
 | |
| 
 | |
|     function untz() {
 | |
|         console.log('untz');
 | |
|         uofs = 14;
 | |
|         document.body.animate([
 | |
|             { boxShadow: 'inset 0 0 1em #f0c' },
 | |
|             { boxShadow: 'inset 0 0 20em #f0c', offset: 0.2 },
 | |
|             { boxShadow: 'inset 0 0 0 #f0c' },
 | |
|         ], { duration: 200, iterations: 1 });
 | |
|     }
 | |
| 
 | |
|     afilt.plugs.push({
 | |
|         "en": true,
 | |
|         "load": rave_load,
 | |
|         "unload": rave_unload
 | |
|     });
 | |
| 
 | |
| })();
 |