mellon 0.0.11 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mellon.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Kt="0.0.11",Yt=[1,1,149,64],Qt=`https://cdn.jsdelivr.net/npm/mellon@${Kt}/dist/assets`,st={assetsPath:`${Qt}`};let D=null,q=null,tt=null;function Vt({assetsPath:i}={}){i!==void 0&&(st.assetsPath=i),D=null,q=null,tt=null}async function Xt(i){return D?(i==null||i(1),D):q||(q=(async()=>{const n=st.assetsPath.endsWith("/")?st.assetsPath:st.assetsPath+"/",t=n+"ort.all.min.mjs",e=n+"model.onnx";tt=await new Function("url","return import(url)")(t),tt.env.wasm.wasmPaths=n;const s=await fetch(e);if(!s.ok)throw new Error(`Failed to fetch model: ${s.status}`);const a=parseInt(s.headers.get("content-length")||"0",10),o=s.body.getReader(),c=[];let l=0;for(;;){const{done:m,value:f}=await o.read();if(m)break;c.push(f),l+=f.byteLength,a>0&&(i==null||i(l/a))}const h=new Uint8Array(l);let d=0;for(const m of c)h.set(m,d),d+=m.byteLength;return D=await tt.InferenceSession.create(h.buffer,{executionProviders:["wasm"],graphOptimizationLevel:"all"}),i==null||i(1),D})(),q)}async function Nt(i){if(!D)throw new Error("Model not loaded — call loadModel() first");const n=new tt.Tensor("float32",i,Yt),t=await D.run({input:n}),e=Object.keys(t)[0];return t[e].data}function Zt(i){return i&&i.__esModule&&Object.prototype.hasOwnProperty.call(i,"default")?i.default:i}var _t,Et;function Ot(){if(Et)return _t;Et=1;function i(n){if(this.size=n|0,this.size<=1||(this.size&this.size-1)!==0)throw new Error("FFT size must be a power of two and bigger than 1");this._csize=n<<1;for(var t=new Array(this.size*2),e=0;e<t.length;e+=2){const l=Math.PI*e/this.size;t[e]=Math.cos(l),t[e+1]=-Math.sin(l)}this.table=t;for(var r=0,s=1;this.size>s;s<<=1)r++;this._width=r%2===0?r-1:r,this._bitrev=new Array(1<<this._width);for(var a=0;a<this._bitrev.length;a++){this._bitrev[a]=0;for(var o=0;o<this._width;o+=2){var c=this._width-o-2;this._bitrev[a]|=(a>>>o&3)<<c}}this._out=null,this._data=null,this._inv=0}return _t=i,i.prototype.fromComplexArray=function(t,e){for(var r=e||new Array(t.length>>>1),s=0;s<t.length;s+=2)r[s>>>1]=t[s];return r},i.prototype.createComplexArray=function(){const t=new Array(this._csize);for(var e=0;e<t.length;e++)t[e]=0;return t},i.prototype.toComplexArray=function(t,e){for(var r=e||this.createComplexArray(),s=0;s<r.length;s+=2)r[s]=t[s>>>1],r[s+1]=0;return r},i.prototype.completeSpectrum=function(t){for(var e=this._csize,r=e>>>1,s=2;s<r;s+=2)t[e-s]=t[s],t[e-s+1]=-t[s+1]},i.prototype.transform=function(t,e){if(t===e)throw new Error("Input and output buffers must be different");this._out=t,this._data=e,this._inv=0,this._transform4(),this._out=null,this._data=null},i.prototype.realTransform=function(t,e){if(t===e)throw new Error("Input and output buffers must be different");this._out=t,this._data=e,this._inv=0,this._realTransform4(),this._out=null,this._data=null},i.prototype.inverseTransform=function(t,e){if(t===e)throw new Error("Input and output buffers must be different");this._out=t,this._data=e,this._inv=1,this._transform4();for(var r=0;r<t.length;r++)t[r]/=this.size;this._out=null,this._data=null},i.prototype._transform4=function(){var t=this._out,e=this._csize,r=this._width,s=1<<r,a=e/s<<1,o,c,l=this._bitrev;if(a===4)for(o=0,c=0;o<e;o+=a,c++){const u=l[c];this._singleTransform2(o,u,s)}else for(o=0,c=0;o<e;o+=a,c++){const u=l[c];this._singleTransform4(o,u,s)}var h=this._inv?-1:1,d=this.table;for(s>>=2;s>=2;s>>=2){a=e/s<<1;var m=a>>>2;for(o=0;o<e;o+=a)for(var f=o+m,g=o,_=0;g<f;g+=2,_+=s){const u=g,p=u+m,v=p+m,w=v+m,b=t[u],E=t[u+1],A=t[p],y=t[p+1],M=t[v],F=t[v+1],C=t[w],T=t[w+1],x=b,R=E,S=d[_],z=h*d[_+1],N=A*S-y*z,k=A*z+y*S,P=d[2*_],L=h*d[2*_+1],G=M*P-F*L,H=M*L+F*P,J=d[3*_],K=h*d[3*_+1],Y=C*J-T*K,Q=C*K+T*J,V=x+G,j=R+H,B=x-G,X=R-H,Z=N+Y,U=k+Q,$=h*(N-Y),O=h*(k-Q),et=V+Z,at=j+U,it=V-Z,ct=j-U,lt=B+O,ht=X-$,dt=B-O,ut=X+$;t[u]=et,t[u+1]=at,t[p]=lt,t[p+1]=ht,t[v]=it,t[v+1]=ct,t[w]=dt,t[w+1]=ut}}},i.prototype._singleTransform2=function(t,e,r){const s=this._out,a=this._data,o=a[e],c=a[e+1],l=a[e+r],h=a[e+r+1],d=o+l,m=c+h,f=o-l,g=c-h;s[t]=d,s[t+1]=m,s[t+2]=f,s[t+3]=g},i.prototype._singleTransform4=function(t,e,r){const s=this._out,a=this._data,o=this._inv?-1:1,c=r*2,l=r*3,h=a[e],d=a[e+1],m=a[e+r],f=a[e+r+1],g=a[e+c],_=a[e+c+1],u=a[e+l],p=a[e+l+1],v=h+g,w=d+_,b=h-g,E=d-_,A=m+u,y=f+p,M=o*(m-u),F=o*(f-p),C=v+A,T=w+y,x=b+F,R=E-M,S=v-A,z=w-y,N=b-F,k=E+M;s[t]=C,s[t+1]=T,s[t+2]=x,s[t+3]=R,s[t+4]=S,s[t+5]=z,s[t+6]=N,s[t+7]=k},i.prototype._realTransform4=function(){var t=this._out,e=this._csize,r=this._width,s=1<<r,a=e/s<<1,o,c,l=this._bitrev;if(a===4)for(o=0,c=0;o<e;o+=a,c++){const mt=l[c];this._singleRealTransform2(o,mt>>>1,s>>>1)}else for(o=0,c=0;o<e;o+=a,c++){const mt=l[c];this._singleRealTransform4(o,mt>>>1,s>>>1)}var h=this._inv?-1:1,d=this.table;for(s>>=2;s>=2;s>>=2){a=e/s<<1;var m=a>>>1,f=m>>>1,g=f>>>1;for(o=0;o<e;o+=a)for(var _=0,u=0;_<=g;_+=2,u+=s){var p=o+_,v=p+f,w=v+f,b=w+f,E=t[p],A=t[p+1],y=t[v],M=t[v+1],F=t[w],C=t[w+1],T=t[b],x=t[b+1],R=E,S=A,z=d[u],N=h*d[u+1],k=y*z-M*N,P=y*N+M*z,L=d[2*u],G=h*d[2*u+1],H=F*L-C*G,J=F*G+C*L,K=d[3*u],Y=h*d[3*u+1],Q=T*K-x*Y,V=T*Y+x*K,j=R+H,B=S+J,X=R-H,Z=S-J,U=k+Q,$=P+V,O=h*(k-Q),et=h*(P-V),at=j+U,it=B+$,ct=X+et,lt=Z-O;if(t[p]=at,t[p+1]=it,t[v]=ct,t[v+1]=lt,_===0){var ht=j-U,dt=B-$;t[w]=ht,t[w+1]=dt;continue}if(_!==g){var ut=X,It=-Z,Wt=j,jt=-B,Bt=-h*et,Ut=-h*O,$t=-h*$,Pt=-h*U,Lt=ut+Bt,Gt=It+Ut,Ht=Wt+Pt,Jt=jt-$t,bt=o+f-_,At=o+m-_;t[bt]=Lt,t[bt+1]=Gt,t[At]=Ht,t[At+1]=Jt}}}},i.prototype._singleRealTransform2=function(t,e,r){const s=this._out,a=this._data,o=a[e],c=a[e+r],l=o+c,h=o-c;s[t]=l,s[t+1]=0,s[t+2]=h,s[t+3]=0},i.prototype._singleRealTransform4=function(t,e,r){const s=this._out,a=this._data,o=this._inv?-1:1,c=r*2,l=r*3,h=a[e],d=a[e+r],m=a[e+c],f=a[e+l],g=h+m,_=h-m,u=d+f,p=o*(d-f),v=g+u,w=_,b=-p,E=g-u,A=_,y=p;s[t]=v,s[t+1]=0,s[t+2]=w,s[t+3]=b,s[t+4]=E,s[t+5]=0,s[t+6]=A,s[t+7]=y},_t}var qt=Ot();const te=Zt(qt),nt=16e3,W=512,I=64,Mt=Math.floor(.025*nt),Ft=Math.floor(.01*nt);function Ct(i){return 2595*Math.log10(1+i/700)}function ee(i){return 700*(10**(i/2595)-1)}function se(){const i=Ct(0),n=Ct(nt/2),t=new Float64Array(I+2);for(let o=0;o<I+2;o++)t[o]=i+o*(n-i)/(I+1);const r=t.map(o=>ee(o)).map(o=>Math.floor((W+1)*o/nt)),s=[],a=Math.floor(W/2)+1;for(let o=0;o<I;o++){const c=new Float32Array(a);for(let l=r[o];l<r[o+1];l++)c[l]=(l-r[o])/(r[o+1]-r[o]);for(let l=r[o+1];l<r[o+2];l++)c[l]=(r[o+2]-l)/(r[o+2]-r[o+1]);s.push(c)}return s}const ne=se(),rt=new te(W),ft=new Float32Array(W),Tt=rt.createComplexArray(),pt=rt.createComplexArray(),xt=new Float32Array(Math.floor(W/2)+1);function kt(i){const n=1+Math.ceil((i.length-Mt)/Ft),t=new Float32Array(n*I),e=Math.floor(W/2)+1;for(let r=0;r<n;r++){const s=r*Ft;ft.fill(0);for(let a=0;a<Mt&&s+a<i.length;a++)ft[a]=i[s+a];rt.toComplexArray(ft,Tt),rt.transform(pt,Tt);for(let a=0;a<e;a++){const o=pt[2*a],c=pt[2*a+1],l=(o*o+c*c)/W;xt[a]=l===0?1e-30:l}for(let a=0;a<I;a++){const o=ne[a];let c=0;for(let l=0;l<e;l++)c+=xt[l]*o[l];t[r*I+a]=Math.log(c===0?1e-30:c)}}return t}function re(i,n){let t=0;for(let e=0;e<i.length;e++)t+=i[e]*n[e];return(t+1)/2}function oe(i,n){let t=0;for(const e of n){const r=re(i,e);r>t&&(t=r)}return t}class Rt extends EventTarget{constructor({name:n,refEmbeddings:t,threshold:e=.65,relaxationMs:r=2e3,inferenceGapMs:s=300}){super(),this.name=n,this.refEmbeddings=t,this.threshold=e,this.relaxationMs=r,this.inferenceGapMs=s,this._lastDetectionAt=0,this._lastInferenceAt=0,this._lastScore=0}get lastScore(){return this._lastScore}async scoreFrame(n){const t=Date.now();if(t-this._lastInferenceAt<this.inferenceGapMs)return null;this._lastInferenceAt=t;const e=kt(n),r=await Nt(e),s=oe(r,this.refEmbeddings);return this._lastScore=s,s>=this.threshold&&t-this._lastDetectionAt>=this.relaxationMs&&(this._lastDetectionAt=t,this.dispatchEvent(new CustomEvent("match",{detail:{name:this.name,confidence:s,timestamp:t}}))),s}}const St=16e3,ae=1500,vt=24e3;function zt(i){if(i.length===vt)return i;const n=new Float32Array(vt);return n.set(i.subarray(0,vt)),n}class Dt extends EventTarget{constructor(n){super(),this.wordName=n.trim().toLowerCase(),this.samples=[]}get sampleCount(){return this.samples.length}async recordSample(){const n=await navigator.mediaDevices.getUserMedia({audio:!0});return new Promise((t,e)=>{const r=new AudioContext({sampleRate:St}),s=new MediaRecorder(n),a=[];this.dispatchEvent(new CustomEvent("recording-start")),s.ondataavailable=o=>{o.data.size>0&&a.push(o.data)},s.onstop=async()=>{n.getTracks().forEach(o=>o.stop());try{const c=await new Blob(a,{type:"audio/webm"}).arrayBuffer(),l=await r.decodeAudioData(c);await r.close();const h=l.getChannelData(0),d=zt(new Float32Array(h)),m=this._push(d,`Recorded #${this.samples.length}`);t(m)}catch(o){await r.close().catch(()=>{}),e(o)}},s.start(),setTimeout(()=>s.stop(),ae)})}async addAudioFile(n){const t=await n.arrayBuffer(),e=new AudioContext({sampleRate:St}),r=await e.decodeAudioData(t);await e.close();const s=r.getChannelData(0),a=zt(new Float32Array(s));return this._push(a,n.name)}removeSample(n){this.samples.splice(n,1),this.dispatchEvent(new CustomEvent("samples-changed",{detail:{count:this.samples.length}}))}clearSamples(){this.samples=[],this.dispatchEvent(new CustomEvent("samples-changed",{detail:{count:0}}))}async generateRef(){if(this.samples.length<3)throw new Error(`Need at least 3 samples (currently have ${this.samples.length})`);this.dispatchEvent(new CustomEvent("generating",{detail:{total:this.samples.length}}));const n=[];for(let t=0;t<this.samples.length;t++){const e=kt(this.samples[t].audioBuffer),r=await Nt(e);n.push(Array.from(r)),this.dispatchEvent(new CustomEvent("progress",{detail:{done:t+1,total:this.samples.length}}))}return{word_name:this.wordName,model_type:"resnet_50_arc",embeddings:n}}_push(n,t){this.samples.push({audioBuffer:n,name:t});const e=this.samples.length;return this.dispatchEvent(new CustomEvent("sample-added",{detail:{count:e,name:t}})),e}}const ie=`/**
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Kt="0.0.12",Yt=[1,1,149,64],Qt=`https://cdn.jsdelivr.net/npm/mellon@${Kt}/dist/assets`,st={assetsPath:`${Qt}`};let D=null,q=null,tt=null;function Vt({assetsPath:a}={}){a!==void 0&&(st.assetsPath=a),D=null,q=null,tt=null}async function Xt(a){return D?(a==null||a(1),D):q||(q=(async()=>{const n=st.assetsPath.endsWith("/")?st.assetsPath:st.assetsPath+"/",t=n+"ort.all.min.mjs",e=n+"model.onnx";tt=await new Function("url","return import(url)")(t),tt.env.wasm.wasmPaths=n;const s=await fetch(e);if(!s.ok)throw new Error(`Failed to fetch model: ${s.status}`);const i=parseInt(s.headers.get("content-length")||"0",10),o=s.body.getReader(),c=[];let l=0;for(;;){const{done:m,value:f}=await o.read();if(m)break;c.push(f),l+=f.byteLength,i>0&&(a==null||a(l/i))}const h=new Uint8Array(l);let d=0;for(const m of c)h.set(m,d),d+=m.byteLength;return D=await tt.InferenceSession.create(h.buffer,{executionProviders:["wasm"],graphOptimizationLevel:"all"}),a==null||a(1),D})(),q)}async function Nt(a){if(!D)throw new Error("Model not loaded — call loadModel() first");const n=new tt.Tensor("float32",a,Yt),t=await D.run({input:n}),e=Object.keys(t)[0];return t[e].data}function Zt(a){return a&&a.__esModule&&Object.prototype.hasOwnProperty.call(a,"default")?a.default:a}var _t,Et;function Ot(){if(Et)return _t;Et=1;function a(n){if(this.size=n|0,this.size<=1||(this.size&this.size-1)!==0)throw new Error("FFT size must be a power of two and bigger than 1");this._csize=n<<1;for(var t=new Array(this.size*2),e=0;e<t.length;e+=2){const l=Math.PI*e/this.size;t[e]=Math.cos(l),t[e+1]=-Math.sin(l)}this.table=t;for(var r=0,s=1;this.size>s;s<<=1)r++;this._width=r%2===0?r-1:r,this._bitrev=new Array(1<<this._width);for(var i=0;i<this._bitrev.length;i++){this._bitrev[i]=0;for(var o=0;o<this._width;o+=2){var c=this._width-o-2;this._bitrev[i]|=(i>>>o&3)<<c}}this._out=null,this._data=null,this._inv=0}return _t=a,a.prototype.fromComplexArray=function(t,e){for(var r=e||new Array(t.length>>>1),s=0;s<t.length;s+=2)r[s>>>1]=t[s];return r},a.prototype.createComplexArray=function(){const t=new Array(this._csize);for(var e=0;e<t.length;e++)t[e]=0;return t},a.prototype.toComplexArray=function(t,e){for(var r=e||this.createComplexArray(),s=0;s<r.length;s+=2)r[s]=t[s>>>1],r[s+1]=0;return r},a.prototype.completeSpectrum=function(t){for(var e=this._csize,r=e>>>1,s=2;s<r;s+=2)t[e-s]=t[s],t[e-s+1]=-t[s+1]},a.prototype.transform=function(t,e){if(t===e)throw new Error("Input and output buffers must be different");this._out=t,this._data=e,this._inv=0,this._transform4(),this._out=null,this._data=null},a.prototype.realTransform=function(t,e){if(t===e)throw new Error("Input and output buffers must be different");this._out=t,this._data=e,this._inv=0,this._realTransform4(),this._out=null,this._data=null},a.prototype.inverseTransform=function(t,e){if(t===e)throw new Error("Input and output buffers must be different");this._out=t,this._data=e,this._inv=1,this._transform4();for(var r=0;r<t.length;r++)t[r]/=this.size;this._out=null,this._data=null},a.prototype._transform4=function(){var t=this._out,e=this._csize,r=this._width,s=1<<r,i=e/s<<1,o,c,l=this._bitrev;if(i===4)for(o=0,c=0;o<e;o+=i,c++){const u=l[c];this._singleTransform2(o,u,s)}else for(o=0,c=0;o<e;o+=i,c++){const u=l[c];this._singleTransform4(o,u,s)}var h=this._inv?-1:1,d=this.table;for(s>>=2;s>=2;s>>=2){i=e/s<<1;var m=i>>>2;for(o=0;o<e;o+=i)for(var f=o+m,g=o,_=0;g<f;g+=2,_+=s){const u=g,p=u+m,v=p+m,w=v+m,b=t[u],E=t[u+1],A=t[p],y=t[p+1],M=t[v],F=t[v+1],C=t[w],T=t[w+1],x=b,R=E,S=d[_],z=h*d[_+1],N=A*S-y*z,k=A*z+y*S,P=d[2*_],L=h*d[2*_+1],G=M*P-F*L,H=M*L+F*P,J=d[3*_],K=h*d[3*_+1],Y=C*J-T*K,Q=C*K+T*J,V=x+G,j=R+H,B=x-G,X=R-H,Z=N+Y,U=k+Q,$=h*(N-Y),O=h*(k-Q),et=V+Z,at=j+U,it=V-Z,ct=j-U,lt=B+O,ht=X-$,dt=B-O,ut=X+$;t[u]=et,t[u+1]=at,t[p]=lt,t[p+1]=ht,t[v]=it,t[v+1]=ct,t[w]=dt,t[w+1]=ut}}},a.prototype._singleTransform2=function(t,e,r){const s=this._out,i=this._data,o=i[e],c=i[e+1],l=i[e+r],h=i[e+r+1],d=o+l,m=c+h,f=o-l,g=c-h;s[t]=d,s[t+1]=m,s[t+2]=f,s[t+3]=g},a.prototype._singleTransform4=function(t,e,r){const s=this._out,i=this._data,o=this._inv?-1:1,c=r*2,l=r*3,h=i[e],d=i[e+1],m=i[e+r],f=i[e+r+1],g=i[e+c],_=i[e+c+1],u=i[e+l],p=i[e+l+1],v=h+g,w=d+_,b=h-g,E=d-_,A=m+u,y=f+p,M=o*(m-u),F=o*(f-p),C=v+A,T=w+y,x=b+F,R=E-M,S=v-A,z=w-y,N=b-F,k=E+M;s[t]=C,s[t+1]=T,s[t+2]=x,s[t+3]=R,s[t+4]=S,s[t+5]=z,s[t+6]=N,s[t+7]=k},a.prototype._realTransform4=function(){var t=this._out,e=this._csize,r=this._width,s=1<<r,i=e/s<<1,o,c,l=this._bitrev;if(i===4)for(o=0,c=0;o<e;o+=i,c++){const mt=l[c];this._singleRealTransform2(o,mt>>>1,s>>>1)}else for(o=0,c=0;o<e;o+=i,c++){const mt=l[c];this._singleRealTransform4(o,mt>>>1,s>>>1)}var h=this._inv?-1:1,d=this.table;for(s>>=2;s>=2;s>>=2){i=e/s<<1;var m=i>>>1,f=m>>>1,g=f>>>1;for(o=0;o<e;o+=i)for(var _=0,u=0;_<=g;_+=2,u+=s){var p=o+_,v=p+f,w=v+f,b=w+f,E=t[p],A=t[p+1],y=t[v],M=t[v+1],F=t[w],C=t[w+1],T=t[b],x=t[b+1],R=E,S=A,z=d[u],N=h*d[u+1],k=y*z-M*N,P=y*N+M*z,L=d[2*u],G=h*d[2*u+1],H=F*L-C*G,J=F*G+C*L,K=d[3*u],Y=h*d[3*u+1],Q=T*K-x*Y,V=T*Y+x*K,j=R+H,B=S+J,X=R-H,Z=S-J,U=k+Q,$=P+V,O=h*(k-Q),et=h*(P-V),at=j+U,it=B+$,ct=X+et,lt=Z-O;if(t[p]=at,t[p+1]=it,t[v]=ct,t[v+1]=lt,_===0){var ht=j-U,dt=B-$;t[w]=ht,t[w+1]=dt;continue}if(_!==g){var ut=X,It=-Z,Wt=j,jt=-B,Bt=-h*et,Ut=-h*O,$t=-h*$,Pt=-h*U,Lt=ut+Bt,Gt=It+Ut,Ht=Wt+Pt,Jt=jt-$t,bt=o+f-_,At=o+m-_;t[bt]=Lt,t[bt+1]=Gt,t[At]=Ht,t[At+1]=Jt}}}},a.prototype._singleRealTransform2=function(t,e,r){const s=this._out,i=this._data,o=i[e],c=i[e+r],l=o+c,h=o-c;s[t]=l,s[t+1]=0,s[t+2]=h,s[t+3]=0},a.prototype._singleRealTransform4=function(t,e,r){const s=this._out,i=this._data,o=this._inv?-1:1,c=r*2,l=r*3,h=i[e],d=i[e+r],m=i[e+c],f=i[e+l],g=h+m,_=h-m,u=d+f,p=o*(d-f),v=g+u,w=_,b=-p,E=g-u,A=_,y=p;s[t]=v,s[t+1]=0,s[t+2]=w,s[t+3]=b,s[t+4]=E,s[t+5]=0,s[t+6]=A,s[t+7]=y},_t}var qt=Ot();const te=Zt(qt),nt=16e3,W=512,I=64,Mt=Math.floor(.025*nt),Ft=Math.floor(.01*nt);function Ct(a){return 2595*Math.log10(1+a/700)}function ee(a){return 700*(10**(a/2595)-1)}function se(){const a=Ct(0),n=Ct(nt/2),t=new Float64Array(I+2);for(let o=0;o<I+2;o++)t[o]=a+o*(n-a)/(I+1);const r=t.map(o=>ee(o)).map(o=>Math.floor((W+1)*o/nt)),s=[],i=Math.floor(W/2)+1;for(let o=0;o<I;o++){const c=new Float32Array(i);for(let l=r[o];l<r[o+1];l++)c[l]=(l-r[o])/(r[o+1]-r[o]);for(let l=r[o+1];l<r[o+2];l++)c[l]=(r[o+2]-l)/(r[o+2]-r[o+1]);s.push(c)}return s}const ne=se(),rt=new te(W),ft=new Float32Array(W),Tt=rt.createComplexArray(),pt=rt.createComplexArray(),xt=new Float32Array(Math.floor(W/2)+1);function kt(a){const n=1+Math.ceil((a.length-Mt)/Ft),t=new Float32Array(n*I),e=Math.floor(W/2)+1;for(let r=0;r<n;r++){const s=r*Ft;ft.fill(0);for(let i=0;i<Mt&&s+i<a.length;i++)ft[i]=a[s+i];rt.toComplexArray(ft,Tt),rt.transform(pt,Tt);for(let i=0;i<e;i++){const o=pt[2*i],c=pt[2*i+1],l=(o*o+c*c)/W;xt[i]=l===0?1e-30:l}for(let i=0;i<I;i++){const o=ne[i];let c=0;for(let l=0;l<e;l++)c+=xt[l]*o[l];t[r*I+i]=Math.log(c===0?1e-30:c)}}return t}function re(a,n){let t=0;for(let e=0;e<a.length;e++)t+=a[e]*n[e];return(t+1)/2}function oe(a,n){let t=0;for(const e of n){const r=re(a,e);r>t&&(t=r)}return t}class Rt extends EventTarget{constructor({name:n,refEmbeddings:t,threshold:e=.65,relaxationMs:r=2e3,inferenceGapMs:s=300}){super(),this.name=n,this.refEmbeddings=t,this.threshold=e,this.relaxationMs=r,this.inferenceGapMs=s,this._lastDetectionAt=0,this._lastInferenceAt=0,this._lastScore=0}get lastScore(){return this._lastScore}async scoreFrame(n){const t=Date.now();if(t-this._lastInferenceAt<this.inferenceGapMs)return null;this._lastInferenceAt=t;const e=kt(n),r=await Nt(e),s=oe(r,this.refEmbeddings);return this._lastScore=s,s>=this.threshold&&t-this._lastDetectionAt>=this.relaxationMs&&(this._lastDetectionAt=t,this.dispatchEvent(new CustomEvent("match",{detail:{name:this.name,confidence:s,timestamp:t}}))),s}}const St=16e3,ae=1500,vt=24e3;function zt(a){if(a.length===vt)return a;const n=new Float32Array(vt);return n.set(a.subarray(0,vt)),n}class Dt extends EventTarget{constructor(n){super(),this.wordName=n.trim().toLowerCase(),this.samples=[]}get sampleCount(){return this.samples.length}async recordSample(){const n=await navigator.mediaDevices.getUserMedia({audio:!0});return new Promise((t,e)=>{const r=new AudioContext({sampleRate:St}),s=new MediaRecorder(n),i=[];this.dispatchEvent(new CustomEvent("recording-start")),s.ondataavailable=o=>{o.data.size>0&&i.push(o.data)},s.onstop=async()=>{n.getTracks().forEach(o=>o.stop());try{const c=await new Blob(i,{type:"audio/webm"}).arrayBuffer(),l=await r.decodeAudioData(c);await r.close();const h=l.getChannelData(0),d=zt(new Float32Array(h)),m=this._push(d,`Recorded #${this.samples.length}`);t(m)}catch(o){await r.close().catch(()=>{}),e(o)}},s.start(),setTimeout(()=>s.stop(),ae)})}async addAudioFile(n){const t=await n.arrayBuffer(),e=new AudioContext({sampleRate:St}),r=await e.decodeAudioData(t);await e.close();const s=r.getChannelData(0),i=zt(new Float32Array(s));return this._push(i,n.name)}removeSample(n){this.samples.splice(n,1),this.dispatchEvent(new CustomEvent("samples-changed",{detail:{count:this.samples.length}}))}clearSamples(){this.samples=[],this.dispatchEvent(new CustomEvent("samples-changed",{detail:{count:0}}))}async generateRef(){if(this.samples.length<3)throw new Error(`Need at least 3 samples (currently have ${this.samples.length})`);this.dispatchEvent(new CustomEvent("generating",{detail:{total:this.samples.length}}));const n=[];for(let t=0;t<this.samples.length;t++){const e=kt(this.samples[t].audioBuffer),r=await Nt(e);n.push(Array.from(r)),this.dispatchEvent(new CustomEvent("progress",{detail:{done:t+1,total:this.samples.length}}))}return{word_name:this.wordName,model_type:"resnet_50_arc",embeddings:n}}_push(n,t){this.samples.push({audioBuffer:n,name:t});const e=this.samples.length;return this.dispatchEvent(new CustomEvent("sample-added",{detail:{count:e,name:t}})),e}}const ie=`/**
2
2
  * public/audio-processor.js
