UNPKG

audio-inspect

Version:

Lightweight yet powerful audio analysis library

2 lines (1 loc) 4.71 kB
var o=class p extends Error{constructor(r,n,i,l){super(n,{cause:i});this.code=r;this.details=l;this.cause=i,Error.captureStackTrace&&Error.captureStackTrace(this,p)}name="AudioInspectError";timestamp=new Date;cause;toJSON(){return{name:this.name,code:this.code,message:this.message,details:this.details,timestamp:this.timestamp,stack:this.stack,cause:this.cause}}};var h=class{constructor(e,r,n=!1){this.size=e;this.sampleRate=r;this.enableProfiling=n;this.initializationPromise=this.initializeWebFFT()}fftInstance=null;initializationPromise=null;get name(){return"WebFFT"}async waitForInitialization(){this.initializationPromise&&await this.initializationPromise}async initializeWebFFT(){try{let r=(await import("webfft")).default;this.fftInstance=new r(this.size),this.enableProfiling&&this.fftInstance?.profile&&await this.fftInstance.profile()}catch(e){throw new o("UNSUPPORTED_FORMAT",`WebFFT\u306E\u521D\u671F\u5316\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${e instanceof Error?e.message:String(e)}`)}}async fft(e){if(this.initializationPromise&&await this.initializationPromise,!this.fftInstance)throw new o("UNSUPPORTED_FORMAT","WebFFT initialization failed");if(e.length!==this.size)throw new o("INVALID_INPUT",`\u5165\u529B\u30B5\u30A4\u30BA\u304C\u4E0D\u6B63\u3067\u3059\u3002\u671F\u5F85\u5024: ${this.size}, \u5B9F\u969B: ${e.length}`);let r=new Float32Array(this.size*2);for(let a=0;a<this.size;a++)r[a*2]=e[a]||0,r[a*2+1]=0;let n=this.fftInstance.fft(r),i=new Float32Array(this.size/2+1),l=new Float32Array(this.size/2+1),u=new Float32Array(this.size/2+1);for(let a=0;a<i.length;a++){let t=n[a*2]||0,s=n[a*2+1]||0;i[a]=Math.sqrt(t*t+s*s),l[a]=Math.atan2(s,t),u[a]=a*this.sampleRate/this.size}return{complex:n,magnitude:i,phase:l,frequencies:u}}async profile(){if(this.initializationPromise&&await this.initializationPromise,!this.fftInstance||!this.fftInstance.profile)throw new o("UNSUPPORTED_FORMAT","WebFFT\u304C\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093");await this.fftInstance.profile()}dispose(){if(this.fftInstance)try{this.fftInstance.dispose&&this.fftInstance.dispose()}catch(e){console.warn("FFT instance disposal failed:",e)}finally{this.fftInstance=null,this.initializationPromise=null}}},F=class{constructor(e,r){this.size=e;this.sampleRate=r;if(!this.isPowerOfTwo(e))throw new o("INVALID_INPUT","FFT\u30B5\u30A4\u30BA\u306F2\u306E\u51AA\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059");this.precomputeTables()}bitReversalTable;twiddleFactorsReal;twiddleFactorsImag;get name(){return"Native FFT (Cooley-Tukey)"}isPowerOfTwo(e){return e>0&&(e&e-1)===0}precomputeTables(){this.bitReversalTable=new Uint32Array(this.size);let e=Math.log2(this.size);for(let n=0;n<this.size;n++){let i=0;for(let l=0;l<e;l++)i=i<<1|n>>l&1;this.bitReversalTable[n]=i}let r=this.size/2;this.twiddleFactorsReal=new Float32Array(r),this.twiddleFactorsImag=new Float32Array(r);for(let n=0;n<r;n++){let i=-2*Math.PI*n/this.size;this.twiddleFactorsReal[n]=Math.cos(i),this.twiddleFactorsImag[n]=Math.sin(i)}}fft(e){if(e.length!==this.size)throw new o("INVALID_INPUT",`\u5165\u529B\u30B5\u30A4\u30BA\u304C\u4E0D\u6B63\u3067\u3059\u3002\u671F\u5F85\u5024: ${this.size}, \u5B9F\u969B: ${e.length}`);let r=new Float32Array(this.size),n=new Float32Array(this.size);for(let t=0;t<this.size;t++){let s=this.bitReversalTable[t];s!==void 0&&(r[s]=e[t]||0,n[s]=0)}for(let t=1;t<this.size;t*=2){let s=t*2,m=this.size/s;for(let f=0;f<this.size;f+=s)for(let c=0;c<t;c++){let y=c*m,A=this.twiddleFactorsReal[y]||0,w=this.twiddleFactorsImag[y]||0,d=f+c,b=f+c+t,R=r[d]||0,g=n[d]||0,v=r[b]||0,T=n[b]||0,P=v*A-T*w,I=v*w+T*A;r[d]=R+P,n[d]=g+I,r[b]=R-P,n[b]=g-I}}let i=new Float32Array(this.size*2),l=new Float32Array(this.size/2+1),u=new Float32Array(this.size/2+1),a=new Float32Array(this.size/2+1);for(let t=0;t<this.size;t++)if(i[t*2]=r[t]||0,i[t*2+1]=n[t]||0,t<=this.size/2){let s=r[t]||0,m=n[t]||0;l[t]=Math.sqrt(s*s+m*m),u[t]=Math.atan2(m,s),a[t]=t*this.sampleRate/this.size}return{complex:i,magnitude:l,phase:u,frequencies:a}}dispose(){}},z=class{static async createProvider(e){switch(e.type){case"webfft":{let r=new h(e.fftSize,e.sampleRate,e.enableProfiling);return await r.waitForInitialization(),r}case"native":return new F(e.fftSize,e.sampleRate);case"custom":if(!e.customProvider)throw new o("INVALID_INPUT","\u30AB\u30B9\u30BF\u30E0\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093");return e.customProvider;default:{let r=e.type;throw new o("UNSUPPORTED_FORMAT",`\u672A\u5BFE\u5FDC\u306EFFT\u30D7\u30ED\u30D0\u30A4\u30C0\u30FC: ${String(r)}`)}}}static getAvailableProviders(){return["webfft","native"]}};export{z as FFTProviderFactory};