UNPKG

wam-community

Version:

A collection of prebuilt Web Audio Modules ready for use

135 lines (109 loc) 3.54 kB
import "https://preview.babylonjs.com/babylon.js"; /** * @param {URL} relativeURL * @returns {string} */ const getBasetUrl = (relativeURL) => { const baseURL = relativeURL.href.substring(0, relativeURL.href.lastIndexOf("/")); return baseURL; }; export default class Visualizer { _baseURL = getBasetUrl(new URL(".", import.meta.url)); constructor(canvas, analyser) { this.canvas = canvas; this.engine = new BABYLON.Engine(this.canvas, true); this.analyser = analyser; this.analyser.fftSize = 4096; this.bufferLengthAlt = this.analyser.frequencyBinCount; this.dataArrayAlt = new Uint8Array(this.bufferLengthAlt); this.createScene(); this.initShader(); this.resize(); this.engine.runRenderLoop(() => { if (this.canvas.on) { this.updateTexture(); this.scene.render(); } }); } resize() { let resized = false; new ResizeObserver(() => { resized = true; }).observe(this.canvas); this.scene.beforeRender = () => { if (resized) { this.engine.resize(); resized = false; } }; } initShader() { let w = this.analyser.fftSize / 2; let raw = new Uint8Array(w * 255 * 4); let texture = BABYLON.RawTexture.CreateRGBATexture( raw, w, 255, this.scene, undefined, undefined, undefined, undefined, undefined, true ); texture.hasAlpha = true; BABYLON.Effect.ShadersStore["customFragmentShader"] = ` varying vec2 vUV; uniform sampler2D textureSampler; uniform float time; // Parameters uniform vec2 screenSize; vec4 firstColor = vec4(1.0,0.0,0.0,1.0); //red vec4 middleColor = vec4(0.0,1.0,0.0,1.0); // green vec4 endColor = vec4(0.0,0.0,1.0,1.0); // blue void main( void ){ vec2 xy = gl_FragCoord.xy / screenSize.xy; float h = 0.5; // adjust position of middleColor vec4 col = mix(mix(firstColor, middleColor, xy.x/h), mix(middleColor, endColor, (xy.x - h)/(1.0 - h)), step(h, xy.x)); gl_FragColor = texture2D(textureSampler, xy) * col; }`; var postProcess = new BABYLON.PostProcess("Wave", "custom", ["screenSize"], null, 0.25, this.camera); postProcess.onApply = () => { let effect = postProcess._drawWrapper.effect; let { width, height } = this.canvas.getBoundingClientRect(); let parentScaling = this.canvas.getBoundingClientRect().width / this.canvas.offsetWidth; effect.setFloat2("screenSize", width / parentScaling, height / parentScaling); effect.setTexture("textureSampler", texture); }; this.updateTexture = () => { this.analyser.getByteTimeDomainData(this.dataArrayAlt); for (let i = 0; i < w; i++) { for (let j = 0; j < 255; j++) { let index = 4 * (w * j + i); let color = Math.abs(this.dataArrayAlt[i] - j) < 3 ? 255 : 0; raw[index + 0] = color; raw[index + 1] = color; raw[index + 2] = color; raw[index + 3] = 255; } } texture.update(raw); }; } createScene() { this.scene = new BABYLON.Scene(this.engine); this.scene.clearColor = new BABYLON.Color3.Black(); var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), this.scene); light.intensity = 0.7; this.camera = new BABYLON.ArcRotateCamera( "Camera", -Math.PI / 2, Math.PI / 2, 5, BABYLON.Vector3.Zero(), this.scene ); } }