web-audio-peakmeter-react
Version:
React component for displaying a peak meter for a web audio source
2 lines (1 loc) • 4.43 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):(e=e||self).Peakmeter=t(e.React)}(this,function(a){"use strict";function o(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function c(e,t){return(c=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function l(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}return a=a&&a.hasOwnProperty("default")?a.default:a,function(e){function i(e){var t,n,r;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,i),n=this;var a=(t=!(r=s(i).call(this,e))||"object"!=typeof r&&"function"!=typeof r?l(n):r).props.channels;t.channelCount=a,t.meterNode=t.props.audioCtx.createScriptProcessor(2048,a,a),t.meterNode.connect(t.props.audioCtx.destination),t.channelPeaks=[],t.maskSizes=[],t.textLabels=[];for(var o=0;o<a;o++)t.channelPeaks.push(0),t.maskSizes.push(100),t.textLabels.push("-∞");return t.clearPeaks=t.clearPeaks.bind(l(l(t))),t.maskSize=t.maskSize.bind(l(l(t))),t.updateMeter=t.updateMeter.bind(l(l(t))),t.paintMeter=t.paintMeter.bind(l(l(t))),t.meterNode.onaudioprocess=t.updateMeter,t}var t,n,r;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&c(e,t)}(i,a.Component),t=i,(n=[{key:"componentDidMount",value:function(){this.paintMeter(),this.connectSourceNodes()}},{key:"connectSourceNodes",value:function(){var t=this;this.props.sourceNodes.forEach(function(e){e.connect(t.meterNode)})}},{key:"getBaseLog",value:function(e,t){return Math.log(t)/Math.log(e)}},{key:"dbFromFloat",value:function(e){return 20*this.getBaseLog(10,e)}},{key:"clearPeaks",value:function(){for(var e=0;e<this.channelCount;e++)this.channelPeaks[e]=0,this.textLabels[e]="-∞"}},{key:"maskSize",value:function(e){var t=Math.floor(100*this.dbFromFloat(e)/-42);return 100<t?100:t}},{key:"updateMeter",value:function(e){var t=e.inputBuffer,n=0,r=[],a=[];for(n=0;n<this.channelCount;n++)r[n]=t.getChannelData(n),a[n]=0;for(var o=0;o<t.length;o++)for(n=0;n<this.channelCount;n++)Math.abs(r[n][o])>a[n]&&(a[n]=Math.abs(r[n][o]));for(n=0;n<this.channelCount;n++)this.maskSizes[n]=this.maskSize(a[n]),a[n]>this.channelPeaks[n]&&(this.channelPeaks[n]=a[n],this.textLabels[n]=this.dbFromFloat(a[n]).toFixed(1))}},{key:"paintMeter",value:function(){for(var e=0;e<this.channelCount;e++)this.props.vertical?this["mask"+e].style.height=this.maskSizes[e]+"%":this["mask"+e].style.width=this.maskSizes[e]+"%",this["peak"+e].textContent=this.textLabels[e];window.requestAnimationFrame(this.paintMeter)}},{key:"render",value:function(){var n=this,r={outer:{backgroundColor:"#222",padding:"5px",display:"flex"},bars:{width:"calc(100% - 30px)"},text:{width:"30px"},meter:{padding:"0 5px"},gradient:{backgroundImage:"linear-gradient(to left, "+["red 1%","#ff0 16%","lime 45%","#080 100%"].join(", ")+")",position:"relative",height:"15px",marginBottom:"5px"},mask:{backgroundColor:"#222",width:"100%",height:"100%",position:"absolute",right:"0",transition:"width 0.1s"},labels:{display:"flex",justifyContent:"space-between",fontSize:"6px",color:"#ccc"},label:{width:"10px",textAlign:"center"},textPeak:{fontSize:"10px",color:"#ccc",textAlign:"center",height:"15px",lineHeight:"15px",marginBottom:"5px"}};return a.createElement("div",{style:r.outer,onClick:this.clearPeaks},a.createElement("div",{style:r.bars},a.createElement("div",{style:r.meter},this.channelPeaks.map(function(e,t){return a.createElement("div",{key:"gradient"+t,style:r.gradient},a.createElement("div",{style:r.mask,ref:function(e){n["mask"+t]=e}}))})),a.createElement("div",{style:r.labels},[-42,-36,-30,-24,-18,-12,-6,0].map(function(e,t){return a.createElement("div",{key:"label"+t,style:r.label},e)}))),a.createElement("div",{style:r.text},this.textLabels.map(function(e,t){return a.createElement("div",{key:"peak"+t,style:r.textPeak,ref:function(e){n["peak"+t]=e}})})))}}])&&o(t.prototype,n),r&&o(t,r),i}()});