audio-inspect
Version:
Lightweight yet powerful audio analysis library
2 lines (1 loc) • 5.06 kB
JavaScript
;var v=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var W=(e,r)=>{for(var c in r)v(e,c,{get:r[c],enumerable:!0})},j=(e,r,c,s)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of V(r))!U.call(e,n)&&n!==c&&v(e,n,{get:()=>r[n],enumerable:!(s=L(r,n))||s.enumerable});return e};var H=e=>j(v({},"__esModule",{value:!0}),e);var ee={};W(ee,{getVAD:()=>Y});module.exports=H(ee);var g=class e extends Error{constructor(c,s,n,o){super(s,{cause:n});this.code=c;this.details=o;this.cause=n,Error.captureStackTrace&&Error.captureStackTrace(this,e)}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}}};function _(e,r=0){if(r===-1){if(e.numberOfChannels===0)throw new g("INVALID_INPUT","No channels available");for(let n=0;n<e.numberOfChannels;n++)if(!e.channelData[n])throw new g("INVALID_INPUT",`Channel ${n} data does not exist for averaging`);let s=new Float32Array(e.length);for(let n=0;n<e.length;n++){let o=0;for(let i=0;i<e.numberOfChannels;i++){let t=e.channelData[i];t&&n<t.length&&(o+=t[n]??0)}s[n]=o/e.numberOfChannels}return s}if(r<-1||r>=e.numberOfChannels)throw new g("INVALID_INPUT",`Invalid channel number: ${r}`);let c=e.channelData[r];if(!c)throw new g("INVALID_INPUT",`Channel ${r} data does not exist`);return c}function x(e){return e==null||isNaN(e)||!isFinite(e)?0:e}function G(e,r=.97){let c=new Float32Array(e.length);c[0]=e[0]||0;for(let s=1;s<e.length;s++){let n=x(e[s]??0),o=x(e[s-1]??0);c[s]=n-r*o}return c}function $(e,r,c,s,n=!1){let o=e.length;if(o<r)return{energies:new Float32Array(0),times:new Float32Array(0)};let i=Math.floor((o-r)/c)+1,t=new Float32Array(i),a=new Float32Array(i);for(let u=0;u<i;u++){let f=u*c,p=Math.min(f+r,o),h=0,y=0;for(let d=f;d<p;d++){let A=x(e[d]??0);h+=A*A,y++}h=y>0?h/y:0,n?t[u]=h>1e-10?10*Math.log10(h):-100:t[u]=h,a[u]=(f+r/2)/s}return{energies:t,times:a}}function K(e,r,c,s=!0){let n=e.length;if(n<r)return new Float32Array(0);let o=Math.floor((n-r)/c)+1,i=new Float32Array(o);for(let t=0;t<o;t++){let a=t*c,u=Math.min(a+r,n),f=0,p=Math.sign(x(e[a]??0));for(let h=a+1;h<u;h++){let y=x(e[h]??0),d=Math.sign(y);p!==d&&p!==0&&d!==0&&f++,p=d}i[t]=s?f/Math.max(1,u-a-1):f}return i}function Q(e,r,c,s=10){let n=new Float32Array(e.length),o=0,i=Math.min(s,e.length);for(let t=0;t<i;t++){let a=e[t]??0;a!==void 0&&(o+=a)}o=i>0?o/i:0;for(let t=0;t<e.length;t++){let a=e[t]??0;if(a===void 0){n[t]=t>0?n[t-1]??o*c:o*c;continue}if(t===0)n[t]=o*c;else{let u=n[t-1];u!==void 0&&a<u&&(o=r*o+(1-r)*a),n[t]=o*c}}return n}function Z(e,r=5){let c=new Float32Array(e.length),s=Math.floor(r/2);for(let n=0;n<e.length;n++){let o=Math.max(0,n-s),i=Math.min(e.length,n+s+1),t=[];for(let a=o;a<i;a++){let u=e[a]??0;u!==void 0&&t.push(u)}if(t.sort((a,u)=>a-u),t.length>0){let a=Math.floor(t.length/2),u=t[a];c[n]=u??0}else c[n]=0}return c}function J(e,r,c=.5,s=.1,n=.3){let o=[],i=null;for(let t=0;t<e.length;t++){let a=e[t]??0,u=r[t]??0;if(a===void 0||u===void 0)continue;let f=a>=c;if(!i)i={start:u,end:u,type:f?"speech":"silence",confidence:Math.abs(a-.5)*2};else if(f&&i.type==="speech"||!f&&i.type==="silence"){i.end=u;let p=Math.abs(a-.5)*2;i.confidence=Math.max(i.confidence||0,p)}else o.push(i),i={start:u,end:u,type:f?"speech":"silence",confidence:Math.abs(a-.5)*2}}return i&&o.push(i),X(o,s,n)}function X(e,r,c){if(e.length===0)return[];let s=[],n=0;for(;n<e.length;){let o=e[n];if(!o){n++;continue}let i=o.end-o.start;if(o.type==="speech"&&i>=r||o.type==="silence"&&i>=c)s.push(o),n++;else{if(s.length>0&&n+1<e.length){let t=s[s.length-1],a=e[n+1];if(t&&a&&t.type===a.type){t.end=a.end,n+=2;continue}}if(s.length>0){let t=s[s.length-1];t&&(t.end=o.end)}n++}}return s}function Y(e,r={}){let{channel:c=0,frameSizeMs:s=30,hopSizeMs:n=10,method:o="combined",energyThreshold:i=.02,zcrThresholdLow:t=.05,zcrThresholdHigh:a=.15,adaptiveAlpha:u=.99,noiseFactor:f=3,minSilenceDurationMs:p=300,minSpeechDurationMs:h=100,preEmphasis:y=!0,smoothing:d=!0}=r,A=_(e,c);y&&(A=G(A));let S=e.sampleRate,I=Math.floor(s/1e3*S),C=Math.floor(n/1e3*S);if(I===0||C===0)return{segments:[],speechRatio:0};let{energies:b,times:E}=$(A,I,C,S,!1),w=K(A,I,C,!0);if(b.length===0)return{segments:[],speechRatio:0};let F=new Float32Array(b.length);switch(o){case"energy":{for(let l=0;l<b.length;l++){let m=b[l]??0;F[l]=m>i?1:0}break}case"zcr":{for(let l=0;l<w.length;l++){let m=w[l]??0;F[l]=m>t&&m<a?1:0}break}case"combined":{for(let l=0;l<b.length;l++){let m=b[l]??0,M=w[l]??0,D=m>i?1:0,O=M>t&&M<a?1:0;F[l]=(D+O)/2}break}case"adaptive":{let l=Q(b,u,f);for(let m=0;m<b.length;m++){let M=b[m]??0,D=w[m]??0,O=l[m]??0,B=M>O?1:0,R=D>t&&D<a?.5:0;F[m]=Math.min(1,B+R)}break}}let T=d?Z(F,5):F,q=h/1e3,z=p/1e3,N=J(T,E,.5,q,z),P=0;for(let l of N)l.type==="speech"&&(P+=l.end-l.start);let k=e.duration>0?Math.min(1,P/e.duration):0;return{segments:N,speechRatio:k,features:{energies:b,zcrs:w,decisions:T,times:E}}}