audio-inspect
Version:
Lightweight yet powerful audio analysis library
2 lines (1 loc) • 4.92 kB
JavaScript
var s=class e extends Error{name="AudioInspectError";code;cause;details;constructor(a,o,r,n){super(o,{cause:r}),this.code=a,this.cause=r,this.details=n,Error.captureStackTrace&&Error.captureStackTrace(this,e)}};function P(e){return Array.isArray(e)}function N(e,a="mix"){if(e.numberOfChannels<=0)throw new s("INVALID_INPUT","No channels available");let o=Array.from({length:e.numberOfChannels},(i,t)=>t),r;if(a==="mix")r=o;else{if(a==="all")throw new s("INVALID_INPUT",'Channel selector "all" is not supported for scalar results; use "mix" or a single channel index');if(P(a)){if(a.length===0)throw new s("INVALID_INPUT","Channel selection array cannot be empty");if(a.length>1)throw new s("INVALID_INPUT",'Multi-channel selector arrays are not supported for scalar results; use "mix" or a single channel index');r=a.slice()}else if(typeof a=="number"){if(!Number.isInteger(a))throw new s("INVALID_INPUT",`Invalid channel number: ${a}`);r=[a]}else throw new s("INVALID_INPUT",`Invalid channel selector: ${String(a)}`)}for(let i of r){if(i<0||i>=e.numberOfChannels)throw new s("INVALID_INPUT",`Invalid channel number: ${i}`);if(!e.channelData[i])throw new s("INVALID_INPUT",`Channel ${i} data does not exist`)}if(r.length===1){let i=r[0];return e.channelData[i]}let n=new Float32Array(e.length);for(let i=0;i<e.length;i++){let t=0;for(let l of r){let m=e.channelData[l];m&&i<m.length&&(t+=m[i])}n[i]=t/r.length}return n}function T(e,a){let{samples:o,frameSize:r,hopSize:n,sampleRate:i,padEnd:t=!0}=e;if(!Number.isInteger(r)||r<=0)throw new s("INVALID_INPUT","frameSize must be a positive integer");if(!Number.isInteger(n)||n<=0)throw new s("INVALID_INPUT","hopSize must be a positive integer");if(!Number.isFinite(i)||i<=0)throw new s("INVALID_INPUT","sampleRate must be positive");if(o.length===0)return 0;let l=new Float32Array(r),m=0,c=0;for(;c<o.length||m===0&&t;){let d=Math.min(c+r,o.length),u=Math.max(0,d-c);if(u<r&&!t&&m>0||(l.fill(0),u>0&&l.set(o.subarray(c,d),0),a({frame:l,frameIndex:m,startSample:c,timeSec:(c+r/2)/i}),m+=1,c+=n,!t&&c+r>o.length)||u<r&&t)break}return m}function S(e){return e==="none"?"rectangular":e}function C(e,a,o){let r=o?.kaiserBeta??8.6,n=o?.tukeyAlpha??.5;return`${a}|${e}|${r}|${n}`}function R(e){let a=1,o=1,r=e*e/4;for(let n=1;n<50&&(o*=r/(n*n),a+=o,!(o<1e-10*a));n++);return a}function M(e,a,o){if(!Number.isInteger(e)||e<0)throw new s("INVALID_INPUT",`Invalid window length: ${e}`);if(e===0)return new Float32Array(0);let r=new Float32Array(e);if(e===1||a==="rectangular")return r.fill(1),r;switch(a){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=o?.kaiserBeta??8.6,i=R(n);for(let t=0;t<e;t++){let l=2*t/(e-1)-1;r[t]=R(n*Math.sqrt(1-l*l))/i}return r}case"tukey":{let n=o?.tukeyAlpha??.5;if(n<=0)return r.fill(1),r;if(n>=1){for(let t=0;t<e;t++)r[t]=.5*(1-Math.cos(2*Math.PI*t/(e-1)));return r}let i=n*(e-1)/2;for(let t=0;t<e;t++)t<i?r[t]=.5*(1+Math.cos(Math.PI*(2*t/(n*(e-1))-1))):t<=(e-1)*(1-n/2)?r[t]=1:r[t]=.5*(1+Math.cos(Math.PI*(2*t/(n*(e-1))-2/n+1)));return r}default:throw new s("INVALID_INPUT",`Unknown window type: ${String(a)}`)}}var g=class{cache=new Map;getOrCreate(a,o,r){let n=S(o),i=C(a,n,r),t=this.cache.get(i);if(t)return t;let l=M(a,n,r);return this.cache.set(i,l),l}clear(){this.cache.clear()}},O=new g;function D(e,a,o){return O.getOrCreate(e,a,o)}function W(e,a){let o=0;for(let r=0;r<e.length;r++){let n=e[r],i=a?n*a[r]:n;o+=i*i}return o}function Q(e,a={}){let{frameSize:o=Math.floor(e.sampleRate*.025),hopSize:r=Math.floor(e.sampleRate*.01),channel:n="mix",normalized:i=!1,windowFunction:t="rectangular"}=a;if(!Number.isInteger(o)||o<=0)throw new s("INVALID_INPUT","frameSize must be a positive integer");if(!Number.isInteger(r)||r<=0)throw new s("INVALID_INPUT","hopSize must be a positive integer");let l=N(e,n);if(l.length===0)return{times:new Float32Array(0),energies:new Float32Array(0),totalEnergy:0,statistics:{mean:0,std:0,max:0,min:0}};let m=t==="rectangular"||t==="none"?null:D(o,t),c=[],d=[],u=0,y=-1/0,b=1/0;T({samples:l,frameSize:o,hopSize:r,sampleRate:e.sampleRate,padEnd:!0},({frame:p,timeSec:h})=>{let w=W(p,m);c.push(h),d.push(w),u+=w,y=Math.max(y,w),b=Math.min(b,w)});let f=new Float32Array(d),x=new Float32Array(c),A=f.length,I=A>0?u/A:0,F=0;for(let p=0;p<A;p++){let h=f[p]-I;F+=h*h}let E=A>0?Math.sqrt(F/A):0;if(i&&u>1e-10){for(let p=0;p<f.length;p++)f[p]=f[p]/u;return{times:x,energies:f,totalEnergy:1,statistics:{mean:I/u,std:E/u,max:y/u,min:b/u}}}return{times:x,energies:f,totalEnergy:u,statistics:{mean:I,std:E,max:Number.isFinite(y)?y:0,min:Number.isFinite(b)?b:0}}}export{Q as getEnergy};