memoscan
← all memos

Memo 0x706995cf…ebd7a0 on Ethereum

!0}catch(e){console.error("Audio load error:",e)}}play(){if(!this._audioBuffer||!this.isLoaded)return;const e=this._getContext();if(this._sourceNode)try{this._sourceNode.stop(),this._sourceNode.disconnect()}catch(e){}this._sourceNode=e.createBufferSource(),this._sourceNode.buffer=this._audioBuffer,this._sourceNode.connect(this._gainNode),this._sourceNode.connect(this._analyser),this._sourceNode.loop=!0;const t=Math.max(0,Math.min(this._startOffset,this._audioBuffer.duration-.01));this._sourceNode.start(0,t),this._lastStartTime=e.currentTime,this._lastStartOffset=t,this.isPlaying=!0}pause(){if(this._sourceNode&&this.isPlaying){const e=this._getContext().currentTime-this._lastStartTime;this._startOffset=(this._lastStartOffset+e)%this._audioBuffer.duration;try{this._sourceNode.stop(),this._sourceNode.disconnect()}catch(e){}this._sourceNode=null,this.isPlaying=!1}}toggle(){this._directionalEnabled&&this.isPlaying?this.stopDirectional():this._directionalEnabled?this.startDirectional(this._isForward):this.isPlaying?this.pause():this.play()}async initDirectionalPlayback(){if(this._forwardBuffer)try{const e=this._getContext();this._reverseBuffer=e.createBuffer(this._forwardBuffer.numberOfChannels,this._forwardBuffer.length,this._forwardBuffer.sampleRate);for(let e=0;e<this._forwardBuffer.numberOfChannels;e++){const t=this._forwardBuffer.getChannelData(e),i=this._reverseBuffer.getChannelData(e);for(let e=0;e<t.length;e++)i[e]=t[t.length-1-e]}this._directionalEnabled=!0,console.log("[AudioEngine] Directional playback initialized")}catch(e){console.error("[AudioEngine] Failed to init directional:",e),this._directionalEnabled=!1}}getDirectionalPosition(){if(!this._audioContext||!this._lastStartTime)return 0;const e=this._audioContext.currentTime-this._lastStartTime;return this._isForward?this._lastStartOffset+e:this._lastStartOffset-e}playDirectional(e,t){if(!this._directionalEnabled||!this._audioContext||!this._forwardBuffer)return;if(this._sourceNode){this._sourceNode.onended=null;try{this._sourceNode.stop(),this._sourceNode.disconnect()}catch(e){}}this._sourceNode=this._audioContext.createBufferSource(),this._sourceNode.buffer=t?this._forwardBuffer:this._reverseBuffer,this._sourceNode.connect(this._gainNode),this._sourceNode.connect(this._analyser);const i=t?e:this._forwardBuffer.duration-e,a=Math.max(0,Math.min(i,this._sourceNode.buffer.duration-.01));this._sourceNode.start(0,a),this._lastStartTime=this._audioContext.currentTime,this._lastStartOffset=e,this._isForward=t,this.isPlaying=!0,this._sourceNode.onended=()=>{this._isForward?this.playDirectional(0,!0):this.playDirectional(this._forwardBuffer.duration,!1)}}setDirection(e){if(!this._directionalEnabled)return;const t=e>=0;if(t===this._isForward)return;const i=this.getDirectionalPosition();this.playDirectional(i,t)}isDirectionalEnabled(){return this._directionalEnabled}getDirection(){return this._isForward?1:-1}stopDirectional(){if(this.isPlaying&&(this._savedDirectionalPosition=this.getDirectionalPosition(),this._forwardBuffer&&(this._savedDirectionalPosition=Math.max(0,Math.min(this._savedDirectionalPosition,this._forwardBuffer.duration)))),this._sourceNode){this._sourceNode.onended=null;try{this._sourceNode.stop(),this._sourceNode.disconnect()}catch(e){}this._sourceNode=null}this.isPlaying=!1}startDirectional(e=!0){const t=this._savedDirectionalPosition>0?this._savedDirectionalPosition:e?0:this._forwardBuffer?this._forwardBuffer.duration:0;this._directionalEnabled?this.playDirectional(t,e):this.initDirectionalPlayback().then(()=>{this._directionalEnabled&&this.playDirectional(t,e)})}analyze(){if(!this._analyser)return;this._analyser.getByteFrequencyData(this._spectrum),this._analyser.getByteTimeDomainData(this._waveform);let e=0;for(let t=0;t<this._waveform.length;t++){const i=(this._waveform[t]-128)/128;e+=i*i}this._amplitude=Math.sqrt(e/this._waveform.length),this._calculateEnergyBands();const t=performance.now();this._energy.bass>this.beatThreshold&&t-this.lastBeatTime>this.beatCooldown?(this.beatDetected=!0,this.lastBeatTime=t):this.beatDetected=!1}_calculateEnergyBands(){const e=this._getContext().sampleRate/2,t=this._analyser.frequencyBinCount;Object.keys(this.energyBands).forEach(i=>{const[a,o]=this.energyBands[i],s=Math.floor(a/e*t),n=Math.min(Math.ceil(o/e*t),t-1);let r=0,l=0;for(let e=s;e<=n;e++)r+=this._spectrum[e],l++;this._energy[i]=l>0?r/l/255:0})}getSpectrum(){return this._spectrum||new Uint8Array(1024)}getWaveform(){return this._waveform||new Uint8Array(1024)}getEnergy(e){return this._energy[e]||0}getAllEnergy(){return{...this._energy}}getAmplitude(){return this._amplitude}isBeat(){return this.beatDetected}hasAudio(){return this.isLoaded}getCentroid(){if(!this._spectrum)return 0;const e=this._getContext().sampleRate/2;let t=0,i=0;for(let a=0;a<this._spectrum.length;a++)t+=a/this._spectrum.length*e*this._spectrum[a],i+=this._spectrum[a];return i>0?t/i:0}}const audioEngine=new AudioEngine;let layers=[],baseImage=null,baseLayerGraphics=null,aspectRatio=STATE.canvasSize.width/STATE.canvasSize.height;const originalWidth=STATE.canvasSize.width,originalHeight=STATE.canvasSize.height,renderEngine={outputBuffer:null};function preload(){STATE.baseLayer&&STATE.baseLayer.sourceUrl&&"image"===STATE.baseLayer.type&&(baseImage=loadImage(STATE.baseLayer.sourceUrl))}function calculateCanvasSize(){let e,t;return windowWidth/windowHeight>aspectRatio?(t=windowHeight,e=t*aspectRatio):(e=windowWidth,t=e/aspectRatio),{w:Math.floor(e),h:Math.floor(t)}}function setup(){console.log("[Composition] Setup starting..."),pixelDensity(1);const e=calculateCanvasSize();createCanvas(e.w,e.h),console.log("[Composition] Canvas created:",width,"x",height,"(pixelDensity: 1)"),audioEngine.init();let t=null;STATE.audio&&(STATE.audio.sourceUrl?t=STATE.audio.sourceUrl:STATE.audio.tracks&&STATE.audio.tracks.length>0&&STATE.audio.tracks[0].url&&(t=STATE.audio.tracks[0].url)),t?(console.log("[Composition] Loading audio from:",t),updateLoadStatus("audio","pending","loading audio"),audioEngine.loadFromUrl(t).then(()=>{console.log("[Composition] Audio loaded successfully"),loadingState.audio=!0,updateLoadStatus("audio","ok"),STATE.audio&&STATE.audio.directionalEnabled&&audioEngine.initDirectionalPlayback().then(()=>console.log("[Composition] Directional playback ready")).catch(e=>console.warn("[Composition] Directional init deferred:",e))}).catch(e=>{console.error("[Composition] Failed to load audio:",e),loadingState.audio=!0,updateLoadStatus("audio","error","audio failed")})):(loadingState.audio=!0,updateLoadStatus("audio","ok")),console.log("[Composition] Creating",STATE.layers.length,"layers..."),updateLoadStatus("images","pending","loading assets");const i=[];STATE.layers.forEach((layerData,e)=>{const ComponentClass=window[layerData.componentType];if(ComponentClass){console.log("[Composition] Creating layer",e,":",layerData.componentType);const component=new ComponentClass(width,height,layerData.componentParams);if("ImageLayer"===layerData.componentType&&layerData.componentParams.imageUrl){loadingState.imageCount++,console.log("[Composition] Loading image for layer",e,":",layerData.componentParams.imageUrl);const t=component.loadImage(layerData.componentParams.imageUrl).then(()=>{loadingState.imagesLoaded++,console.log("[Composition] Image loaded successfully for layer",e),updateLoadStatus("images","pending",loadingState.imagesLoaded+"/"+loadingState.imageCount)}).catch(t=>{loadingState.imagesLoaded++,console.error("[Composition] Failed to load image for layer",e,":",t)});i.push(t)}if("VideoLayer"===layerData.componentType&&layerData.componentParams.videoUrl){loadingState.imageCount++,console.log("[Composition] Loading video for layer",e,":",layerData.componentParams.videoUrl);const t=component.loadVideo(layerData.componentParams.videoUrl).then(()=>{loadingState.imagesLoaded++,console.log("[Composition] Video loaded successfully for layer",e),updateLoadStatus("images","pending",loadingState.imagesLoaded+"/"+loadingState.imageCount)}).catch(t=>{loadingState.imagesLoaded++,console.error("[Composition] Failed to load video for layer",e,":",t)});i.push(t)}const t=createGraphics(width,height);layers.push({component:component,...layerData,graphics:t})}else console.error("[Composition] Unknown component type:",layerData.componentType)}),STATE.baseLayer&&STATE.baseLayer.filters&&(baseLayerGraphics=createGraphics(width,height)),renderEngine.outputBuffer=createGraphics(width,height),0===i.length?(loadingState.images=!0,updateLoadStatus("images","ok")):Promise.all(i).then(()=>{loadingState.images=!0,updateLoadStatus("images","ok")}),loadingState.ready=!0,updateLoadStatus("ready","ok"),console.log("[Composition] Setup complete. Total layers:",layers.length)}function draw(){1===frameCount&&(console.log("[Composition] First draw() call. Layers:",layers.length),layers.forEach((e,t)=>console.log("[Composition] Layer",t,":",e.componentType,"visible:",e.visible))),audioEngine.analyze();const e=audioEngine.getSpectrum(),t=audioEngine.getWaveform(),i=audioEngine.getAllEnergy(),a=audioEngine.getAmplitude(),waveform=new Float32Array(t.length);for(let e=0;e<t.length;e++)waveform[e]=(t[e]-128)/128;const o=audioEngine.isBeat(),s={fftSpectrum:e,fftEnergy:i,amplitude:a,waveform:waveform,beatDetected:o,beat:o,centroid:audioEngine.getCentroid(),bass:i.bass||0,mid:i.mid||0,high:i.treble||0,mouseX:mouseX,mouseY:mouseY,pmouseX:pmouseX,pmouseY:pmouseY,mousePressed:mouseIsPressed,touches:[],mouseXNorm:mouseX/width,mouseYNorm:mouseY/height,time:millis()/1e3,deltaTime:deltaTime,frameCount:frameCount,fps:frameRate(),width:width,height:height,centerX:width/2,centerY:height/2,aspectRatio:width/height,minDim:min(width,height),maxDim:max(width,height)};if(background(STATE.backgroundColor||"#000000"),baseImage&&STATE.baseLayer&&STATE.baseLayer.visible){const e=baseImage.width/baseImage.height;let t,i,a,o;if(e>width/height?(i=height,t=height*e):(t=width,i=width/e),a=(width-t)/2,o=(height-i)/2,STATE.baseLayer.filters&&(STATE.