UNPKG

wavesurfer.js

Version:

Interactive navigable audio visualization using Web Audio and Canvas

7 lines 10.8 kB
/*! * wavesurfer.js spectrogram plugin 6.6.3 (2023-04-04) * https://wavesurfer-js.org * @license BSD-3-Clause */ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("WaveSurfer",[],t):"object"==typeof exports?exports.WaveSurfer=t():(e.WaveSurfer=e.WaveSurfer||{},e.WaveSurfer.spectrogram=t())}(self,(()=>(()=>{"use strict";var e={325:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t,r,a){switch(this.bufferSize=e,this.sampleRate=t,this.bandwidth=2/e*(t/2),this.sinTable=new Float32Array(e),this.cosTable=new Float32Array(e),this.windowValues=new Float32Array(e),this.reverseTable=new Uint32Array(e),this.peakBand=0,this.peak=0,r){case"bartlett":for(i=0;i<e;i++)this.windowValues[i]=2/(e-1)*((e-1)/2-Math.abs(i-(e-1)/2));break;case"bartlettHann":for(i=0;i<e;i++)this.windowValues[i]=.62-.48*Math.abs(i/(e-1)-.5)-.38*Math.cos(2*Math.PI*i/(e-1));break;case"blackman":for(a=a||.16,i=0;i<e;i++)this.windowValues[i]=(1-a)/2-.5*Math.cos(2*Math.PI*i/(e-1))+a/2*Math.cos(4*Math.PI*i/(e-1));break;case"cosine":for(i=0;i<e;i++)this.windowValues[i]=Math.cos(Math.PI*i/(e-1)-Math.PI/2);break;case"gauss":for(a=a||.25,i=0;i<e;i++)this.windowValues[i]=Math.pow(Math.E,-.5*Math.pow((i-(e-1)/2)/(a*(e-1)/2),2));break;case"hamming":for(i=0;i<e;i++)this.windowValues[i]=.54-.46*Math.cos(2*Math.PI*i/(e-1));break;case"hann":case void 0:for(i=0;i<e;i++)this.windowValues[i]=.5*(1-Math.cos(2*Math.PI*i/(e-1)));break;case"lanczoz":for(i=0;i<e;i++)this.windowValues[i]=Math.sin(Math.PI*(2*i/(e-1)-1))/(Math.PI*(2*i/(e-1)-1));break;case"rectangular":for(i=0;i<e;i++)this.windowValues[i]=1;break;case"triangular":for(i=0;i<e;i++)this.windowValues[i]=2/e*(e/2-Math.abs(i-(e-1)/2));break;default:throw Error("No such window function '"+r+"'")}var i,n=1,s=e>>1;for(;n<e;){for(i=0;i<n;i++)this.reverseTable[i+n]=this.reverseTable[i]+s;n<<=1,s>>=1}for(i=0;i<e;i++)this.sinTable[i]=Math.sin(-Math.PI/i),this.cosTable[i]=Math.cos(-Math.PI/i);this.calculateSpectrum=function(e){var t,r,a,i=this.bufferSize,n=this.cosTable,s=this.sinTable,o=this.reverseTable,l=new Float32Array(i),h=new Float32Array(i),f=2/this.bufferSize,c=Math.sqrt,u=new Float32Array(i/2),p=Math.floor(Math.log(i)/Math.LN2);if(Math.pow(2,p)!==i)throw"Invalid buffer size, must be a power of 2.";if(i!==e.length)throw"Supplied buffer is not the same size as defined FFT. FFT Size: "+i+" Buffer Size: "+e.length;for(var d,v,w,y,m,b,M,g,S=1,k=0;k<i;k++)l[k]=e[o[k]]*this.windowValues[o[k]],h[k]=0;for(;S<i;){d=n[S],v=s[S],w=1,y=0;for(var x=0;x<S;x++){for(k=x;k<i;)b=w*l[m=k+S]-y*h[m],M=w*h[m]+y*l[m],l[m]=l[k]-b,h[m]=h[k]-M,l[k]+=b,h[k]+=M,k+=S<<1;w=(g=w)*d-y*v,y=g*v+y*d}S<<=1}k=0;for(var C=i/2;k<C;k++)(a=f*c((t=l[k])*t+(r=h[k])*r))>this.peak&&(this.peakBand=k,this.peak=a),u[k]=a;return u}},e.exports=t.default},943:(e,t,r)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a,i=(a=r(325))&&a.__esModule?a:{default:a};function n(e){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n(e)}function s(e,t){for(var r=0;r<t.length;r++){var a=t[r];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,(i=a.key,s=void 0,s=function(e,t){if("object"!==n(e)||null===e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var a=r.call(e,t||"default");if("object"!==n(a))return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(i,"string"),"symbol"===n(s)?s:String(s)),a)}var i,s}var o=function(){function e(t,r){var a=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.params=t,this.wavesurfer=r,this.util=r.util,this.frequenciesDataUrl=t.frequenciesDataUrl,this._onScroll=function(e){a.updateScroll(e)},this._onRender=function(){a.render()},this._onWrapperClick=function(e){a._wrapperClickHandler(e)},this._onReady=function(){var e=a.drawer=r.drawer;if(a.container="string"==typeof t.container?document.querySelector(t.container):t.container,!a.container)throw Error("No container for WaveSurfer spectrogram");if(t.colorMap){if(t.colorMap.length<256)throw new Error("Colormap must contain 256 elements");for(var i=0;i<t.colorMap.length;i++){if(4!==t.colorMap[i].length)throw new Error("ColorMap entries must contain 4 values")}a.colorMap=t.colorMap}else{a.colorMap=[];for(var n=0;n<256;n++){var s=(255-n)/256;a.colorMap.push([s,s,s,1])}}a.width=e.width,a.pixelRatio=a.params.pixelRatio||r.params.pixelRatio,a.fftSamples=a.params.fftSamples||r.params.fftSamples||512,a.height=a.params.height||a.fftSamples/2,a.noverlap=t.noverlap,a.windowFunc=t.windowFunc,a.alpha=t.alpha,a.splitChannels=t.splitChannels,a.channels=a.splitChannels?r.backend.buffer.numberOfChannels:1,a.frequencyMin=t.frequencyMin||0,a.frequencyMax=t.frequencyMax||12e3,a.createWrapper(),a.createCanvas(),a.render(),e.wrapper.addEventListener("scroll",a._onScroll),r.on("redraw",a._onRender)}}var t,r,a;return t=e,a=[{key:"create",value:function(t){return{name:"spectrogram",deferInit:!(!t||!t.deferInit)&&t.deferInit,params:t,staticProps:{FFT:i.default},instance:e}}}],(r=[{key:"init",value:function(){this.wavesurfer.isReady?this._onReady():this.wavesurfer.once("ready",this._onReady)}},{key:"destroy",value:function(){this.unAll(),this.wavesurfer.un("ready",this._onReady),this.wavesurfer.un("redraw",this._onRender),this.drawer&&this.drawer.wrapper.removeEventListener("scroll",this._onScroll),this.wavesurfer=null,this.util=null,this.params=null,this.wrapper&&(this.wrapper.removeEventListener("click",this._onWrapperClick),this.wrapper.parentNode.removeChild(this.wrapper),this.wrapper=null)}},{key:"createWrapper",value:function(){var e=this.container.querySelector("spectrogram");e&&this.container.removeChild(e);var t=this.wavesurfer.params;if(this.wrapper=document.createElement("spectrogram"),this.params.labels){var r=this.labelsEl=document.createElement("canvas");r.classList.add("spec-labels"),this.drawer.style(r,{position:"absolute",zIndex:9,height:"".concat(this.height*this.channels,"px"),width:"55px"}),this.wrapper.appendChild(r),this.loadLabels("rgba(68,68,68,0.5)","12px","10px","","#fff","#f7f7f7","center","#specLabels")}this.drawer.style(this.wrapper,{display:"block",position:"relative",userSelect:"none",webkitUserSelect:"none",height:"".concat(this.height*this.channels,"px")}),(t.fillParent||t.scrollParent)&&this.drawer.style(this.wrapper,{width:"100%",overflowX:"hidden",overflowY:"hidden"}),this.container.appendChild(this.wrapper),this.wrapper.addEventListener("click",this._onWrapperClick)}},{key:"_wrapperClickHandler",value:function(e){e.preventDefault();var t="offsetX"in e?e.offsetX:e.layerX;this.fireEvent("click",t/this.width||0)}},{key:"createCanvas",value:function(){var e=this.canvas=this.wrapper.appendChild(document.createElement("canvas"));this.spectrCc=e.getContext("2d"),this.util.style(e,{position:"absolute",zIndex:4})}},{key:"render",value:function(){this.updateCanvasStyle(),this.frequenciesDataUrl?this.loadFrequenciesData(this.frequenciesDataUrl):this.getFrequencies(this.drawSpectrogram)}},{key:"updateCanvasStyle",value:function(){var e=Math.round(this.width/this.pixelRatio)+"px";this.canvas.width=this.width,this.canvas.height=this.fftSamples/2*this.channels,this.canvas.style.width=e,this.canvas.style.height=this.height+"px"}},{key:"drawSpectrogram",value:function(e,t){isNaN(e[0][0])||(e=[e]);var r=t.spectrCc,a=t.fftSamples/2,i=t.width,n=t.buffer.sampleRate/2,s=t.frequencyMin,o=t.frequencyMax;if(r)for(var l=function(l){for(var h=t.resample(e[l]),f=new ImageData(i,a),c=0;c<h.length;c++)for(var u=0;u<h[c].length;u++){var p=t.colorMap[h[c][u]],d=4*((a-u)*i+c);f.data[d]=255*p[0],f.data[d+1]=255*p[1],f.data[d+2]=255*p[2],f.data[d+3]=255*p[3]}createImageBitmap(f).then((function(e){return r.drawImage(e,0,a*(1-o/n),i,a*(o-s)/n,0,a*l,i,a)}))},h=0;h<e.length;h++)l(h)}},{key:"getFrequencies",value:function(e){var t=this.fftSamples,r=this.buffer=this.wavesurfer.backend.buffer,a=this.channels;if(r){var n=r.sampleRate,s=[],o=this.noverlap;if(!o){var l=r.length/this.canvas.width;o=Math.max(0,Math.round(t-l))}for(var h=new i.default(t,n,this.windowFunc,this.alpha),f=0;f<a;f++){for(var c=r.getChannelData(f),u=[],p=0;p+t<c.length;){var d=c.slice(p,p+t),v=h.calculateSpectrum(d),w=new Uint8Array(t/2),y=void 0;for(y=0;y<t/2;y++)w[y]=Math.max(-255,45*Math.log10(v[y]));u.push(w),p+=t-o}s.push(u)}e(s,this)}else this.fireEvent("error","Web Audio buffer is not available")}},{key:"loadFrequenciesData",value:function(e){var t=this,r=this.util.fetchFile({url:e});return r.on("success",(function(e){return t.drawSpectrogram(JSON.parse(e),t)})),r.on("error",(function(e){return t.fireEvent("error",e)})),r}},{key:"freqType",value:function(e){return e>=1e3?(e/1e3).toFixed(1):Math.round(e)}},{key:"unitType",value:function(e){return e>=1e3?"KHz":"Hz"}},{key:"loadLabels",value:function(e,t,r,a,i,n,s,o){e=e||"rgba(68,68,68,0)",t=t||"12px",r=r||"10px",a=a||"Helvetica",i=i||"#fff",n=n||"#fff",s=s||"center",o=o||"#specLabels";var l=this.height||512,h=l/256*5,f=this.frequencyMin,c=(this.frequencyMax-f)/h,u=this.labelsEl.getContext("2d"),p=window.devicePixelRatio;if(this.labelsEl.height=this.height*this.channels*p,this.labelsEl.width=55*p,u.scale(p,p),u)for(var d=0;d<this.channels;d++){u.fillStyle=e,u.fillRect(0,d*l,55,(1+d)*l),u.fill();var v=void 0;for(v=0;v<=h;v++){u.textAlign=s,u.textBaseline="middle";var w=f+c*v,y=this.freqType(w),m=this.unitType(w),b=void 0;0==v?(b=(1+d)*l+v-10,u.fillStyle=n,u.font=r+" "+a,u.fillText(m,40,b),u.fillStyle=i,u.font=t+" "+a,u.fillText(y,16,b)):(b=(1+d)*l-50*v+2,u.fillStyle=n,u.font=r+" "+a,u.fillText(m,40,b),u.fillStyle=i,u.font=t+" "+a,u.fillText(y,16,b))}}}},{key:"updateScroll",value:function(e){this.wrapper&&(this.wrapper.scrollLeft=e.target.scrollLeft)}},{key:"resample",value:function(e){var t,r=this.width,a=[],i=1/e.length,n=1/r;for(t=0;t<r;t++){var s=new Array(e[0].length),o=void 0;for(o=0;o<e.length;o++){var l=o*i,h=l+i,f=t*n,c=f+n,u=h<=f||c<=l?0:Math.min(Math.max(h,f),Math.max(c,l))-Math.max(Math.min(h,f),Math.min(c,l)),p=void 0;if(u>0)for(p=0;p<e[0].length;p++)null==s[p]&&(s[p]=0),s[p]+=u/n*e[o][p]}var d=new Uint8Array(e[0].length),v=void 0;for(v=0;v<e[0].length;v++)d[v]=s[v];a.push(d)}return a}}])&&s(t.prototype,r),a&&s(t,a),Object.defineProperty(t,"prototype",{writable:!1}),e}();t.default=o,e.exports=t.default}},t={};var r=function r(a){var i=t[a];if(void 0!==i)return i.exports;var n=t[a]={exports:{}};return e[a](n,n.exports,r),n.exports}(943);return r})())); //# sourceMappingURL=wavesurfer.spectrogram.min.js.map