UNPKG

modern-audio

Version:
2 lines (1 loc) 8.2 kB
(function(d,A){typeof exports=="object"&&typeof module<"u"?A(exports):typeof define=="function"&&define.amd?define(["exports"],A):(d=typeof globalThis<"u"?globalThis:d||self,A(d["modern-audio"]={}))})(this,function(d){"use strict";const A=({context:e})=>{const o=e.createAnalyser();return o.fftSize=2048,{name:"analyser",node:o}},H=({context:e})=>({name:"destination",node:e.destination}),V=({source:e})=>({name:"loop",props:{loop:{value:!1,getter(){return this.value},setter(o){this.value=o=Boolean(o),e instanceof MediaElementAudioSourceNode?e.mediaElement.loop=o:e instanceof AudioBufferSourceNode&&(e.loop=o)}}}}),F=e=>{const{context:o}=e;let t=!1;const n=o.createBiquadFilter();n.Q.value=8.3,n.frequency.value=355,n.gain.value=3,n.type="bandpass";const r=o.createDynamicsCompressor();return r.attack.value=0,r.knee.value=40,r.ratio.value=12,r.release.value=.25,r.threshold.value=-50,{name:"noise-reduction",node:()=>t?n:void 0,connect:i=>n.connect(r).connect(i),disconnect:()=>{n.disconnect(),r.disconnect()},props:{noiseReduction:{value:t,getter(){return this.value},setter(i){i===""&&(i=!0),t!==i&&(this.value=t=i,e.reconnect())}}}}},j=({context:e})=>{const o=e.createStereoPanner();return{name:"panner",node:o,props:{pan:{value:o.pan.value,getter(){return this.value},setter(t){this.value=o.pan.value=Number(t)}}}}},W=({source:e})=>({name:"playbackRate",props:{playbackRate:{value:1,getter(){return this.value},setter(o){this.value=o=Number(o),e instanceof MediaElementAudioSourceNode?e.mediaElement.playbackRate=o:e instanceof AudioBufferSourceNode&&(e.playbackRate.value=o)}}}}),q=({source:e})=>({name:"source",node:e});function z(e){return e instanceof MediaElementAudioSourceNode?e.mediaElement.playbackRate:e instanceof AudioBufferSourceNode?e.playbackRate.value:0}function $(e){var o,t;return e instanceof MediaElementAudioSourceNode?e.mediaElement.duration:e instanceof AudioBufferSourceNode&&(t=(o=e.buffer)==null?void 0:o.duration)!=null?t:0}const G=({context:e,source:o})=>{const t=e.createGain();return{name:"volume",node:t,props:{db:{value:1,getter(){return this.value},setter(n){this.value=n=Number(n),t.gain.value=Math.pow(10,n/20)}},fadeIn:{value:0,getter(){return this.value},setter(n){this.value=n;const{at:r,duration:i}=typeof n=="object"?n:{at:e.currentTime,duration:Number(n)};t.gain.setValueAtTime(.01,r),t.gain.exponentialRampToValueAtTime(t.gain.value,r+i)}},fadeOut:{value:0,getter(){return this.value},setter(n){this.value=n;const{at:r,duration:i}=typeof n=="object"?n:{at:e.currentTime+$(o)/z(o)-Number(n),duration:Number(n)};t.gain.setValueAtTime(t.gain.value,r),t.gain.exponentialRampToValueAtTime(.01,r+i)}}}}};function Q(e){return e=e||[],[q,W,V,F,G,j,...e,A,H]}function _(e){return e}function J(e,o){return Q(o).map(t=>t(e))}function x({node:e}){return typeof e=="function"?e():e}function E(e){e.slice(1).reduce((o,t)=>{var r;const n=x(t);return n?(o.connect?o.connect(n):(r=x(o))==null||r.connect(n),t):o},e[0])}function N(e){e.forEach(o=>{var t;o.disconnect?o.disconnect():(t=x(o))==null||t.disconnect()})}function K(e){const o=new Map;for(const t of e)if(!!t.props)for(const n in t.props)o.set(n,t.props[n]);return o}function T(e){return e.replace(/-(\w)/g,(o,t)=>t.toLocaleUpperCase())}function v(e,o){const t=o in e?e[o]:void 0;return t instanceof Function?t.bind(e):t}function C(e,o){return fetch(e).then(t=>t.arrayBuffer()).then(t=>o.decodeAudioData(t))}function X(e,o,t=0,n){t=t||0,n=n||o-1;const r=e.length/o,i=~~(r/10)||1,s=e.numberOfChannels,c=[],a=[];for(let u=0;u<s;u++){c[u]=c[u]||[];const l=c[u],h=e.getChannelData(u);let f;for(f=t;f<=n;f++){const b=~~(f*r),S=~~(b+r);let p=h[b],m=p;for(let B=b;B<S;B+=i){const y=h[B];y>m&&(m=y),y<p&&(p=y)}l[2*f]=m,l[2*f+1]=p,(u===0||m>a[2*f])&&(a[2*f]=m),(u===0||p<a[2*f+1])&&(a[2*f+1]=p)}}return{splitPeaks:c,mergedPeaks:a}}async function Y(e,o="#364356",t,n){const{width:r,height:i}=e,s=e.getContext("2d"),c=typeof t=="string"?await C(t,n):t.buffer,{mergedPeaks:a}=X(c,r),u=window.devicePixelRatio||1,l=a.some(g=>g<0)?2:1,f=a.length/l/r,b=i/2,S=.5/u,p=2,m=1,y=1/1,k=p*u,ae=Math.max(u,~~(k/2)),O=k+ae;s.clearRect(0,0,r,i);for(let g=0;g<a.length;g+=O){let R=0,P=Math.floor(g*f)*l;const ce=Math.floor((g+O)*f)*l;do{const I=Math.abs(a[P]);I>R&&(R=I),P+=l}while(P<ce);const L=Math.max(Math.round(R/y*b),m);s.fillStyle=o,s.fillRect(g+S,b-L,k+S,L*2)}}function Z(e,o="#364356",t){const{width:n,height:r}=e,i=e.getContext("2d"),s=t.frequencyBinCount,c=new Uint8Array(s);i.clearRect(0,0,n,r),function a(){requestAnimationFrame(a),t.getByteTimeDomainData(c);const u=n/s*1.5;i.clearRect(0,0,n,r);for(let l=0,h=0;l<s;l++){const f=c[l];i.fillStyle=o,i.fillRect(h,r-f,u,f),h+=u+1}}()}function ee(e,o){const t=o!=null?o:new AudioContext;if(typeof e=="string"){const n=t.createBufferSource();return{context:t,source:n,src:e,load:async()=>{n.buffer=await C(e,t)},clone:()=>{const r=n.buffer,i=t.createBufferSource();return i.buffer=r,i}}}else if(e instanceof AudioBuffer){const n=t.createBufferSource();return n.buffer=e,{context:t,source:n,clone:()=>{const r=n.buffer,i=t.createBufferSource();return i.buffer=r,i}}}else return t instanceof AudioContext&&e instanceof HTMLMediaElement?{context:t,source:t.createMediaElementSource(e),src:e.src}:{context:t,source:e}}function U(e,o){const{load:t,clone:n,...r}=ee(e,o),i={...r,processors:[],props:new Map,setup(){N(this.processors),this.processors=J(this),this.props=K(this.processors),E(this.processors)},reconnect(){N(this.processors),E(this.processors)},get(s){var c,a;if(s)return(a=(c=this.props.get(T(s)))==null?void 0:c.getter)==null?void 0:a.call(c);{const u={};return this.props.forEach((l,h)=>{u[h]=this.get(h)}),u}},set(s,c){var a,u;if(typeof s=="string")(u=(a=this.props.get(T(s)))==null?void 0:a.setter)==null||u.call(a,c);else for(const l in s)this.set(l,s[l])},renderBarChart(s,c){return Y(s,c,this.source instanceof MediaElementAudioSourceNode?this.source.mediaElement.src:this.source,this.context)},renderTimeDomainBarChart(s,c){return Z(s,c,this.processors.find(a=>a.name==="analyser").node)}};return t&&(i.load=async function(){await t(),this.setup()}),n&&(i.reset=function(){this.source=n();const s=this.get();this.setup(),this.set(s)},i.resetAndStart=function(s,c,a){var u;(u=this.reset)==null||u.call(this),this.source.start(s,c,a)}),i.source instanceof AudioBufferSourceNode||i.setup(),new Proxy(i,{get(s,c){var a;return(a=v(s,c))!=null?a:v(s.source,c)},set(s,c,a){return c in s?s[c]=a:s.source[c]=a,!0}})}class M extends HTMLAudioElement{constructor(){super(),this.source=U(this),this.setup()}static install(){customElements.define("modern-audio",M,{extends:"audio"})}async setup(){this.setupListeners();for(let o=0;o<this.attributes.length;o++){const t=this.attributes.item(o);t&&this.source.set(t.name,t.value)}}setupListeners(){this.addEventListener("play",()=>this.source.context.resume())}}function te(e){return new Blob([oe(ne(e),e.sampleRate)],{type:"audio/wav"})}function ne(e){const o=e.getChannelData(0),t=o.length*2,n=new Float32Array(t);let r=0,i=0;for(;r<t;)n[r++]=o[i],n[r++]=o[i],i++;return n}function oe(e,o){const t=new ArrayBuffer(44+e.length*2),n=new DataView(t);return w(n,0,"RIFF"),n.setUint32(4,32+e.length*2,!0),w(n,8,"WAVE"),w(n,12,"fmt "),n.setUint32(16,16,!0),n.setUint16(20,1,!0),n.setUint16(22,2,!0),n.setUint32(24,o,!0),n.setUint32(28,o*4,!0),n.setUint16(32,4,!0),n.setUint16(34,16,!0),w(n,36,"data"),n.setUint32(40,e.length*2,!0),re(n,e,44)}function re(e,o,t){for(let n=0;n<o.length;n++,t+=2){const r=Math.max(-1,Math.min(1,o[n]));e.setInt16(t,r<0?r*32768:r*32767,!0)}return e}function w(e,o,t){for(let n=0;n<t.length;n++)e.setUint8(o+n,t.charCodeAt(n))}function ie(e,o=2,t=44100){return new OfflineAudioContext({length:t*e,numberOfChannels:o,sampleRate:t})}async function D(e){return te(await e.startRendering())}async function se(e,o="audio"){const t=await D(e),n=document.createElement("a");n.style.display="none",n.href=URL.createObjectURL(t),n.download=`${o}.${t.type.split("/")[1]}`,n.click()}d.ModernAudio=M,d.createAudio=U,d.createOfflineAudioContext=ie,d.defineProcessor=_,d.downloadOfflineAudio=se,d.exportOfflineAudio=D,Object.defineProperties(d,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});