0xa89f3db4…071asent to0xecb92cc7…1463·#25,210,183·view on Etherscan
&&(this._smoothedWaveform&&this._smoothedWaveform.length===waveform.length?(i=waveform.map((e,i)=>this._smoothedWaveform[i]+(e-this._smoothedWaveform[i])*(1-t.smoothing)),this._smoothedWaveform=i):this._smoothedWaveform=[...waveform]);const a=[];if(t._paths&&t._paths.length>0)for(const e of t._paths)e&&e.length>=2&&a.push(e);this._tempPath.length>=2&&a.push(this._tempPath),0===a.length&&a.push([{x:0,y:.5},{x:1,y:.5}]);const o=e.color(t.color);o.setAlpha(t.opacity/100*255);const s=Math.min(this.width,this.height),n=Math.max(1,.003*s*(t.strokeWeight/2)),r=t.amplitude/100*(s/2);e.push(),e.noFill(),e.stroke(o),e.strokeWeight(n);for(const o of a){const a=o.map(e=>({x:e.x*this.width,y:e.y*this.height})),s=this._segmentLengths(a);if(this._drawWaveformAlongPath(e,i,a,s,r,!1),t.mirror&&a.length>=2){const t=a[0],o=a.map(e=>({x:2*t.x-e.x,y:2*t.y-e.y})),s=this._segmentLengths(o);this._drawWaveformAlongPath(e,i,o,s,r,!0)}}if(e.pop(),t.showPath){const i=e.color(t.pathColor);i.setAlpha(t.pathOpacity/100*255),e.push(),e.noFill(),e.stroke(i),e.strokeWeight(1);for(const t of a){const a=t.map(e=>({x:e.x*this.width,y:e.y*this.height}));if(!(a.length<2)){e.beginShape();for(const t of a)e.vertex(t.x,t.y);e.endShape(),e.noStroke(),e.fill(i),e.circle(a[0].x,a[0].y,6),e.stroke(i)}}e.pop()}}_segmentLengths(e){const t=[];let i=0;for(let a=1;a<e.length;a++){const o=e[a].x-e[a-1].x,s=e[a].y-e[a-1].y,n=Math.sqrt(o*o+s*s);t.push(n),i+=n}return{segLengths:t,totalLen:i}}_drawWaveformAlongPath(e,waveform,t,i,a,o){if(t.length<2||i.totalLen<=0)return;const{segLengths:s,totalLen:n}=i,r=waveform.length,l=o?-1:1;e.beginShape();for(let i=0;i<r;i++){const o=(r>1?i/(r-1):.5)*n;let h=0,c=0;for(;c<s.length-1&&h+s[c]<o;)h+=s[c],c++;const d=t[c],p=t[c+1],m=s[c]||1,u=Math.max(0,Math.min(1,(o-h)/m)),g=d.x+(p.x-d.x)*u,f=d.y+(p.y-d.y)*u,y=p.x-d.x,_=p.y-d.y,v=Math.sqrt(y*y+_*_)||1,w=-_/v,x=y/v,P=waveform[i]*l;e.vertex(g+w*P*a,f+x*P*a)}e.endShape()}}class SolidColor extends BaseComponent{static category="media";static isAudioReactive=!1;static displayName="Solid Color";static description="Solid color fill layer";getDefaultParams(){return{color:"#000000",opacity:1}}getParameters(){return[{name:"color",type:"color",label:"Color"},{name:"opacity",type:"range",min:0,max:1,step:.05,label:"Opacity"}]}update(e,t){}draw(e){const t=this.params;e.push();const i=t.color,a=parseInt(i.slice(1,3),16),o=parseInt(i.slice(3,5),16),b=parseInt(i.slice(5,7),16);e.noStroke(),e.fill(a,o,b,255*t.opacity),e.rect(0,0,this.width,this.height),e.pop()}}class MelodyTrace extends BaseComponent{static category="fft";static isAudioReactive=!0;static displayName="Melody Trace";static description="Symmetric melody trace based on dominant frequency";getDefaultParams(){return{verticalScale:1,strokeWeight:1.5,colorHue:200,colorSaturation:80,colorBrightness:90,trailLength:400,minFreq:50,maxFreq:2e3,topMirror:!0,drawConnections:!0,connectionOpacity:30,connectionSpacing:20}}getParameters(){return[{name:"verticalScale",type:"range",min:.5,max:3,step:.1,label:"Vertical Scale"},{name:"strokeWeight",type:"range",min:.5,max:4,step:.5,label:"Stroke Weight"},{name:"colorHue",type:"range",min:0,max:360,step:1,label:"Color Hue"},{name:"colorSaturation",type:"range",min:0,max:100,step:1,label:"Saturation"},{name:"colorBrightness",type:"range",min:0,max:100,step:1,label:"Brightness"},{name:"trailLength",type:"range",min:100,max:800,step:50,label:"Trail Length"},{name:"minFreq",type:"range",min:20,max:200,step:10,label:"Min Frequency"},{name:"maxFreq",type:"range",min:500,max:5e3,step:100,label:"Max Frequency"},{name:"topMirror",type:"boolean",label:"Top Mirror"},{name:"drawConnections",type:"boolean",label:"Draw Connections"},{name:"connectionOpacity",type:"range",min:10,max:100,step:5,label:"Connection Opacity"},{name:"connectionSpacing",type:"range",min:5,max:50,step:5,label:"Connection Spacing"}]}constructor(e,t,i){super(e,t,i),this._melodyPoints=[],this._particles=[]}setParticleSystem(e){this._particles=e}update(e,t){this._metrics=e;const i=this.params,a=e?.fftSpectrum;if(!a||0===a.length)return;const o=22050*a.indexOf(Math.max(...a))/a.length;let s;if(o>i.minFreq&&o<i.maxFreq){const e=Math.log(i.minFreq),t=Math.log(i.maxFreq),a=(Math.log(o)-e)/(t-e);s=this.height*(.85-.4*a*i.verticalScale)}else s=this._melodyPoints.length>0?this._melodyPoints[this._melodyPoints.length-1].y:this.height*(.75-.25*i.verticalScale);const n=70+80*Math.random();this._melodyPoints.push({y:s,reach:n});const r=i.trailLength;this._melodyPoints.length>r&&this._melodyPoints.shift()}draw(e){const t=this.params;if(this._melodyPoints.length<2)return;e.push(),e.colorMode(e.HSB,360,100,100,100),e.noFill(),e.stroke(t.colorHue,t.colorSaturation,t.colorBrightness,90),e.strokeWeight(t.strokeWeight);const i=this.width/2;this.height,this._drawTrace(e,i,-1,!1),this._drawTrace(e,i,1,!1),t.topMirror&&(this._drawTrace(e,i,-1,!0),this._drawTrace(e,i,1,!0)),e.colorMode(e.RGB,255),e.pop()}_drawTrace(e,t,i,a){const o=this.params,s=void 0!==window._playbackDirection?window._playbackDirection:1,n=this._melodyPoints.length;if(n<2)return;const r=this.width/2*.98;e.beginShape();for(let l=0;l<n;l++){const h=t+i*(l/(n-1))*r,c=1===s?n-1-l:l,d=this._melodyPoints[c];let p=d.y;a&&(p=this.height-p),e.vertex(h,p),o.drawConnections&&l%o.connectionSpacing<1&&this._drawConnections(e,h,p,d.reach)}e.endShape()}_drawConnections(e,t,i,a){const o=this.params;if(this._particles&&this._particles.length>0){e.stroke(o.colorHue,o.colorSaturation,o.colorBrightness,o.connectionOpacity),e.strokeWeight(.5);for(const o of this._particles)Math.sqrt((t-o.x)**2+(i-o.y)**2)<a&&Math.random()<.05&&e.line(t,i,o.x,o.y);e.stroke(o.colorHue,o.colorSaturation,o.colorBrightness,90),e.strokeWeight(o.strokeWeight)}}getMelodyPoints(){return this._melodyPoints}}window.DirectionalPlayback=DirectionalPlayback,window.VideoLoop=VideoLoop,window.SpinningStar=SpinningStar,window.NoiseLayer=NoiseLayer,window.DrawWaveform=DrawWaveform,window.SolidColor=SolidColor,window.MelodyTrace=MelodyTrace;class BaseFilter{constructor(){this.enabled=!1,this.params={...this.getDefaultParams()},this._time=0}getDefaultParams(){return{}}getParameters(){return[]}setParameter(e,t){this.params.hasOwnProperty(e)&&(this.params[e]=t)}setParameters(e){Object.entries(e).forEach(([e,t])=>this.setParameter(e,t))}setEnabled(e){this.enabled=e}update(e){this._time+=e}processPixels(e,t,i){return e}processGraphics(e,t,i){e.loadPixels();const a=this.processPixels(e.pixels,t,i);if(a!==e.pixels)for(let t=0;t<a.length;t++)e.pixels[t]=a[t];e.updatePixels()}needsGraphicsAccess(){return!1}dispose(){}}const FilterRegistry={_filters:new Map,register(e,t){this._filters.set(e,t)},get(e){return this._filters.get(e)||null},create(e){const t=this.get(e);return t?new t:null}};class VhsFilter extends BaseFilter{static filterType="main";static displayName="VHS";static description="Retro video tape artifacts";getDefaultParams(){return{scanlines:.3,colorBleed:5,noise:.1,tracking:.5,jitter:2}}getParameters(){return[{name:"scanlines",type:"range",min:0,max:1,step:.01,label:"Scanlines"},{name:"colorBleed",type:"range",min:0,max:20,step:1,label:"Color Bleed"},{name:"noise",type:"range",min:0,max:.5,step:.01,label:"Noise"},{name:"tracking",type:"range",min:0,max:1,step:.01,label:"Tracking Error"},{name:"jitter",type:"range",min:0,max:10,step:1,label:"Horizontal Jitter"}]}processPixels(e,t,i){const a=this.params.scanlines,o=Math.floor(this.params.colorBleed),s=this.params.noise,n=this.params.tracking,r=this.params.jitter,output=new Uint8ClampedArray(e.length),l=.1*this._time,h=e=>{const t=43758.5453*Math.sin(e+l);return t-Math.floor(t)},c=[];if(n>0){const e=Math.floor(5*n)+1;for(let t=0;t<e;t++){const e=Math.floor(h(100*t)*i),a=Math.floor(20*h(100*t+50))+5;c.push({start:e,height:a})}}for(let l=0;l<i;l++){let i=0;for(const e of c)if(l>=e.start&&l<e.start+e.height){i=Math.floor(50*(h(l)-.5)*n);break}const d=r>0?Math.floor((h(l+1e3)-.5)*r*2):0;for(let n=0;n<t;n++){const r=Math.min(Math.max(n+i+d,0),t-1),c=4*(l*t+n),p=4*(l*t+r);let m,u,b;if(o>0){const i=Math.min(Math.max(r-o,0),t-1),a=Math.min(Math.max(r+o,0),t-1);m=e[4*(l*t+i)],u=e[p+1],b=e[4*(l*t+a)+2]}else m=e[p],u=e[p+1],b=e[p+2];if(s>0){const e=255*(h(n*t+l)-.5)*s;m=Math.min(255,Math.max(0,m+e)),u=Math.min(255,Math.max(0,u+e)),b=Math.min(255,Math.max(0,b+e))}if(a>0&&l%2==0){const e=1-.5*a;m*=e,u*=e,b*=e}output[c]=m,output[c+1]=u,output[c+2]=b,output[c+3]=e[p+3]}}return output}}FilterRegistry.register("vhs",VhsFilter);class AudioEngine{constructor(){this._audioContext=null,this._analyser=null,this._gainNode=null,this._sourceNode=null,this._audioBuffer=null,this.isLoaded=!1,this.isPlaying=!1,this._spectrum=null,this._waveform=null,this._energy={bass:0,lowMid:0,mid:0,highMid:0,treble:0},this._amplitude=0,this.beatThreshold=.15,this.beatCooldown=100,this.lastBeatTime=0,this.beatDetected=!1,this._startOffset=0,this._lastStartTime=0,this._lastStartOffset=0,this.energyBands={bass:[20,140],lowMid:[140,400],mid:[400,2600],highMid:[2600,5200],treble:[5200,14e3]},this._forwardBuffer=null,this._reverseBuffer=null,this._directionalEnabled=!1,this._isForward=!0,this._savedDirectionalPosition=0}_getContext(){return this._audioContext||(this._audioContext=new(window.AudioContext||window.webkitAudioContext)),this._audioContext}init(){const e=this._getContext();this._analyser=e.createAnalyser(),this._analyser.fftSize=2048,this._analyser.smoothingTimeConstant=.8,this._gainNode=e.createGain(),this._gainNode.connect(e.destination),this._analyser.connect(e.destination),this._spectrum=new Uint8Array(this._analyser.frequencyBinCount),this._waveform=new Uint8Array(this._analyser.frequencyBinCount)}async resume(){const e=this._getContext();"suspended"===e.state&&await e.resume()}async loadFromUrl(e){try{const t=this._getContext(),i=await fetch(e);if(!i.ok)throw new Error("Failed to fetch audio: "+i.status);const a=await i.arrayBuffer();this._audioBuffer=await t.decodeAudioData(a),this._forwardBuffer=this._audioBuffer,this.isLoaded=