Comparing version 0.2.3 to 0.2.4
@@ -1,1 +0,1 @@ | ||
module.exports=function(e){var n={};function t(r){if(n[r])return n[r].exports;var a=n[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,t),a.l=!0,a.exports}return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var a in e)t.d(r,a,function(n){return e[n]}.bind(null,a));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=1)}([function(e,n){!function(){var e,n=[];function t(e){var t=this,a={},o=-1;this.parameters.forEach(function(e,r){var u=n[++o]||(n[o]=new Float32Array(t.bufferSize));u.fill(e.value),a[r]=u}),this.processor.realm.exec("self.sampleRate=sampleRate="+this.context.sampleRate+";self.currentTime=currentTime="+this.context.currentTime);var u=r(e.inputBuffer),i=r(e.outputBuffer);this.instance.process([u],[i],a)}function r(e){for(var n=[],t=0;t<e.numberOfChannels;t++)n[t]=e.getChannelData(t);return n}function a(e){return e.$$processors||(e.$$processors={})}"function"!=typeof AudioWorkletNode&&(self.AudioWorkletNode=function(n,r,o){var u=a(n)[r],i=n.createScriptProcessor(void 0,2,o&&o.outputChannelCount?o.outputChannelCount[0]:2);if(i.parameters=new Map,u.properties)for(var l=0;l<u.properties.length;l++){var c=u.properties[l],s=n.createGain().gain;s.value=c.defaultValue,i.parameters.set(c.name,s)}var p=new MessageChannel;e=p.port2;var f=new u.Processor(o||{});return e=null,i.port=p.port1,i.processor=u,i.instance=f,i.onaudioprocess=t,i},Object.defineProperty((self.AudioContext||self.webkitAudioContext).prototype,"audioWorklet",{get:function(){return this.$$audioWorklet||(this.$$audioWorklet=new self.AudioWorklet(this))}}),self.AudioWorklet=function(){function n(e){this.$$context=e}return n.prototype.addModule=function(n,t){var r=this;return fetch(n).then(function(e){if(!e.ok)throw Error(e.status);return e.text()}).then(function(n){var o={sampleRate:0,currentTime:0,AudioWorkletProcessor:function(){this.port=e},registerProcessor:function(e,n){a(r.$$context)[e]={realm:u,context:o,Processor:n,properties:n.parameterDescriptors||[]}}};o.self=o;var u=new function(e,n){var t=document.createElement("iframe");t.style.cssText="position:absolute;left:0;top:-999px;width:1px;height:1px;",n.appendChild(t);var r=t.contentWindow,a=r.document,o="var window,$hook";for(var u in r)u in e||"eval"===u||(o+=",",o+=u);for(var i in e)o+=",",o+=i,o+="=self.",o+=i;var l=a.createElement("script");l.appendChild(a.createTextNode('function $hook(self,console) {"use strict";\n '+o+";return function() {return eval(arguments[0])}}")),a.body.appendChild(l),this.exec=r.$hook(e,console)}(o,document.documentElement);return u.exec((t&&t.transpile||String)(n)),null})},n}())}()},function(e,n,t){"use strict";t.r(n);t(0);var r,a,o=Array(72).fill().map(function(e,n){return Math.round(2048-2004*Math.pow(.5,n/12))}),u=(a=72,function(e){if(Array.isArray(e))return e}(r=o)||function(e,n){var t=[],r=!0,a=!1,o=void 0;try{for(var u,i=e[Symbol.iterator]();!(r=(u=i.next()).done)&&(t.push(u.value),!n||t.length!==n);r=!0);}catch(e){a=!0,o=e}finally{try{r||null==i.return||i.return()}finally{if(a)throw o}}return t}(r,a)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()),i=u[0],l=u[1],c=u[2],s=u[3],p=u[4],f=u[5],d=u[6],h=u[7],m=u[8],v=u[9],S=u[10],y=u[11],x=u[12],C=u[13],g=u[14],b=u[15],w=u[16],F=u[17],L=u[18],k=u[19],R=u[20],_=u[21],T=u[22],E=u[23],P=u[24],O=u[25],A=u[26],q=u[27],N=u[28],I=u[29],M=u[30],D=u[31],V=u[32],W=u[33],U=u[34],B=u[35],j=u[36],G=u[37],H=u[38],$=u[39],z=u[40],Y=u[41],X=u[42],J=u[43],K=u[44],Q=u[45],Z=u[46],ee=u[47],ne=u[48],te=u[49],re=u[50],ae=u[51],oe=u[52],ue=u[53],ie=u[54],le=u[55],ce=u[56],se=u[57],pe=u[58],fe=u[59],de=u[60],he=u[61],me=u[62],ve=u[63],Se=u[64],ye=u[65],xe=u[66],Ce=u[67],ge=u[68],be=u[69],we=u[70],Fe=u[71];t.d(n,"audioContext",function(){return Le}),t.d(n,"allow",function(){return ke}),t.d(n,"changeUserVolume",function(){return Te}),t.d(n,"audioNode",function(){return Pe}),t.d(n,"bgm",function(){return Ie}),t.d(n,"sfx",function(){return Me}),t.d(n,"fromFile",function(){return De}),t.d(n,"C3",function(){return i}),t.d(n,"Cs3",function(){return l}),t.d(n,"D3",function(){return c}),t.d(n,"Ds3",function(){return s}),t.d(n,"E3",function(){return p}),t.d(n,"F3",function(){return f}),t.d(n,"Fs3",function(){return d}),t.d(n,"G3",function(){return h}),t.d(n,"Gs3",function(){return m}),t.d(n,"A3",function(){return v}),t.d(n,"As3",function(){return S}),t.d(n,"B3",function(){return y}),t.d(n,"C4",function(){return x}),t.d(n,"Cs4",function(){return C}),t.d(n,"D4",function(){return g}),t.d(n,"Ds4",function(){return b}),t.d(n,"E4",function(){return w}),t.d(n,"F4",function(){return F}),t.d(n,"Fs4",function(){return L}),t.d(n,"G4",function(){return k}),t.d(n,"Gs4",function(){return R}),t.d(n,"A4",function(){return _}),t.d(n,"As4",function(){return T}),t.d(n,"B4",function(){return E}),t.d(n,"C5",function(){return P}),t.d(n,"Cs5",function(){return O}),t.d(n,"D5",function(){return A}),t.d(n,"Ds5",function(){return q}),t.d(n,"E5",function(){return N}),t.d(n,"F5",function(){return I}),t.d(n,"Fs5",function(){return M}),t.d(n,"G5",function(){return D}),t.d(n,"Gs5",function(){return V}),t.d(n,"A5",function(){return W}),t.d(n,"As5",function(){return U}),t.d(n,"B5",function(){return B}),t.d(n,"C6",function(){return j}),t.d(n,"Cs6",function(){return G}),t.d(n,"D6",function(){return H}),t.d(n,"Ds6",function(){return $}),t.d(n,"E6",function(){return z}),t.d(n,"F6",function(){return Y}),t.d(n,"Fs6",function(){return X}),t.d(n,"G6",function(){return J}),t.d(n,"Gs6",function(){return K}),t.d(n,"A6",function(){return Q}),t.d(n,"As6",function(){return Z}),t.d(n,"B6",function(){return ee}),t.d(n,"C7",function(){return ne}),t.d(n,"Cs7",function(){return te}),t.d(n,"D7",function(){return re}),t.d(n,"Ds7",function(){return ae}),t.d(n,"E7",function(){return oe}),t.d(n,"F7",function(){return ue}),t.d(n,"Fs7",function(){return ie}),t.d(n,"G7",function(){return le}),t.d(n,"Gs7",function(){return ce}),t.d(n,"A7",function(){return se}),t.d(n,"As7",function(){return pe}),t.d(n,"B7",function(){return fe}),t.d(n,"C8",function(){return de}),t.d(n,"Cs8",function(){return he}),t.d(n,"D8",function(){return me}),t.d(n,"Ds8",function(){return ve}),t.d(n,"E8",function(){return Se}),t.d(n,"F8",function(){return ye}),t.d(n,"Fs8",function(){return xe}),t.d(n,"G8",function(){return Ce}),t.d(n,"Gs8",function(){return ge}),t.d(n,"A8",function(){return be}),t.d(n,"As8",function(){return we}),t.d(n,"B8",function(){return Fe}),window.AudioContext=window.AudioContext||window.webkitAudioContext;var Le=new AudioContext({latencyHint:"interactive"});function ke(){Le.resume()}var Re=1,_e=Le.createGain();function Te(e){e>=0&&e<=1&&(_e.gain.setValueAtTime(Re,Le.currentTime),_e.gain.linearRampToValueAtTime(e,Le.currentTime+.05),Re=e)}_e.gain.setValueAtTime(Re,Le.currentTime),_e.connect(Le.destination);var Ee,Pe=_e,Oe=new Blob(['function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n/*\n APU\n Copyright (C) 2019 Nigel Nelson\n\n MIT License\n\n Many parts of this are taken from Grant Galitz\'s GameBoy Color Emulator, which is also under the MIT\n license. This is included below.\n\n JavaScript GameBoy Color Emulator\n Copyright (C) 2010-2016 Grant Galitz\n\n Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\nvar dutyLookup = [1, 129, 135, 126];\nvar LSFR15Table = new Int8Array(0x80000);\nvar LSFR7Table = new Int8Array(0x800); //Noise Sample Tables:\n\nvar lsfrRandomFactor = 1; //15-bit LSFR Cache Generation:\n\nvar LSFR = 0x7FFF; //Seed value has all its bits set.\n\nvar LSFRShifted = 0x3FFF;\n\nfor (var index = 0; index < 0x8000; ++index) {\n //Normalize the last LSFR value for usage:\n lsfrRandomFactor = 1 - (LSFR & 1); //Docs say it\'s the inverse.\n //Cache the different volume level results:\n\n for (var j = 0x1; j <= 0xF; ++j) {\n LSFR15Table[j * 0x8000 | index] = lsfrRandomFactor * j;\n } //Recompute the LSFR algorithm:\n\n\n LSFRShifted = LSFR >> 1;\n LSFR = LSFRShifted | ((LSFRShifted ^ LSFR) & 0x1) << 14;\n} //7-bit LSFR Cache Generation:\n\n\nLSFR = 0x7F; //Seed value has all its bits set.\n\nfor (index = 0; index < 0x80; ++index) {\n //Normalize the last LSFR value for usage:\n lsfrRandomFactor = 1 - (LSFR & 1); //Docs say it\'s the inverse.\n //Cache the different volume level results:\n\n for (var _j = 0x1; _j <= 0xF; ++_j) {\n LSFR7Table[_j * 0x80 | index] = lsfrRandomFactor * _j;\n } //Recompute the LSFR algorithm:\n\n\n LSFRShifted = LSFR >> 1;\n LSFR = LSFRShifted | ((LSFRShifted ^ LSFR) & 0x1) << 6;\n}\n\nfunction pulse(ch1) {\n var _setMem;\n\n var volumeEnvelopeRegister = 0;\n var FrequencyTracker = 0x2000;\n var DutyTracker = 0;\n var CachedDuty = dutyLookup[2];\n var totalLength = 0;\n var envelopeVolume = 0;\n var envelopeType = false;\n var envelopeSweeps = 0;\n var envelopeSweepsLast = 0;\n var consecutive = true;\n var frequency = 0;\n var SweepFault = false;\n var ShadowFrequency = 0;\n var timeSweep = 1;\n var lastTimeSweep = 0;\n var Swept = false;\n var frequencySweepDivider = 0;\n var decreaseSweep = false;\n var FrequencyCounter = 0x2000;\n var Enabled = false;\n var canPlay = false;\n OutputLevelCache();\n var leftChannel = false;\n var rightChannel = false;\n var currentSampleLeft = 0;\n var currentSampleRight = 0;\n var currentSampleLeftSecondary = 0;\n var currentSampleRightSecondary = 0;\n var currentSampleLeftTrimary = 0;\n var currentSampleRightTrimary = 0;\n var output = 0;\n\n function pushState() {\n var state = [volumeEnvelopeRegister, CachedDuty, frequency, lastTimeSweep, frequencySweepDivider, decreaseSweep, leftChannel, rightChannel];\n return function () {\n ;\n volumeEnvelopeRegister = state[0];\n CachedDuty = state[1];\n frequency = state[2];\n lastTimeSweep = state[3];\n frequencySweepDivider = state[4];\n decreaseSweep = state[5];\n leftChannel = state[6];\n rightChannel = state[7];\n };\n }\n\n function audioComputeSequencer(sequencePosition) {\n switch (sequencePosition % 8) {\n case 0:\n clockAudioLength();\n break;\n\n case 2:\n clockAudioLength();\n clockAudioSweep();\n break;\n\n case 4:\n clockAudioLength();\n break;\n\n case 6:\n clockAudioLength();\n clockAudioSweep();\n break;\n\n case 7:\n clockAudioEnvelope();\n break;\n }\n }\n\n function clockAudioLength() {\n if (totalLength > 1) {\n --totalLength;\n } else if (totalLength == 1) {\n totalLength = 0;\n EnableCheck();\n }\n }\n\n function clockAudioSweep() {\n //Channel 1:\n if (!SweepFault && timeSweep > 0) {\n if (--timeSweep == 0) {\n runAudioSweep();\n }\n }\n }\n\n function runAudioSweep() {\n //Channel 1:\n if (lastTimeSweep > 0) {\n if (frequencySweepDivider > 0) {\n Swept = true;\n\n if (decreaseSweep) {\n ShadowFrequency -= ShadowFrequency >> frequencySweepDivider;\n frequency = ShadowFrequency & 0x7FF;\n FrequencyTracker = 0x800 - frequency << 2;\n } else {\n ShadowFrequency += ShadowFrequency >> frequencySweepDivider;\n frequency = ShadowFrequency;\n\n if (ShadowFrequency <= 0x7FF) {\n FrequencyTracker = 0x800 - frequency << 2; //Run overflow check twice:\n\n if (ShadowFrequency + (ShadowFrequency >> frequencySweepDivider) > 0x7FF) {\n SweepFault = true;\n EnableCheck();\n }\n } else {\n frequency &= 0x7FF;\n SweepFault = true;\n EnableCheck();\n }\n }\n\n timeSweep = lastTimeSweep;\n } else {\n //Channel has sweep disabled and timer becomes a length counter:\n SweepFault = true;\n EnableCheck();\n }\n }\n }\n\n function audioSweepPerformDummy() {\n //Channel 1:\n if (frequencySweepDivider > 0) {\n if (!decreaseSweep) {\n var ShadowFrequency = ShadowFrequency + (ShadowFrequency >> frequencySweepDivider);\n\n if (ShadowFrequency <= 0x7FF) {\n //Run overflow check twice:\n if (ShadowFrequency + (ShadowFrequency >> frequencySweepDivider) > 0x7FF) {\n SweepFault = true;\n EnableCheck();\n }\n } else {\n SweepFault = true;\n EnableCheck();\n }\n }\n }\n }\n\n function clockAudioEnvelope() {\n if (envelopeSweepsLast > -1) {\n if (envelopeSweeps > 0) {\n --envelopeSweeps;\n } else {\n if (!envelopeType) {\n if (envelopeVolume > 0) {\n --envelopeVolume;\n envelopeSweeps = envelopeSweepsLast;\n OutputLevelCache();\n } else {\n envelopeSweepsLast = -1;\n }\n } else if (envelopeVolume < 0xF) {\n ++envelopeVolume;\n envelopeSweeps = envelopeSweepsLast;\n OutputLevelCache();\n } else {\n envelopeSweepsLast = -1;\n }\n }\n }\n }\n\n function audioClocksUntilNextEvent() {\n return FrequencyCounter;\n }\n\n function computeAudioChannels(clockForward) {\n FrequencyCounter -= clockForward;\n\n if (FrequencyCounter == 0) {\n FrequencyCounter = FrequencyTracker;\n DutyTracker = DutyTracker + 1 & 0x7;\n OutputLevelTrimaryCache();\n }\n }\n\n function EnableCheck() {\n Enabled = (consecutive || totalLength > 0) && !SweepFault && canPlay;\n OutputLevelSecondaryCache();\n }\n\n function VolumeEnableCheck() {\n canPlay = volumeEnvelopeRegister > 7;\n EnableCheck();\n OutputLevelSecondaryCache();\n }\n\n function OutputLevelCache() {\n currentSampleLeft = leftChannel ? envelopeVolume : 0;\n currentSampleRight = rightChannel ? envelopeVolume : 0;\n OutputLevelSecondaryCache();\n }\n\n function OutputLevelSecondaryCache() {\n if (Enabled) {\n currentSampleLeftSecondary = currentSampleLeft;\n currentSampleRightSecondary = currentSampleRight;\n } else {\n currentSampleLeftSecondary = 0;\n currentSampleRightSecondary = 0;\n }\n\n OutputLevelTrimaryCache();\n }\n\n function OutputLevelTrimaryCache() {\n if (CachedDuty & 1 << DutyTracker) {\n currentSampleLeftTrimary = currentSampleLeftSecondary;\n currentSampleRightTrimary = currentSampleRightSecondary;\n } else {\n currentSampleLeftTrimary = 0;\n currentSampleRightTrimary = 0;\n }\n\n mixerOutputLevelCache();\n }\n\n function mixerOutputLevelCache() {\n output = currentSampleLeftTrimary << 16 | currentSampleRightTrimary;\n }\n\n var setMem = (_setMem = {}, _defineProperty(_setMem, ch1 ? 0x10 : 0x15, function (data) {\n if (decreaseSweep && (data & 0x08) == 0) {\n if (Swept) {\n SweepFault = true;\n }\n }\n\n lastTimeSweep = (data & 0x70) >> 4;\n frequencySweepDivider = data & 0x07;\n decreaseSweep = (data & 0x08) == 0x08;\n EnableCheck();\n }), _defineProperty(_setMem, ch1 ? 0x11 : 0x16, function (data) {\n CachedDuty = dutyLookup[data >> 6];\n totalLength = 0x40 - (data & 0x3F);\n EnableCheck();\n }), _defineProperty(_setMem, ch1 ? 0x12 : 0x17, function (data) {\n envelopeType = (data & 0x08) == 0x08;\n volumeEnvelopeRegister = data;\n VolumeEnableCheck();\n }), _defineProperty(_setMem, ch1 ? 0x13 : 0x18, function (data) {\n frequency = frequency & 0x700 | data;\n FrequencyTracker = 0x800 - frequency << 2;\n }), _defineProperty(_setMem, ch1 ? 0x14 : 0x19, function (data) {\n consecutive = (data & 0x40) == 0x0;\n frequency = (data & 0x7) << 8 | frequency & 0xFF;\n frequency -= data & 0x8 ? 2048 : 0; // UNOFFICIAL BEHAVIOR! i wanted to allow slightly lower notes than normal.\n\n FrequencyTracker = 0x800 - frequency << 2;\n\n if (data > 0x7F) {\n //Reload 0xFF10:\n timeSweep = lastTimeSweep;\n Swept = false; //Reload 0xFF12:\n\n envelopeVolume = volumeEnvelopeRegister >> 4;\n OutputLevelCache();\n envelopeSweepsLast = (volumeEnvelopeRegister & 0x7) - 1;\n\n if (totalLength == 0) {\n totalLength = 0x40;\n }\n\n ShadowFrequency = frequency; //Reset frequency overflow check + frequency sweep type check:\n\n SweepFault = false; //Supposed to run immediately:\n\n audioSweepPerformDummy();\n }\n\n EnableCheck();\n }), _defineProperty(_setMem, 0x25, function _(data) {\n if (ch1) {\n leftChannel = !!(data & 0x10);\n rightChannel = !!(data & 0x01);\n } else {\n leftChannel = !!(data & 0x20);\n rightChannel = !!(data & 0x02);\n }\n\n OutputLevelCache();\n }), _setMem);\n return {\n get output() {\n return output;\n },\n\n audioComputeSequencer: audioComputeSequencer,\n audioClocksUntilNextEvent: audioClocksUntilNextEvent,\n computeAudioChannels: computeAudioChannels,\n setMem: setMem,\n pushState: pushState\n };\n}\n\nfunction wav() {\n var canPlay = false;\n var totalLength = 0;\n var patternType = 4;\n var frequency = 0;\n var consecutive = true;\n var Counter = 0x800;\n var FrequencyPeriod = 0x800;\n var lastSampleLookup = 0;\n var cachedSample = 0;\n var Enabled = false;\n OutputLevelCache();\n var PCM = new Int8Array(0x20);\n var leftChannel = false;\n var rightChannel = false;\n var currentSampleLeft = 0;\n var currentSampleRight = 0;\n var currentSampleLeftSecondary = 0;\n var currentSampleRightSecondary = 0;\n var output = 0;\n\n function pushState() {\n var state = [patternType, frequency, PCM, leftChannel, rightChannel];\n return function () {\n ;\n patternType = state[0];\n frequency = state[1];\n PCM = state[2];\n leftChannel = state[3];\n rightChannel = state[4];\n };\n }\n\n function audioComputeSequencer(sequencePosition) {\n switch (sequencePosition % 8) {\n case 0:\n clockAudioLength();\n break;\n\n case 2:\n clockAudioLength();\n break;\n\n case 4:\n clockAudioLength();\n break;\n\n case 6:\n clockAudioLength();\n break;\n }\n }\n\n function clockAudioLength() {\n if (totalLength > 1) {\n --totalLength;\n } else if (totalLength == 1) {\n totalLength = 0;\n EnableCheck();\n }\n }\n\n function audioClocksUntilNextEvent() {\n return Counter;\n }\n\n function computeAudioChannels(clockForward) {\n Counter -= clockForward;\n\n if (Counter == 0) {\n if (canPlay) {\n lastSampleLookup = lastSampleLookup + 1 & 0x1F;\n }\n\n Counter = FrequencyPeriod;\n UpdateCache();\n }\n }\n\n function EnableCheck() {\n Enabled =\n /*canPlay && */\n consecutive || totalLength > 0;\n OutputLevelSecondaryCache();\n }\n\n function OutputLevelCache() {\n currentSampleLeft = leftChannel ? cachedSample : 0;\n currentSampleRight = rightChannel ? cachedSample : 0;\n OutputLevelSecondaryCache();\n }\n\n function OutputLevelSecondaryCache() {\n if (Enabled) {\n currentSampleLeftSecondary = currentSampleLeft;\n currentSampleRightSecondary = currentSampleRight;\n } else {\n currentSampleLeftSecondary = 0;\n currentSampleRightSecondary = 0;\n }\n\n mixerOutputLevelCache();\n }\n\n function UpdateCache() {\n cachedSample = PCM[lastSampleLookup] >> patternType;\n OutputLevelCache();\n }\n\n function mixerOutputLevelCache() {\n output = currentSampleLeftSecondary << 16 | currentSampleRightSecondary;\n }\n\n var setMem = {\n //NR30:\n 0x1A: function _(data) {\n if (!canPlay && data >= 0x80) {\n lastSampleLookup = 0;\n UpdateCache();\n }\n\n canPlay = data > 0x7F; //EnableCheck();\n },\n //NR31:\n 0x1B: function _(data) {\n totalLength = 0x100 - data;\n EnableCheck();\n },\n //NR32:\n 0x1C: function _(data) {\n data &= 0x60;\n patternType = data == 0 ? 4 : (data >> 5) - 1;\n },\n //NR33:\n 0x1D: function _(data) {\n frequency = frequency & 0x700 | data;\n FrequencyPeriod = 0x800 - frequency << 1;\n },\n //NR34:\n 0x1E: function _(data) {\n if (data > 0x7F) {\n if (totalLength == 0) {\n totalLength = 0x100;\n }\n\n lastSampleLookup = 0;\n }\n\n consecutive = (data & 0x40) == 0x0;\n frequency = (data & 0x7) << 8 | frequency & 0xFF;\n FrequencyPeriod = 0x800 - frequency << 1;\n EnableCheck();\n },\n //NR51\n 0x25: function _(data) {\n leftChannel = !!(data & 0x40);\n rightChannel = !!(data & 0x04);\n OutputLevelCache();\n },\n //Wavetable\n 0x30: setWaveTableByte.bind(null, 0x00),\n 0x31: setWaveTableByte.bind(null, 0x01),\n 0x32: setWaveTableByte.bind(null, 0x02),\n 0x33: setWaveTableByte.bind(null, 0x03),\n 0x34: setWaveTableByte.bind(null, 0x04),\n 0x35: setWaveTableByte.bind(null, 0x05),\n 0x36: setWaveTableByte.bind(null, 0x06),\n 0x37: setWaveTableByte.bind(null, 0x07),\n 0x38: setWaveTableByte.bind(null, 0x08),\n 0x39: setWaveTableByte.bind(null, 0x09),\n 0x3A: setWaveTableByte.bind(null, 0x0A),\n 0x3B: setWaveTableByte.bind(null, 0x0B),\n 0x3C: setWaveTableByte.bind(null, 0x0C),\n 0x3D: setWaveTableByte.bind(null, 0x0D),\n 0x3E: setWaveTableByte.bind(null, 0x0E),\n 0x3F: setWaveTableByte.bind(null, 0x0F)\n };\n\n function setWaveTableByte(addr, value) {\n PCM[addr * 2] = value >> 4;\n PCM[addr * 2 + 1] = value & 0xF;\n }\n\n return {\n get output() {\n return output;\n },\n\n audioComputeSequencer: audioComputeSequencer,\n audioClocksUntilNextEvent: audioClocksUntilNextEvent,\n computeAudioChannels: computeAudioChannels,\n setMem: setMem,\n pushState: pushState\n };\n}\n\nfunction noise() {\n var volumeEnvelopeRegister = 0;\n var totalLength = 0;\n var envelopeVolume = 0;\n var currentVolume = 0;\n var envelopeType = false;\n var envelopeSweeps = 0;\n var envelopeSweepsLast = 0;\n var consecutive = true;\n var BitRange = 0x7FFF;\n var VolumeShifter = 15;\n var lastSampleLookup = 0;\n var noiseSampleTable = LSFR15Table;\n var FrequencyPeriod = 8;\n var Counter = 8;\n var cachedSample = 0;\n var Enabled = false;\n var canPlay = false;\n OutputLevelCache();\n var leftChannel = false;\n var rightChannel = false;\n var currentSampleLeft = 0;\n var currentSampleRight = 0;\n var currentSampleLeftSecondary = 0;\n var currentSampleRightSecondary = 0;\n var output = 0;\n\n function pushState() {\n var state = [volumeEnvelopeRegister, BitRange, VolumeShifter, noiseSampleTable, FrequencyPeriod, leftChannel, rightChannel];\n return function () {\n ;\n volumeEnvelopeRegister = state[0];\n BitRange = state[1];\n VolumeShifter = state[2];\n noiseSampleTable = state[3];\n FrequencyPeriod = state[4];\n leftChannel = state[5];\n rightChannel = state[6];\n };\n }\n\n function audioComputeSequencer(sequencePosition) {\n switch (sequencePosition % 8) {\n case 0:\n clockAudioLength();\n break;\n\n case 2:\n clockAudioLength();\n break;\n\n case 4:\n clockAudioLength();\n break;\n\n case 6:\n clockAudioLength();\n break;\n\n case 7:\n clockAudioEnvelope();\n break;\n }\n }\n\n function clockAudioLength() {\n if (totalLength > 1) {\n --totalLength;\n } else if (totalLength == 1) {\n totalLength = 0;\n EnableCheck();\n }\n }\n\n function clockAudioEnvelope() {\n if (envelopeSweepsLast > -1) {\n if (envelopeSweeps > 0) {\n --envelopeSweeps;\n } else {\n if (!envelopeType) {\n if (envelopeVolume > 0) {\n currentVolume = --envelopeVolume << VolumeShifter;\n envelopeSweeps = envelopeSweepsLast;\n UpdateCache();\n } else {\n envelopeSweepsLast = -1;\n }\n } else if (envelopeVolume < 0xF) {\n currentVolume = ++envelopeVolume << VolumeShifter;\n envelopeSweeps = envelopeSweepsLast;\n UpdateCache();\n } else {\n envelopeSweepsLast = -1;\n }\n }\n }\n }\n\n function audioClocksUntilNextEvent() {\n return Counter;\n }\n\n function computeAudioChannels(clockForward) {\n Counter -= clockForward;\n\n if (Counter == 0) {\n lastSampleLookup = lastSampleLookup + 1 & BitRange;\n Counter = FrequencyPeriod;\n UpdateCache();\n }\n }\n\n function EnableCheck() {\n Enabled = (consecutive || totalLength > 0) && canPlay;\n OutputLevelSecondaryCache();\n }\n\n function VolumeEnableCheck() {\n canPlay = volumeEnvelopeRegister > 7;\n EnableCheck();\n OutputLevelSecondaryCache();\n }\n\n function OutputLevelCache() {\n currentSampleLeft = leftChannel ? cachedSample : 0;\n currentSampleRight = rightChannel ? cachedSample : 0;\n OutputLevelSecondaryCache();\n }\n\n function OutputLevelSecondaryCache() {\n if (Enabled) {\n currentSampleLeftSecondary = currentSampleLeft;\n currentSampleRightSecondary = currentSampleRight;\n } else {\n currentSampleLeftSecondary = 0;\n currentSampleRightSecondary = 0;\n }\n\n mixerOutputLevelCache();\n }\n\n function UpdateCache() {\n cachedSample = noiseSampleTable[currentVolume | lastSampleLookup];\n OutputLevelCache();\n }\n\n function mixerOutputLevelCache() {\n output = currentSampleLeftSecondary << 16 | currentSampleRightSecondary;\n }\n\n var setMem = {\n //NR41:\n 0x20: function _(data) {\n totalLength = 0x40 - (data & 0x3F);\n EnableCheck();\n },\n //NR42:\n 0x21: function _(data) {\n envelopeType = (data & 0x08) == 0x08;\n volumeEnvelopeRegister = data;\n UpdateCache();\n VolumeEnableCheck();\n },\n //NR43:\n 0x22: function _(data) {\n FrequencyPeriod = Math.max((data & 0x7) << 4, 8) << (data >> 4);\n var bitWidth = data & 0x8;\n\n if (bitWidth == 0x8 && BitRange == 0x7FFF || bitWidth == 0 && BitRange == 0x7F) {\n lastSampleLookup = 0;\n BitRange = bitWidth == 0x8 ? 0x7F : 0x7FFF;\n VolumeShifter = bitWidth == 0x8 ? 7 : 15;\n currentVolume = envelopeVolume << VolumeShifter;\n noiseSampleTable = bitWidth == 0x8 ? LSFR7Table : LSFR15Table;\n }\n\n UpdateCache();\n },\n //NR44:\n 0x23: function _(data) {\n consecutive = (data & 0x40) == 0x0;\n\n if (data > 0x7F) {\n volumeEnvelopeRegister;\n envelopeVolume = volumeEnvelopeRegister >> 4;\n currentVolume = envelopeVolume << VolumeShifter;\n envelopeSweepsLast = (volumeEnvelopeRegister & 0x7) - 1;\n\n if (totalLength == 0) {\n totalLength = 0x40;\n }\n }\n\n EnableCheck();\n },\n //NR51\n 0x25: function _(data) {\n leftChannel = data > 0x7F;\n rightChannel = !!(data & 0x08);\n OutputLevelCache();\n }\n };\n return {\n get output() {\n return output;\n },\n\n audioComputeSequencer: audioComputeSequencer,\n audioClocksUntilNextEvent: audioClocksUntilNextEvent,\n computeAudioChannels: computeAudioChannels,\n setMem: setMem,\n pushState: pushState\n };\n}\n\nvar channels = [pulse(true), pulse(false), wav(), noise()]; //Sound variables:\n\nvar gameboyClockHertz = 0x400000;\nvar VinLeftChannelMasterVolume = 8;\nvar VinRightChannelMasterVolume = 8;\nvar sequencerClocks = 0x2000;\nvar sequencePosition = 0;\nvar audioClocksUntilNextEvent = 1;\nvar audioClocksUntilNextEventCounter = 1;\nvar gameboySamplePerOutputSample;\nvar downSampleInputDivider;\n\nvar GameboyProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(GameboyProcessor, _AudioWorkletProcesso);\n\n function GameboyProcessor() {\n var _getPrototypeOf2;\n\n var _this;\n\n _classCallCheck(this, GameboyProcessor);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(GameboyProcessor)).call.apply(_getPrototypeOf2, [this].concat(args)));\n\n _this.port.onmessage = function (_ref) {\n var e = _ref.data;\n\n if (e.type === \'play\') {\n var arr = new Uint8Array(e.data);\n\n if (e.mask) {\n playSFX(arr, e.mask);\n } else {\n playSong(arr, e.loop);\n }\n }\n };\n\n return _this;\n }\n\n _createClass(GameboyProcessor, [{\n key: "process",\n value: function process(inputs, outputs, parameters) {\n if (!sampleRate) throw new Error(\'No sample rate\');\n gameboySamplePerOutputSample = Math.round(gameboyClockHertz / sampleRate); // not sure why 30, but /8 is the max VinXChannelMasterVolume\n // and the /2 is because originally the gb soundchip expects samples in a range of (0,1)\n // which we can turn into (-.5,.5) BUT this causes audio pop whenever we start the emulator\n // so we settle for (0,.5) instead.\n\n downSampleInputDivider = 1 / (gameboySamplePerOutputSample * 30) / 8 / 2;\n var out1 = outputs[0][0];\n var out2 = outputs[0][1];\n\n for (var i = 0; i < out1.length; ++i) {\n var sample = generateAudio();\n out1[i] = (sample >>> 16) * VinLeftChannelMasterVolume * downSampleInputDivider;\n out2[i] = (sample & 0xFFFF) * VinRightChannelMasterVolume * downSampleInputDivider; // if (i%256 === 0) console.log(`${i.toString(16).padStart(4,0)} sample === ${sample.toString(2).padStart(32,0)}`)\n }\n\n return true;\n }\n }]);\n\n return GameboyProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(\'gameboy-processor\', GameboyProcessor);\nvar song = null;\nvar songIdx = -1;\nvar songTimer = 0;\nvar songLoopPoint = -1;\nvar sfx = null;\nvar sfxIdx = -1;\nvar sfxTimer = 0;\nvar sfxMask = [0, 0, 0, 0];\nvar restoreSongState = null;\n\nfunction playSong(newSong, loopPoint) {\n var resumePoint = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n song = newSong;\n songIdx = resumePoint;\n songTimer = 0;\n songLoopPoint = loopPoint;\n sfx = null;\n sfxIdx = -1;\n sfxTimer = 0;\n sfxMask = [0, 0, 0, 0];\n restoreSongState = null;\n}\n\nfunction playSFX(newSFX, mask) {\n sfx = newSFX;\n sfxIdx = 0;\n sfxTimer = 0;\n sfxMask = mask;\n\n if (restoreSongState == null) {\n var undos = channels.map(function (ch) {\n return ch.pushState();\n });\n\n restoreSongState = function restoreSongState() {\n return undos.forEach(function (fn) {\n return fn();\n });\n };\n }\n}\n/**\n * Rougly 0x400000/44100 (clock speed / audio sampling speed)\n * You may be wondering: isn\'t that the same as gameboySamplePerOutputSample?\n * Answer: no. This is just used for determining the timing of the delay commands.\n * Those commands come from the .vgm format, which always assumes 44100 sample rate.\n */\n\n\nvar atomicDelayUnit = 0x60; //Below are the audio generation functions timed against the CPU:\n\nfunction generateAudio() {\n var realSample = 0;\n\n for (var downsampledFramesLeft = gameboySamplePerOutputSample; downsampledFramesLeft > 0;) {\n while (songTimer === 0 && songIdx >= 0) {\n if (songIdx >= song.length) {\n songIdx = songLoopPoint;\n if (songIdx === -1) break;\n }\n\n var op = song[songIdx++];\n\n if (op === 0xB3) {\n // gameboy apu register write\n var reg = song[songIdx++] + 0x10;\n var val = song[songIdx++];\n registerWrite(reg, val, sfxMask.map(function (i) {\n return !i;\n }));\n } else if (op === 0x61) {\n var t = song[songIdx++] + (song[songIdx++] << 8);\n songTimer += t * atomicDelayUnit;\n } else if (op === 0x62) {\n var _t = 735; // exactly 44100/60\n\n songTimer += _t * atomicDelayUnit;\n } else if ((op & 0xF0) === 0x70) {\n var _t2 = 1 + (op & 0xf);\n\n songTimer += _t2 * atomicDelayUnit;\n } else if (op === 0x66) {\n songIdx = songLoopPoint;\n } else {\n throw new Error(\'What is op \' + op.toString(16));\n }\n }\n\n while (sfxTimer === 0 && sfxIdx >= 0) {\n if (sfxIdx >= sfx.length) {\n sfxIdx = -1;\n sfxMask = [0, 0, 0, 0];\n restoreSongState();\n break;\n }\n\n var _op = sfx[sfxIdx++];\n\n if (_op === 0xB3) {\n // gameboy apu register write\n var _reg = sfx[sfxIdx++] + 0x10;\n\n var _val = sfx[sfxIdx++];\n registerWrite(_reg, _val, sfxMask);\n } else if (_op === 0x61) {\n var _t3 = sfx[sfxIdx++] + (sfx[sfxIdx++] << 8);\n\n sfxTimer += _t3 * atomicDelayUnit;\n } else if (_op === 0x62) {\n var _t4 = 735; // exactly 44100/60\n\n sfxTimer += _t4 * atomicDelayUnit;\n } else if ((_op & 0xF0) === 0x70) {\n var _t5 = 1 + (_op & 0xf);\n\n sfxTimer += _t5 * atomicDelayUnit;\n } else if (_op === 0x66) {\n sfxIdx = -1;\n sfxMask = [0, 0, 0, 0];\n restoreSongState();\n } else {\n throw new Error(\'What is op \' + _op.toString(16));\n }\n }\n\n if (sequencerClocks == 0) {\n sequencePosition++;\n\n for (var _i = 0, _channels = channels; _i < _channels.length; _i++) {\n var channel = _channels[_i];\n channel.audioComputeSequencer(sequencePosition);\n }\n\n sequencerClocks = 0x2000;\n }\n\n if (audioClocksUntilNextEventCounter == 0) {\n //Clock down the four audio channels to the next closest audio event:\n for (var _i2 = 0, _channels2 = channels; _i2 < _channels2.length; _i2++) {\n var _channel = _channels2[_i2];\n\n _channel.computeAudioChannels(audioClocksUntilNextEvent);\n } //Find the number of clocks to next closest counter event:\n\n\n audioClocksUntilNextEvent = Math.min.apply(null, channels.map(function (ch) {\n return ch.audioClocksUntilNextEvent();\n }));\n audioClocksUntilNextEventCounter = audioClocksUntilNextEvent;\n }\n\n var multiplier = Math.min(audioClocksUntilNextEventCounter, sequencerClocks, downsampledFramesLeft, songIdx >= 0 ? songTimer : Infinity, sfxIdx >= 0 ? sfxTimer : Infinity);\n\n if (!(multiplier > 0)) {\n throw new Error(\'multipler should greater than 0\');\n }\n\n audioClocksUntilNextEventCounter -= multiplier;\n sequencerClocks -= multiplier;\n downsampledFramesLeft -= multiplier;\n songTimer -= multiplier;\n sfxTimer -= multiplier;\n var output = channels.reduce(function (output, ch) {\n return output + ch.output;\n }, 0);\n realSample += output * multiplier;\n }\n\n return realSample;\n}\n\nfunction registerWrite(address, data, channelMask) {\n if (miscRegisterFuncs[address]) {\n miscRegisterFuncs[address](data);\n } else {\n var didSet = 0;\n\n for (var i = 0; i < 4; ++i) {\n if (channels[i].setMem[address]) {\n if (channelMask[i]) {\n channels[i].setMem[address](data);\n }\n\n ++didSet;\n }\n }\n\n if (!didSet) {\n throw new Error("Unsupported register write: FF".concat(address.toString(16).padStart(2, 0)));\n }\n } // console.log(`FF${address.toString(16).padStart(2)} <= ${data}`)\n\n}\n\nvar miscRegisterFuncs = {\n //NR50:\n 0x24: function _(data) {\n VinLeftChannelMasterVolume = (data >> 4 & 0x07) + 1;\n VinRightChannelMasterVolume = (data & 0x07) + 1; // mixerOutputLevelCache();\n },\n //NR52:\n 0x26: function _() {// allowed, but ignored\n }\n};'],{type:"application/javascript"}),Ae=URL.createObjectURL(Oe),qe=Le.audioWorklet.addModule(Ae).then(function(){var e=new AudioWorkletNode(Le,"gameboy-processor",{outputChannelCount:[2]});return e.connect(_e),e});function Ne(e,n){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return{play:function(){var r=++Ee;return qe.then(function(a){a.port.postMessage({id:r,type:"play",data:e,loop:n,mask:t})}),{pause:function(){node.port.postMessage({id:r,type:"pause"})},resume:function(){node.port.postMessage({id:r,type:"resume"})}}}}}function Ie(e){return Ne(e,arguments.length>1&&void 0!==arguments[1]?arguments[1]:0)}function Me(e){return Ne(e,-1,arguments.length>1&&void 0!==arguments[1]?arguments[1]:[1,1,1,1])}function De(e){for(var n=new Uint8Array(e,0,4),t=0;t<4;++t)if(n[t]!=="Vgm "[t].charCodeAt())throw new Error("Invalid header");var r=52+new Uint32Array(e,52,1)[0],a=28+new Uint32Array(e,28,1)[0]-r;return Ie(e.slice(r),a)}}]); | ||
module.exports=function(e){var n={};function t(r){if(n[r])return n[r].exports;var a=n[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,t),a.l=!0,a.exports}return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var a in e)t.d(r,a,function(n){return e[n]}.bind(null,a));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=1)}([function(e,n){!function(){var e,n=[];function t(e){var t=this,a={},o=-1;this.parameters.forEach(function(e,r){var u=n[++o]||(n[o]=new Float32Array(t.bufferSize));u.fill(e.value),a[r]=u}),this.processor.realm.exec("self.sampleRate=sampleRate="+this.context.sampleRate+";self.currentTime=currentTime="+this.context.currentTime);var u=r(e.inputBuffer),i=r(e.outputBuffer);this.instance.process([u],[i],a)}function r(e){for(var n=[],t=0;t<e.numberOfChannels;t++)n[t]=e.getChannelData(t);return n}function a(e){return e.$$processors||(e.$$processors={})}"function"!=typeof AudioWorkletNode&&(self.AudioWorkletNode=function(n,r,o){var u=a(n)[r],i=n.createScriptProcessor(void 0,2,o&&o.outputChannelCount?o.outputChannelCount[0]:2);if(i.parameters=new Map,u.properties)for(var l=0;l<u.properties.length;l++){var c=u.properties[l],s=n.createGain().gain;s.value=c.defaultValue,i.parameters.set(c.name,s)}var p=new MessageChannel;e=p.port2;var f=new u.Processor(o||{});return e=null,i.port=p.port1,i.processor=u,i.instance=f,i.onaudioprocess=t,i},Object.defineProperty((self.AudioContext||self.webkitAudioContext).prototype,"audioWorklet",{get:function(){return this.$$audioWorklet||(this.$$audioWorklet=new self.AudioWorklet(this))}}),self.AudioWorklet=function(){function n(e){this.$$context=e}return n.prototype.addModule=function(n,t){var r=this;return fetch(n).then(function(e){if(!e.ok)throw Error(e.status);return e.text()}).then(function(n){var o={sampleRate:0,currentTime:0,AudioWorkletProcessor:function(){this.port=e},registerProcessor:function(e,n){a(r.$$context)[e]={realm:u,context:o,Processor:n,properties:n.parameterDescriptors||[]}}};o.self=o;var u=new function(e,n){var t=document.createElement("iframe");t.style.cssText="position:absolute;left:0;top:-999px;width:1px;height:1px;",n.appendChild(t);var r=t.contentWindow,a=r.document,o="var window,$hook";for(var u in r)u in e||"eval"===u||(o+=",",o+=u);for(var i in e)o+=",",o+=i,o+="=self.",o+=i;var l=a.createElement("script");l.appendChild(a.createTextNode('function $hook(self,console) {"use strict";\n '+o+";return function() {return eval(arguments[0])}}")),a.body.appendChild(l),this.exec=r.$hook(e,console)}(o,document.documentElement);return u.exec((t&&t.transpile||String)(n)),null})},n}())}()},function(e,n,t){"use strict";t.r(n);t(0);var r,a,o=Array(72).fill().map(function(e,n){return Math.round(2048-2004*Math.pow(.5,n/12))}),u=(a=72,function(e){if(Array.isArray(e))return e}(r=o)||function(e,n){var t=[],r=!0,a=!1,o=void 0;try{for(var u,i=e[Symbol.iterator]();!(r=(u=i.next()).done)&&(t.push(u.value),!n||t.length!==n);r=!0);}catch(e){a=!0,o=e}finally{try{r||null==i.return||i.return()}finally{if(a)throw o}}return t}(r,a)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()),i=u[0],l=u[1],c=u[2],s=u[3],p=u[4],f=u[5],d=u[6],h=u[7],m=u[8],v=u[9],S=u[10],y=u[11],x=u[12],C=u[13],g=u[14],b=u[15],w=u[16],F=u[17],L=u[18],k=u[19],R=u[20],_=u[21],T=u[22],E=u[23],P=u[24],O=u[25],A=u[26],q=u[27],N=u[28],I=u[29],M=u[30],D=u[31],V=u[32],W=u[33],U=u[34],B=u[35],j=u[36],G=u[37],H=u[38],$=u[39],z=u[40],Y=u[41],X=u[42],J=u[43],K=u[44],Q=u[45],Z=u[46],ee=u[47],ne=u[48],te=u[49],re=u[50],ae=u[51],oe=u[52],ue=u[53],ie=u[54],le=u[55],ce=u[56],se=u[57],pe=u[58],fe=u[59],de=u[60],he=u[61],me=u[62],ve=u[63],Se=u[64],ye=u[65],xe=u[66],Ce=u[67],ge=u[68],be=u[69],we=u[70],Fe=u[71];t.d(n,"audioContext",function(){return Le}),t.d(n,"allow",function(){return ke}),t.d(n,"changeUserVolume",function(){return Te}),t.d(n,"audioNode",function(){return Pe}),t.d(n,"bgm",function(){return Ie}),t.d(n,"sfx",function(){return Me}),t.d(n,"fromFile",function(){return De}),t.d(n,"C3",function(){return i}),t.d(n,"Cs3",function(){return l}),t.d(n,"D3",function(){return c}),t.d(n,"Ds3",function(){return s}),t.d(n,"E3",function(){return p}),t.d(n,"F3",function(){return f}),t.d(n,"Fs3",function(){return d}),t.d(n,"G3",function(){return h}),t.d(n,"Gs3",function(){return m}),t.d(n,"A3",function(){return v}),t.d(n,"As3",function(){return S}),t.d(n,"B3",function(){return y}),t.d(n,"C4",function(){return x}),t.d(n,"Cs4",function(){return C}),t.d(n,"D4",function(){return g}),t.d(n,"Ds4",function(){return b}),t.d(n,"E4",function(){return w}),t.d(n,"F4",function(){return F}),t.d(n,"Fs4",function(){return L}),t.d(n,"G4",function(){return k}),t.d(n,"Gs4",function(){return R}),t.d(n,"A4",function(){return _}),t.d(n,"As4",function(){return T}),t.d(n,"B4",function(){return E}),t.d(n,"C5",function(){return P}),t.d(n,"Cs5",function(){return O}),t.d(n,"D5",function(){return A}),t.d(n,"Ds5",function(){return q}),t.d(n,"E5",function(){return N}),t.d(n,"F5",function(){return I}),t.d(n,"Fs5",function(){return M}),t.d(n,"G5",function(){return D}),t.d(n,"Gs5",function(){return V}),t.d(n,"A5",function(){return W}),t.d(n,"As5",function(){return U}),t.d(n,"B5",function(){return B}),t.d(n,"C6",function(){return j}),t.d(n,"Cs6",function(){return G}),t.d(n,"D6",function(){return H}),t.d(n,"Ds6",function(){return $}),t.d(n,"E6",function(){return z}),t.d(n,"F6",function(){return Y}),t.d(n,"Fs6",function(){return X}),t.d(n,"G6",function(){return J}),t.d(n,"Gs6",function(){return K}),t.d(n,"A6",function(){return Q}),t.d(n,"As6",function(){return Z}),t.d(n,"B6",function(){return ee}),t.d(n,"C7",function(){return ne}),t.d(n,"Cs7",function(){return te}),t.d(n,"D7",function(){return re}),t.d(n,"Ds7",function(){return ae}),t.d(n,"E7",function(){return oe}),t.d(n,"F7",function(){return ue}),t.d(n,"Fs7",function(){return ie}),t.d(n,"G7",function(){return le}),t.d(n,"Gs7",function(){return ce}),t.d(n,"A7",function(){return se}),t.d(n,"As7",function(){return pe}),t.d(n,"B7",function(){return fe}),t.d(n,"C8",function(){return de}),t.d(n,"Cs8",function(){return he}),t.d(n,"D8",function(){return me}),t.d(n,"Ds8",function(){return ve}),t.d(n,"E8",function(){return Se}),t.d(n,"F8",function(){return ye}),t.d(n,"Fs8",function(){return xe}),t.d(n,"G8",function(){return Ce}),t.d(n,"Gs8",function(){return ge}),t.d(n,"A8",function(){return be}),t.d(n,"As8",function(){return we}),t.d(n,"B8",function(){return Fe}),window.AudioContext=window.AudioContext||window.webkitAudioContext;var Le=new AudioContext({latencyHint:"interactive"});function ke(){Le.resume()}var Re=1,_e=Le.createGain();function Te(e){e>=0&&e<=1&&(_e.gain.setValueAtTime(Re,Le.currentTime),_e.gain.linearRampToValueAtTime(e,Le.currentTime+.05),Re=e)}_e.gain.setValueAtTime(Re,Le.currentTime),_e.connect(Le.destination);var Ee,Pe=_e,Oe=new Blob(['function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }\n\nfunction _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\n\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\n\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }\n\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn\'t been initialised - super() hasn\'t been called"); } return self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\n\nfunction _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }\n\nfunction isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }\n\nfunction _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }\n\nfunction _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }\n\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\n\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\n\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n\n/*\n APU\n Copyright (C) 2019 Nigel Nelson\n\n MIT License\n\n Many parts of this are taken from Grant Galitz\'s GameBoy Color Emulator, which is also under the MIT\n license. This is included below.\n\n JavaScript GameBoy Color Emulator\n Copyright (C) 2010-2016 Grant Galitz\n\n Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\nvar dutyLookup = [1, 129, 135, 126];\nvar LSFR15Table = new Int8Array(0x80000);\nvar LSFR7Table = new Int8Array(0x800); //Noise Sample Tables:\n\nvar lsfrRandomFactor = 1; //15-bit LSFR Cache Generation:\n\nvar LSFR = 0x7FFF; //Seed value has all its bits set.\n\nvar LSFRShifted = 0x3FFF;\n\nfor (var index = 0; index < 0x8000; ++index) {\n //Normalize the last LSFR value for usage:\n lsfrRandomFactor = 1 - (LSFR & 1); //Docs say it\'s the inverse.\n //Cache the different volume level results:\n\n for (var j = 0x1; j <= 0xF; ++j) {\n LSFR15Table[j * 0x8000 | index] = lsfrRandomFactor * j;\n } //Recompute the LSFR algorithm:\n\n\n LSFRShifted = LSFR >> 1;\n LSFR = LSFRShifted | ((LSFRShifted ^ LSFR) & 0x1) << 14;\n} //7-bit LSFR Cache Generation:\n\n\nLSFR = 0x7F; //Seed value has all its bits set.\n\nfor (index = 0; index < 0x80; ++index) {\n //Normalize the last LSFR value for usage:\n lsfrRandomFactor = 1 - (LSFR & 1); //Docs say it\'s the inverse.\n //Cache the different volume level results:\n\n for (var _j = 0x1; _j <= 0xF; ++_j) {\n LSFR7Table[_j * 0x80 | index] = lsfrRandomFactor * _j;\n } //Recompute the LSFR algorithm:\n\n\n LSFRShifted = LSFR >> 1;\n LSFR = LSFRShifted | ((LSFRShifted ^ LSFR) & 0x1) << 6;\n}\n\nfunction pulse(ch1) {\n var _setMem;\n\n var volumeEnvelopeRegister = 0;\n var FrequencyTracker = 0x2000;\n var DutyTracker = 0;\n var CachedDuty = dutyLookup[2];\n var totalLength = 0;\n var envelopeVolume = 0;\n var envelopeType = false;\n var envelopeSweeps = 0;\n var envelopeSweepsLast = 0;\n var consecutive = true;\n var frequency = 0;\n var SweepFault = false;\n var ShadowFrequency = 0;\n var timeSweep = 1;\n var lastTimeSweep = 0;\n var Swept = false;\n var frequencySweepDivider = 0;\n var decreaseSweep = false;\n var FrequencyCounter = 0x2000;\n var Enabled = false;\n var canPlay = false;\n OutputLevelCache();\n var leftChannel = false;\n var rightChannel = false;\n var currentSampleLeft = 0;\n var currentSampleRight = 0;\n var currentSampleLeftSecondary = 0;\n var currentSampleRightSecondary = 0;\n var currentSampleLeftTrimary = 0;\n var currentSampleRightTrimary = 0;\n var output = 0;\n\n function pushState() {\n var state = [volumeEnvelopeRegister, CachedDuty, frequency, lastTimeSweep, frequencySweepDivider, decreaseSweep, leftChannel, rightChannel];\n return function () {\n ;\n volumeEnvelopeRegister = state[0];\n CachedDuty = state[1];\n frequency = state[2];\n lastTimeSweep = state[3];\n frequencySweepDivider = state[4];\n decreaseSweep = state[5];\n leftChannel = state[6];\n rightChannel = state[7];\n };\n }\n\n function audioComputeSequencer(sequencePosition) {\n switch (sequencePosition % 8) {\n case 0:\n clockAudioLength();\n break;\n\n case 2:\n clockAudioLength();\n clockAudioSweep();\n break;\n\n case 4:\n clockAudioLength();\n break;\n\n case 6:\n clockAudioLength();\n clockAudioSweep();\n break;\n\n case 7:\n clockAudioEnvelope();\n break;\n }\n }\n\n function clockAudioLength() {\n if (totalLength > 1) {\n --totalLength;\n } else if (totalLength == 1) {\n totalLength = 0;\n EnableCheck();\n }\n }\n\n function clockAudioSweep() {\n //Channel 1:\n if (!SweepFault && timeSweep > 0) {\n if (--timeSweep == 0) {\n runAudioSweep();\n }\n }\n }\n\n function runAudioSweep() {\n //Channel 1:\n if (lastTimeSweep > 0) {\n if (frequencySweepDivider > 0) {\n Swept = true;\n\n if (decreaseSweep) {\n ShadowFrequency -= ShadowFrequency >> frequencySweepDivider;\n frequency = ShadowFrequency & 0x7FF;\n FrequencyTracker = 0x800 - frequency << 2;\n } else {\n ShadowFrequency += ShadowFrequency >> frequencySweepDivider;\n frequency = ShadowFrequency;\n\n if (ShadowFrequency <= 0x7FF) {\n FrequencyTracker = 0x800 - frequency << 2; //Run overflow check twice:\n\n if (ShadowFrequency + (ShadowFrequency >> frequencySweepDivider) > 0x7FF) {\n SweepFault = true;\n EnableCheck();\n }\n } else {\n frequency &= 0x7FF;\n SweepFault = true;\n EnableCheck();\n }\n }\n\n timeSweep = lastTimeSweep;\n } else {\n //Channel has sweep disabled and timer becomes a length counter:\n SweepFault = true;\n EnableCheck();\n }\n }\n }\n\n function audioSweepPerformDummy() {\n //Channel 1:\n if (frequencySweepDivider > 0) {\n if (!decreaseSweep) {\n var shf = ShadowFrequency + (ShadowFrequency >> frequencySweepDivider);\n\n if (shf <= 0x7FF) {\n //Run overflow check twice:\n if (shf + (shf >> frequencySweepDivider) > 0x7FF) {\n SweepFault = true;\n EnableCheck();\n }\n } else {\n SweepFault = true;\n EnableCheck();\n }\n }\n }\n }\n\n function clockAudioEnvelope() {\n if (envelopeSweepsLast > -1) {\n if (envelopeSweeps > 0) {\n --envelopeSweeps;\n } else {\n if (!envelopeType) {\n if (envelopeVolume > 0) {\n --envelopeVolume;\n envelopeSweeps = envelopeSweepsLast;\n OutputLevelCache();\n } else {\n envelopeSweepsLast = -1;\n }\n } else if (envelopeVolume < 0xF) {\n ++envelopeVolume;\n envelopeSweeps = envelopeSweepsLast;\n OutputLevelCache();\n } else {\n envelopeSweepsLast = -1;\n }\n }\n }\n }\n\n function audioClocksUntilNextEvent() {\n return FrequencyCounter;\n }\n\n function computeAudioChannels(clockForward) {\n FrequencyCounter -= clockForward;\n\n if (FrequencyCounter == 0) {\n FrequencyCounter = FrequencyTracker;\n DutyTracker = DutyTracker + 1 & 0x7;\n OutputLevelTrimaryCache();\n }\n }\n\n function EnableCheck() {\n Enabled = (consecutive || totalLength > 0) && !SweepFault && canPlay;\n OutputLevelSecondaryCache();\n }\n\n function VolumeEnableCheck() {\n canPlay = volumeEnvelopeRegister > 7;\n EnableCheck();\n OutputLevelSecondaryCache();\n }\n\n function OutputLevelCache() {\n currentSampleLeft = leftChannel ? envelopeVolume : 0;\n currentSampleRight = rightChannel ? envelopeVolume : 0;\n OutputLevelSecondaryCache();\n }\n\n function OutputLevelSecondaryCache() {\n if (Enabled) {\n currentSampleLeftSecondary = currentSampleLeft;\n currentSampleRightSecondary = currentSampleRight;\n } else {\n currentSampleLeftSecondary = 0;\n currentSampleRightSecondary = 0;\n }\n\n OutputLevelTrimaryCache();\n }\n\n function OutputLevelTrimaryCache() {\n if (CachedDuty & 1 << DutyTracker) {\n currentSampleLeftTrimary = currentSampleLeftSecondary;\n currentSampleRightTrimary = currentSampleRightSecondary;\n } else {\n currentSampleLeftTrimary = 0;\n currentSampleRightTrimary = 0;\n }\n\n mixerOutputLevelCache();\n }\n\n function mixerOutputLevelCache() {\n output = currentSampleLeftTrimary << 16 | currentSampleRightTrimary;\n }\n\n var setMem = (_setMem = {}, _defineProperty(_setMem, ch1 ? 0x10 : 0x15, function (data) {\n if (decreaseSweep && (data & 0x08) == 0) {\n if (Swept) {\n SweepFault = true;\n }\n }\n\n lastTimeSweep = (data & 0x70) >> 4;\n frequencySweepDivider = data & 0x07;\n decreaseSweep = (data & 0x08) == 0x08;\n EnableCheck();\n }), _defineProperty(_setMem, ch1 ? 0x11 : 0x16, function (data) {\n CachedDuty = dutyLookup[data >> 6];\n totalLength = 0x40 - (data & 0x3F);\n EnableCheck();\n }), _defineProperty(_setMem, ch1 ? 0x12 : 0x17, function (data) {\n envelopeType = (data & 0x08) == 0x08;\n volumeEnvelopeRegister = data;\n VolumeEnableCheck();\n }), _defineProperty(_setMem, ch1 ? 0x13 : 0x18, function (data) {\n frequency = frequency & 0x700 | data;\n FrequencyTracker = 0x800 - frequency << 2;\n }), _defineProperty(_setMem, ch1 ? 0x14 : 0x19, function (data) {\n consecutive = (data & 0x40) == 0x0;\n frequency = (data & 0x7) << 8 | frequency & 0xFF;\n frequency -= data & 0x8 ? 2048 : 0; // UNOFFICIAL BEHAVIOR! i wanted to allow slightly lower notes than normal.\n\n FrequencyTracker = 0x800 - frequency << 2;\n\n if (data > 0x7F) {\n //Reload 0xFF10:\n timeSweep = lastTimeSweep;\n Swept = false; //Reload 0xFF12:\n\n envelopeVolume = volumeEnvelopeRegister >> 4;\n OutputLevelCache();\n envelopeSweepsLast = (volumeEnvelopeRegister & 0x7) - 1;\n\n if (totalLength == 0) {\n totalLength = 0x40;\n }\n\n ShadowFrequency = frequency; //Reset frequency overflow check + frequency sweep type check:\n\n SweepFault = false; //Supposed to run immediately:\n\n audioSweepPerformDummy();\n }\n\n EnableCheck();\n }), _defineProperty(_setMem, 0x25, function _(data) {\n if (ch1) {\n leftChannel = !!(data & 0x10);\n rightChannel = !!(data & 0x01);\n } else {\n leftChannel = !!(data & 0x20);\n rightChannel = !!(data & 0x02);\n }\n\n OutputLevelCache();\n }), _setMem);\n return {\n get output() {\n return output;\n },\n\n audioComputeSequencer: audioComputeSequencer,\n audioClocksUntilNextEvent: audioClocksUntilNextEvent,\n computeAudioChannels: computeAudioChannels,\n setMem: setMem,\n pushState: pushState\n };\n}\n\nfunction wav() {\n var canPlay = false;\n var totalLength = 0;\n var patternType = 4;\n var frequency = 0;\n var consecutive = true;\n var Counter = 0x800;\n var FrequencyPeriod = 0x800;\n var lastSampleLookup = 0;\n var cachedSample = 0;\n var Enabled = false;\n OutputLevelCache();\n var PCM = new Int8Array(0x20);\n var leftChannel = false;\n var rightChannel = false;\n var currentSampleLeft = 0;\n var currentSampleRight = 0;\n var currentSampleLeftSecondary = 0;\n var currentSampleRightSecondary = 0;\n var output = 0;\n\n function pushState() {\n var state = [patternType, frequency, PCM, leftChannel, rightChannel];\n return function () {\n ;\n patternType = state[0];\n frequency = state[1];\n PCM = state[2];\n leftChannel = state[3];\n rightChannel = state[4];\n };\n }\n\n function audioComputeSequencer(sequencePosition) {\n switch (sequencePosition % 8) {\n case 0:\n clockAudioLength();\n break;\n\n case 2:\n clockAudioLength();\n break;\n\n case 4:\n clockAudioLength();\n break;\n\n case 6:\n clockAudioLength();\n break;\n }\n }\n\n function clockAudioLength() {\n if (totalLength > 1) {\n --totalLength;\n } else if (totalLength == 1) {\n totalLength = 0;\n EnableCheck();\n }\n }\n\n function audioClocksUntilNextEvent() {\n return Counter;\n }\n\n function computeAudioChannels(clockForward) {\n Counter -= clockForward;\n\n if (Counter == 0) {\n if (canPlay) {\n lastSampleLookup = lastSampleLookup + 1 & 0x1F;\n }\n\n Counter = FrequencyPeriod;\n UpdateCache();\n }\n }\n\n function EnableCheck() {\n Enabled =\n /*canPlay && */\n consecutive || totalLength > 0;\n OutputLevelSecondaryCache();\n }\n\n function OutputLevelCache() {\n currentSampleLeft = leftChannel ? cachedSample : 0;\n currentSampleRight = rightChannel ? cachedSample : 0;\n OutputLevelSecondaryCache();\n }\n\n function OutputLevelSecondaryCache() {\n if (Enabled) {\n currentSampleLeftSecondary = currentSampleLeft;\n currentSampleRightSecondary = currentSampleRight;\n } else {\n currentSampleLeftSecondary = 0;\n currentSampleRightSecondary = 0;\n }\n\n mixerOutputLevelCache();\n }\n\n function UpdateCache() {\n cachedSample = PCM[lastSampleLookup] >> patternType;\n OutputLevelCache();\n }\n\n function mixerOutputLevelCache() {\n output = currentSampleLeftSecondary << 16 | currentSampleRightSecondary;\n }\n\n var setMem = {\n //NR30:\n 0x1A: function _(data) {\n if (!canPlay && data >= 0x80) {\n lastSampleLookup = 0;\n UpdateCache();\n }\n\n canPlay = data > 0x7F; //EnableCheck();\n },\n //NR31:\n 0x1B: function _(data) {\n totalLength = 0x100 - data;\n EnableCheck();\n },\n //NR32:\n 0x1C: function _(data) {\n data &= 0x60;\n patternType = data == 0 ? 4 : (data >> 5) - 1;\n },\n //NR33:\n 0x1D: function _(data) {\n frequency = frequency & 0x700 | data;\n FrequencyPeriod = 0x800 - frequency << 1;\n },\n //NR34:\n 0x1E: function _(data) {\n if (data > 0x7F) {\n if (totalLength == 0) {\n totalLength = 0x100;\n }\n\n lastSampleLookup = 0;\n }\n\n consecutive = (data & 0x40) == 0x0;\n frequency = (data & 0x7) << 8 | frequency & 0xFF;\n FrequencyPeriod = 0x800 - frequency << 1;\n EnableCheck();\n },\n //NR51\n 0x25: function _(data) {\n leftChannel = !!(data & 0x40);\n rightChannel = !!(data & 0x04);\n OutputLevelCache();\n },\n //Wavetable\n 0x30: setWaveTableByte.bind(null, 0x00),\n 0x31: setWaveTableByte.bind(null, 0x01),\n 0x32: setWaveTableByte.bind(null, 0x02),\n 0x33: setWaveTableByte.bind(null, 0x03),\n 0x34: setWaveTableByte.bind(null, 0x04),\n 0x35: setWaveTableByte.bind(null, 0x05),\n 0x36: setWaveTableByte.bind(null, 0x06),\n 0x37: setWaveTableByte.bind(null, 0x07),\n 0x38: setWaveTableByte.bind(null, 0x08),\n 0x39: setWaveTableByte.bind(null, 0x09),\n 0x3A: setWaveTableByte.bind(null, 0x0A),\n 0x3B: setWaveTableByte.bind(null, 0x0B),\n 0x3C: setWaveTableByte.bind(null, 0x0C),\n 0x3D: setWaveTableByte.bind(null, 0x0D),\n 0x3E: setWaveTableByte.bind(null, 0x0E),\n 0x3F: setWaveTableByte.bind(null, 0x0F)\n };\n\n function setWaveTableByte(addr, value) {\n PCM[addr * 2] = value >> 4;\n PCM[addr * 2 + 1] = value & 0xF;\n }\n\n return {\n get output() {\n return output;\n },\n\n audioComputeSequencer: audioComputeSequencer,\n audioClocksUntilNextEvent: audioClocksUntilNextEvent,\n computeAudioChannels: computeAudioChannels,\n setMem: setMem,\n pushState: pushState\n };\n}\n\nfunction noise() {\n var volumeEnvelopeRegister = 0;\n var totalLength = 0;\n var envelopeVolume = 0;\n var currentVolume = 0;\n var envelopeType = false;\n var envelopeSweeps = 0;\n var envelopeSweepsLast = 0;\n var consecutive = true;\n var BitRange = 0x7FFF;\n var VolumeShifter = 15;\n var lastSampleLookup = 0;\n var noiseSampleTable = LSFR15Table;\n var FrequencyPeriod = 8;\n var Counter = 8;\n var cachedSample = 0;\n var Enabled = false;\n var canPlay = false;\n OutputLevelCache();\n var leftChannel = false;\n var rightChannel = false;\n var currentSampleLeft = 0;\n var currentSampleRight = 0;\n var currentSampleLeftSecondary = 0;\n var currentSampleRightSecondary = 0;\n var output = 0;\n\n function pushState() {\n var state = [volumeEnvelopeRegister, BitRange, VolumeShifter, noiseSampleTable, FrequencyPeriod, leftChannel, rightChannel];\n return function () {\n ;\n volumeEnvelopeRegister = state[0];\n BitRange = state[1];\n VolumeShifter = state[2];\n noiseSampleTable = state[3];\n FrequencyPeriod = state[4];\n leftChannel = state[5];\n rightChannel = state[6];\n };\n }\n\n function audioComputeSequencer(sequencePosition) {\n switch (sequencePosition % 8) {\n case 0:\n clockAudioLength();\n break;\n\n case 2:\n clockAudioLength();\n break;\n\n case 4:\n clockAudioLength();\n break;\n\n case 6:\n clockAudioLength();\n break;\n\n case 7:\n clockAudioEnvelope();\n break;\n }\n }\n\n function clockAudioLength() {\n if (totalLength > 1) {\n --totalLength;\n } else if (totalLength == 1) {\n totalLength = 0;\n EnableCheck();\n }\n }\n\n function clockAudioEnvelope() {\n if (envelopeSweepsLast > -1) {\n if (envelopeSweeps > 0) {\n --envelopeSweeps;\n } else {\n if (!envelopeType) {\n if (envelopeVolume > 0) {\n currentVolume = --envelopeVolume << VolumeShifter;\n envelopeSweeps = envelopeSweepsLast;\n UpdateCache();\n } else {\n envelopeSweepsLast = -1;\n }\n } else if (envelopeVolume < 0xF) {\n currentVolume = ++envelopeVolume << VolumeShifter;\n envelopeSweeps = envelopeSweepsLast;\n UpdateCache();\n } else {\n envelopeSweepsLast = -1;\n }\n }\n }\n }\n\n function audioClocksUntilNextEvent() {\n return Counter;\n }\n\n function computeAudioChannels(clockForward) {\n Counter -= clockForward;\n\n if (Counter == 0) {\n lastSampleLookup = lastSampleLookup + 1 & BitRange;\n Counter = FrequencyPeriod;\n UpdateCache();\n }\n }\n\n function EnableCheck() {\n Enabled = (consecutive || totalLength > 0) && canPlay;\n OutputLevelSecondaryCache();\n }\n\n function VolumeEnableCheck() {\n canPlay = volumeEnvelopeRegister > 7;\n EnableCheck();\n OutputLevelSecondaryCache();\n }\n\n function OutputLevelCache() {\n currentSampleLeft = leftChannel ? cachedSample : 0;\n currentSampleRight = rightChannel ? cachedSample : 0;\n OutputLevelSecondaryCache();\n }\n\n function OutputLevelSecondaryCache() {\n if (Enabled) {\n currentSampleLeftSecondary = currentSampleLeft;\n currentSampleRightSecondary = currentSampleRight;\n } else {\n currentSampleLeftSecondary = 0;\n currentSampleRightSecondary = 0;\n }\n\n mixerOutputLevelCache();\n }\n\n function UpdateCache() {\n cachedSample = noiseSampleTable[currentVolume | lastSampleLookup];\n OutputLevelCache();\n }\n\n function mixerOutputLevelCache() {\n output = currentSampleLeftSecondary << 16 | currentSampleRightSecondary;\n }\n\n var setMem = {\n //NR41:\n 0x20: function _(data) {\n totalLength = 0x40 - (data & 0x3F);\n EnableCheck();\n },\n //NR42:\n 0x21: function _(data) {\n envelopeType = (data & 0x08) == 0x08;\n volumeEnvelopeRegister = data;\n UpdateCache();\n VolumeEnableCheck();\n },\n //NR43:\n 0x22: function _(data) {\n FrequencyPeriod = Math.max((data & 0x7) << 4, 8) << (data >> 4);\n var bitWidth = data & 0x8;\n\n if (bitWidth == 0x8 && BitRange == 0x7FFF || bitWidth == 0 && BitRange == 0x7F) {\n lastSampleLookup = 0;\n BitRange = bitWidth == 0x8 ? 0x7F : 0x7FFF;\n VolumeShifter = bitWidth == 0x8 ? 7 : 15;\n currentVolume = envelopeVolume << VolumeShifter;\n noiseSampleTable = bitWidth == 0x8 ? LSFR7Table : LSFR15Table;\n }\n\n UpdateCache();\n },\n //NR44:\n 0x23: function _(data) {\n consecutive = (data & 0x40) == 0x0;\n\n if (data > 0x7F) {\n volumeEnvelopeRegister;\n envelopeVolume = volumeEnvelopeRegister >> 4;\n currentVolume = envelopeVolume << VolumeShifter;\n envelopeSweepsLast = (volumeEnvelopeRegister & 0x7) - 1;\n\n if (totalLength == 0) {\n totalLength = 0x40;\n }\n }\n\n EnableCheck();\n },\n //NR51\n 0x25: function _(data) {\n leftChannel = data > 0x7F;\n rightChannel = !!(data & 0x08);\n OutputLevelCache();\n }\n };\n return {\n get output() {\n return output;\n },\n\n audioComputeSequencer: audioComputeSequencer,\n audioClocksUntilNextEvent: audioClocksUntilNextEvent,\n computeAudioChannels: computeAudioChannels,\n setMem: setMem,\n pushState: pushState\n };\n}\n\nvar channels = [pulse(true), pulse(false), wav(), noise()]; //Sound variables:\n\nvar gameboyClockHertz = 0x400000;\nvar VinLeftChannelMasterVolume = 8;\nvar VinRightChannelMasterVolume = 8;\nvar sequencerClocks = 0x2000;\nvar sequencePosition = 0;\nvar audioClocksUntilNextEvent = 1;\nvar audioClocksUntilNextEventCounter = 1;\nvar gameboySamplePerOutputSample;\nvar downSampleInputDivider;\n\nvar GameboyProcessor =\n/*#__PURE__*/\nfunction (_AudioWorkletProcesso) {\n _inherits(GameboyProcessor, _AudioWorkletProcesso);\n\n function GameboyProcessor() {\n var _getPrototypeOf2;\n\n var _this;\n\n _classCallCheck(this, GameboyProcessor);\n\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(GameboyProcessor)).call.apply(_getPrototypeOf2, [this].concat(args)));\n\n _this.port.onmessage = function (_ref) {\n var e = _ref.data;\n\n if (e.type === \'play\') {\n var arr = new Uint8Array(e.data);\n\n if (e.mask) {\n playSFX(arr, e.mask);\n } else {\n playSong(arr, e.loop);\n }\n }\n };\n\n return _this;\n }\n\n _createClass(GameboyProcessor, [{\n key: "process",\n value: function process(inputs, outputs, parameters) {\n if (!sampleRate) throw new Error(\'No sample rate\');\n gameboySamplePerOutputSample = Math.round(gameboyClockHertz / sampleRate); // not sure why 30, but /8 is the max VinXChannelMasterVolume\n // and the /2 is because originally the gb soundchip expects samples in a range of (0,1)\n // which we can turn into (-.5,.5) BUT this causes audio pop whenever we start the emulator\n // so we settle for (0,.5) instead.\n\n downSampleInputDivider = 1 / (gameboySamplePerOutputSample * 30) / 8 / 2;\n var out1 = outputs[0][0];\n var out2 = outputs[0][1];\n\n for (var i = 0; i < out1.length; ++i) {\n var sample = generateAudio();\n out1[i] = (sample >>> 16) * VinLeftChannelMasterVolume * downSampleInputDivider;\n out2[i] = (sample & 0xFFFF) * VinRightChannelMasterVolume * downSampleInputDivider; // if (i%256 === 0) console.log(`${i.toString(16).padStart(4,0)} sample === ${sample.toString(2).padStart(32,0)}`)\n }\n\n return true;\n }\n }]);\n\n return GameboyProcessor;\n}(_wrapNativeSuper(AudioWorkletProcessor));\n\nregisterProcessor(\'gameboy-processor\', GameboyProcessor);\nvar song = null;\nvar songIdx = -1;\nvar songTimer = 0;\nvar songLoopPoint = -1;\nvar sfx = null;\nvar sfxIdx = -1;\nvar sfxTimer = 0;\nvar sfxMask = [0, 0, 0, 0];\nvar restoreSongState = null;\n\nfunction playSong(newSong, loopPoint) {\n var resumePoint = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;\n song = newSong;\n songIdx = resumePoint;\n songTimer = 0;\n songLoopPoint = loopPoint;\n sfx = null;\n sfxIdx = -1;\n sfxTimer = 0;\n sfxMask = [0, 0, 0, 0];\n restoreSongState = null;\n}\n\nfunction playSFX(newSFX, mask) {\n sfx = newSFX;\n sfxIdx = 0;\n sfxTimer = 0;\n sfxMask = mask;\n\n if (restoreSongState == null) {\n var undos = channels.map(function (ch) {\n return ch.pushState();\n });\n\n restoreSongState = function restoreSongState() {\n return undos.forEach(function (fn) {\n return fn();\n });\n };\n }\n}\n/**\n * Rougly 0x400000/44100 (clock speed / audio sampling speed)\n * You may be wondering: isn\'t that the same as gameboySamplePerOutputSample?\n * Answer: no. This is just used for determining the timing of the delay commands.\n * Those commands come from the .vgm format, which always assumes 44100 sample rate.\n */\n\n\nvar atomicDelayUnit = 0x60; //Below are the audio generation functions timed against the CPU:\n\nfunction generateAudio() {\n var realSample = 0;\n\n for (var downsampledFramesLeft = gameboySamplePerOutputSample; downsampledFramesLeft > 0;) {\n while (songTimer === 0 && songIdx >= 0) {\n if (songIdx >= song.length) {\n songIdx = songLoopPoint;\n if (songIdx === -1) break;\n }\n\n var op = song[songIdx++];\n\n if (op === 0xB3) {\n // gameboy apu register write\n var reg = song[songIdx++] + 0x10;\n var val = song[songIdx++];\n registerWrite(reg, val, sfxMask.map(function (i) {\n return !i;\n }));\n } else if (op === 0x61) {\n var t = song[songIdx++] + (song[songIdx++] << 8);\n songTimer += t * atomicDelayUnit;\n } else if (op === 0x62) {\n var _t = 735; // exactly 44100/60\n\n songTimer += _t * atomicDelayUnit;\n } else if ((op & 0xF0) === 0x70) {\n var _t2 = 1 + (op & 0xf);\n\n songTimer += _t2 * atomicDelayUnit;\n } else if (op === 0x66) {\n songIdx = songLoopPoint;\n } else {\n throw new Error(\'What is op \' + op.toString(16));\n }\n }\n\n while (sfxTimer === 0 && sfxIdx >= 0) {\n if (sfxIdx >= sfx.length) {\n sfxIdx = -1;\n sfxMask = [0, 0, 0, 0];\n restoreSongState();\n break;\n }\n\n var _op = sfx[sfxIdx++];\n\n if (_op === 0xB3) {\n // gameboy apu register write\n var _reg = sfx[sfxIdx++] + 0x10;\n\n var _val = sfx[sfxIdx++];\n registerWrite(_reg, _val, sfxMask);\n } else if (_op === 0x61) {\n var _t3 = sfx[sfxIdx++] + (sfx[sfxIdx++] << 8);\n\n sfxTimer += _t3 * atomicDelayUnit;\n } else if (_op === 0x62) {\n var _t4 = 735; // exactly 44100/60\n\n sfxTimer += _t4 * atomicDelayUnit;\n } else if ((_op & 0xF0) === 0x70) {\n var _t5 = 1 + (_op & 0xf);\n\n sfxTimer += _t5 * atomicDelayUnit;\n } else if (_op === 0x66) {\n sfxIdx = -1;\n sfxMask = [0, 0, 0, 0];\n restoreSongState();\n } else {\n throw new Error(\'What is op \' + _op.toString(16));\n }\n }\n\n if (sequencerClocks == 0) {\n sequencePosition++;\n\n for (var _i = 0, _channels = channels; _i < _channels.length; _i++) {\n var channel = _channels[_i];\n channel.audioComputeSequencer(sequencePosition);\n }\n\n sequencerClocks = 0x2000;\n }\n\n if (audioClocksUntilNextEventCounter == 0) {\n //Clock down the four audio channels to the next closest audio event:\n for (var _i2 = 0, _channels2 = channels; _i2 < _channels2.length; _i2++) {\n var _channel = _channels2[_i2];\n\n _channel.computeAudioChannels(audioClocksUntilNextEvent);\n } //Find the number of clocks to next closest counter event:\n\n\n audioClocksUntilNextEvent = Math.min.apply(null, channels.map(function (ch) {\n return ch.audioClocksUntilNextEvent();\n }));\n audioClocksUntilNextEventCounter = audioClocksUntilNextEvent;\n }\n\n var multiplier = Math.min(audioClocksUntilNextEventCounter, sequencerClocks, downsampledFramesLeft, songIdx >= 0 ? songTimer : Infinity, sfxIdx >= 0 ? sfxTimer : Infinity);\n\n if (!(multiplier > 0)) {\n throw new Error(\'multipler should greater than 0\');\n }\n\n audioClocksUntilNextEventCounter -= multiplier;\n sequencerClocks -= multiplier;\n downsampledFramesLeft -= multiplier;\n songTimer -= multiplier;\n sfxTimer -= multiplier;\n var output = channels.reduce(function (output, ch) {\n return output + ch.output;\n }, 0);\n realSample += output * multiplier;\n }\n\n return realSample;\n}\n\nfunction registerWrite(address, data, channelMask) {\n if (miscRegisterFuncs[address]) {\n miscRegisterFuncs[address](data);\n } else {\n var didSet = 0;\n\n for (var i = 0; i < 4; ++i) {\n if (channels[i].setMem[address]) {\n if (channelMask[i]) {\n channels[i].setMem[address](data);\n }\n\n ++didSet;\n }\n }\n\n if (!didSet) {\n throw new Error("Unsupported register write: FF".concat(address.toString(16).padStart(2, 0)));\n }\n } // console.log(`FF${address.toString(16).padStart(2)} <= ${data}`)\n\n}\n\nvar miscRegisterFuncs = {\n //NR50:\n 0x24: function _(data) {\n VinLeftChannelMasterVolume = (data >> 4 & 0x07) + 1;\n VinRightChannelMasterVolume = (data & 0x07) + 1; // mixerOutputLevelCache();\n },\n //NR52:\n 0x26: function _() {// allowed, but ignored\n }\n};'],{type:"application/javascript"}),Ae=URL.createObjectURL(Oe),qe=Le.audioWorklet.addModule(Ae).then(function(){var e=new AudioWorkletNode(Le,"gameboy-processor",{outputChannelCount:[2]});return e.connect(_e),e});function Ne(e,n){var t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return{play:function(){var r=++Ee;return qe.then(function(a){a.port.postMessage({id:r,type:"play",data:e,loop:n,mask:t})}),{pause:function(){node.port.postMessage({id:r,type:"pause"})},resume:function(){node.port.postMessage({id:r,type:"resume"})}}}}}function Ie(e){return Ne(e,arguments.length>1&&void 0!==arguments[1]?arguments[1]:0)}function Me(e){return Ne(e,-1,arguments.length>1&&void 0!==arguments[1]?arguments[1]:[1,1,1,1])}function De(e){for(var n=new Uint8Array(e,0,4),t=0;t<4;++t)if(n[t]!=="Vgm "[t].charCodeAt())throw new Error("Invalid header");var r=52+new Uint32Array(e,52,1)[0],a=28+new Uint32Array(e,28,1)[0]-r;return Ie(e.slice(r),a)}}]); |
{ | ||
"name": "apu", | ||
"version": "0.2.3", | ||
"version": "0.2.4", | ||
"description": "Easy 3 kB library for 98% accurate Gameboy audio", | ||
@@ -5,0 +5,0 @@ "main": "dist/apu.js", |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
45964