audio-inspect
Version:
Lightweight yet powerful audio analysis library
2 lines (1 loc) • 24.2 kB
JavaScript
"use strict";var ge=Object.create;var O=Object.defineProperty;var Ae=Object.getOwnPropertyDescriptor;var xe=Object.getOwnPropertyNames;var Ie=Object.getPrototypeOf,Te=Object.prototype.hasOwnProperty;var Se=(e,t)=>{for(var a in t)O(e,a,{get:t[a],enumerable:!0})},j=(e,t,a,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of xe(t))!Te.call(e,n)&&n!==a&&O(e,n,{get:()=>t[n],enumerable:!(r=Ae(t,n))||r.enumerable});return e};var ve=(e,t,a)=>(a=e!=null?ge(Ie(e)):{},j(t||!e||!e.__esModule?O(a,"default",{value:e,enumerable:!0}):a,e)),Me=e=>j(O({},"__esModule",{value:!0}),e);var tt={};Se(tt,{computeDeltaCoefficients:()=>de,getCQT:()=>Ye,getMFCC:()=>he,getMFCCWithDelta:()=>et,getMelSpectrogram:()=>Xe,getSpectralCrest:()=>Qe,getSpectralEntropy:()=>$e,getSpectralFeatures:()=>_e,getTimeVaryingSpectralFeatures:()=>Ue});module.exports=Me(tt);var b=class e extends Error{name="AudioInspectError";code;cause;details;constructor(t,a,r,n){super(a,{cause:r}),this.code=t,this.cause=r,this.details=n,Error.captureStackTrace&&Error.captureStackTrace(this,e)}};function Pe(e){return Array.isArray(e)}function N(e,t="mix"){if(e.numberOfChannels<=0)throw new b("INVALID_INPUT","No channels available");let a=Array.from({length:e.numberOfChannels},(o,i)=>i),r;if(t==="mix")r=a;else{if(t==="all")throw new b("INVALID_INPUT",'Channel selector "all" is not supported for scalar results; use "mix" or a single channel index');if(Pe(t)){if(t.length===0)throw new b("INVALID_INPUT","Channel selection array cannot be empty");if(t.length>1)throw new b("INVALID_INPUT",'Multi-channel selector arrays are not supported for scalar results; use "mix" or a single channel index');r=t.slice()}else if(typeof t=="number"){if(!Number.isInteger(t))throw new b("INVALID_INPUT",`Invalid channel number: ${t}`);r=[t]}else throw new b("INVALID_INPUT",`Invalid channel selector: ${String(t)}`)}for(let o of r){if(o<0||o>=e.numberOfChannels)throw new b("INVALID_INPUT",`Invalid channel number: ${o}`);if(!e.channelData[o])throw new b("INVALID_INPUT",`Channel ${o} data does not exist`)}if(r.length===1){let o=r[0];return e.channelData[o]}let n=new Float32Array(e.length);for(let o=0;o<e.length;o++){let i=0;for(let s of r){let l=e.channelData[s];l&&o<l.length&&(i+=l[o])}n[o]=i/r.length}return n}function Re(e){return Number.isInteger(e)&&e>0&&(e&e-1)===0}function G(e){if(!Number.isFinite(e)||e<=1)return 1;if(Re(e))return e;let t=1;for(;t<e&&t<Number.MAX_SAFE_INTEGER;)t*=2;return t}function H(e,t){let a=new Float32Array(e/2+1),r=t/e;for(let n=0;n<a.length;n++)a[n]=n*r;return a}var k=class{constructor(t,a,r=!1){this.size=t;this.sampleRate=a;this.enableProfiling=r;this.complexInput=new Float32Array(this.size*2),this.frequencyBins=H(this.size,this.sampleRate),this.initializationPromise=this.initializeWebFFT()}fftInstance=null;initializationPromise=null;complexInput;frequencyBins;get name(){return"WebFFT"}async waitForInitialization(){this.initializationPromise&&await this.initializationPromise}async initializeWebFFT(){try{let a=(await import("webfft")).default;this.fftInstance=new a(this.size),this.enableProfiling&&this.fftInstance?.profile&&await this.fftInstance.profile()}catch(t){throw new b("UNSUPPORTED_FORMAT",`Failed to initialize WebFFT: ${t instanceof Error?t.message:String(t)}`)}}async fft(t){if(this.initializationPromise&&await this.initializationPromise,!this.fftInstance)throw new b("UNSUPPORTED_FORMAT","WebFFT initialization failed");if(t.length!==this.size)throw new b("INVALID_INPUT",`Invalid input size. Expected: ${this.size}, Actual: ${t.length}`);for(let o=0;o<this.size;o++)this.complexInput[o*2]=t[o],this.complexInput[o*2+1]=0;let a=this.fftInstance.fft(this.complexInput),r=new Float32Array(this.size/2+1),n=new Float32Array(this.size/2+1);for(let o=0;o<r.length;o++){let i=a[o*2],s=a[o*2+1];r[o]=Math.sqrt(i*i+s*s),n[o]=Math.atan2(s,i)}return{complex:a,magnitude:r,phase:n,frequencies:this.frequencyBins}}async profile(){if(this.initializationPromise&&await this.initializationPromise,!this.fftInstance||!this.fftInstance.profile)throw new b("UNSUPPORTED_FORMAT","WebFFT is not initialized");await this.fftInstance.profile()}dispose(){if(this.fftInstance)try{this.fftInstance.dispose&&this.fftInstance.dispose()}catch(t){console.warn("FFT instance disposal failed:",t)}finally{this.fftInstance=null,this.initializationPromise=null}}},W=class{constructor(t,a){this.size=t;this.sampleRate=a;if(!this.isPowerOfTwo(t))throw new b("INVALID_INPUT","FFT size must be a power of two");this.precomputeTables()}bitReversalTable;twiddleFactorsReal;twiddleFactorsImag;scratchReal;scratchImag;frequencyBins;get name(){return"Native FFT (Cooley-Tukey)"}isPowerOfTwo(t){return t>0&&(t&t-1)===0}precomputeTables(){this.bitReversalTable=new Uint32Array(this.size);let t=Math.log2(this.size);for(let r=0;r<this.size;r++){let n=0;for(let o=0;o<t;o++)n=n<<1|r>>o&1;this.bitReversalTable[r]=n}let a=this.size/2;this.twiddleFactorsReal=new Float32Array(a),this.twiddleFactorsImag=new Float32Array(a);for(let r=0;r<a;r++){let n=-2*Math.PI*r/this.size;this.twiddleFactorsReal[r]=Math.cos(n),this.twiddleFactorsImag[r]=Math.sin(n)}this.scratchReal=new Float32Array(this.size),this.scratchImag=new Float32Array(this.size),this.frequencyBins=H(this.size,this.sampleRate)}fft(t){if(t.length!==this.size)throw new b("INVALID_INPUT",`Invalid input size. Expected: ${this.size}, Actual: ${t.length}`);let a=this.scratchReal,r=this.scratchImag;for(let s=0;s<this.size;s++){let l=this.bitReversalTable[s];a[l]=t[s],r[l]=0}for(let s=1;s<this.size;s*=2){let l=s*2,c=this.size/l;for(let m=0;m<this.size;m+=l)for(let u=0;u<s;u++){let d=u*c,h=this.twiddleFactorsReal[d],F=this.twiddleFactorsImag[d],p=m+u,f=m+u+s,y=a[p],g=r[p],w=a[f],x=r[f],S=w*h-x*F,A=w*F+x*h;a[p]=y+S,r[p]=g+A,a[f]=y-S,r[f]=g-A}}let n=new Float32Array(this.size*2),o=new Float32Array(this.size/2+1),i=new Float32Array(this.size/2+1);for(let s=0;s<this.size;s++)if(n[s*2]=a[s],n[s*2+1]=r[s],s<=this.size/2){let l=a[s],c=r[s];o[s]=Math.sqrt(l*l+c*c),i[s]=Math.atan2(c,l)}return{complex:n,magnitude:o,phase:i,frequencies:this.frequencyBins}}dispose(){this.scratchReal=new Float32Array(0),this.scratchImag=new Float32Array(0),this.bitReversalTable=new Uint32Array(0),this.twiddleFactorsReal=new Float32Array(0),this.twiddleFactorsImag=new Float32Array(0),this.frequencyBins=new Float32Array(0)}},E=class{static async createProvider(t){switch(t.type){case"webfft":{let a=new k(t.fftSize,t.sampleRate,t.enableProfiling);return await a.waitForInitialization(),a}case"native":return new W(t.fftSize,t.sampleRate);case"custom":if(!t.customProvider)throw new b("INVALID_INPUT","Custom provider is not specified");return t.customProvider;default:{let a=t.type;throw new b("UNSUPPORTED_FORMAT",`Unsupported FFT provider: ${String(a)}`)}}}static getAvailableProviders(){return["webfft","native"]}};function ze(e){let t=e.provider??"native",a=e.enableProfiling?1:0,r=e.fallbackToNative?1:0;return`${t}|${e.fftSize}|${e.sampleRate}|${a}|${r}`}var _=class{providers=new Map;async getOrCreate(t){let a=ze(t),r=this.providers.get(a);if(r)return r;let n=await Z(t);return this.providers.set(a,n),n}clear(){for(let t of this.providers.values())t.dispose();this.providers.clear()}},Ce=new _;async function q(e){let{cache:t,useSharedCache:a=!1,...r}=e,n=t??(a?Ce:void 0);if(n)return{provider:await n.getOrCreate(r),release:()=>{}};let o=await Z(r);return{provider:o,release:()=>{o.dispose()}}}async function Z(e){let{fftSize:t,sampleRate:a,provider:r="native",enableProfiling:n=!1,fallbackToNative:o=r==="webfft",resolver:i=E}=e,s=o&&r!=="native"?[r,"native"]:[r],l;for(let c of s)try{return await i.createProvider({type:c,fftSize:t,sampleRate:a,enableProfiling:n})}catch(m){l=m}throw new b("INITIALIZATION_FAILED","Failed to create FFT provider",l)}function U(e,t=1,a=-1/0){return!Number.isFinite(e)||!Number.isFinite(t)||e<=0||t<=0?a:20*Math.log10(e/t)}function Y(e){return e==="none"?"rectangular":e}function Ne(e,t,a){let r=a?.kaiserBeta??8.6,n=a?.tukeyAlpha??.5;return`${t}|${e}|${r}|${n}`}function X(e){let t=1,a=1,r=e*e/4;for(let n=1;n<50&&(a*=r/(n*n),t+=a,!(a<1e-10*t));n++);return t}function qe(e,t,a){if(!Number.isInteger(e)||e<0)throw new b("INVALID_INPUT",`Invalid window length: ${e}`);if(e===0)return new Float32Array(0);let r=new Float32Array(e);if(e===1||t==="rectangular")return r.fill(1),r;switch(t){case"hann":{for(let n=0;n<e;n++)r[n]=.5*(1-Math.cos(2*Math.PI*n/(e-1)));return r}case"hamming":{for(let n=0;n<e;n++)r[n]=.54-.46*Math.cos(2*Math.PI*n/(e-1));return r}case"blackman":{for(let n=0;n<e;n++)r[n]=.42-.5*Math.cos(2*Math.PI*n/(e-1))+.08*Math.cos(4*Math.PI*n/(e-1));return r}case"bartlett":{for(let n=0;n<e;n++)r[n]=1-Math.abs((n-(e-1)/2)/((e-1)/2));return r}case"kaiser":{let n=a?.kaiserBeta??8.6,o=X(n);for(let i=0;i<e;i++){let s=2*i/(e-1)-1;r[i]=X(n*Math.sqrt(1-s*s))/o}return r}case"tukey":{let n=a?.tukeyAlpha??.5;if(n<=0)return r.fill(1),r;if(n>=1){for(let i=0;i<e;i++)r[i]=.5*(1-Math.cos(2*Math.PI*i/(e-1)));return r}let o=n*(e-1)/2;for(let i=0;i<e;i++)i<o?r[i]=.5*(1+Math.cos(Math.PI*(2*i/(n*(e-1))-1))):i<=(e-1)*(1-n/2)?r[i]=1:r[i]=.5*(1+Math.cos(Math.PI*(2*i/(n*(e-1))-2/n+1)));return r}default:throw new b("INVALID_INPUT",`Unknown window type: ${String(t)}`)}}var L=class{cache=new Map;getOrCreate(t,a,r){let n=Y(a),o=Ne(t,n,r),i=this.cache.get(o);if(i)return i;let s=qe(t,n,r);return this.cache.set(o,s),s}clear(){this.cache.clear()}},J=new L;function ee(e,t,a){return J.getOrCreate(e,t,a)}function D(e){let{src:t,srcStart:a,frameLength:r,dst:n,windowType:o,windowParams:i,cache:s=J}=e;if(n.fill(0),n.length===0||r<=0||a>=t.length)return n;let l=Math.max(0,a),c=Math.min(r,n.length),m=Math.max(0,Math.min(c,t.length-l));if(m===0)return n;let u=Y(o);if(u==="rectangular"||c===1)return n.set(t.subarray(l,l+m),0),n;let d=s.getOrCreate(c,u,i);for(let h=0;h<m;h++)n[h]=t[l+h]*d[h];return n}var V=new WeakMap;function De(e){return Array.isArray(e)?`[${e.map(t=>String(t)).join(",")}]`:String(e)}function Oe(e){return[e.fftSize,e.windowFunction,De(e.channel),e.provider,e.enableProfiling?1:0,e.normalization].join("|")}function Ee(e,t){if(!Number.isInteger(e)||e<=0||(e&e-1)!==0)throw new b("INVALID_INPUT",`${t} must be a power of two`)}function Be(e,t){if(t<=1||e==="none")return 1;let a=ee(t,e),r=0;for(let o=0;o<a.length;o++)r+=a[o]??0;let n=r/t;return n>0?n:1}function ke(e,t,a,r){if(t==="none")return e;if(a<=0||e.length===0)return e.fill(0),e;let n=Be(r,a),o=a*n;if(o<=0)return e.fill(0),e;let i=1/o,s=i*2,l=e.length-1;for(let c=0;c<e.length;c++){let m=c===0||c===l?i:s;e[c]=(e[c]??0)*m}return e}async function B(e,t={}){let{fftSize:a=2048,windowFunction:r="hann",channel:n="mix",provider:o="native",enableProfiling:i=!1,providerCache:s,normalization:l="amplitude"}=t;Ee(a,"FFT size");let c=Oe({fftSize:a,windowFunction:r,channel:n,provider:o,enableProfiling:i,normalization:l}),m=V.get(e);m||(m=new Map,V.set(e,m));let u=m.get(c);if(u)return u;let d=(async()=>{let F=N(e,n),p=new Float32Array(a),f=Math.min(F.length,a);D({src:F,srcStart:0,frameLength:f,dst:p,windowType:r});let{provider:y,release:g}=await q({fftSize:a,sampleRate:e.sampleRate,provider:o,enableProfiling:i,fallbackToNative:o==="webfft",cache:s});try{let w=await y.fft(p),x=new Float32Array(w.magnitude);return ke(x,l,f,r),{...w,magnitude:x,fftSize:a,windowFunction:r,providerName:y.name,normalization:l}}finally{g()}})();m.set(c,d);let h=()=>{m.delete(c),m.size===0&&V.delete(e)};return d.then(h,h),d}function oe(e,t,a,r){let n=0,o=0;for(let i=0;i<e.length&&i<t.length;i++){let s=t[i],l=e[i];s>=a&&s<=r&&(n+=s*l,o+=l)}return o>1e-10?n/o:0}function ie(e,t,a,r,n){let o=0,i=0;for(let s=0;s<e.length&&s<t.length;s++){let l=t[s],c=e[s];if(l>=r&&l<=n){let m=l-a;o+=m*m*c,i+=c}}return i>1e-10?Math.sqrt(o/i):0}function se(e,t,a,r,n){let o=0;for(let l=0;l<e.length&&l<t.length;l++){let c=t[l],m=e[l];c>=r&&c<=n&&(o+=m*m)}let i=o*a,s=0;for(let l=0;l<e.length&&l<t.length;l++){let c=t[l],m=e[l];if(c>=r&&c<=n&&(s+=m*m,s>=i))return c}return n}function le(e,t,a){let r=0,n=0,o=0;for(let i=t;i<=a&&i<e.length;i++){let s=Math.max(e[i],1e-10);r+=Math.log(s),n+=s,o++}return o===0?0:(r=Math.exp(r/o),n=n/o,n>1e-10?r/n:0)}function ce(e){if(e.length<2)return 0;let t=0;for(let a=1;a<e.length;a++){let r=e[a-1],n=e[a];(r>=0&&n<0||r<0&&n>=0)&&t++}return t/(e.length-1)}function We(e,t,a={normalize:!0}){if(!t||t.length===0)return 0;let r=Math.min(e.length,t.length);if(r===0)return 0;if(a.normalize!==!1){let o=0,i=0;for(let c=0;c<r;c++){let m=e[c],u=t[c];o+=m*m,i+=u*u}let s=Math.sqrt(o),l=Math.sqrt(i);if(s>1e-10&&l>1e-10){let c=1/s,m=1/l,u=0;for(let d=0;d<r;d++){let h=e[d]*c-t[d]*m;u+=h*h}return Math.sqrt(u)}}let n=0;for(let o=0;o<r;o++){let i=e[o]-t[o];n+=i*i}return Math.sqrt(n)}async function _e(e,t={}){let{fftSize:a=2048,windowFunction:r="hann",channel:n="mix",provider:o="native",enableProfiling:i=!1,providerCache:s,minFrequency:l=0,maxFrequency:c=e.sampleRate/2,rolloffThreshold:m=.85}=t,u=N(e,n),d=await B(e,{fftSize:a,windowFunction:r,channel:n,provider:o,enableProfiling:i,providerCache:s}),h=Math.max(0,Math.floor(l*a/e.sampleRate)),F=Math.min(d.frequencies.length-1,Math.floor(c*a/e.sampleRate)),p=oe(d.magnitude,d.frequencies,l,c),f=ie(d.magnitude,d.frequencies,p,l,c),y=se(d.magnitude,d.frequencies,m,l,c),g=le(d.magnitude,h,F),w=ce(u);return{spectralCentroid:p,spectralBandwidth:f,spectralRolloff:y,spectralFlatness:g,spectralFlux:0,zeroCrossingRate:w,frequencyRange:{min:l,max:c}}}async function Ue(e,t={}){let{frameSize:a=2048,hopSize:r=a/2,fftSize:n=a,windowFunction:o="hann",channel:i="mix",provider:s="native",enableProfiling:l=!1,providerCache:c,minFrequency:m=0,maxFrequency:u=e.sampleRate/2,rolloffThreshold:d=.85,numFrames:h}=t,F=N(e,i),p=Math.floor((F.length-a)/r)+1,f=h??(F.length>0?Math.max(1,p):0);if(f<=0||F.length===0)throw new b("INVALID_INPUT","Invalid frame count");let y=new Float32Array(f),g=new Float32Array(f),w=new Float32Array(f),x=new Float32Array(f),S=new Float32Array(f),A=new Float32Array(f),T=new Float32Array(f),v=new Float32Array(n),C,{provider:R,release:M}=await q({fftSize:n,sampleRate:e.sampleRate,provider:s,enableProfiling:l,fallbackToNative:s==="webfft",cache:c});try{for(let I=0;I<f;I++){let P=I*r,Fe=Math.min(P+a,F.length);y[I]=P/e.sampleRate;let be=F.subarray(P,Fe);D({src:F,srcStart:P,frameLength:Math.min(a,Math.max(0,F.length-P)),dst:v,windowType:o});let z=await R.fft(v),ye=Math.max(0,Math.floor(m*n/e.sampleRate)),we=Math.min(z.frequencies.length-1,Math.floor(u*n/e.sampleRate)),K=oe(z.magnitude,z.frequencies,m,u);g[I]=K,w[I]=ie(z.magnitude,z.frequencies,K,m,u),x[I]=se(z.magnitude,z.frequencies,d,m,u),S[I]=le(z.magnitude,ye,we),T[I]=ce(be),A[I]=We(z.magnitude,C),C=new Float32Array(z.magnitude)}}finally{M()}return{times:y,spectralCentroid:g,spectralBandwidth:w,spectralRolloff:x,spectralFlatness:S,spectralFlux:A,zeroCrossingRate:T,frameInfo:{frameSize:a,hopSize:r,numFrames:f}}}function Le(e,t,a){let r=[],n=0;for(let c=t;c<=a&&c<e.length;c++){let m=e[c];if(m!==void 0){let u=m*m;r.push(u),n+=u}}if(r.length===0||n<=1e-10)return{entropy:0,entropyNorm:0};let o=r.map(c=>c/n),i=0;for(let c of o)c>1e-10&&(i-=c*Math.log2(c));let s=Math.log2(r.length),l=s>0?i/s:0;return{entropy:i,entropyNorm:l}}function Ve(e,t,a){let r=0,n=0,o=0;for(let l=t;l<=a&&l<e.length;l++){let c=e[l];c!==void 0&&(r=Math.max(r,c),n+=c,o++)}if(o===0)return{crest:0,peak:0,average:0};let i=n/o;return{crest:i>1e-10?r/i:0,peak:r,average:i}}async function $e(e,t={}){let{fftSize:a=2048,windowFunction:r="hann",channel:n="mix",provider:o="native",enableProfiling:i=!1,providerCache:s,minFrequency:l=0,maxFrequency:c=e.sampleRate/2}=t,m=await B(e,{fftSize:a,windowFunction:r,channel:n,provider:o,enableProfiling:i,providerCache:s}),u=Math.max(0,Math.floor(l*a/e.sampleRate)),d=Math.min(m.frequencies.length-1,Math.floor(c*a/e.sampleRate)),{entropy:h,entropyNorm:F}=Le(m.magnitude,u,d);return{entropy:h,entropyNorm:F,frequencyRange:{min:l,max:c}}}async function Qe(e,t={}){let{fftSize:a=2048,windowFunction:r="hann",channel:n="mix",provider:o="native",enableProfiling:i=!1,providerCache:s,minFrequency:l=0,maxFrequency:c=e.sampleRate/2,asDB:m=!1}=t,u=await B(e,{fftSize:a,windowFunction:r,channel:n,provider:o,enableProfiling:i,providerCache:s}),d=Math.max(0,Math.floor(l*a/e.sampleRate)),h=Math.min(u.frequencies.length-1,Math.floor(c*a/e.sampleRate)),{crest:F,peak:p,average:f}=Ve(u.magnitude,d,h),y={crest:F,peak:p,average:f,frequencyRange:{min:l,max:c}};return m&&(y.crestDB=U(F,1)),y}var te=new Map,re=new Map;function Ke(e,t,a,r,n){return`${e}|${t}|${a}|${r}|${n}`}function je(e,t,a,r,n){return`${e}|${t}|${a}|${r}|${n??"auto"}`}function ne(e){return 2595*Math.log10(1+e/700)}function ae(e){return 700*(Math.pow(10,e/2595)-1)}function me(e,t,a,r,n){let o=Ke(e,t,a,r,n),i=te.get(o);if(i)return i;let s=[],l=a/2,c=Math.floor(t/2)+1,m=ne(r),u=ne(n),d=new Array(e+2);for(let f=0;f<e+2;f++)d[f]=m+(u-m)*f/(e+1);let h=new Float32Array(e),F=d.map(f=>{let y=ae(f);return Math.floor(y/l*(c-1))});for(let f=1;f<=e;f++){let y=new Float32Array(c),g=F[f-1],w=F[f],x=F[f+1];if(g===void 0||w===void 0||x===void 0)continue;let S=d[f];S!==void 0&&(h[f-1]=ae(S));for(let A=g;A<=x;A++)A<0||A>=c||A>=y.length||(A<w?w-g>0&&(y[A]=(A-g)/(w-g)):x-w>0&&(y[A]=(x-A)/(x-w)));s.push(y)}let p={filters:s,centerFrequencies:h};return te.set(o,p),p}function $(e,t,a,r){let n=a.frameSizeMs??25,o=a.hopSizeMs??10,i=Math.round(n/1e3*e.sampleRate),s=Math.round(o/1e3*e.sampleRate),l=a.fftSize??Math.max(1024,G(i));if(i<=0||s<=0)throw new b("INVALID_INPUT","Frame size or hop size is too small");if(l<=0||(l&l-1)!==0)throw new b("INVALID_INPUT","FFT size must be a power of two");let c=Math.floor((t-i)/s)+1,m=t>0?Math.max(1,c):0;if(m<=0)throw new b("INSUFFICIENT_DATA","Invalid frame count");return{frameSizeMs:n,hopSizeMs:o,frameSizeSamples:i,hopSizeSamples:s,fftSize:l,windowFunction:a.windowFunction??r,channel:a.channel??"mix",numFrames:m}}function ue(e){let t=e??2;if(!Number.isFinite(t)||t<=0)throw new b("INVALID_INPUT","power must be a positive finite number");return t}function fe(e,t){let a=new Float32Array(e.length);if(t===1)return a.set(e),a;if(t===2){for(let r=0;r<e.length;r++){let n=e[r];a[r]=n*n}return a}for(let r=0;r<e.length;r++){let n=e[r];a[r]=Math.pow(n,t)}return a}function pe(e,t,a){let r=new Float32Array(t.length);for(let n=0;n<t.length;n++){let o=t[n];if(!o)continue;let i=0;for(let s=0;s<o.length&&s<e.length;s++)i+=e[s]*o[s];r[n]=Math.max(i,a)}return r}function Ge(e,t,a,r,n){let o=je(e,t,a,r,n),i=re.get(o);if(i)return i;let s=t/2,l=t/e,c=Math.floor(e/2);if(!Number.isFinite(a)||a<=0)throw new b("INVALID_INPUT","fMin must be a positive number");if(!Number.isFinite(r)||r<=0)throw new b("INVALID_INPUT","binsPerOctave must be a positive number");if(n!==void 0&&(!Number.isFinite(n)||n<=0))throw new b("INVALID_INPUT","numBins must be a positive number");let m=Math.max(1,Math.floor(r*Math.log2(s/a))),u=Math.min(n??m,m),d=1/(2*r),h=[];for(let F=0;F<u;F++){let p=a*Math.pow(2,F/r);if(p<=0||p>=s)break;let f=Math.max(0,p*Math.pow(2,-d)),y=Math.min(s,p*Math.pow(2,d)),g=Math.max(1,Math.floor(f/l)),w=Math.min(c,Math.ceil(y/l));w<g||h.push({centerFrequency:p,lowerFrequency:f,upperFrequency:y,startIndex:g,endIndex:w})}if(h.length===0)throw new b("INVALID_INPUT","Failed to build CQT frequency bins. Review fMin/numBins settings.");return re.set(o,h),h}function He(e,t,a,r,n,o){let i=1/(2*n),s=0,l=0;for(let u=t.startIndex;u<=t.endIndex;u++){let d=u*a/r;if(d<=0)continue;let h=Math.abs(Math.log2(d/t.centerFrequency));if(h>i)continue;let F=1-h/i,p=e[u],f=o===1?p:o===2?p*p:Math.pow(p,o);s+=f*F,l+=F}if(l>1e-10)return s/l;let c=Math.min(Math.floor(t.centerFrequency*r/a),e.length-1),m=c>=0?e[c]:0;return o===1?m:o===2?m*m:Math.pow(m,o)}function Ze(e,t){let a=e.length,r=new Array(t);for(let n=0;n<t;n++){let o=0;for(let s=0;s<a;s++){let l=e[s];l!==void 0&&(o+=l*Math.cos(Math.PI*n*(s+.5)/a))}let i=Math.sqrt(n===0?1/a:2/a);r[n]=o*i}return r}function Q(e,t){let a=new Float32Array(e.length);if(e.length===0)return a;a[0]=e[0];for(let r=1;r<e.length;r++)a[r]=e[r]-t*e[r-1];return a}async function Xe(e,t={}){let{numMelFilters:a=80,minFrequency:r=0,maxFrequency:n=e.sampleRate/2,preEmphasis:o=.97,provider:i="native",enableProfiling:s=!1,providerCache:l,power:c,logScale:m=!0,logEpsilon:u=1e-10}=t,d=ue(c),h=N(e,t.channel??"mix"),F=Q(h,o),p=$(e,F.length,t,"hamming"),f=me(a,p.fftSize,e.sampleRate,r,n),y=[],g=new Float32Array(p.numFrames),w=new Float32Array(p.fftSize),{provider:x,release:S}=await q({fftSize:p.fftSize,sampleRate:e.sampleRate,provider:i,enableProfiling:s,fallbackToNative:i==="webfft",cache:l});try{for(let A=0;A<p.numFrames;A++){let T=A*p.hopSizeSamples;g[A]=T/e.sampleRate,D({src:F,srcStart:T,frameLength:Math.min(p.frameSizeSamples,Math.max(0,F.length-T)),dst:w,windowType:p.windowFunction});let v=await x.fft(w),C=fe(v.magnitude,d),R=pe(C,f.filters,u),M=new Array(R.length);for(let I=0;I<R.length;I++){let P=R[I];M[I]=m?Math.log(Math.max(P,u)):P}y.push(M)}}finally{S()}return{melSpectrogram:y,times:g,melFrequencies:f.centerFrequencies,frameInfo:{frameSizeMs:p.frameSizeMs,hopSizeMs:p.hopSizeMs,numFrames:p.numFrames,numBins:f.filters.length},frequencyRange:{min:r,max:n}}}async function Ye(e,t={}){let{fMin:a=32.70319566257483,binsPerOctave:r=12,numBins:n,preEmphasis:o=.97,provider:i="native",enableProfiling:s=!1,providerCache:l,power:c,logScale:m=!0,logEpsilon:u=1e-10}=t,d=ue(c),h=N(e,t.channel??"mix"),F=Q(h,o),p=$(e,F.length,t,"hann"),f=Ge(p.fftSize,e.sampleRate,a,r,n),y=new Float32Array(f.length);for(let T=0;T<f.length;T++)y[T]=f[T].centerFrequency;let g=[],w=new Float32Array(p.numFrames),x=new Float32Array(p.fftSize),{provider:S,release:A}=await q({fftSize:p.fftSize,sampleRate:e.sampleRate,provider:i,enableProfiling:s,fallbackToNative:i==="webfft",cache:l});try{for(let T=0;T<p.numFrames;T++){let v=T*p.hopSizeSamples;w[T]=v/e.sampleRate,D({src:F,srcStart:v,frameLength:Math.min(p.frameSizeSamples,Math.max(0,F.length-v)),dst:x,windowType:p.windowFunction});let C=await S.fft(x),R=new Array(f.length);for(let M=0;M<f.length;M++){let I=f[M];if(!I)continue;let P=He(C.magnitude,I,e.sampleRate,p.fftSize,r,d);R[M]=m?Math.log(Math.max(P,u)):P}g.push(R)}}finally{A()}return{cqt:g,times:w,frequencies:y,frameInfo:{frameSizeMs:p.frameSizeMs,hopSizeMs:p.hopSizeMs,numFrames:p.numFrames,numBins:y.length,binsPerOctave:r},frequencyRange:{min:f[0]?.lowerFrequency??a,max:f[f.length-1]?.upperFrequency??e.sampleRate/2}}}function Je(e,t){return e.map((a,r)=>{if(t===0)return a;let n=1+t/2*Math.sin(Math.PI*r/t);return a*n})}async function he(e,t={}){let{numMelFilters:a=40,numMfccCoeffs:r=13,minFrequency:n=0,maxFrequency:o=e.sampleRate/2,preEmphasis:i=.97,lifterCoeff:s=22,provider:l="native",enableProfiling:c=!1,providerCache:m}=t,u=N(e,t.channel??"mix"),d=Q(u,i),h=$(e,d.length,t,"hamming"),F=me(a,h.fftSize,e.sampleRate,n,o),p=[],f=new Float32Array(h.numFrames),y=new Float32Array(h.fftSize),{provider:g,release:w}=await q({fftSize:h.fftSize,sampleRate:e.sampleRate,provider:l,enableProfiling:c,fallbackToNative:l==="webfft",cache:m});try{for(let x=0;x<h.numFrames;x++){let S=x*h.hopSizeSamples;f[x]=S/e.sampleRate,D({src:d,srcStart:S,frameLength:Math.min(h.frameSizeSamples,Math.max(0,d.length-S)),dst:y,windowType:h.windowFunction});let A=await g.fft(y),T=fe(A.magnitude,2),v=pe(T,F.filters,1e-10),C=new Array(v.length);for(let I=0;I<v.length;I++)C[I]=Math.log(Math.max(v[I],1e-10));let R=Ze(C,r),M=Je(R,s);p.push(M)}}finally{w()}return{mfcc:p,times:f,frameInfo:{frameSizeMs:h.frameSizeMs,hopSizeMs:h.hopSizeMs,numFrames:h.numFrames,numCoeffs:r},frequencyRange:{min:n,max:o}}}function de(e,t=2){let a=e.length,r=e[0]?.length||0,n=[],o=[];for(let i=0;i<a;i++){let s=[];for(let l=0;l<r;l++){let c=0,m=0;for(let u=-t;u<=t;u++){let d=Math.max(0,Math.min(a-1,i+u)),h=e[d]?.[l]||0;c+=u*h,m+=u*u}s[l]=m>0?c/m:0}n.push(s)}for(let i=0;i<a;i++){let s=[];for(let l=0;l<r;l++){let c=0,m=0;for(let u=-t;u<=t;u++){let d=Math.max(0,Math.min(a-1,i+u)),h=n[d]?.[l]||0;c+=u*h,m+=u*u}s[l]=m>0?c/m:0}o.push(s)}return{delta:n,deltaDelta:o}}async function et(e,t={}){let{deltaWindowSize:a=2,computeDelta:r=!0,computeDeltaDelta:n=!0,...o}=t,i=await he(e,o),s={...i};if(r||n){let l=de(i.mfcc,a);r&&(s.delta=l.delta),n&&(s.deltaDelta=l.deltaDelta)}return s}