1export default async function (req: Request): Promise<Response> {
2 const fftSize = 2048;
3 const TWO_PI = 2.0 * 3.141592653579;
74
75
76 function showError(e) {
77 console.error(e);
78 errorBox.style.display = "block";
81
82 // DPR-aware resize
83 function resize() {
84 const dpr = Math.min(window.devicePixelRatio || 1, 2);
85 const w = Math.floor(window.innerWidth * dpr);
196 \`;
197
198 function compileShader(type, src) {
199 const s = gl.createShader(type);
200 gl.shaderSource(s, src);
222 gl.bindVertexArray(vao);
223
224 function createAttrib(data, attribName, usage) {
225 const loc = gl.getAttribLocation(program, attribName);
226 if (loc === -1) throw new Error("Attrib not found or optimized out: " + attribName);
248
249 // Matrices
250 function mat4Perspective(fovDeg, aspect, near, far) {
251 const f = 1.0 / Math.tan((fovDeg * Math.PI) / 360);
252 const nf = 1 / (near - far);
259 return out;
260 }
261 function subtract(a, b) { return [a[0]-b[0], a[1]-b[1], a[2]-b[2]]; }
262 function normalize(v) {
263 const l = Math.hypot(v[0], v[1], v[2]) || 1;
264 return [v[0]/l, v[1]/l, v[2]/l];
265 }
266 function cross(a, b) {
267 return [a[1]*b[2] - a[2]*b[1], a[2]*b[0] - a[0]*b[2], a[0]*b[1] - a[1]*b[0]];
268 }
269 function dot(a, b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
270 function mat4LookAt(eye, target, up) {
271 const z = normalize(subtract(eye, target));
272 const x = normalize(cross(up, z));
314
315 // Render loop
316 function render(ts) {
317 // Update audio only if ready
318 if (analyser) {