UNPKG

audio-inspect

Version:

Lightweight yet powerful audio analysis library

2 lines (1 loc) 6.79 kB
var y=class e extends Error{constructor(t,c,o,s){super(c,{cause:o});this.code=t;this.details=s;this.cause=o,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 M(e){return e==null||isNaN(e)||!isFinite(e)?0:e}var S=new Map;function _(e){if(!isFinite(e)||e<=0)throw new y("INVALID_INPUT","\u30B5\u30F3\u30D7\u30EB\u30EC\u30FC\u30C8\u306F\u6B63\u306E\u6709\u9650\u5024\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059");if(e<8e3||e>384e3)throw new y("UNSUPPORTED_FORMAT",`\u30B5\u30F3\u30D7\u30EB\u30EC\u30FC\u30C8 ${e}Hz \u306F\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093`)}function O(e){_(e);let a=S.get(e);if(a)return a;let t=[];if(e===48e3)t.push({b0:1.53512485958697,b1:-2.69169618940638,b2:1.19839281085285,a0:1,a1:-1.69065929318241,a2:.73248077421585}),t.push({b0:1,b1:-2,b2:1,a0:1,a1:-1.99004745483398,a2:.99007225036621});else{let c=1681.974450955532,o=3.99984385397,s=.7071752369554193,n=Math.tan(Math.PI*c/e),b=Math.pow(10,o/20),r=Math.pow(b,.499666774155),f=1+n/s+n*n;t.push({b0:(b+r*n/s+n*n)/f,b1:2*(n*n-b)/f,b2:(b-r*n/s+n*n)/f,a0:1,a1:2*(n*n-1)/f,a2:(1-n/s+n*n)/f});let u=38.13547087613982,m=.5003270373253953,h=Math.tan(Math.PI*u/e),g=1+h/m+h*h;t.push({b0:1,b1:-2,b2:1,a0:1,a1:2*(h*h-1)/g,a2:(1-h/m+h*h)/g});let i=1/T(t,997,e).magnitude;t[0]&&(t[0].b0*=i,t[0].b1*=i,t[0].b2*=i)}return S.set(e,t),t}function T(e,a,t){let c=2*Math.PI*a/t,o=1,s=0;for(let r of e){let f=Math.cos(c),u=Math.sin(c),m=Math.cos(2*c),h=Math.sin(2*c),g=r.b0+r.b1*f+r.b2*m,p=-r.b1*u-r.b2*h,i=r.a0+r.a1*f+r.a2*m,l=-r.a1*u-r.a2*h,d=i*i+l*l;if(d===0)throw new y("INVALID_INPUT","\u5468\u6CE2\u6570\u5FDC\u7B54\u8A08\u7B97\u3067\u30BC\u30ED\u9664\u7B97\u304C\u767A\u751F\u3057\u307E\u3057\u305F");let A=(g*i+p*l)/d,x=(p*i-g*l)/d,C=o*A-s*x,D=o*x+s*A;o=C,s=D}let n=Math.sqrt(o*o+s*s),b=Math.atan2(s,o);return{magnitude:n,phase:b}}function w(e){return O(e)}var k=-70,P=10,B=400,q=.75,E=3e3,N=400;function I(e,a,t={x1:0,x2:0,y1:0,y2:0}){let c=new Float32Array(e.length),{x1:o,x2:s,y1:n,y2:b}=t;for(let r=0;r<e.length;r++){let f=M(e[r]??0),u=a.b0*f+a.b1*o+a.b2*s-a.a1*n-a.a2*b;c[r]=u,s=o,o=f,b=n,n=u}return t.x1=o,t.x2=s,t.y1=n,t.y2=b,c}function v(e){let a=0,t=e.length;if(t===0)return-1/0;for(let c=0;c<t;c++){let o=e[c];if(!o||o.length===0)continue;let s=0,n=0;for(let r=0;r<o.length;r++){let f=M(o[r]??0);s+=f*f,n++}if(n===0)continue;a+=1*(s/n)}return-.691+10*Math.log10(Math.max(1e-15,a))}function re(e){return w(e)}function oe(e,a={}){let{channelMode:t=e.numberOfChannels>=2?"stereo":"mono",calculateShortTerm:c=!1,calculateMomentary:o=!1,calculateLoudnessRange:s=!1,calculateTruePeak:n=!1}=a;if(e.numberOfChannels===0)throw new y("INVALID_INPUT","\u51E6\u7406\u53EF\u80FD\u306A\u30C1\u30E3\u30F3\u30CD\u30EB\u304C\u3042\u308A\u307E\u305B\u3093");let b=L(e.sampleRate,{channelMode:t,maxDurationMs:e.duration*1e3+5e3}),r=[];if(t==="mono"){let i=e.channelData[0];i&&r.push(i)}else{let i=e.channelData[0],l=e.channelData[1];i&&r.push(i),l&&r.push(l)}if(r.length===0)throw new y("INVALID_INPUT","\u51E6\u7406\u53EF\u80FD\u306A\u30C1\u30E3\u30F3\u30CD\u30EB\u304C\u3042\u308A\u307E\u305B\u3093");let f=[],u=r[0].length;if(e.duration<5)f.push(r);else{let i=Math.floor(e.sampleRate*.5);for(let l=0;l<u;l+=i){let d=Math.min(l+i,u),A=r.map(x=>x.subarray(l,d));f.push(A)}}let m=[],h=[],g;for(let i of f)g=b.process(i),o&&isFinite(g.momentary)&&m.push(g.momentary),c&&isFinite(g.shortTerm)&&h.push(g.shortTerm);let p={integrated:g?.integrated??-1/0};if(c&&h.length>0&&(p.shortTerm=new Float32Array(h)),o&&m.length>0&&(p.momentary=new Float32Array(m)),s&&p.shortTerm){let i=Array.from(p.shortTerm).filter(l=>l>-70&&isFinite(l)).sort((l,d)=>l-d);if(i.length>0){let l=Math.floor(i.length*.1),d=Math.floor(i.length*.95),A=i[l]??-1/0,x=i[d]??-1/0;p.loudnessRange=x-A,p.statistics={percentile10:A,percentile95:x}}}return n&&(p.truePeak=r.map(i=>{let l=0;for(let d of i){let A=M(d??0);l=Math.max(l,Math.abs(A))}return l>0?20*Math.log10(l):-1/0})),p}var F=class{sampleRate;channelMode;blockSize;hopSize;blockBuffer=[];maxBlocks;currentSamples=[];sampleCount=0;biquadStates=[];totalSamplesProcessed=0;constructor(a,t="stereo",c=3e4){this.sampleRate=a,this.channelMode=t,this.blockSize=Math.floor(B/1e3*a),this.hopSize=Math.floor(this.blockSize*(1-q)),this.maxBlocks=Math.ceil(c/(this.hopSize/a*1e3));let o=t==="stereo"?2:1;for(let s=0;s<o;s++)this.currentSamples.push(new Float32Array(this.blockSize)),this.biquadStates.push([{x1:0,x2:0,y1:0,y2:0},{x1:0,x2:0,y1:0,y2:0}])}process(a){let t=this.channelMode==="stereo"?Math.min(a.length,2):1,c=w(this.sampleRate);for(let o=0;o<t;o++){let s=a[o];if(!s)continue;let n=I(s,c[0],this.biquadStates[o][0]);n=I(n,c[1],this.biquadStates[o][1]);let b=this.currentSamples[o],r=0;for(;r<n.length;){let f=this.blockSize-this.sampleCount,u=Math.min(n.length-r,f);if(b.set(n.subarray(r,r+u),this.sampleCount),this.sampleCount+=u,r+=u,this.sampleCount>=this.blockSize){let m=v(this.currentSamples.slice(0,t));if(isFinite(m)){let h=this.totalSamplesProcessed+this.blockSize/2;this.blockBuffer.push([m,h]),this.blockBuffer.length>this.maxBlocks&&this.blockBuffer.shift()}b.copyWithin(0,this.hopSize),this.sampleCount=this.blockSize-this.hopSize,this.totalSamplesProcessed+=this.hopSize}}}return this.calculateCurrentLUFS()}calculateCurrentLUFS(){if(this.blockBuffer.length===0)return{integrated:-1/0,momentary:-1/0,shortTerm:-1/0};let a=this.totalSamplesProcessed+this.sampleCount,t=N/1e3*this.sampleRate,c=E/1e3*this.sampleRate,o=this.blockBuffer.filter(([u,m])=>a-m<=t).map(([u])=>u),s=this.blockBuffer.filter(([u,m])=>a-m<=c).map(([u])=>u),n=this.blockBuffer.map(([u])=>u);n=n.filter(u=>u>=k);let b=-1/0;if(n.length>0){let u=n.reduce((p,i)=>p+Math.pow(10,(i+.691)/10),0),h=-.691+10*Math.log10(u/n.length)-P,g=n.filter(p=>p>=h);if(g.length>0){let p=g.reduce((i,l)=>i+Math.pow(10,(l+.691)/10),0);b=-.691+10*Math.log10(p/g.length)}}let r=-1/0;if(o.length>0){let u=o.reduce((m,h)=>m+Math.pow(10,(h+.691)/10),0);r=-.691+10*Math.log10(u/o.length)}let f=-1/0;if(s.length>0){let u=s.reduce((m,h)=>m+Math.pow(10,(h+.691)/10),0);f=-.691+10*Math.log10(u/s.length)}return{integrated:b,momentary:r,shortTerm:f}}reset(){this.blockBuffer=[],this.sampleCount=0,this.totalSamplesProcessed=0;for(let a=0;a<this.currentSamples.length;a++){this.currentSamples[a].fill(0);for(let t=0;t<this.biquadStates[a].length;t++)this.biquadStates[a][t]={x1:0,x2:0,y1:0,y2:0}}}getBufferSize(){return this.blockBuffer.length}};function L(e,a={}){let{channelMode:t="stereo",maxDurationMs:c=3e4}=a;return new F(e,t,c)}export{re as getKWeightingCoeffs,oe as getLUFS,L as getLUFSRealtime};