3
3
  * AudioWorklet that runs at 16 kHz and continuously emits the last
4
4
  * 1.5-second window (24 000 samples) via a circular buffer.
@@ -35,4 +35,4 @@ class AudioProcessor extends AudioWorkletProcessor {
35
35
  }
36
36
 
37
37
  registerProcessor('audio-processor', AudioProcessor)
38
- `;let wt=null;function ce(){if(!wt){const i=new Blob([ie],{type:"application/javascript"});wt=URL.createObjectURL(i)}return wt}const gt="mellon_custom_refs";function yt(){try{const i=localStorage.getItem(gt);return i?JSON.parse(i):[]}catch{return[]}}function le(i){const n=yt().filter(t=>t.word_name!==i.word_name);n.push(i),localStorage.setItem(gt,JSON.stringify(n))}function he(i){const n=yt().filter(t=>t.word_name!==i);localStorage.setItem(gt,JSON.stringify(n))}function de(i){const n=JSON.stringify(i,null,2),t=new Blob([n],{type:"application/json"}),e=URL.createObjectURL(t),r=Object.assign(document.createElement("a"),{href:e,download:`${i.word_name}_ref.json`});document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(e)}async function ue(i){const n=await i.text();let t;try{t=JSON.parse(n)}catch{throw new Error("Invalid JSON")}if(!t.embeddings||!Array.isArray(t.embeddings)||!t.embeddings.length)throw new Error('Missing or empty "embeddings" array');if(!Array.isArray(t.embeddings[0]))throw new Error('"embeddings" must be a 2D array');return t.word_name||(t.word_name=i.name.replace(/_ref\.json$/i,"").replace(/\.json$/i,"")),t}class ot extends EventTarget{constructor(n={}){super(),this._opts={refs:n.refs??[],threshold:n.threshold??.65,relaxationMs:n.relaxationMs??2e3,inferenceGapMs:n.inferenceGapMs??300,matchDebounceMs:n.matchDebounceMs??1e3,assetsPath:n.assetsPath},this._refs=new Map,this._detectors=new Map,this._audioCtx=null,this._workletNode=null,this._stream=null,this._initialized=!1,this._running=!1,this._lastMatchAt=0}get isInitialized(){return this._initialized}get isRunning(){return this._running}async init(n){var e;if(this._initialized){n==null||n(1);return}this._opts.assetsPath&&Vt({assetsPath:this._opts.assetsPath});try{await Xt(n)}catch(r){throw this.dispatchEvent(new CustomEvent("error",{detail:{error:r}})),r}const t=await ot.loadWords();console.log("existing refs in localstorage",{exisitngRefs:t});for(const r of this._opts.refs){const s=(e=r.match(/\/([^/]+?)_ref\.json$/))==null?void 0:e[1],a=t.find(o=>o.word_name===s);console.log({word:s,alreadySaveWord:a});try{let o;if(a){this.addCustomWord(a);break}else if(typeof r=="string"){console.log("fetching ref : ",r);const c=await fetch(r);if(!c.ok)throw new Error(`HTTP ${c.status}`);o=await c.json()}else o=r;ot.saveWord(o),this.addCustomWord(o)}catch(o){const c=typeof r=="string"?r:r.word_name;console.warn(`[Mellon] Failed to load ref "${c}": ${o.message}`)}}this._initialized=!0,this.dispatchEvent(new CustomEvent("ready"))}async start(){this._initialized||await this.init();try{this._stream=await navigator.mediaDevices.getUserMedia({audio:!0})}catch(e){const r=new Error(`Microphone access denied: ${e.message}`);throw this.dispatchEvent(new CustomEvent("error",{detail:{error:r}})),r}this._audioCtx=new AudioContext({sampleRate:16e3});const n=ce();await this._audioCtx.audioWorklet.addModule(n);const t=this._audioCtx.createMediaStreamSource(this._stream);this._workletNode=new AudioWorkletNode(this._audioCtx,"audio-processor"),t.connect(this._workletNode),this._workletNode.connect(this._audioCtx.destination);for(const[e,r]of this._refs){const s=new Rt({name:e,refEmbeddings:r.embeddings,threshold:this._opts.threshold,relaxationMs:this._opts.relaxationMs,inferenceGapMs:this._opts.inferenceGapMs});s.addEventListener("match",a=>this._onMatch(a)),this._detectors.set(e,s)}this._workletNode.port.onmessage=async e=>{const r=[];for(const s of this._detectors.values())r.push(s.scoreFrame(e.data));await Promise.allSettled(r)},this._running=!0}stop(){this._workletNode&&(this._workletNode.port.onmessage=null,this._workletNode.disconnect(),this._workletNode=null),this._stream&&(this._stream.getTracks().forEach(n=>n.stop()),this._stream=null),this._audioCtx&&(this._audioCtx.close(),this._audioCtx=null),this._detectors.clear(),this._running=!1}addCustomWord(n){if(this._refs.set(n.word_name,n),this._running&&this._workletNode){const t=new Rt({name:n.word_name,refEmbeddings:n.embeddings,threshold:this._opts.threshold,relaxationMs:this._opts.relaxationMs,inferenceGapMs:this._opts.inferenceGapMs});t.addEventListener("match",e=>this._onMatch(e)),this._detectors.set(n.word_name,t)}}_onMatch(n){const t=Date.now();t-this._lastMatchAt<this._opts.matchDebounceMs||(this._lastMatchAt=t,this.dispatchEvent(new CustomEvent("match",{detail:n.detail})))}enrollWord(n){return new Dt(n)}static loadWords(){return yt()}static saveWord(n){le(n)}static deleteWord(n){he(n)}static importWordFile(n){return ue(n)}static exportWord(n){de(n)}}exports.EnrollmentSession=Dt;exports.Mellon=ot;
38
+ `;let wt=null;function ce(){if(!wt){const a=new Blob([ie],{type:"application/javascript"});wt=URL.createObjectURL(a)}return wt}const gt="mellon_custom_refs";function yt(){try{const a=localStorage.getItem(gt);return a?JSON.parse(a):[]}catch{return[]}}function le(a){const n=yt().filter(t=>t.word_name!==a.word_name);n.push(a),localStorage.setItem(gt,JSON.stringify(n))}function he(a){const n=yt().filter(t=>t.word_name!==a);localStorage.setItem(gt,JSON.stringify(n))}function de(a){const n=JSON.stringify(a,null,2),t=new Blob([n],{type:"application/json"}),e=URL.createObjectURL(t),r=Object.assign(document.createElement("a"),{href:e,download:`${a.word_name}_ref.json`});document.body.appendChild(r),r.click(),document.body.removeChild(r),URL.revokeObjectURL(e)}async function ue(a){const n=await a.text();let t;try{t=JSON.parse(n)}catch{throw new Error("Invalid JSON")}if(!t.embeddings||!Array.isArray(t.embeddings)||!t.embeddings.length)throw new Error('Missing or empty "embeddings" array');if(!Array.isArray(t.embeddings[0]))throw new Error('"embeddings" must be a 2D array');return t.word_name||(t.word_name=a.name.replace(/_ref\.json$/i,"").replace(/\.json$/i,"")),t}class ot extends EventTarget{constructor(n={}){super(),this._opts={refs:n.refs??[],threshold:n.threshold??.65,relaxationMs:n.relaxationMs??2e3,inferenceGapMs:n.inferenceGapMs??300,matchDebounceMs:n.matchDebounceMs??1e3,assetsPath:n.assetsPath},this._refs=new Map,this._detectors=new Map,this._audioCtx=null,this._workletNode=null,this._stream=null,this._initialized=!1,this._running=!1,this._lastMatchAt=0}get isInitialized(){return this._initialized}get isRunning(){return this._running}async init(n){var e;if(this._initialized){n==null||n(1);return}this._opts.assetsPath&&Vt({assetsPath:this._opts.assetsPath});try{await Xt(n)}catch(r){throw this.dispatchEvent(new CustomEvent("error",{detail:{error:r}})),r}const t=await ot.loadWords();for(const r of this._opts.refs){const s=(e=r.match(/\/([^/]+?)_ref\.json$/))==null?void 0:e[1],i=t.find(o=>o.word_name===s);try{let o;if(i)continue;if(typeof r=="string"){console.log("fetching ref : ",r);const c=await fetch(r);if(!c.ok)throw new Error(`HTTP ${c.status}`);o=await c.json()}else o=r;ot.saveWord(o),this.addCustomWord(o)}catch(o){const c=typeof r=="string"?r:r.word_name;console.warn(`[Mellon] Failed to load ref "${c}": ${o.message}`)}}t.forEach(r=>this.addCustomWord(r)),this._initialized=!0,this.dispatchEvent(new CustomEvent("ready"))}async start(){this._initialized||await this.init();try{this._stream=await navigator.mediaDevices.getUserMedia({audio:!0})}catch(e){const r=new Error(`Microphone access denied: ${e.message}`);throw this.dispatchEvent(new CustomEvent("error",{detail:{error:r}})),r}this._audioCtx=new AudioContext({sampleRate:16e3});const n=ce();await this._audioCtx.audioWorklet.addModule(n);const t=this._audioCtx.createMediaStreamSource(this._stream);this._workletNode=new AudioWorkletNode(this._audioCtx,"audio-processor"),t.connect(this._workletNode),this._workletNode.connect(this._audioCtx.destination);for(const[e,r]of this._refs){const s=new Rt({name:e,refEmbeddings:r.embeddings,threshold:this._opts.threshold,relaxationMs:this._opts.relaxationMs,inferenceGapMs:this._opts.inferenceGapMs});s.addEventListener("match",i=>this._onMatch(i)),this._detectors.set(e,s)}this._workletNode.port.onmessage=async e=>{const r=[];for(const s of this._detectors.values())r.push(s.scoreFrame(e.data));await Promise.allSettled(r)},this._running=!0}stop(){this._workletNode&&(this._workletNode.port.onmessage=null,this._workletNode.disconnect(),this._workletNode=null),this._stream&&(this._stream.getTracks().forEach(n=>n.stop()),this._stream=null),this._audioCtx&&(this._audioCtx.close(),this._audioCtx=null),this._detectors.clear(),this._running=!1}addCustomWord(n){if(this._refs.set(n.word_name,n),this._running&&this._workletNode){const t=new Rt({name:n.word_name,refEmbeddings:n.embeddings,threshold:this._opts.threshold,relaxationMs:this._opts.relaxationMs,inferenceGapMs:this._opts.inferenceGapMs});t.addEventListener("match",e=>this._onMatch(e)),this._detectors.set(n.word_name,t)}}_onMatch(n){const t=Date.now();t-this._lastMatchAt<this._opts.matchDebounceMs||(this._lastMatchAt=t,this.dispatchEvent(new CustomEvent("match",{detail:n.detail})))}enrollWord(n){return new Dt(n)}static loadWords(){return yt()}static saveWord(n){le(n)}static deleteWord(n){he(n)}static importWordFile(n){return ue(n)}static exportWord(n){de(n)}}exports.EnrollmentSession=Dt;exports.Mellon=ot;
package/dist/mellon.mjs CHANGED
@@ -1,22 +1,22 @@
1
- const Jt = "0.0.11", Kt = [1, 1, 149, 64], Yt = `https://cdn.jsdelivr.net/npm/mellon@${Jt}/dist/assets`, st = {
1
+ const Jt = "0.0.12", Kt = [1, 1, 149, 64], Yt = `https://cdn.jsdelivr.net/npm/mellon@${Jt}/dist/assets`, st = {
2
2
  assetsPath: `${Yt}`
3
3
  };
4
4
  let D = null, q = null, tt = null;
5
- function Qt({ assetsPath: i } = {}) {
6
- i !== void 0 && (st.assetsPath = i), D = null, q = null, tt = null;
5
+ function Qt({ assetsPath: a } = {}) {
6
+ a !== void 0 && (st.assetsPath = a), D = null, q = null, tt = null;
7
7
  }
8
- async function Vt(i) {
9
- return D ? (i == null || i(1), D) : q || (q = (async () => {
8
+ async function Vt(a) {
9
+ return D ? (a == null || a(1), D) : q || (q = (async () => {
10
10
  const n = st.assetsPath.endsWith("/") ? st.assetsPath : st.assetsPath + "/", t = n + "ort.all.min.mjs", e = n + "model.onnx";
11
11
  tt = await new Function("url", "return import(url)")(t), tt.env.wasm.wasmPaths = n;
12
12
  const s = await fetch(e);
13
13
  if (!s.ok) throw new Error(`Failed to fetch model: ${s.status}`);
14
- const a = parseInt(s.headers.get("content-length") || "0", 10), o = s.body.getReader(), c = [];
14
+ const i = parseInt(s.headers.get("content-length") || "0", 10), o = s.body.getReader(), c = [];
15
15
  let l = 0;
16
16
  for (; ; ) {
17
17
  const { done: m, value: f } = await o.read();
18
18
  if (m) break;
19
- c.push(f), l += f.byteLength, a > 0 && (i == null || i(l / a));
19
+ c.push(f), l += f.byteLength, i > 0 && (a == null || a(l / i));
20
20
  }
21
21
  const h = new Uint8Array(l);
22
22
  let d = 0;
@@ -25,22 +25,22 @@ async function Vt(i) {
25
25
  return D = await tt.InferenceSession.create(h.buffer, {
26
26
  executionProviders: ["wasm"],
27
27
  graphOptimizationLevel: "all"
28
- }), i == null || i(1), D;
28
+ }), a == null || a(1), D;
29
29
  })(), q);
30
30
  }
31
- async function Nt(i) {
31
+ async function Nt(a) {
32
32
  if (!D) throw new Error("Model not loaded — call loadModel() first");
33
- const n = new tt.Tensor("float32", i, Kt), t = await D.run({ input: n }), e = Object.keys(t)[0];
33
+ const n = new tt.Tensor("float32", a, Kt), t = await D.run({ input: n }), e = Object.keys(t)[0];
34
34
  return t[e].data;
35
35
  }
36
- function Xt(i) {
37
- return i && i.__esModule && Object.prototype.hasOwnProperty.call(i, "default") ? i.default : i;
36
+ function Xt(a) {
37
+ return a && a.__esModule && Object.prototype.hasOwnProperty.call(a, "default") ? a.default : a;
38
38
  }
39
39
  var mt, Et;
40
40
  function Zt() {
41
41
  if (Et) return mt;
42
42
  Et = 1;
43
- function i(n) {
43
+ function a(n) {
44
44
  if (this.size = n | 0, this.size <= 1 || (this.size & this.size - 1) !== 0)
45
45
  throw new Error("FFT size must be a power of two and bigger than 1");
46
46
  this._csize = n << 1;
@@ -52,91 +52,91 @@ function Zt() {
52
52
  for (var r = 0, s = 1; this.size > s; s <<= 1)
53
53
  r++;
54
54
  this._width = r % 2 === 0 ? r - 1 : r, this._bitrev = new Array(1 << this._width);
55
- for (var a = 0; a < this._bitrev.length; a++) {
56
- this._bitrev[a] = 0;
55
+ for (var i = 0; i < this._bitrev.length; i++) {
56
+ this._bitrev[i] = 0;
57
57
  for (var o = 0; o < this._width; o += 2) {
58
58
  var c = this._width - o - 2;
59
- this._bitrev[a] |= (a >>> o & 3) << c;
59
+ this._bitrev[i] |= (i >>> o & 3) << c;
60
60
  }
61
61
  }
62
62
  this._out = null, this._data = null, this._inv = 0;
63
63
  }
64
- return mt = i, i.prototype.fromComplexArray = function(t, e) {
64
+ return mt = a, a.prototype.fromComplexArray = function(t, e) {
65
65
  for (var r = e || new Array(t.length >>> 1), s = 0; s < t.length; s += 2)
66
66
  r[s >>> 1] = t[s];
67
67
  return r;
68
- }, i.prototype.createComplexArray = function() {
68
+ }, a.prototype.createComplexArray = function() {
69
69
  const t = new Array(this._csize);
70
70
  for (var e = 0; e < t.length; e++)
71
71
  t[e] = 0;
72
72
  return t;
73
- }, i.prototype.toComplexArray = function(t, e) {
73
+ }, a.prototype.toComplexArray = function(t, e) {
74
74
  for (var r = e || this.createComplexArray(), s = 0; s < r.length; s += 2)
75
75
  r[s] = t[s >>> 1], r[s + 1] = 0;
76
76
  return r;
77
- }, i.prototype.completeSpectrum = function(t) {
77
+ }, a.prototype.completeSpectrum = function(t) {
78
78
  for (var e = this._csize, r = e >>> 1, s = 2; s < r; s += 2)
79
79
  t[e - s] = t[s], t[e - s + 1] = -t[s + 1];
80
- }, i.prototype.transform = function(t, e) {
80
+ }, a.prototype.transform = function(t, e) {
81
81
  if (t === e)
82
82
  throw new Error("Input and output buffers must be different");
83
83
  this._out = t, this._data = e, this._inv = 0, this._transform4(), this._out = null, this._data = null;
84
- }, i.prototype.realTransform = function(t, e) {
84
+ }, a.prototype.realTransform = function(t, e) {
85
85
  if (t === e)
86
86
  throw new Error("Input and output buffers must be different");
87
87
  this._out = t, this._data = e, this._inv = 0, this._realTransform4(), this._out = null, this._data = null;
88
- }, i.prototype.inverseTransform = function(t, e) {
88
+ }, a.prototype.inverseTransform = function(t, e) {
89
89
  if (t === e)
90
90
  throw new Error("Input and output buffers must be different");
91
91
  this._out = t, this._data = e, this._inv = 1, this._transform4();
92
92
  for (var r = 0; r < t.length; r++)
93
93
  t[r] /= this.size;
94
94
  this._out = null, this._data = null;
95
- }, i.prototype._transform4 = function() {
96
- var t = this._out, e = this._csize, r = this._width, s = 1 << r, a = e / s << 1, o, c, l = this._bitrev;
97
- if (a === 4)
98
- for (o = 0, c = 0; o < e; o += a, c++) {
95
+ }, a.prototype._transform4 = function() {
96
+ var t = this._out, e = this._csize, r = this._width, s = 1 << r, i = e / s << 1, o, c, l = this._bitrev;
97
+ if (i === 4)
98
+ for (o = 0, c = 0; o < e; o += i, c++) {
99
99
  const u = l[c];
100
100
  this._singleTransform2(o, u, s);
101
101
  }
102
102
  else
103
- for (o = 0, c = 0; o < e; o += a, c++) {
103
+ for (o = 0, c = 0; o < e; o += i, c++) {
104
104
  const u = l[c];
105
105
  this._singleTransform4(o, u, s);
106
106
  }
107
107
  var h = this._inv ? -1 : 1, d = this.table;
108
108
  for (s >>= 2; s >= 2; s >>= 2) {
109
- a = e / s << 1;
110
- var m = a >>> 2;
111
- for (o = 0; o < e; o += a)
109
+ i = e / s << 1;
110
+ var m = i >>> 2;
111
+ for (o = 0; o < e; o += i)
112
112
  for (var f = o + m, g = o, _ = 0; g < f; g += 2, _ += s) {
113
113
  const u = g, p = u + m, v = p + m, w = v + m, b = t[u], E = t[u + 1], A = t[p], y = t[p + 1], M = t[v], F = t[v + 1], C = t[w], T = t[w + 1], x = b, R = E, z = d[_], S = h * d[_ + 1], N = A * z - y * S, k = A * S + y * z, L = d[2 * _], P = h * d[2 * _ + 1], G = M * L - F * P, H = M * P + F * L, J = d[3 * _], K = h * d[3 * _ + 1], Y = C * J - T * K, Q = C * K + T * J, V = x + G, j = R + H, B = x - G, X = R - H, Z = N + Y, U = k + Q, $ = h * (N - Y), O = h * (k - Q), et = V + Z, ot = j + U, at = V - Z, it = j - U, ct = B + O, lt = X - $, ht = B - O, dt = X + $;
114
114
  t[u] = et, t[u + 1] = ot, t[p] = ct, t[p + 1] = lt, t[v] = at, t[v + 1] = it, t[w] = ht, t[w + 1] = dt;
115
115
  }
116
116
  }
117
- }, i.prototype._singleTransform2 = function(t, e, r) {
118
- const s = this._out, a = this._data, o = a[e], c = a[e + 1], l = a[e + r], h = a[e + r + 1], d = o + l, m = c + h, f = o - l, g = c - h;
117
+ }, a.prototype._singleTransform2 = function(t, e, r) {
118
+ const s = this._out, i = this._data, o = i[e], c = i[e + 1], l = i[e + r], h = i[e + r + 1], d = o + l, m = c + h, f = o - l, g = c - h;
119
119
  s[t] = d, s[t + 1] = m, s[t + 2] = f, s[t + 3] = g;
120
- }, i.prototype._singleTransform4 = function(t, e, r) {
121
- const s = this._out, a = this._data, o = this._inv ? -1 : 1, c = r * 2, l = r * 3, h = a[e], d = a[e + 1], m = a[e + r], f = a[e + r + 1], g = a[e + c], _ = a[e + c + 1], u = a[e + l], p = a[e + l + 1], v = h + g, w = d + _, b = h - g, E = d - _, A = m + u, y = f + p, M = o * (m - u), F = o * (f - p), C = v + A, T = w + y, x = b + F, R = E - M, z = v - A, S = w - y, N = b - F, k = E + M;
120
+ }, a.prototype._singleTransform4 = function(t, e, r) {
121
+ const s = this._out, i = this._data, o = this._inv ? -1 : 1, c = r * 2, l = r * 3, h = i[e], d = i[e + 1], m = i[e + r], f = i[e + r + 1], g = i[e + c], _ = i[e + c + 1], u = i[e + l], p = i[e + l + 1], v = h + g, w = d + _, b = h - g, E = d - _, A = m + u, y = f + p, M = o * (m - u), F = o * (f - p), C = v + A, T = w + y, x = b + F, R = E - M, z = v - A, S = w - y, N = b - F, k = E + M;
122
122
  s[t] = C, s[t + 1] = T, s[t + 2] = x, s[t + 3] = R, s[t + 4] = z, s[t + 5] = S, s[t + 6] = N, s[t + 7] = k;
123
- }, i.prototype._realTransform4 = function() {
124
- var t = this._out, e = this._csize, r = this._width, s = 1 << r, a = e / s << 1, o, c, l = this._bitrev;
125
- if (a === 4)
126
- for (o = 0, c = 0; o < e; o += a, c++) {
123
+ }, a.prototype._realTransform4 = function() {
124
+ var t = this._out, e = this._csize, r = this._width, s = 1 << r, i = e / s << 1, o, c, l = this._bitrev;
125
+ if (i === 4)
126
+ for (o = 0, c = 0; o < e; o += i, c++) {
127
127
  const ut = l[c];
128
128
  this._singleRealTransform2(o, ut >>> 1, s >>> 1);
129
129
  }
130
130
  else
131
- for (o = 0, c = 0; o < e; o += a, c++) {
131
+ for (o = 0, c = 0; o < e; o += i, c++) {
132
132
  const ut = l[c];
133
133
  this._singleRealTransform4(o, ut >>> 1, s >>> 1);
134
134
  }
135
135
  var h = this._inv ? -1 : 1, d = this.table;
136
136
  for (s >>= 2; s >= 2; s >>= 2) {
137
- a = e / s << 1;
138
- var m = a >>> 1, f = m >>> 1, g = f >>> 1;
139
- for (o = 0; o < e; o += a)
137
+ i = e / s << 1;
138
+ var m = i >>> 1, f = m >>> 1, g = f >>> 1;
139
+ for (o = 0; o < e; o += i)
140
140
  for (var _ = 0, u = 0; _ <= g; _ += 2, u += s) {
141
141
  var p = o + _, v = p + f, w = v + f, b = w + f, E = t[p], A = t[p + 1], y = t[v], M = t[v + 1], F = t[w], C = t[w + 1], T = t[b], x = t[b + 1], R = E, z = A, S = d[u], N = h * d[u + 1], k = y * S - M * N, L = y * N + M * S, P = d[2 * u], G = h * d[2 * u + 1], H = F * P - C * G, J = F * G + C * P, K = d[3 * u], Y = h * d[3 * u + 1], Q = T * K - x * Y, V = T * Y + x * K, j = R + H, B = z + J, X = R - H, Z = z - J, U = k + Q, $ = L + V, O = h * (k - Q), et = h * (L - V), ot = j + U, at = B + $, it = X + et, ct = Z - O;
142
142
  if (t[p] = ot, t[p + 1] = at, t[v] = it, t[v + 1] = ct, _ === 0) {
@@ -150,29 +150,29 @@ function Zt() {
150
150
  }
151
151
  }
152
152
  }
153
- }, i.prototype._singleRealTransform2 = function(t, e, r) {
154
- const s = this._out, a = this._data, o = a[e], c = a[e + r], l = o + c, h = o - c;
153
+ }, a.prototype._singleRealTransform2 = function(t, e, r) {
154
+ const s = this._out, i = this._data, o = i[e], c = i[e + r], l = o + c, h = o - c;
155
155
  s[t] = l, s[t + 1] = 0, s[t + 2] = h, s[t + 3] = 0;
156
- }, i.prototype._singleRealTransform4 = function(t, e, r) {
157
- const s = this._out, a = this._data, o = this._inv ? -1 : 1, c = r * 2, l = r * 3, h = a[e], d = a[e + r], m = a[e + c], f = a[e + l], g = h + m, _ = h - m, u = d + f, p = o * (d - f), v = g + u, w = _, b = -p, E = g - u, A = _, y = p;
156
+ }, a.prototype._singleRealTransform4 = function(t, e, r) {
157
+ const s = this._out, i = this._data, o = this._inv ? -1 : 1, c = r * 2, l = r * 3, h = i[e], d = i[e + r], m = i[e + c], f = i[e + l], g = h + m, _ = h - m, u = d + f, p = o * (d - f), v = g + u, w = _, b = -p, E = g - u, A = _, y = p;
158
158
  s[t] = v, s[t + 1] = 0, s[t + 2] = w, s[t + 3] = b, s[t + 4] = E, s[t + 5] = 0, s[t + 6] = A, s[t + 7] = y;
159
159
  }, mt;
160
160
  }
161
161
  var Ot = Zt();
162
162
  const qt = /* @__PURE__ */ Xt(Ot), nt = 16e3, W = 512, I = 64, Mt = Math.floor(0.025 * nt), Ft = Math.floor(0.01 * nt);
163
- function Ct(i) {
164
- return 2595 * Math.log10(1 + i / 700);
163
+ function Ct(a) {
164
+ return 2595 * Math.log10(1 + a / 700);
165
165
  }
166
- function te(i) {
167
- return 700 * (10 ** (i / 2595) - 1);
166
+ function te(a) {
167
+ return 700 * (10 ** (a / 2595) - 1);
168
168
  }
169
169
  function ee() {
170
- const i = Ct(0), n = Ct(nt / 2), t = new Float64Array(I + 2);
170
+ const a = Ct(0), n = Ct(nt / 2), t = new Float64Array(I + 2);
171
171
  for (let o = 0; o < I + 2; o++)
172
- t[o] = i + o * (n - i) / (I + 1);
173
- const r = t.map((o) => te(o)).map((o) => Math.floor((W + 1) * o / nt)), s = [], a = Math.floor(W / 2) + 1;
172
+ t[o] = a + o * (n - a) / (I + 1);
173
+ const r = t.map((o) => te(o)).map((o) => Math.floor((W + 1) * o / nt)), s = [], i = Math.floor(W / 2) + 1;
174
174
  for (let o = 0; o < I; o++) {
175
- const c = new Float32Array(a);
175
+ const c = new Float32Array(i);
176
176
  for (let l = r[o]; l < r[o + 1]; l++) c[l] = (l - r[o]) / (r[o + 1] - r[o]);
177
177
  for (let l = r[o + 1]; l < r[o + 2]; l++) c[l] = (r[o + 2] - l) / (r[o + 2] - r[o + 1]);
178
178
  s.push(c);
@@ -180,36 +180,36 @@ function ee() {
180
180
  return s;
181
181
  }
182
182
  const se = ee(), rt = new qt(W), _t = new Float32Array(W), Tt = rt.createComplexArray(), ft = rt.createComplexArray(), xt = new Float32Array(Math.floor(W / 2) + 1);
183
- function kt(i) {
184
- const n = 1 + Math.ceil((i.length - Mt) / Ft), t = new Float32Array(n * I), e = Math.floor(W / 2) + 1;
183
+ function kt(a) {
184
+ const n = 1 + Math.ceil((a.length - Mt) / Ft), t = new Float32Array(n * I), e = Math.floor(W / 2) + 1;
185
185
  for (let r = 0; r < n; r++) {
186
186
  const s = r * Ft;
187
187
  _t.fill(0);
188
- for (let a = 0; a < Mt && s + a < i.length; a++)
189
- _t[a] = i[s + a];
188
+ for (let i = 0; i < Mt && s + i < a.length; i++)
189
+ _t[i] = a[s + i];
190
190
  rt.toComplexArray(_t, Tt), rt.transform(ft, Tt);
191
- for (let a = 0; a < e; a++) {
192
- const o = ft[2 * a], c = ft[2 * a + 1], l = (o * o + c * c) / W;
193
- xt[a] = l === 0 ? 1e-30 : l;
191
+ for (let i = 0; i < e; i++) {
192
+ const o = ft[2 * i], c = ft[2 * i + 1], l = (o * o + c * c) / W;
193
+ xt[i] = l === 0 ? 1e-30 : l;
194
194
  }
195
- for (let a = 0; a < I; a++) {
196
- const o = se[a];
195
+ for (let i = 0; i < I; i++) {
196
+ const o = se[i];
197
197
  let c = 0;
198
198
  for (let l = 0; l < e; l++) c += xt[l] * o[l];
199
- t[r * I + a] = Math.log(c === 0 ? 1e-30 : c);
199
+ t[r * I + i] = Math.log(c === 0 ? 1e-30 : c);
200
200
  }
201
201
  }
202
202
  return t;
203
203
  }
204
- function ne(i, n) {
204
+ function ne(a, n) {
205
205
  let t = 0;
206
- for (let e = 0; e < i.length; e++) t += i[e] * n[e];
206
+ for (let e = 0; e < a.length; e++) t += a[e] * n[e];
207
207
  return (t + 1) / 2;
208
208
  }
209
- function re(i, n) {
209
+ function re(a, n) {
210
210
  let t = 0;
211
211
  for (const e of n) {
212
- const r = ne(i, e);
212
+ const r = ne(a, e);
213
213
  r > t && (t = r);
214
214
  }
215
215
  return t;
@@ -246,10 +246,10 @@ class Rt extends EventTarget {
246
246
  }
247
247
  }
248
248
  const zt = 16e3, oe = 1500, pt = 24e3;
249
- function St(i) {
250
- if (i.length === pt) return i;
249
+ function St(a) {
250
+ if (a.length === pt) return a;
251
251
  const n = new Float32Array(pt);
252
- return n.set(i.subarray(0, pt)), n;
252
+ return n.set(a.subarray(0, pt)), n;
253
253
  }
254
254
  class ae extends EventTarget {
255
255
  /** @param {string} wordName — the wake word label */
@@ -269,13 +269,13 @@ class ae extends EventTarget {
269
269
  async recordSample() {
270
270
  const n = await navigator.mediaDevices.getUserMedia({ audio: !0 });
271
271
  return new Promise((t, e) => {
272
- const r = new AudioContext({ sampleRate: zt }), s = new MediaRecorder(n), a = [];
272
+ const r = new AudioContext({ sampleRate: zt }), s = new MediaRecorder(n), i = [];
273
273
  this.dispatchEvent(new CustomEvent("recording-start")), s.ondataavailable = (o) => {
274
- o.data.size > 0 && a.push(o.data);
274
+ o.data.size > 0 && i.push(o.data);
275
275
  }, s.onstop = async () => {
276
276
  n.getTracks().forEach((o) => o.stop());
277
277
  try {
278
- const c = await new Blob(a, { type: "audio/webm" }).arrayBuffer(), l = await r.decodeAudioData(c);
278
+ const c = await new Blob(i, { type: "audio/webm" }).arrayBuffer(), l = await r.decodeAudioData(c);
279
279
  await r.close();
280
280
  const h = l.getChannelData(0), d = St(new Float32Array(h)), m = this._push(d, `Recorded #${this.samples.length}`);
281
281
  t(m);
@@ -296,8 +296,8 @@ class ae extends EventTarget {
296
296
  async addAudioFile(n) {
297
297
  const t = await n.arrayBuffer(), e = new AudioContext({ sampleRate: zt }), r = await e.decodeAudioData(t);
298
298
  await e.close();
299
- const s = r.getChannelData(0), a = St(new Float32Array(s));
300
- return this._push(a, n.name);
299
+ const s = r.getChannelData(0), i = St(new Float32Array(s));
300
+ return this._push(i, n.name);
301
301
  }
302
302
  // ─── Manage ────────────────────────────────────────────────────────────────
303
303
  /**
@@ -382,37 +382,37 @@ registerProcessor('audio-processor', AudioProcessor)
382
382
  let vt = null;
383
383
  function ce() {
384
384
  if (!vt) {
385
- const i = new Blob([ie], { type: "application/javascript" });
386
- vt = URL.createObjectURL(i);
385
+ const a = new Blob([ie], { type: "application/javascript" });
386
+ vt = URL.createObjectURL(a);
387
387
  }
388
388
  return vt;
389
389
  }
390
390
  const gt = "mellon_custom_refs";
391
391
  function yt() {
392
392
  try {
393
- const i = localStorage.getItem(gt);
394
- return i ? JSON.parse(i) : [];
393
+ const a = localStorage.getItem(gt);
394
+ return a ? JSON.parse(a) : [];
395
395
  } catch {
396
396
  return [];
397
397
  }
398
398
  }
399
- function le(i) {
400
- const n = yt().filter((t) => t.word_name !== i.word_name);
401
- n.push(i), localStorage.setItem(gt, JSON.stringify(n));
399
+ function le(a) {
400
+ const n = yt().filter((t) => t.word_name !== a.word_name);
401
+ n.push(a), localStorage.setItem(gt, JSON.stringify(n));
402
402
  }
403
- function he(i) {
404
- const n = yt().filter((t) => t.word_name !== i);
403
+ function he(a) {
404
+ const n = yt().filter((t) => t.word_name !== a);
405
405
  localStorage.setItem(gt, JSON.stringify(n));
406
406
  }
407
- function de(i) {
408
- const n = JSON.stringify(i, null, 2), t = new Blob([n], { type: "application/json" }), e = URL.createObjectURL(t), r = Object.assign(document.createElement("a"), {
407
+ function de(a) {
408
+ const n = JSON.stringify(a, null, 2), t = new Blob([n], { type: "application/json" }), e = URL.createObjectURL(t), r = Object.assign(document.createElement("a"), {
409
409
  href: e,
410
- download: `${i.word_name}_ref.json`
410
+ download: `${a.word_name}_ref.json`
411
411
  });
412
412
  document.body.appendChild(r), r.click(), document.body.removeChild(r), URL.revokeObjectURL(e);
413
413
  }
414
- async function ue(i) {
415
- const n = await i.text();
414
+ async function ue(a) {
415
+ const n = await a.text();
416
416
  let t;
417
417
  try {
418
418
  t = JSON.parse(n);
@@ -423,7 +423,7 @@ async function ue(i) {
423
423
  throw new Error('Missing or empty "embeddings" array');
424
424
  if (!Array.isArray(t.embeddings[0]))
425
425
  throw new Error('"embeddings" must be a 2D array');
426
- return t.word_name || (t.word_name = i.name.replace(/_ref\.json$/i, "").replace(/\.json$/i, "")), t;
426
+ return t.word_name || (t.word_name = a.name.replace(/_ref\.json$/i, "").replace(/\.json$/i, "")), t;
427
427
  }
428
428
  class wt extends EventTarget {
429
429
  /**
@@ -476,16 +476,13 @@ class wt extends EventTarget {
476
476
  throw this.dispatchEvent(new CustomEvent("error", { detail: { error: r } })), r;
477
477
  }
478
478
  const t = await wt.loadWords();
479
- console.log("existing refs in localstorage", { exisitngRefs: t });
480
479
  for (const r of this._opts.refs) {
481
- const s = (e = r.match(/\/([^/]+?)_ref\.json$/)) == null ? void 0 : e[1], a = t.find((o) => o.word_name === s);
482
- console.log({ word: s, alreadySaveWord: a });
480
+ const s = (e = r.match(/\/([^/]+?)_ref\.json$/)) == null ? void 0 : e[1], i = t.find((o) => o.word_name === s);
483
481
  try {
484
482
  let o;
485
- if (a) {
486
- this.addCustomWord(a);
487
- break;
488
- } else if (typeof r == "string") {
483
+ if (i)
484
+ continue;
485
+ if (typeof r == "string") {
489
486
  console.log("fetching ref : ", r);
490
487
  const c = await fetch(r);
491
488
  if (!c.ok) throw new Error(`HTTP ${c.status}`);
@@ -498,7 +495,7 @@ class wt extends EventTarget {
498
495
  console.warn(`[Mellon] Failed to load ref "${c}": ${o.message}`);
499
496
  }
500
497
  }
501
- this._initialized = !0, this.dispatchEvent(new CustomEvent("ready"));
498
+ t.forEach((r) => this.addCustomWord(r)), this._initialized = !0, this.dispatchEvent(new CustomEvent("ready"));
502
499
  }
503
500
  /**
504
501
  * Request microphone access and start hotword detection.
@@ -526,7 +523,7 @@ class wt extends EventTarget {
526
523
  relaxationMs: this._opts.relaxationMs,
527
524
  inferenceGapMs: this._opts.inferenceGapMs
528
525
  });
529
- s.addEventListener("match", (a) => this._onMatch(a)), this._detectors.set(e, s);
526
+ s.addEventListener("match", (i) => this._onMatch(i)), this._detectors.set(e, s);
530
527
  }
531
528
  this._workletNode.port.onmessage = async (e) => {
532
529
  const r = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mellon",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "Offline, in-browser hotword detection powered by EfficientWord-Net (ResNet-50 ArcFace). Works as a standalone app or npm library.",
5
5
  "type": "module",
6
6
  "main": "./dist/mellon.cjs",