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