diff --git a/index.html b/index.html index 0f47c95..10afc47 100644 --- a/index.html +++ b/index.html @@ -272,7 +272,7 @@

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. - */class e{}function i(t){let e=0;for(let i=0;i>1;1==(t+e&1)&&(e+=16384),t=e}}else if(1==t)for(let t=0;t>1;1==(t+e&1)&&(e+=32768),t=e}}else if(3==t){let t=1;for(let i=0;i>1;1==(t+e&1)&&(e+=40),t=e}}else{if(4!=t)throw new Error("Unrecognized drum index: "+t);r(n,e.chipNoiseLength,10,11,1,1,0),r(n,e.chipNoiseLength,11,14,.6578,.6578,0),i(n,e.chipNoiseLength),s(n,1/Math.sqrt(e.chipNoiseLength))}n[e.chipNoiseLength]=n[0]}return n}function r(t,e,i,s,n,r,h){const a=0|Math.pow(2,i),l=Math.min(e>>1,0|Math.pow(2,s)),c=o(0,null,null);let u=0;for(let o=a;oMath.max(t,e)))),e.chords=a([{name:"simultaneous",customInterval:!1,arpeggiates:!1,strumParts:0,singleTone:!1},{name:"strum",customInterval:!1,arpeggiates:!1,strumParts:1,singleTone:!1},{name:"arpeggio",customInterval:!1,arpeggiates:!0,strumParts:0,singleTone:!0},{name:"custom interval",customInterval:!0,arpeggiates:!1,strumParts:0,singleTone:!0}]),e.maxChordSize=4,e.operatorCount=4,e.maxPitchOrOperatorCount=Math.max(e.maxChordSize,e.operatorCount),e.algorithms=a([{name:"1←(2 3 4)",carrierCount:1,associatedCarrier:[1,1,1,1],modulatedBy:[[2,3,4],[],[],[]]},{name:"1←(2 3←4)",carrierCount:1,associatedCarrier:[1,1,1,1],modulatedBy:[[2,3],[],[4],[]]},{name:"1←2←(3 4)",carrierCount:1,associatedCarrier:[1,1,1,1],modulatedBy:[[2],[3,4],[],[]]},{name:"1←(2 3)←4",carrierCount:1,associatedCarrier:[1,1,1,1],modulatedBy:[[2,3],[4],[4],[]]},{name:"1←2←3←4",carrierCount:1,associatedCarrier:[1,1,1,1],modulatedBy:[[2],[3],[4],[]]},{name:"1←3 2←4",carrierCount:2,associatedCarrier:[1,2,1,2],modulatedBy:[[3],[4],[],[]]},{name:"1 2←(3 4)",carrierCount:2,associatedCarrier:[1,2,2,2],modulatedBy:[[],[3,4],[],[]]},{name:"1 2←3←4",carrierCount:2,associatedCarrier:[1,2,2,2],modulatedBy:[[],[3],[4],[]]},{name:"(1 2)←3←4",carrierCount:2,associatedCarrier:[1,2,2,2],modulatedBy:[[3],[3],[4],[]]},{name:"(1 2)←(3 4)",carrierCount:2,associatedCarrier:[1,2,2,2],modulatedBy:[[3,4],[3,4],[],[]]},{name:"1 2 3←4",carrierCount:3,associatedCarrier:[1,2,3,3],modulatedBy:[[],[],[4],[]]},{name:"(1 2 3)←4",carrierCount:3,associatedCarrier:[1,2,3,3],modulatedBy:[[4],[4],[4],[]]},{name:"1 2 3 4",carrierCount:4,associatedCarrier:[1,2,3,4],modulatedBy:[[],[],[],[]]}]),e.operatorCarrierInterval=[0,.04,-.073,.091],e.operatorAmplitudeMax=15,e.operatorFrequencies=a([{name:"1×",mult:1,hzOffset:0,amplitudeSign:1},{name:"~1×",mult:1,hzOffset:1.5,amplitudeSign:-1},{name:"2×",mult:2,hzOffset:0,amplitudeSign:1},{name:"~2×",mult:2,hzOffset:-1.3,amplitudeSign:-1},{name:"3×",mult:3,hzOffset:0,amplitudeSign:1},{name:"4×",mult:4,hzOffset:0,amplitudeSign:1},{name:"5×",mult:5,hzOffset:0,amplitudeSign:1},{name:"6×",mult:6,hzOffset:0,amplitudeSign:1},{name:"7×",mult:7,hzOffset:0,amplitudeSign:1},{name:"8×",mult:8,hzOffset:0,amplitudeSign:1},{name:"9×",mult:9,hzOffset:0,amplitudeSign:1},{name:"11×",mult:11,hzOffset:0,amplitudeSign:1},{name:"13×",mult:13,hzOffset:0,amplitudeSign:1},{name:"16×",mult:16,hzOffset:0,amplitudeSign:1},{name:"20×",mult:20,hzOffset:0,amplitudeSign:1}]),e.envelopes=a([{name:"none",type:1,speed:0},{name:"note size",type:0,speed:0},{name:"punch",type:2,speed:0},{name:"flare 1",type:3,speed:32},{name:"flare 2",type:3,speed:8},{name:"flare 3",type:3,speed:2},{name:"twang 1",type:4,speed:32},{name:"twang 2",type:4,speed:8},{name:"twang 3",type:4,speed:2},{name:"swell 1",type:5,speed:32},{name:"swell 2",type:5,speed:8},{name:"swell 3",type:5,speed:2},{name:"tremolo1",type:6,speed:4},{name:"tremolo2",type:6,speed:2},{name:"tremolo3",type:6,speed:1},{name:"tremolo4",type:7,speed:4},{name:"tremolo5",type:7,speed:2},{name:"tremolo6",type:7,speed:1},{name:"decay 1",type:8,speed:10},{name:"decay 2",type:8,speed:7},{name:"decay 3",type:8,speed:4}]),e.feedbacks=a([{name:"1⟲",indices:[[1],[],[],[]]},{name:"2⟲",indices:[[],[2],[],[]]},{name:"3⟲",indices:[[],[],[3],[]]},{name:"4⟲",indices:[[],[],[],[4]]},{name:"1⟲ 2⟲",indices:[[1],[2],[],[]]},{name:"3⟲ 4⟲",indices:[[],[],[3],[4]]},{name:"1⟲ 2⟲ 3⟲",indices:[[1],[2],[3],[]]},{name:"2⟲ 3⟲ 4⟲",indices:[[],[2],[3],[4]]},{name:"1⟲ 2⟲ 3⟲ 4⟲",indices:[[1],[2],[3],[4]]},{name:"1→2",indices:[[],[1],[],[]]},{name:"1→3",indices:[[],[],[1],[]]},{name:"1→4",indices:[[],[],[],[1]]},{name:"2→3",indices:[[],[],[2],[]]},{name:"2→4",indices:[[],[],[],[2]]},{name:"3→4",indices:[[],[],[],[3]]},{name:"1→3 2→4",indices:[[],[],[1],[2]]},{name:"1→4 2→3",indices:[[],[],[2],[1]]},{name:"1→2→3→4",indices:[[],[1],[2],[3]]}]),e.chipNoiseLength=32768,e.spectrumNoiseLength=32768,e.spectrumBasePitch=24,e.spectrumControlPoints=30,e.spectrumControlPointsPerOctave=7,e.spectrumControlPointBits=3,e.spectrumMax=(1<Math.log2(t)*e.pitchesPerOctave)),e.pitchShiftRange=e.justIntonationSemitones.length,e.pitchShiftCenter=e.pitchShiftRange>>1,e.detuneCenter=9,e.detuneMax=2*e.detuneCenter,e.sineWaveLength=256,e.sineWaveMask=e.sineWaveLength-1,e.sineWave=function(){const t=new Float32Array(e.sineWaveLength+1);for(let i=0;i>6,i=63&t;return x.presetCategories[e].presets[i]}static midiProgramToPresetValue(t){for(let e=0;e=t.length&&(t=void 0),{value:t&&t[s++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")},F=t&&t.i||function(t,e){var i="function"==typeof Symbol&&t[Symbol.iterator];if(!i)return t;var s,n,o=i.call(t),r=[];try{for(;(void 0===e||e-- >0)&&!(s=o.next()).done;)r.push(s.value)}catch(t){n={error:t}}finally{try{s&&!s.done&&(i=o.return)&&i.call(o)}finally{if(n)throw n.error}}return r},P=t&&t.o||function(){for(var t=[],e=0;e=t.length&&(t=void 0),{value:t&&t[s++],done:!t}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")},D=function(){for(var t=[],e=0;e'+t.join()+"","image/svg+xml").documentElement;null!==s.firstChild;)document.importNode(s.firstChild,!0),i.appendChild(s.firstChild);return i},B=function(t){D[t]=function(){for(var e=[],i=0;i');\n\t--pause-symbol: url('data:image/svg+xml,');\n\t--record-symbol: url('data:image/svg+xml,');\n\t--stop-symbol: url('data:image/svg+xml,');\n\t--prev-bar-symbol: url('data:image/svg+xml,');\n\t--next-bar-symbol: url('data:image/svg+xml,');\n\t--volume-symbol: url('data:image/svg+xml,');\n\t--unmuted-symbol: url('data:image/svg+xml,');\n\t--muted-symbol: url('data:image/svg+xml,');\n\t--menu-down-symbol: url('data:image/svg+xml,');\n\t--select-arrows-symbol: url('data:image/svg+xml,');\n\t--file-page-symbol: url('data:image/svg+xml,');\n\t--edit-pencil-symbol: url('data:image/svg+xml,');\n\t--preferences-gear-symbol: url('data:image/svg+xml,');\n\t--customize-dial-symbol: url('data:image/svg+xml, \t\t\t \t\t\t\t \t\t\t\t \t\t\t\t \t\t\t\t \t\t\t\t \t\t\t\t \t\t\t\t \t\t\t\t \t\t\t\t \t\t\t\t \t\t\t\t \t\t\t \t\t');\n\t--instrument-copy-symbol: url('data:image/svg+xml,');\n\t--instrument-paste-symbol: url('data:image/svg+xml,');\n\t--export-symbol: url('data:image/svg+xml,');\n\t--close-symbol: url('data:image/svg+xml,');\n\t--add-symbol: url('data:image/svg+xml,');\n\t--zoom-in-symbol: url('data:image/svg+xml,');\n\t--zoom-out-symbol: url('data:image/svg+xml,');\n\t--checkmark-symbol: url('data:image/svg+xml,');\n\t--drum-symbol: url('data:image/svg+xml, \t\t\t \t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t \t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t \t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t \t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t \t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t');\n\t--piano-key-symbol: url('data:image/svg+xml, \t\t\t \t\t\t\t \t\t\t\t\t \t\t\t\t\t \t\t\t\t \t\t\t \t\t\t \t\t\t \t\t\t \t\t');\n}\n\n\n.obtrusive-scrollbars, .obtrusive-scrollbars * {\n\tscrollbar-width: thin;\n\tscrollbar-color: ${$.uiWidgetBackground} ${$.editorBackground};\n}\n.obtrusive-scrollbars::-webkit-scrollbar, .obtrusive-scrollbars *::-webkit-scrollbar {\n\twidth: 12px;\n}\n.obtrusive-scrollbars::-webkit-scrollbar-track, .obtrusive-scrollbars *::-webkit-scrollbar-track {\n\tbackground: ${$.editorBackground};\n}\n.obtrusive-scrollbars::-webkit-scrollbar-thumb, .obtrusive-scrollbars *::-webkit-scrollbar-thumb {\n\tbackground-color: ${$.uiWidgetBackground};\n\tborder: 3px solid ${$.editorBackground};\n}\n\n\n.beepboxEditor {\n\tdisplay: grid;\n grid-template-columns: minmax(0, 1fr) max-content;\n grid-template-rows: max-content 1fr; /* max-content minmax(0, 1fr); Chrome 80 grid layout regression. https://bugs.chromium.org/p/chromium/issues/detail?id=1050307 */\n grid-template-areas: "pattern-area settings-area" "track-area settings-area";\n\tgrid-column-gap: 6px;\n\tgrid-row-gap: 6px;\n\tposition: relative;\n\ttouch-action: manipulation;\n\tcursor: default;\n\tfont-size: 13px;\n\toverflow: hidden;\n\tcolor: ${$.primaryText};\n\tbackground: ${$.editorBackground};\n}\n\n.beepboxEditor .noSelection {\n\t-webkit-touch-callout: none;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n\n.beepboxEditor div {\n\tmargin: 0;\n\tpadding: 0;\n}\n\n.beepboxEditor .pattern-area {\n\tgrid-area: pattern-area;\n\theight: 481px;\n\tdisplay: flex;\n\tflex-direction: row;\n\tposition: relative;\n}\n\n.beepboxEditor .track-area {\n\tgrid-area: track-area;\n}\n\n.beepboxEditor .loopEditor {\n\theight: 20px;\n\tposition: sticky;\n\tbottom: 0;\n\tpadding: 5px 0;\n\tbackground-color: ${$.editorBackground};\n}\n\n.beepboxEditor .settings-area {\n\tgrid-area: settings-area;\n\tdisplay: grid;\n grid-template-columns: auto;\n grid-template-rows: min-content min-content min-content min-content min-content;\n grid-template-areas: "version-area" "play-pause-area" "menu-area" "song-settings-area" "instrument-settings-area";\n\tgrid-column-gap: 6px;\n}\n\n.beepboxEditor .version-area{ grid-area: version-area; }\n.beepboxEditor .play-pause-area{ grid-area: play-pause-area; }\n.beepboxEditor .menu-area{ grid-area: menu-area; }\n.beepboxEditor .song-settings-area{ grid-area: song-settings-area; }\n.beepboxEditor .instrument-settings-area{ grid-area: instrument-settings-area; }\n\n.beepboxEditor .tip {\n\tcursor: help;\n\tcolor: ${$.secondaryText};\n\ttext-decoration: none;\n}\n\n.beepboxEditor .tip:hover {\n\tcolor: ${$.linkAccent};\n\ttext-decoration: underline;\n}\n.beepboxEditor .tip:active {\n\tcolor: ${$.primaryText};\n}\n\n.beepboxEditor .volume-speaker {\n\tflex-shrink: 0;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: ${$.secondaryText};\n\t-webkit-mask-image: var(--volume-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--volume-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n\n.beepboxEditor .drum-button {\n\tflex: 1;\n\tbackground-color: transparent;\n\tbackground-image: var(--drum-symbol);\n\tbackground-repeat: no-repeat;\n\tbackground-position: center;\n}\n\n.beepboxEditor .piano-button {\n\tflex: 1;\n\tposition: relative;\n\tdisplay: flex;\n\talign-items: center;\n}\n.beepboxEditor .piano-button::before {\n\tcontent: "";\n\tposition: absolute;\n\tleft: 0;\n\ttop: 0;\n\twidth: 100%;\n\theight: 100%;\n\tpointer-events: none;\n\tbackground-image: var(--piano-key-symbol);\n\tbackground-repeat: no-repeat;\n\tbackground-position: center;\n\tbackground-size: 100% 115.38%;\n}\n.beepboxEditor .piano-button.disabled::after {\n\tcontent: "";\n\tposition: absolute;\n\tright: 0;\n\ttop: 0;\n\twidth: 70%;\n\theight: 100%;\n\tpointer-events: none;\n\tbackground: ${$.editorBackground};\n\t-webkit-mask-image: linear-gradient(90deg, transparent 0%, gray 70%, gray 100%);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: linear-gradient(90deg, transparent 0%, gray 70%, gray 100%);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n\n.beepboxEditor .piano-button.pressed, .beepboxEditor .drum-button.pressed {\n\tfilter: brightness(0.5);\n}\n\n.beepboxEditor .customize-instrument {\n\tmargin: 2px 0;\n}\n.beepboxEditor .customize-instrument::before {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tleft: 0;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--customize-dial-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--customize-dial-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n\n.beepboxEditor .instrumentCopyPasteRow {\n\tgap: 2px;\n}\n\n.beepboxEditor .copy-instrument {\n\tmargin: 2px 0;\n\tflex-grow: 1;\n}\n.beepboxEditor .copy-instrument::before {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tleft: 0;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--instrument-copy-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--instrument-copy-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n\n.beepboxEditor .paste-instrument {\n\tmargin: 2px 0;\n\tflex-grow: 1;\n}\n.beepboxEditor .paste-instrument::before {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tleft: 0;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--instrument-paste-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--instrument-paste-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n\n.beepboxEditor .envelopeEditor {\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.beepboxEditor .envelope-row {\n\tdisplay: flex;\n\tmargin: 2px 0;\n\tgap: 2px;\n}\n\n.beepboxEditor .add-envelope {\n\twidth: var(--button-size);\n}\n.beepboxEditor .add-envelope::before {\n\tcontent: "";\n\tposition: absolute;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tleft: 0;\n\ttop: 0;\n\tpointer-events: none;\n\tbackground: currentColor;\n\tmask-image: var(--add-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n\t-webkit-mask-image: var(--add-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n}\n.beepboxEditor .add-envelope:disabled {\n\tvisibility: hidden;\n}\n\n.beepboxEditor .effects-menu {\n\twidth: var(--button-size);\n\tposition: relative;\n}\n.beepboxEditor .effects-menu::before {\n\tcontent: "";\n\tposition: absolute;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tleft: 0;\n\ttop: 0;\n\tpointer-events: none;\n\tbackground: currentColor;\n\tmask-image: var(--menu-down-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n\t-webkit-mask-image: var(--menu-down-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n}\n\n.beepboxEditor .zoomInButton, .beepboxEditor .zoomOutButton {\n\twidth: var(--button-size);\n\tposition: absolute;\n\tright: 10px;\n}\n.beepboxEditor .zoomInButton {\n\ttop: 10px;\n}\n.beepboxEditor .zoomOutButton {\n\ttop: 50px;\n}\n.beepboxEditor .zoomInButton::before {\n\tcontent: "";\n\tposition: absolute;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tleft: 0;\n\ttop: 0;\n\tpointer-events: none;\n\tbackground: currentColor;\n\tmask-image: var(--zoom-in-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n\t-webkit-mask-image: var(--zoom-in-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n}\n.beepboxEditor .zoomOutButton::before {\n\tcontent: "";\n\tposition: absolute;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tleft: 0;\n\ttop: 0;\n\tpointer-events: none;\n\tbackground: currentColor;\n\tmask-image: var(--zoom-out-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n\t-webkit-mask-image: var(--zoom-out-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n}\n\n.beepboxEditor .delete-envelope {\n\twidth: var(--button-size);\n\tflex-shrink: 0;\n\tflex-grow: 0;\n}\n.beepboxEditor .delete-envelope::before {\n\tcontent: "";\n\tposition: absolute;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tleft: 0;\n\ttop: 0;\n\tpointer-events: none;\n\tbackground: currentColor;\n\tmask-image: var(--close-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n\t-webkit-mask-image: var(--close-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n}\n.beepboxEditor .delete-envelope:disabled {\n\tvisibility: hidden;\n}\n\n.beepboxEditor .menu.file::before {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tleft: 0;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--file-page-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--file-page-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n\n.beepboxEditor .menu.edit::before {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tleft: 0;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--edit-pencil-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--edit-pencil-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n\n.beepboxEditor .menu.preferences::before {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tleft: 0;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--preferences-gear-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--preferences-gear-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n\n.beepboxEditor .mute-button::before {\n\tcontent: "";\n\tpointer-events: none;\n\twidth: 100%;\n\theight: 100%;\n\tbackground: ${$.primaryText};\n\tdisplay: inline-block;\n\t-webkit-mask-image: var(--unmuted-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\t-webkit-mask-size: contain;\n\tmask-image: var(--unmuted-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n\tmask-size: contain;\n}\n\n.beepboxEditor .mute-button.muted::before {\n\tbackground: ${$.editorBackground};\n\t-webkit-mask-image: var(--muted-symbol);\n\tmask-image: var(--muted-symbol);\n}\n\n.beepboxEditor .promptContainer {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tdisplay: flex;\n\tjustify-content: center;\n\talign-items: center;\n\tz-index: 100;\n}\n\n.beepboxEditor .promptContainer::before {\n\tcontent: "";\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tbackground: ${$.editorBackground};\n\topacity: 0.5;\n\tdisplay: flex;\n}\n\n.beepboxEditor .prompt {\n\tmargin: auto;\n\ttext-align: center;\n\tbackground: ${$.editorBackground};\n\tborder-radius: 15px;\n\tborder: 4px solid ${$.uiWidgetBackground};\n\tcolor: ${$.primaryText};\n\tpadding: 20px;\n\tdisplay: flex;\n\tflex-direction: column;\n\tposition: relative;\n\tbox-shadow: 5px 5px 20px 10px rgba(0,0,0,0.5);\n}\n\n.beepboxEditor .prompt > *:not(:first-child):not(.cancelButton) {\n\tmargin-top: 1.5em;\n}\n\n.beepboxEditor .prompt h2 {\n\tfont-size: 2em;\n\tmargin: 0 16px;\n\tfont-weight: normal;\n}\n\n.beepboxEditor .prompt p {\n\ttext-align: left;\n\tmargin: 1em 0;\n}\n\n.beepboxEditor .prompt label {\n\tcursor: pointer;\n}\n\n.beepboxEditor .prompt.recordingSetupPrompt p {\n\tmargin-top: 0.75em;\n\tmargin-bottom: 0;\n}\n\n.beepboxEditor .prompt.recordingSetupPrompt > label:not(:first-child):not(.cancelButton) {\n\tmargin: 2px 0;\n}\n\n.beepboxEditor .layout-option {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1;\n\tcursor: pointer;\n\tcolor: ${$.secondaryText};\n}\n\n.beepboxEditor .layout-option input {\n\tdisplay: none;\n}\n\n.beepboxEditor .layout-option input:checked ~ * {\n\tcolor: ${$.primaryText};\n}\n\n.beepboxEditor .selectContainer {\n\tposition: relative;\n}\n.beepboxEditor .selectContainer:not(.menu)::after {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tright: 0;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n\tpointer-events: none;\n\twidth: 14px;\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--select-arrows-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--select-arrows-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n.beepboxEditor .selectContainer.menu::after {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tright: 0;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--menu-down-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--menu-down-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n.beepboxEditor select {\n\tmargin: 0;\n\tpadding: 0 4px;\n\tdisplay: block;\n\theight: var(--button-size);\n\tborder: none;\n\tborder-radius: 5px;\n\tbackground: ${$.uiWidgetBackground};\n\tcolor: inherit;\n\tfont-size: inherit;\n\tcursor: pointer;\n\tfont-family: inherit;\n\tfont-weight: inherit;\n\n\t-webkit-appearance:none;\n\t-moz-appearance: none;\n\tappearance: none;\n}\n.beepboxEditor .menu select {\n\tpadding: 0 var(--button-size);\n}\n.beepboxEditor select:focus {\n\tbackground: ${$.uiWidgetFocus};\n\toutline: none;\n}\n.beepboxEditor .menu select {\n\ttext-align: center;\n\ttext-align-last: center;\n}\n.beepboxEditor .settings-area select {\n width: 100%;\n}\n\n/* This makes it look better in firefox on my computer... What about others?\n@-moz-document url-prefix() {\n\t.beepboxEditor select { padding: 0 2px; }\n}\n*/\n.beepboxEditor button {\n\tmargin: 0;\n\tposition: relative;\n\theight: var(--button-size);\n\tborder: none;\n\tborder-radius: 5px;\n\tbackground: ${$.uiWidgetBackground};\n\tcolor: inherit;\n\tfont-size: inherit;\n\tfont-family: inherit;\n\tfont-weight: inherit;\n\tcursor: pointer;\n}\n.beepboxEditor button:focus {\n\tbackground: ${$.uiWidgetFocus};\n\toutline: none;\n}\n\n.beepboxEditor button.cancelButton {\n\tfloat: right;\n\twidth: var(--button-size);\n\tposition: absolute;\n\ttop: 8px;\n\tright: 8px;\n}\n\n.beepboxEditor .playback-bar-controls {\n\tdisplay: grid;\n\tgrid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);\n\tgrid-template-rows: min-content;\n\tgrid-column-gap: 4px;\n}\n\n.beepboxEditor button.playButton::before {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tleft: 0;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--play-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--play-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n.beepboxEditor button.pauseButton::before {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tleft: 0;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--pause-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--pause-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n.beepboxEditor button.recordButton::before {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tleft: 0;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--record-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--record-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n.beepboxEditor button.stopButton::before {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tleft: 0;\n\ttop: 50%;\n\ttransform: translateY(-50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--stop-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--stop-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n\n.beepboxEditor button.prevBarButton::before {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tleft: 50%;\n\ttop: 50%;\n\ttransform: translate(-50%, -50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--prev-bar-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--prev-bar-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n\n.beepboxEditor button.nextBarButton::before {\n\tcontent: "";\n\tflex-shrink: 0;\n\tposition: absolute;\n\tleft: 50%;\n\ttop: 50%;\n\ttransform: translate(-50%, -50%);\n\tpointer-events: none;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--next-bar-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--next-bar-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n\n.beepboxEditor button.playButton, .beepboxEditor button.pauseButton, .beepboxEditor button.recordButton, .beepboxEditor button.stopButton, .beepboxEditor button.okayButton, .beepboxEditor button.exportButton {\n\tpadding-left: var(--button-size);\n}\n.beepboxEditor button.playButton, .beepboxEditor button.pauseButton, .beepboxEditor button.recordButton {\n\tgrid-column-start: 1;\n\tgrid-column-end: 3;\n}\n.beepboxEditor button.stopButton {\n\tgrid-column-start: 1;\n\tgrid-column-end: 5;\n}\n.beepboxEditor button.prevBarButton {\n\tgrid-column-start: 3;\n\tgrid-column-end: 4;\n}\n.beepboxEditor button.nextBarButton {\n\tgrid-column-start: 4;\n\tgrid-column-end: 5;\n}\n\n.beepboxEditor button.playButton.shrunk, .beepboxEditor button.recordButton.shrunk {\n\tpadding: 0;\n}\n.beepboxEditor button.playButton.shrunk::before, .beepboxEditor button.recordButton.shrunk::before {\n\tleft: 50%;\n\ttop: 50%;\n\ttransform: translate(-50%, -50%);\n}\n.beepboxEditor button.playButton.shrunk span, .beepboxEditor button.recordButton.shrunk span {\n\tdisplay: none;\n}\n.beepboxEditor button.playButton.shrunk {\n\tgrid-column-start: 1;\n\tgrid-column-end: 2;\n}\n.beepboxEditor button.recordButton.shrunk {\n\tgrid-column-start: 2;\n\tgrid-column-end: 3;\n}\n\n.beepboxEditor button.cancelButton::before {\n\tcontent: "";\n\tposition: absolute;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tleft: 0;\n\ttop: 0;\n\tpointer-events: none;\n\tbackground: currentColor;\n\tmask-image: var(--close-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n\t-webkit-mask-image: var(--close-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n}\n\n.beepboxEditor button.okayButton::before {\n\tcontent: "";\n\tposition: absolute;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tleft: 0;\n\ttop: 0;\n\tpointer-events: none;\n\tbackground: currentColor;\n\t-webkit-mask-image: var(--checkmark-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n\tmask-image: var(--checkmark-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n}\n\n.beepboxEditor button.exportButton::before {\n\tcontent: "";\n\tposition: absolute;\n\twidth: var(--button-size);\n\theight: var(--button-size);\n\tleft: 0;\n\ttop: 0;\n\tpointer-events: none;\n\tbackground: currentColor;\n\tmask-image: var(--export-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n\t-webkit-mask-image: var(--export-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n}\n\n.beepboxEditor .instrument-bar {\n\tdisplay: flex;\n\tgap: 2px;\n}\n\n.beepboxEditor .instrument-bar button {\n\tflex-grow: 1;\n\tmin-width: 0;\n\tpadding: 0;\n\tflex-basis: 0;\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tcolor: var(--text-color-lit);\n}\n\n.beepboxEditor .instrument-bar .remove-instrument, .beepboxEditor .instrument-bar .add-instrument {\n\tmax-width: var(--button-size);\n}\n\n.beepboxEditor .instrument-bar > :not(:first-child) {\n\tborder-top-left-radius: 0;\n\tborder-bottom-left-radius: 0;\n}\n\n.beepboxEditor .instrument-bar > :not(.last-button) {\n\tborder-top-right-radius: 0;\n\tborder-bottom-right-radius: 0;\n}\n\n.beepboxEditor .instrument-bar .selected-instrument {\n\tbackground: var(--background-color-lit);\n\tcolor: ${$.invertedText};\n}\n\n.beepboxEditor .instrument-bar .deactivated {\n\tbackground: ${$.editorBackground};\n\tcolor: var(--text-color-dim);\n}\n\n.beepboxEditor .instrument-bar .deactivated.selected-instrument {\n\tbackground: var(--background-color-dim);\n\tcolor: ${$.invertedText};\n}\n\n.beepboxEditor .instrument-bar .remove-instrument::before {\n\tcontent: "";\n\tposition: absolute;\n\twidth: 100%;\n\theight: var(--button-size);\n\tleft: 0;\n\ttop: 0;\n\tpointer-events: none;\n\tbackground: currentColor;\n\tmask-image: var(--close-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n\t-webkit-mask-image: var(--close-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n}\n\n.beepboxEditor .instrument-bar .add-instrument::before {\n\tcontent: "";\n\tposition: absolute;\n\twidth: 100%;\n\theight: var(--button-size);\n\tleft: 0;\n\ttop: 0;\n\tpointer-events: none;\n\tbackground: currentColor;\n\tmask-image: var(--add-symbol);\n\tmask-repeat: no-repeat;\n\tmask-position: center;\n\t-webkit-mask-image: var(--add-symbol);\n\t-webkit-mask-repeat: no-repeat;\n\t-webkit-mask-position: center;\n}\n\n.beepboxEditor canvas {\n\toverflow: hidden;\n\tposition: absolute;\n\tdisplay: block;\n}\n\n.beepboxEditor .trackContainer {\n\tflex-grow: 1;\n}\n\n.beepboxEditor .trackAndMuteContainer {\n\tdisplay: flex;\n\talign-items: flex-start;\n\twidth: 100%;\n\tmin-height: 0;\n\tflex: 1;\n\toverflow-x: hidden;\n\tposition: relative;\n}\n\n.beepboxEditor .channelRow {\n\tdisplay: flex;\n}\n\n.beepboxEditor .channelBox {\n\tdisplay: flex;\n\ttext-align: center;\n\talign-items: center;\n\tjustify-content: center;\n\tbox-sizing: border-box;\n\tpadding-top: 1px;\n}\n\n.beepboxEditor .channelBoxLabel {\n\tfont-size: 20px;\n\tfont-family: sans-serif;\n\tfont-weight: bold;\n}\n\n.beepboxEditor .muteEditor {\n\twidth: 32px;\n\tflex-shrink: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: stretch;\n\tposition: sticky;\n\tleft: 0;\n\tz-index: 1;\n\tbackground: ${$.editorBackground};\n}\n\n.beepboxEditor .selectRow, .beepboxEditor .instrumentCopyPasteRow {\n\tmargin: 2px 0;\n\theight: var(--button-size);\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: center;\n\tjustify-content: space-between;\n}\n\n.beepboxEditor .selectRow > :last-child {\n\twidth: 62.5%;\n\tflex-shrink: 0;\n}\n\n.beepboxEditor .menu-area {\n\tdisplay: flex;\n\tflex-direction: column;\n}\n.beepboxEditor .menu-area > * {\n\tmargin: 2px 0;\n}\n.beepboxEditor .menu-area > button {\n\tpadding: 0 var(--button-size);\n\twhite-space: nowrap;\n}\n\n.beepboxEditor .song-settings-area {\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.beepboxEditor .editor-controls {\n\tflex-shrink: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.beepboxEditor .instrument-settings-area {\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.beepboxEditor .editor-right-side-top > *, .beepboxEditor .editor-right-side-bottom > * {\n\tflex-shrink: 0;\n}\n\n.beepboxEditor .pitchShiftMarkerContainer {\n\tbox-sizing: border-box;\n\tdisplay: flex;\n\theight: 100%;\n\tleft: 3px;\n\tright: 3px;\n\tposition: absolute;\n\talign-items: center;\n\tpointer-events: none;\n}\n\n.beepboxEditor .pitchShiftMarker {\n\twidth: 0;\n\theight: 0;\n\tposition: absolute;\n}\n\n.beepboxEditor .pitchShiftMarker::before {\n\tcontent: "";\n\twidth: 2px;\n\theight: 20px;\n\ttransform: translate(-50%, -50%);\n\tposition: absolute;\n\tbackground: currentColor;\n\tborder-radius: 3px;\n}\n\n.beepboxEditor input[type=text], .beepboxEditor input[type=number] {\n\tfont-size: inherit;\n\tfont-weight: inherit;\n\tfont-family: inherit;\n\tbackground: transparent;\n\tborder: 1px solid ${$.uiWidgetFocus};\n\tcolor: ${$.primaryText};\n}\n\n.beepboxEditor input[type=text]::selection, .beepboxEditor input[type=number]::selection {\n\tbackground-color: ${$.textSelection};\n\tcolor: ${$.primaryText};\n}\n\n.beepboxEditor input[type=checkbox] {\n transform: scale(1.5);\n}\n\n.beepboxEditor input[type=range] {\n\t-webkit-appearance: none;\n\tcolor: inherit;\n\twidth: 100%;\n\theight: var(--button-size);\n\tfont-size: inherit;\n\tmargin: 0;\n\tcursor: pointer;\n\tbackground: none;\n\ttouch-action: pan-y;\n}\n.beepboxEditor input[type=range]:focus {\n\toutline: none;\n}\n.beepboxEditor input[type=range]::-webkit-slider-runnable-track {\n\twidth: 100%;\n\theight: 6px;\n\tcursor: pointer;\n\tbackground: ${$.uiWidgetBackground};\n}\n.beepboxEditor input[type=range]::-webkit-slider-thumb {\n\theight: var(--button-size);\n\twidth: 6px;\n\tborder-radius: 3px;\n\tbackground: currentColor;\n\tcursor: pointer;\n\t-webkit-appearance: none;\n\tmargin-top: -10px;\n}\n.beepboxEditor input[type=range]:focus::-webkit-slider-runnable-track {\n\tbackground: ${$.uiWidgetFocus};\n}\n.beepboxEditor input[type=range]::-moz-range-track {\n\twidth: 100%;\n\theight: 6px;\n\tcursor: pointer;\n\tbackground: ${$.uiWidgetBackground};\n}\n.beepboxEditor input[type=range]:focus::-moz-range-track {\n\tbackground: ${$.uiWidgetFocus};\n}\n.beepboxEditor input[type=range]::-moz-range-thumb {\n\theight: var(--button-size);\n\twidth: 6px;\n\tborder-radius: 3px;\n\tborder: none;\n\tbackground: currentColor;\n\tcursor: pointer;\n}\n.beepboxEditor input[type=range]::-ms-track {\n\twidth: 100%;\n\theight: 6px;\n\tcursor: pointer;\n\tbackground: ${$.uiWidgetBackground};\n\tborder-color: transparent;\n}\n.beepboxEditor input[type=range]:focus::-ms-track {\n\tbackground: ${$.uiWidgetFocus};\n}\n.beepboxEditor input[type=range]::-ms-thumb {\n\theight: var(--button-size);\n\twidth: 6px;\n\tborder-radius: 3px;\n\tbackground: currentColor;\n\tcursor: pointer;\n}\n\n/* wide screen */\n@media (min-width: 711px) {\n\t#beepboxEditorContainer {\n\t\tdisplay: table;\n\t}\n\t.beepboxEditor {\n\t\tflex-direction: row;\n\t}\n\t.beepboxEditor:focus-within {\n\t\toutline: 3px solid ${$.uiWidgetBackground};\n\t}\n\t.beepboxEditor .trackAndMuteContainer {\n\t\twidth: 512px;\n\t}\n\t.beepboxEditor .play-pause-area {\n\t\tdisplay: flex;\n\t\tflex-direction: column;\n\t}\n\t.beepboxEditor .playback-bar-controls {\n\t\tmargin: 2px 0;\n\t}\n\t.beepboxEditor .playback-volume-controls {\n\t\tdisplay: flex;\n\t\tflex-direction: row;\n\t\tmargin: 2px 0;\n\t\talign-items: center;\n\t}\n\t.beepboxEditor .settings-area {\n\t\twidth: var(--settings-area-width);\n\t}\n}\n\n/* narrow screen */\n@media (max-width: 710px) {\n\t.beepboxEditor {\n\t\tgrid-template-columns: minmax(0, 1fr);\n\t\tgrid-template-rows: min-content 6px min-content min-content;\n\t\tgrid-template-areas: "pattern-area" "." "track-area" "settings-area";\n\t\tgrid-row-gap: 0;\n\t}\n\t.beepboxEditor .settings-area {\n\t\tgrid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n\t\tgrid-template-rows: min-content min-content 1fr min-content;\n\t\tgrid-template-areas:\n\t\t\t"play-pause-area play-pause-area"\n\t\t\t"menu-area instrument-settings-area"\n\t\t\t"song-settings-area instrument-settings-area"\n\t\t\t"version-area version-area";\n\t\tgrid-column-gap: 8px;\n\t\tmargin: 0 4px;\n\t}\n\t.beepboxEditor:focus-within {\n\t\toutline: none;\n\t}\n\t.beepboxEditor .pattern-area {\n\t\tmax-height: 75vh;\n\t}\n\t.beepboxEditor .trackAndMuteContainer {\n\t\toverflow-x: auto;\n\t}\n\t.beepboxEditor .barScrollBar {\n\t\tdisplay: none;\n\t}\n\t.beepboxEditor .play-pause-area {\n\t\tdisplay: grid;\n\t\tgrid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n\t\tgrid-column-gap: 8px;\n\t\tmargin: 2px 0;\n\t}\n\t.beepboxEditor .playback-bar-controls {\n\t\tflex-grow: 1;\n\t}\n\t.beepboxEditor .playback-volume-controls {\n\t\tdisplay: flex;\n\t\tflex-direction: row;\n\t\talign-items: center;\n\t\tflex-grow: 1;\n\t}\n}\n\n`));class U{static setLayout(t){this.h.textContent=this.l[t]}}function V(t,e){for(let i=0;i=2;s--){const i=1<>1,o=i<<1,r=2*Math.PI/o,h=Math.cos(r),a=Math.sin(r),l=2*h;for(let s=0;s16)throw new Error("FFT array length must not be greater than 2^16.");const s=16-i;for(let i=0;i>1|(21845&i)<<1,e=(52428&e)>>2|(13107&e)<<2,e=(61680&e)>>4|(3855&e)<<4,e=(e>>8|(255&e)<<8)>>s,e>i){let s=t[i];t[i]=t[e],t[e]=s}}}(t,e)}U.l={small:"",long:`\t\t\t/* long layout */\n\t\t\t@media (min-width: 711px) {\n\t\t\t\t#beepboxEditorContainer {\n\t\t\t\t\tmax-width: initial;\n\t\t\t\t\theight: 100vh;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor {\n\t\t\t\t\twidth: 100%;\n\t\t\t\t\theight: 100vh;\n\t\t\t\t\tgrid-template-columns: minmax(0, 1fr) 390px; /* minmax(0, 1fr) min-content; Chrome 80 grid layout regression. https://bugs.chromium.org/p/chromium/issues/detail?id=1050307 */\n\t\t\t\t\tgrid-template-rows: minmax(481px, 1fr) minmax(0, min-content);\n\t\t\t\t\tgrid-template-areas: "pattern-area settings-area" "track-area track-area";\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .pattern-area {\n\t\t\t\t\twidth: 100%;\n\t\t\t\t\theight: 100%;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .track-area {\n\t\t\t\t\twidth: 100%;\n\t\t\t\t\tdisplay: flex;\n\t\t\t\t\tflex-direction: column;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackAndMuteContainer {\n\t\t\t\t\twidth: 100%;\n\t\t\t\t\tmin-height: 0;\n\t\t\t\t\tflex: 1;\n\t\t\t\t\toverflow: auto;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .instrument-settings-area {\n\t\t\t\t\toverflow-y: auto;\n\t\t\t\t\tposition: relative;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .instrument-settings-area > .editor-controls {\n\t\t\t\t\tposition: absolute;\n\t\t\t\t\twidth: 100%;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .song-settings-area {\n\t\t\t\t\toverflow-y: auto;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t.beepboxEditor .settings-area {\n\t\t\t\t\twidth: 390px;\n\t\t\t\t\tgrid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n\t\t\t\t\tgrid-template-rows: auto auto auto minmax(0, 1fr);\n\t\t\t\t\tgrid-template-areas:\n\t\t\t\t\t\t"instrument-settings-area version-area"\n\t\t\t\t\t\t"instrument-settings-area play-pause-area"\n\t\t\t\t\t\t"instrument-settings-area menu-area"\n\t\t\t\t\t\t"instrument-settings-area song-settings-area";\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t.beepboxEditor .barScrollBar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackContainer {\n\t\t\t\t\toverflow: visible;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackAndMuteContainer {\n\t\t\t\t\tscrollbar-width: auto;\n\t\t\t\t\tscrollbar-color: ${$.uiWidgetBackground} ${$.editorBackground};\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackAndMuteContainer::-webkit-scrollbar {\n\t\t\t\t\twidth: 20px;\n\t\t\t\t\theight: 20px;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackAndMuteContainer::-webkit-scrollbar-track {\n\t\t\t\t\tbackground: ${$.editorBackground};\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackAndMuteContainer::-webkit-scrollbar-thumb {\n\t\t\t\t\tbackground-color: ${$.uiWidgetBackground};\n\t\t\t\t\tborder: 3px solid ${$.editorBackground};\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackAndMuteContainer::-webkit-scrollbar-corner {\n\t\t\t\t\tbackground-color: ${$.editorBackground};\n\t\t\t\t}\n\t\t\t}\n\t\t`,tall:`\t\t\t/* tall layout */\n\t\t\t@media (min-width: 711px) {\n\t\t\t\t#beepboxEditorContainer {\n\t\t\t\t\tmax-width: initial;\n\t\t\t\t\theight: 100vh;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor {\n\t\t\t\t\twidth: 100%;\n\t\t\t\t\theight: 100vh;\n\t\t\t\t\tgrid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 192px;\n\t\t\t\t\tgrid-template-rows: 1fr;\n\t\t\t\t\tgrid-template-areas: "track-area pattern-area settings-area";\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .pattern-area {\n\t\t\t\t\twidth: 100%;\n\t\t\t\t\theight: 100%;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .track-area {\n\t\t\t\t\twidth: 100%;\n\t\t\t\t\theight: 100%;\n\t\t\t\t\tdisplay: flex;\n\t\t\t\t\tflex-direction: column;\n\t\t\t\t\tjustify-content: center;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackAndMuteContainer {\n\t\t\t\t\twidth: 100%;\n\t\t\t\t\tmin-height: 0;\n\t\t\t\t\tflex: 0;\n\t\t\t\t\toverflow: auto;\n\t\t\t\t\tflex-basis: initial;\n\t\t\t\t\tflex-grow: 0;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .instrument-settings-area > .editor-controls {\n\t\t\t\t\tposition: absolute;\n\t\t\t\t\twidth: 100%;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t.beepboxEditor .settings-area {\n\t\t\t\t\twidth: 192px;\n\t\t\t\t\tposition: relative;\n\t\t\t\t\toverflow-y: auto;\n\t\t\t\t\tgrid-template-columns: minmax(0, 1fr);\n\t\t\t\t\tgrid-template-rows: auto auto auto auto minmax(0, 1fr);\n\t\t\t\t\tgrid-template-areas:\n\t\t\t\t\t\t"version-area"\n\t\t\t\t\t\t"play-pause-area"\n\t\t\t\t\t\t"menu-area"\n\t\t\t\t\t\t"song-settings-area"\n\t\t\t\t\t\t"instrument-settings-area";\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .version-area {\n\t\t\t\t\tposition: sticky;\n\t\t\t\t\ttop: 0;\n\t\t\t\t\tz-index: 1;\n\t\t\t\t\tbackground: ${$.editorBackground};\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .play-pause-area {\n\t\t\t\t\tposition: sticky;\n\t\t\t\t\ttop: 22px;\n\t\t\t\t\tz-index: 1;\n\t\t\t\t\tbackground: ${$.editorBackground};\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .menu-area {\n\t\t\t\t\tposition: sticky;\n\t\t\t\t\ttop: 82px;\n\t\t\t\t\tz-index: 1;\n\t\t\t\t\tbackground: ${$.editorBackground};\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t.beepboxEditor .barScrollBar {\n\t\t\t\t\tdisplay: none;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackContainer {\n\t\t\t\t\toverflow: visible;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackAndMuteContainer {\n\t\t\t\t\tscrollbar-width: auto;\n\t\t\t\t\tscrollbar-color: ${$.uiWidgetBackground} ${$.editorBackground};\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackAndMuteContainer::-webkit-scrollbar {\n\t\t\t\t\twidth: 20px;\n\t\t\t\t\theight: 20px;\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackAndMuteContainer::-webkit-scrollbar-track {\n\t\t\t\t\tbackground: ${$.editorBackground};\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackAndMuteContainer::-webkit-scrollbar-thumb {\n\t\t\t\t\tbackground-color: ${$.uiWidgetBackground};\n\t\t\t\t\tborder: 3px solid ${$.editorBackground};\n\t\t\t\t}\n\t\t\t\t.beepboxEditor .trackAndMuteContainer::-webkit-scrollbar-corner {\n\t\t\t\t\tbackground-color: ${$.editorBackground};\n\t\t\t\t}\n\t\t\t}\n\t\t`},U.h=document.head.appendChild(D.style({type:"text/css"}));class K{constructor(){this.u=1,this.m=[void 0],this.g=0,this.v=0,this.k=0}pushFront(t){this.k>=this.u&&this.M(),this.v=this.v-1&this.g,this.m[this.v]=t,this.k++}pushBack(t){this.k>=this.u&&this.M(),this.m[this.v+this.k&this.g]=t,this.k++}popFront(){if(this.k<=0)throw new Error("No elements left to pop.");const t=this.m[this.v];return this.m[this.v]=void 0,this.v=this.v+1&this.g,this.k--,t}popBack(){if(this.k<=0)throw new Error("No elements left to pop.");this.k--;const t=this.v+this.k&this.g,e=this.m[t];return this.m[t]=void 0,e}peakFront(){if(this.k<=0)throw new Error("No elements left to pop.");return this.m[this.v]}peakBack(){if(this.k<=0)throw new Error("No elements left to pop.");return this.m[this.v+this.k-1&this.g]}count(){return this.k}set(t,e){if(t<0||t>=this.k)throw new Error("Invalid index");this.m[this.v+t&this.g]=e}get(t){if(t<0||t>=this.k)throw new Error("Invalid index");return this.m[this.v+t&this.g]}remove(t){if(t<0||t>=this.k)throw new Error("Invalid index");if(t<=this.k>>1){for(;t>0;)this.set(t,this.get(t-1)),t--;this.popFront()}else{for(t++;t=1073741824)throw new Error("Capacity too big.");this.u=this.u<<1;const t=this.m,e=new Array(this.u),i=0|this.k,s=0|this.v;for(let n=0;n=1?s:1/s),o=Math.tan(.5*n),r=1+o/s;this.b[0]=(1+o*s)/r,this.b[1]=this.a[1]=-2*Math.cos(t)/r,this.b[2]=(1-o*s)/r,this.a[2]=(1-o/s)/r,this.order=2}}class J{constructor(){this.real=0,this.imag=0,this.denom=1}analyze(t,e){this.analyzeComplex(t,Math.cos(e),Math.sin(e))}analyzeComplex(t,e,i){const s=t.a,n=t.b,o=e,r=-i;let h=n[0]+n[1]*o,a=n[1]*r,l=1+s[1]*o,c=s[1]*r,u=o,f=r;for(let e=2;e<=t.order;e++){const t=u*r+f*o;u=u*o-f*r,f=t,h+=n[e]*u,a+=n[e]*f,l+=s[e]*u,c+=s[e]*f}this.denom=l*l+c*c,this.real=h*l+a*c,this.imag=a*l-h*c}magnitude(){return Math.sqrt(this.real*this.real+this.imag*this.imag)/this.denom}angle(){return Math.atan2(this.imag,this.real)}}class Q{constructor(){this.a1=0,this.a2=0,this.b0=1,this.b1=0,this.b2=0,this.a1Delta=0,this.a2Delta=0,this.b0Delta=0,this.b1Delta=0,this.b2Delta=0,this.output1=0,this.output2=0,this.useMultiplicativeInputCoefficients=!1}resetOutput(){this.output1=0,this.output2=0}loadCoefficientsWithGradient(t,e,i,s){if(2!=t.order||2!=e.order)throw new Error;this.a1=t.a[1],this.a2=t.a[2],this.b0=t.b[0],this.b1=t.b[1],this.b2=t.b[2],this.a1Delta=(e.a[1]-t.a[1])*i,this.a2Delta=(e.a[2]-t.a[2])*i,s?(this.b0Delta=Math.pow(e.b[0]/t.b[0],i),this.b1Delta=Math.pow(e.b[1]/t.b[1],i),this.b2Delta=Math.pow(e.b[2]/t.b[2],i)):(this.b0Delta=(e.b[0]-t.b[0])*i,this.b1Delta=(e.b[1]-t.b[1])*i,this.b2Delta=(e.b[2]-t.b[2])*i),this.useMultiplicativeInputCoefficients=s}}function X(t){return 2*Math.atan(.5*t)}const Z=1e-24;function tt(t,e,i){return i<=(e-=1)?i>=t?i:t:e}function et(t,e,i){if(t<=i&&i<=e)return i;throw new Error(`Value ${i} not in range [${t}, ${e}]`)}const it=[48,49,50,51,52,53,54,55,56,57,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,45,95],st=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,62,62,0,0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,0,0,0,0,63,0,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,0,0,0,0,0];class nt{constructor(t,e,i){this.S=[],this.P=0;for(let s=e;s>5&1),this.S.push(e>>4&1),this.S.push(e>>3&1),this.S.push(e>>2&1),this.S.push(e>>1&1),this.S.push(1&e)}}read(t){let e=0;for(;t>0;)e<<=1,e+=this.S[this.P++],t--;return e}readLongTail(t,e){let i=t,s=e;for(;this.S[this.P++];)i+=1<0;)s--,this.S[this.P++]&&(i+=1<=0;)this.S[this.I++]=e>>>t&1,t--}writeLongTail(t,e,i){if(i=1<0;)s--,this.S[this.I++]=i>>>s&1}writePartDuration(t){this.writeLongTail(1,3,t)}writePinCount(t){this.writeLongTail(1,0,t)}writePitchInterval(t){t<0?(this.write(1,1),this.writeLongTail(1,3,-t)):(this.write(1,0),this.writeLongTail(1,3,t))}concat(t){for(let e=0;et);e++);return e}}class at{constructor(){this.notes=[],this.instruments=[0]}cloneNotes(){const t=[];for(const e of this.notes)t.push(e.clone());return t}reset(){this.notes.length=0,this.instruments[0]=0,this.instruments.length=1}toJsonObject(t){const i=[];for(const s of this.notes){const n=[];for(const i of s.pins)n.push({tick:(i.time+s.start)*e.rhythms[t.rhythm].stepsPerBeat/e.partsPerBeat,pitchBend:i.interval,volume:Math.round(100*i.size/3)});const o={pitches:s.pitches,points:n};0==s.start&&(o.continuesLastPattern=s.continuesLastPattern),i.push(o)}const s={notes:i};return t.patternInstruments&&(s.instruments=this.instruments.map((t=>t+1))),s}fromJsonObject(t,i,s,n,o){if(i.patternInstruments)if(Array.isArray(t.instruments)){const n=t.instruments,o=tt(e.instrumentCountMin,i.getMaxInstrumentsPerPatternForChannel(s)+1,n.length);for(let t=0;t0){const s=Math.min(i.beatsPerBar*e.partsPerBeat,t.notes.length>>>0);let r=0;for(let h=0;h=s);h++){const s=t.notes[h];if(!(s&&s.pitches&&s.pitches.length>=1&&s.points&&s.points.length>=2))continue;const a=new ht(0,0,0,0);a.pitches=[],a.pins=[];for(let t=0;t=e.maxChordSize))break}if(a.pitches.length<1)continue;let l=r,c=0;for(let t=0;ti.beatsPerBar*e.partsPerBeat)){if(0==a.pins.length){if(hu)&&(a.pitches.splice(t,1),t--),a.pitches[t]p&&(p=a.pitches[t]);if(!(a.pitches.length<1)){for(let t=0;tu&&(e.interval=u-p),t>=2&&e.interval==a.pins[t-1].interval&&e.interval==a.pins[t-2].interval&&e.size==a.pins[t-1].size&&e.size==a.pins[t-2].size&&(a.pins.splice(t-1,1),t--)}0==a.start?a.continuesLastPattern=!0===s.continuesLastPattern:a.continuesLastPattern=!1,this.notes.push(a),r=a.end}}}}}class lt{constructor(t){this.frequency=0,this.amplitude=0,this.reset(t)}reset(t){this.frequency=0,this.amplitude=t<=1?e.operatorAmplitudeMax:0}}class ct{constructor(t){this.spectrum=[],this.hash=-1,this.reset(t)}reset(t){for(let i=0;i=25;this.spectrum[i]=t?Math.max(0,Math.round(e.spectrumMax*(1-i/30))):0}this.markCustomWaveDirty()}markCustomWaveDirty(){const t=Ft.fittingPowerOfTwo(e.spectrumMax+2)-1;let i=0;for(const e of this.spectrum)i=i*t+e>>>0;this.hash=i}}class ut{constructor(){this.wave=null,this.T=-1}getCustomWave(t,i){if(this.T==t.hash)return this.wave;this.T=t.hash;const s=e.spectrumNoiseLength;null!=this.wave&&this.wave.length==s+1||(this.wave=new Float32Array(s+1));const n=this.wave;for(let t=0;t=e.spectrumControlPoints?t.spectrum[e.spectrumControlPoints-1]:t.spectrum[i],c=h(i-1);let u=h(i);i>=e.spectrumControlPoints&&(u=14+.25*(u-14)),0==o&&0==l||(a+=.02*r(n,s,c,u,o/e.spectrumMax,l/e.spectrumMax,-.5))}return t.spectrum[e.spectrumControlPoints-1]>0&&(a+=.02*r(n,s,14+.25*(h(e.spectrumControlPoints)-14),14,t.spectrum[e.spectrumControlPoints-1]/e.spectrumMax,0,-.5)),W(n,s),V(n,5/(Math.sqrt(s)*Math.pow(a,.75))),n[s]=n[0],n}}class ft{constructor(){this.harmonics=[],this.hash=-1,this.reset()}reset(){for(let t=0;t>>0;this.hash=i}}class pt{constructor(){this.wave=null,this.T=-1}getCustomWave(t,i){if(this.T==t.hash&&this.q==i)return this.wave;this.T=t.hash,this.q=i;const n=7==i?e.harmonicsRenderedForPickedString:e.harmonicsRendered,r=e.harmonicsWavelength,h=o(0,null,null);null!=this.wave&&this.wave.length==r+1||(this.wave=new Float32Array(r+1));const a=this.wave;for(let t=0;t=e.harmonicsControlPoints&&(o*=1-(i-e.harmonicsControlPoints)/(n-e.harmonicsControlPoints));const c=o/e.harmonicsMax;let u=Math.pow(2,o-e.harmonicsMax+1)*Math.sqrt(c);i1,o=0==e,r=10==t,h=3==i.type||4==i.type||8==i.type||0==i.type,a=48e3,l=8e3*Math.pow(2,.5*(t-10)),c=Math.min(s,2*Math.PI*l/a);if(1==i.type&&!n&&r);else if(o){const t=3.5,e=c*Math.pow(2,t),i=a*(e/(1+e/Math.PI))/(2*Math.PI),s=dt.getRoundedSettingValueFromHz(i),n=dt.getHzFromSettingValue(s),o=2*Math.PI*n/a,r=new Y;r.lowPass1stOrderSimplified(c);const l=new J;l.analyze(r,o);const u=l.magnitude();let f=Math.log2(u);f=.82*(f+t)-t,h&&(f=Math.min(f,-1));const p=Math.pow(2,f),d=dt.getRoundedSettingValueFromLinearGain(p);this.addPoint(0,s,d)}else{const t=.5/(1-.95*Math.sqrt(Math.max(0,e-1)/6)),i=.5/t,s=c+(c*(c/(2*Math.PI*8e3/a)*Math.pow(i,.9)+1)-c)*i;let o;o=h?a*Math.min(s,c*Math.pow(2,.25))/(2*Math.PI):a*s/(2*Math.PI);const r=dt.getRoundedSettingValueFromHz(o);let l;if(h)l=t;else{const e=new Y;e.lowPass2ndOrderSimplified(c,t);const i=new J;i.analyze(e,s),l=i.magnitude()}n||(l=Math.min(l,Math.sqrt(.5)));const u=dt.getRoundedSettingValueFromLinearGain(l);this.addPoint(0,r,u)}}}class yt{constructor(){this.target=0,this.index=0,this.envelope=0,this.reset()}reset(){this.target=0,this.index=0,this.envelope=0}toJsonObject(){const t={target:e.instrumentAutomationTargets[this.target].name,envelope:e.envelopes[this.envelope].name};return e.instrumentAutomationTargets[this.target].maxCount>1&&(t.index=this.index),t}fromJsonObject(t){this.reset();let i=e.instrumentAutomationTargets.dictionary[t.target];null==i&&(i=e.instrumentAutomationTargets.dictionary.noteVolume),this.target=i.index;let s=e.envelopes.dictionary[t.envelope];null==s&&(s=e.envelopes.dictionary.none),this.envelope=s.index,null!=t.index?this.index=tt(0,e.instrumentAutomationTargets[this.target].maxCount,0|t.index):this.index=0}}class gt{constructor(t){this.type=0,this.preset=0,this.chipWave=2,this.chipNoise=1,this.eqFilter=new mt,this.noteFilter=new mt,this.envelopes=[],this.envelopeCount=0,this.fadeIn=0,this.fadeOut=e.fadeOutNeutral,this.transition=e.transitions.dictionary.normal.index,this.pitchShift=0,this.detune=0,this.vibrato=0,this.unison=0,this.effects=0,this.chord=1,this.volume=0,this.pan=e.panCenter,this.pulseWidth=e.pulseWidthRange-1,this.supersawDynamism=e.supersawDynamismMax,this.supersawSpread=Math.ceil(e.supersawSpreadMax/2),this.supersawShape=0,this.stringSustain=10,this.stringSustainType=1,this.distortion=0,this.bitcrusherFreq=0,this.bitcrusherQuantization=0,this.chorus=0,this.reverb=0,this.echoSustain=0,this.echoDelay=0,this.algorithm=0,this.feedbackType=0,this.feedbackAmplitude=0,this.operators=[],this.harmonicsWave=new ft,this.drumsetEnvelopes=[],this.drumsetSpectrumWaves=[],this.spectrumWave=new ct(t);for(let t=0;t>>0),null!=t.volume?this.volume=tt(0,e.volumeRange,Math.round(5-(0|t.volume)/20)):this.volume=0,Array.isArray(t.effects)){let i=0;for(let s=0;se.name==t.wave)),-1==this.chipNoise&&(this.chipNoise=1));const a={custom:"note size",steady:"none","pluck 1":"twang 1","pluck 2":"twang 2","pluck 3":"twang 3"},l=t=>null!=a[t]?e.envelopes.dictionary[a[t]]:e.envelopes.dictionary[t];if(4==this.type&&null!=t.drums)for(let i=0;ie.name==t.wave)),-1==this.chipWave&&(this.chipWave=1)}if(1==this.type){this.algorithm=e.algorithms.findIndex((e=>e.name==t.algorithm)),-1==this.algorithm&&(this.algorithm=0),this.feedbackType=e.feedbacks.findIndex((e=>e.name==t.feedbackType)),-1==this.feedbackType&&(this.feedbackType=0),null!=t.feedbackAmplitude?this.feedbackAmplitude=tt(0,e.operatorAmplitudeMax+1,0|t.feedbackAmplitude):this.feedbackAmplitude=0;for(let i=0;it.name==n.frequency)),-1==s.frequency&&(s.frequency=0),null!=n.amplitude?s.amplitude=tt(0,e.operatorAmplitudeMax+1,0|n.amplitude):s.amplitude=0}}if(null!=t.noteFilter?this.noteFilter.fromJsonObject(t.noteFilter):this.noteFilter.reset(),Array.isArray(t.eqFilter))this.eqFilter.fromJsonObject(t.eqFilter);else{this.eqFilter.reset();const i={},s=8e3,n=11,o=8;if(null!=t.filterCutoffHz?i.filterCutoff=tt(0,n,Math.round(n-1+2*Math.log((0|t.filterCutoffHz)/s)/Math.LN2)):i.filterCutoff=0==this.type?6:10,null!=t.filterResonance?i.filterResonance=tt(0,o,Math.round((o-1)*(0|t.filterResonance)/100)):i.filterResonance=0,i.filterEnvelope=l(t.filterEnvelope),i.pulseEnvelope=l(t.pulseEnvelope),i.feedbackEnvelope=l(t.feedbackEnvelope),Array.isArray(t.operators)){i.operatorEnvelopes=[];for(let s=0;s=e.maxEnvelopeCount);t++){const e=new yt;e.fromJsonObject(i[t]),this.addEnvelope(e.target,e.index,e.envelope)}}}static frequencyFromPitch(t){return 440*Math.pow(2,(t-69)/12)}addEnvelope(t,i,s){if(!this.supportsEnvelopeTarget(t,i))throw new Error;if(this.envelopeCount>=e.maxEnvelopeCount)throw new Error;for(;this.envelopes.length<=this.envelopeCount;)this.envelopes[this.envelopes.length]=new yt;const n=this.envelopes[this.envelopeCount];n.target=t,n.index=i,n.envelope=s,this.envelopeCount++}supportsEnvelopeTarget(t,i){const s=e.instrumentAutomationTargets[t];return(null!=s.computeIndex||"none"==s.name)&&(!(i>=s.maxCount)&&((null==s.compatibleInstruments||-1!=s.compatibleInstruments.indexOf(this.type))&&((null==s.effect||0!=(this.effects&1<=this.noteFilter.controlPointCount))))}clearInvalidEnvelopeTargets(){for(let t=0;t=this.pitchChannelCount}initToDefault(t=!0){if(this.scale=0,this.key=0,this.loopStart=0,this.loopLength=4,this.tempo=150,this.beatsPerBar=8,this.barCount=16,this.patternsPerChannel=8,this.rhythm=1,this.layeredInstruments=!1,this.patternInstruments=!1,t){this.pitchChannelCount=3,this.noiseChannelCount=1;for(let t=0;t=this.pitchChannelCount;this.channels.length<=t&&(this.channels[t]=new bt);const s=this.channels[t];s.octave=i?0:4-t;for(let t=0;t>6],it[63&this.loopStart]),i.push(101,it[this.loopLength-1>>6],it[this.loopLength-1&63]),i.push(116,it[this.tempo>>6],it[63&this.tempo]),i.push(97,it[this.beatsPerBar-1]),i.push(103,it[this.barCount-1>>6],it[this.barCount-1&63]),i.push(106,it[this.patternsPerChannel-1>>6],it[this.patternsPerChannel-1&63]),i.push(114,it[this.rhythm]),i.push(105,it[this.layeredInstruments<<1|this.patternInstruments]),this.layeredInstruments||this.patternInstruments)for(let t=0;t>6],it[63&n.preset]),i.push(102,it[n.eqFilter.controlPointCount]);for(let t=0;t>6],it[63&n.effects]),d(n.effects)){i.push(it[n.noteFilter.controlPointCount]);for(let t=0;t32)throw new Error("Not enough bits to represent sustain value and type in same base64 character.");i.push(73,it[n.stringSustain|n.stringSustainType<<5])}i.push(69,it[n.envelopeCount]);for(let t=0;t1&&i.push(it[n.envelopes[t].index]),i.push(it[n.envelopes[t].envelope])}i.push(98),t=new ot;let s=0;for(;1<0){t.write(1,1);let s=0;for(const r of i.notes){r.start>s&&(t.write(2,0),t.writePartDuration(r.start-s)),n.clear();for(let t=1;t10&&p.pop();const m=r.pitches.concat(l);for(let e=0;e8&&f.pop(),u=e==r.pitches.length-1?r.pitches[0]:i}0==r.start&&t.write(1,r.continuesLastPattern?1:0),s=r.end}s0;)h.unshift(it[63&r]),r>>=6;i.push(it[h.length]),Array.prototype.push.apply(i,h),t.encodeBase64(i);const a=64e3;if(i.lengthwt.L||s1;for(let t=0;t=this.pitchChannelCount;for(let i=this.channels[t].instruments.length;i=this.pitchChannelCount&&(this.channels[s].octave=0)}else if(M)for(let s=0;s=this.pitchChannelCount&&(this.channels[s].octave=0);else{for(let s=0;s=this.channels[P].instruments.length&&(P++,I=0),et(0,this.channels.length-1,P);const s=this.channels[P].instruments[I],n=et(0,8,st[t.charCodeAt(i++)]);s.setTypeAndReset(n,P>=this.pitchChannelCount),a&&(s.effects=0,F>0&&!this.getChannelIsNoise(P)&&(s.reverb=F,s.effects|=1),s.chord!=e.chords.dictionary.simultaneous.index&&(s.effects|=2048))}break;case 117:{const e=st[t.charCodeAt(i++)]<<6|st[t.charCodeAt(i++)];this.channels[P].instruments[I].preset=e}break;case 119:if(n){const s=[1,2,3,4,5,6,7,8,0],n=st[t.charCodeAt(i++)],o=this.channels[n].instruments[0];o.chipWave=tt(0,e.chipWaves.length,0|s[st[t.charCodeAt(i++)]]),o.convertLegacySettings(x[n][0])}else if(h){const s=[1,2,3,4,5,6,7,8,0];for(let n=0;n=this.pitchChannelCount?o.chipNoise=tt(0,e.chipNoises.length,st[t.charCodeAt(i++)]):o.chipWave=tt(0,e.chipWaves.length,0|s[st[t.charCodeAt(i++)]])}else if(a){const s=[1,2,3,4,5,6,7,8,0];P>=this.pitchChannelCount?this.channels[P].instruments[I].chipNoise=tt(0,e.chipNoises.length,st[t.charCodeAt(i++)]):this.channels[P].instruments[I].chipWave=tt(0,e.chipWaves.length,0|s[st[t.charCodeAt(i++)]])}else P>=this.pitchChannelCount?this.channels[P].instruments[I].chipNoise=tt(0,e.chipNoises.length,st[t.charCodeAt(i++)]):this.channels[P].instruments[I].chipWave=tt(0,e.chipWaves.length,st[t.charCodeAt(i++)]);break;case 102:if(M)if(a){const s=[10,6,3,0,8,5,2],o=["none","none","none","none","decay 1","decay 2","decay 3"];if(n){const n=st[t.charCodeAt(i++)],r=this.channels[n].instruments[0],h=x[n][0],a=[1,3,4,5][tt(0,s.length,st[t.charCodeAt(i++)])];h.filterCutoff=s[a],h.filterResonance=0,h.filterEnvelope=e.envelopes.dictionary[o[a]],r.convertLegacySettings(h)}else if(h)for(let n=0;n>5):0}break;case 100:if(M){const s=[{transition:"interrupt",fadeInSeconds:0,fadeOutTicks:-1},{transition:"normal",fadeInSeconds:0,fadeOutTicks:-3},{transition:"normal",fadeInSeconds:.025,fadeOutTicks:-3},{transition:"slide in pattern",fadeInSeconds:.025,fadeOutTicks:-3},{transition:"normal",fadeInSeconds:.04,fadeOutTicks:6},{transition:"normal",fadeInSeconds:0,fadeOutTicks:48},{transition:"normal",fadeInSeconds:.0125,fadeOutTicks:72},{transition:"normal",fadeInSeconds:.06,fadeOutTicks:96}];if(n){const n=st[t.charCodeAt(i++)],o=s[tt(0,s.length,st[t.charCodeAt(i++)])],r=this.channels[n].instruments[0];r.fadeIn=Ft.secondsToFadeInSetting(o.fadeInSeconds),r.fadeOut=Ft.ticksToFadeOutSetting(o.fadeOutTicks),r.transition=e.transitions.dictionary[o.transition].index,r.transition!=e.transitions.dictionary.normal.index&&(r.effects|=1024)}else if(h)for(let n=0;n1&&(o=tt(0,r,st[t.charCodeAt(i++)]));const h=tt(0,e.envelopes.length,st[t.charCodeAt(i++)]);s.addEnvelope(n,o,h)}}}break;case 83:{const s=this.channels[P].instruments[I];if(3==s.type){const n=Math.ceil(e.spectrumControlPoints*e.spectrumControlPointBits/6),o=new nt(t,i,i+n);for(let t=0;t0;)o<<=6,o+=st[t.charCodeAt(i++)],e--}const r=new nt(t,i,i+o);i+=o;const h=wt.getNeededBits(e.noteSizeMax);for(;;){const t=this.channels[s],i=this.getChannelIsNoise(s),o=this.getMaxInstrumentsPerPattern(s),l=wt.getNeededBits(o-e.instrumentCountMin),c=wt.getNeededBits(t.instruments.length-1),u=i?0:12*t.octave;let f=i?4:u;const p=i?[4,6,7,2,3,8,0,10]:[0,7,12,19,24,-5,-12],d=[];for(let t=0;t10&&d.pop(),m.length<=y?(n=new ht(0,u,u+i.length,i.initialSize),m[y++]=n):(n=m[y++],n.start=u,n.end=u+i.length,n.pins[0].size=i.initialSize);let l=0;const c=[];for(let t=0;t0;){for(o++;-1!=p.indexOf(o);)o++;e--}for(;e<0;){for(o--;-1!=p.indexOf(o);)o--;e++}}p.unshift(o),p.length>8&&p.pop(),t=this.getChannelCount())break}}break;default:throw new Error("Unrecognized song tag code "+String.fromCharCode(S)+" at index "+(i-1))}}toJsonObject(t=!0,i=1,s=!0){const n=[];for(let e=0;et.name==s));-1!=n&&(this.scale=n)}if(null!=t.key)if("number"==typeof t.key)this.key=(t.key+1200>>>0)%e.keys.length;else if("string"==typeof t.key){const e=t.key,i=e.charAt(0).toUpperCase(),s=e.charAt(1).toLowerCase();let n={C:0,D:2,E:4,F:5,G:7,A:9,B:11}[i];const o={"#":1,"♯":1,b:-1,"♭":-1}[s];null!=n&&(null!=o&&(n+=o),n<0&&(n+=12),n%=12,this.key=n)}null!=t.beatsPerMinute&&(this.tempo=tt(e.tempoMin,e.tempoMax+1,0|t.beatsPerMinute));let i=0;null!=t.reverb&&(i=tt(0,4,0|t.reverb)),null!=t.beatsPerBar&&(this.beatsPerBar=Math.max(e.beatsPerBarMin,Math.min(e.beatsPerBarMax,0|t.beatsPerBar)));let s=4;null!=t.ticksPerBeat&&(s=0|t.ticksPerBeat||4,this.rhythm=e.rhythms.findIndex((t=>t.stepsPerBeat==s)),-1==this.rhythm&&(this.rhythm=1));let n=1,o=1,r=1;if(null!=t.channels)for(const e of t.channels)e.instruments&&(n=Math.max(n,0|e.instruments.length)),e.patterns&&(o=Math.max(o,0|e.patterns.length)),e.sequence&&(r=Math.max(r,0|e.sequence.length));null!=t.layeredInstruments?this.layeredInstruments=!!t.layeredInstruments:this.layeredInstruments=!1,null!=t.patternInstruments?this.patternInstruments=!!t.patternInstruments:this.patternInstruments=n>1,this.patternsPerChannel=Math.min(o,e.barCountMax),this.barCount=Math.min(r,e.barCountMax),null!=t.introBars&&(this.loopStart=tt(0,this.barCount,0|t.introBars)),null!=t.loopBars&&(this.loopLength=tt(1,this.barCount-this.loopStart+1,0|t.loopBars));const h=[],a=[];if(null!=t.channels)for(let n=0;n=3,l?a.push(r):h.push(r),null!=o.octaveScrollBar&&(r.octave=tt(0,e.pitchOctaves,1+(0|o.octaveScrollBar)),l&&(r.octave=0)),Array.isArray(o.instruments)){const t=o.instruments;for(let e=0;e=this.getMaxInstrumentsPerChannel());e++){const s=new gt(l);r.instruments[e]=s,s.fromJsonObject(t[e],l,i)}}for(let t=0;t>>0):0;r.bars.length=this.barCount}h.length>e.pitchChannelCountMax&&(h.length=e.pitchChannelCountMax),a.length>e.noiseChannelCountMax&&(a.length=e.noiseChannelCountMax),this.pitchChannelCount=h.length,this.noiseChannelCount=a.length,this.channels.length=0,Array.prototype.push.apply(this.channels,h),Array.prototype.push.apply(this.channels,a)}getPattern(t,e){if(e<0||e>=this.barCount)return null;const i=this.channels[t].bars[e];return 0==i?null:this.channels[t].patterns[i-1]}getBeatsPerMinute(){return this.tempo}static getNeededBits(t){return 32-Math.clz32(Math.ceil(t+1)-1)}}wt.R="BeepBox",wt.N=2,wt.L=9;class vt{constructor(){this.delayLine=null,this.allPassG=0,this.allPassGDelta=0,this.sustainFilterA1=0,this.sustainFilterA1Delta=0,this.sustainFilterA2=0,this.sustainFilterA2Delta=0,this.sustainFilterB0=0,this.sustainFilterB0Delta=0,this.sustainFilterB1=0,this.sustainFilterB1Delta=0,this.sustainFilterB2=0,this.sustainFilterB2Delta=0,this.reset()}reset(){this.delayIndex=-1,this.allPassSample=0,this.allPassPrevInput=0,this.sustainFilterSample=0,this.sustainFilterPrevOutput2=0,this.sustainFilterPrevInput1=0,this.sustainFilterPrevInput2=0,this.fractionalDelaySample=0,this.prevDelayLength=-1,this.delayResetOffset=0}update(t,i,s,n,o,r,h,a){const l=2*Math.PI*e.pickedStringDispersionCenterFreq/t.samplesPerSecond,c=this.prevDelayLength,u=s.phaseDeltas[n],f=s.phaseDeltaScales[n],p=u*Math.pow(f,o),d=2*Math.PI*u,m=2*Math.PI*p,y=2*d,g=2*m,b=Math.min(Math.PI,d*e.pickedStringDispersionFreqMult*Math.pow(l/d,e.pickedStringDispersionFreqScale)),w=Math.min(Math.PI,m*e.pickedStringDispersionFreqMult*Math.pow(l/m,e.pickedStringDispersionFreqScale)),v=2*Math.PI*e.pickedStringShelfHz/t.samplesPerSecond,k=(Math.pow(100,r)-1)/99,M=(Math.pow(100,h)-1)/99,x=1==a?.25:0,S=15.6,F=3*t.samplesPerSecond/48e3,P=Math.pow(.5,k*Math.pow(v/(d*S),1+2*x)*S),I=Math.pow(.5,M*Math.pow(v/(m*S),1+2*x)*S),T=Math.pow(P,.002),q=Math.pow(I,.002);Ft.tempFilterStartCoefficients.allPass1stOrderInvertPhaseAbove(b),t.tempFrequencyResponse.analyze(Ft.tempFilterStartCoefficients,y);const E=Ft.tempFilterStartCoefficients.b[0],C=-t.tempFrequencyResponse.angle()/y;Ft.tempFilterEndCoefficients.allPass1stOrderInvertPhaseAbove(w),t.tempFrequencyResponse.analyze(Ft.tempFilterEndCoefficients,g);const L=Ft.tempFilterEndCoefficients.b[0],z=-t.tempFrequencyResponse.angle()/g,D=0==a?0:1;if(0==D){const t=Math.pow(P,e.stringDecayRate),i=Math.pow(I,e.stringDecayRate);Ft.tempFilterStartCoefficients.highShelf2ndOrder(v,t,.5),Ft.tempFilterEndCoefficients.highShelf2ndOrder(v,i,.5)}else{const e=Math.pow(1==D?0:1,.25),i=Math.pow(F*F*d*3.3*48e3/t.samplesPerSecond,.5+x)/F/Math.pow(k,.5),s=Math.pow(F*F*m*3.3*48e3/t.samplesPerSecond,.5+x)/F/Math.pow(M,.5),n=i*Math.pow(2,.5-1.75*(1-Math.pow(1-e,.85))),o=s*Math.pow(2,.5-1.75*(1-Math.pow(1-e,.85))),r=Math.pow(2,-Math.pow(2,-Math.pow(e,.9))),h=Math.pow(2,-Math.pow(2,-Math.pow(e,.9)));Ft.tempFilterStartCoefficients.lowPass2ndOrderButterworth(X(n),r),Ft.tempFilterEndCoefficients.lowPass2ndOrderButterworth(X(o),h)}t.tempFrequencyResponse.analyze(Ft.tempFilterStartCoefficients,y);const A=Ft.tempFilterStartCoefficients.a[1],B=Ft.tempFilterStartCoefficients.a[2],O=Ft.tempFilterStartCoefficients.b[0]*T,N=Ft.tempFilterStartCoefficients.b[1]*T,R=Ft.tempFilterStartCoefficients.b[2]*T,H=-t.tempFrequencyResponse.angle()/y;t.tempFrequencyResponse.analyze(Ft.tempFilterEndCoefficients,g);const G=Ft.tempFilterEndCoefficients.a[1],$=Ft.tempFilterEndCoefficients.a[2],_=Ft.tempFilterEndCoefficients.b[0]*q,U=Ft.tempFilterEndCoefficients.b[1]*q,V=Ft.tempFilterEndCoefficients.b[2]*q,j=-t.tempFrequencyResponse.angle()/g,W=1/u,K=1/p,Y=Math.ceil(2*Math.max(W,K)),J=W-C-H,Q=K-z-j;this.prevDelayLength=J,this.delayLengthDelta=(Q-J)/o,this.allPassG=E,this.sustainFilterA1=A,this.sustainFilterA2=B,this.sustainFilterB0=O,this.sustainFilterB1=N,this.sustainFilterB2=R,this.allPassGDelta=(L-E)/o,this.sustainFilterA1Delta=(G-A)/o,this.sustainFilterA2Delta=($-B)/o,this.sustainFilterB0Delta=(_-O)/o,this.sustainFilterB1Delta=(U-N)/o,this.sustainFilterB2Delta=(V-R)/o;const Z=Math.abs(Math.log2(J/c))>.01,tt=-1==this.delayIndex||Z;if(null==this.delayLine||this.delayLine.length<=Y){const e=Math.ceil(2*t.samplesPerSecond/gt.frequencyFromPitch(12)),i=new Float32Array(Ft.fittingPowerOfTwo(Math.max(e,Y)));if(!tt&&null!=this.delayLine){const t=this.delayLine.length-1>>0,e=this.delayIndex+this.delayResetOffset;this.delayIndex=this.delayLine.length-this.delayResetOffset;for(let s=0;s>0;if(tt){this.delayIndex=0,this.allPassSample=0,this.allPassPrevInput=0,this.sustainFilterSample=0,this.sustainFilterPrevOutput2=0,this.sustainFilterPrevInput1=0,this.sustainFilterPrevInput2=0,this.fractionalDelaySample=0;const e=-J,s=Math.floor(e-W/2),n=Math.ceil(s+2*W);this.delayResetOffset=n;for(let t=s;t<=n;t++)et[t&it]=0;const o=i.wave,r=o.length-1,h=r/W,a=Math.min(.2*W,.003*t.samplesPerSecond),l=Math.ceil(e),c=e+W+a,u=c;let f=(l-e)*h,p=0;for(let t=l;t<=u;t++){const i=0|f,s=i%r;let n=o[s];const l=f-i;n+=(o[s+1]-n)*l;const u=(n-p)/h,d=Math.min(1,(t-e)/a)*Math.min(1,(c-t)/a),m=d*d*(3-2*d);et[t&it]+=u*m,p=n,f+=h}}}}class kt{constructor(){this.noteSecondsStart=0,this.noteSecondsEnd=0,this.noteTicksStart=0,this.noteTicksEnd=0,this.noteSizeStart=e.noteSizeMax,this.noteSizeEnd=e.noteSizeMax,this.prevNoteSize=e.noteSizeMax,this.nextNoteSize=e.noteSizeMax,this.H=e.noteSizeMax,this.prevNoteSecondsStart=0,this.prevNoteSecondsEnd=0,this.prevNoteTicksStart=0,this.prevNoteTicksEnd=0,this.$=e.noteSizeMax,this.prevSlideStart=!1,this.prevSlideEnd=!1,this.nextSlideStart=!1,this.nextSlideEnd=!1,this.prevSlideRatioStart=0,this.prevSlideRatioEnd=0,this.nextSlideRatioStart=0,this.nextSlideRatioEnd=0,this.envelopeStarts=[],this.envelopeEnds=[],this._=[],this.U=0,this.lowpassCutoffDecayVolumeCompensation=1;for(let t=0;t<36;t++)this.envelopeStarts[t]=1,this.envelopeEnds[t]=1;this.reset()}reset(){this.noteSecondsEnd=0,this.noteTicksEnd=0,this.H=e.noteSizeMax,this.prevNoteSecondsEnd=0,this.prevNoteTicksEnd=0,this.$=e.noteSizeMax,this.U=0}computeEnvelopes(t,i,s,n,o){const r=t.getTransition();null==o||!o.atNoteStart||r.continues||o.forceContinueAtStart||(this.prevNoteSecondsEnd=this.noteSecondsEnd,this.prevNoteTicksEnd=this.noteTicksEnd,this.$=this.H,this.noteSecondsEnd=0,this.noteTicksEnd=0),null!=o&&(null!=o.note?this.H=o.note.pins[o.note.pins.length-1].size:this.H=e.noteSizeMax);const h=s+1,a=this.noteSecondsEnd,l=a+n,c=this.noteTicksEnd,u=c+1,f=this.prevNoteSecondsEnd,p=f+n,d=this.prevNoteTicksEnd,m=d+1,y=1/(e.ticksPerPart*e.partsPerBeat),g=y*s,b=y*h;let w=this.H,v=this.H,k=this.$,M=0,x=!1,S=!1,F=!1,P=!1,I=0,T=0,q=0,E=0;if(null!=o&&null!=o.note&&!o.passedEndOfNote){const t=o.note.getEndPinIndex(i),n=o.note.pins[t-1],a=o.note.pins[t],l=(o.note.start+n.time)*e.ticksPerPart,c=(o.note.start+a.time)*e.ticksPerPart,u=(s-l)/(c-l),f=(h-l)/(c-l);if(w=n.size+(a.size-n.size)*u,v=n.size+(a.size-n.size)*f,r.slides){const t=o.noteStartPart*e.ticksPerPart,i=o.noteEndPart*e.ticksPerPart,n=.5*(i-t),a=Math.min(n,r.slideTicks);null==o.prevNote||o.forceContinueAtStart||(s-tn&&0==e.controlPoints[n].type&&(C=Math.max(C,kt.getLowpassCutoffDecayVolumeCompensation(o)))}}}this.noteSecondsStart=a,this.noteSecondsEnd=l,this.noteTicksStart=c,this.noteTicksEnd=u,this.prevNoteSecondsStart=f,this.prevNoteSecondsEnd=p,this.prevNoteTicksStart=d,this.prevNoteTicksEnd=m,this.prevNoteSize=k,this.nextNoteSize=M,this.noteSizeStart=w,this.noteSizeEnd=v,this.prevSlideStart=x,this.prevSlideEnd=S,this.nextSlideStart=F,this.nextSlideEnd=P,this.prevSlideRatioStart=I,this.prevSlideRatioEnd=T,this.nextSlideRatioStart=q,this.nextSlideRatioEnd=E,this.lowpassCutoffDecayVolumeCompensation=C}clearEnvelopes(){for(let t=0;t>1,i.echoDelay+1),n=2*Ft.fittingPowerOfTwo(t*e.echoDelayStepTicks*s);if(null==this.echoDelayLineL||null==this.echoDelayLineR)this.echoDelayLineL=new Float32Array(n),this.echoDelayLineR=new Float32Array(n);else if(this.echoDelayLineL.length=i&&(this.deactivateAfterThisTick=!0)}else{0==this.attentuationProgress||(S=0),F=0;const t=1/256,i=-Math.log2(t);let n=0;if(u&&(n+=e.chorusMaxDelay),f){const t=Math.pow(T,1/q);n+=-1/Math.log2(t)*i}if(p){const t=2*E,s=e.reverbDelayBufferSize/4/h,o=Math.pow(t,1/s);n+=-1/Math.log2(o)*i}const o=s/h/n,r=this.attentuationProgress+o;r>=1&&(I=0),this.attentuationProgress=r,this.attentuationProgress>=1&&(this.flushingDelayLines=!0)}this.eqFilterVolume=S,this.eqFilterVolumeDelta=(F-S)/n,this.delayInputMult=P,this.delayInputMultDelta=(I-P)/n}updateWaves(t,i){if(0==t.type)this.wave=e.chipWaves[t.chipWave].samples;else if(2==t.type)this.wave=o(t.chipNoise,W,V);else if(5==t.type)this.wave=this.harmonicsWave.getCustomWave(t.harmonicsWave,t.type);else if(7==t.type)this.wave=this.harmonicsWave.getCustomWave(t.harmonicsWave,t.type);else if(3==t.type)this.wave=this.spectrumWave.getCustomWave(t.spectrumWave,8);else if(4==t.type){for(let i=0;i{const e=t.outputBuffer,i=e.getChannelData(0),s=e.getChannelData(1);if(!this.browserAutomaticallyClearsAudioBuffer||0==i[0]&&0==s[0]&&0==i[e.length-1]&&0==s[e.length-1]||(this.browserAutomaticallyClearsAudioBuffer=!1),!this.browserAutomaticallyClearsAudioBuffer){const t=e.length;for(let e=0;e=this.liveInputEndTime?this.deactivateAudio():this.synthesize(i,s,e.length,this.isPlayingSong)},this.computeDelayBufferSizes(),null!=t&&this.setSong(t)}syncSongState(){const t=this.song.getChannelCount();for(let e=this.channels.length;e=this.song.loopStart+this.song.loopLength)){const t=this.bar;this.bar=this.song.loopStart,this.playheadInternal+=this.bar-t,this.prevBar=null}}goToNextBar(){if(!this.song)return;this.prevBar=this.bar;const t=this.bar;this.bar++,this.bar>=this.song.barCount&&(this.bar=0),this.playheadInternal+=this.bar-t}goToPrevBar(){if(!this.song)return;this.prevBar=null;const t=this.bar;this.bar--,(this.bar<0||this.bar>=this.song.barCount)&&(this.bar=this.song.barCount-1),this.playheadInternal+=this.bar-t}getNextBar(){let t=this.bar+1;return this.isRecording?t>=this.song.barCount&&(t=this.song.barCount-1):0!=this.loopRepeatCount&&t==this.song.loopStart+this.song.loopLength&&(t=this.song.loopStart),t}synthesize(t,i,s,n=!0){if(null==this.song){for(let e=0;er)&&(this.tickSampleCountdown=r,this.isAtStartOfTick=!0),n&&(this.beat>=o.beatsPerBar&&(this.beat=0,this.part=0,this.tick=0,this.tickSampleCountdown=r,this.isAtStartOfTick=!0,this.prevBar=this.bar,this.bar=this.getNextBar(),this.bar<=this.prevBar&&this.loopRepeatCount>0&&this.loopRepeatCount--),this.bar>=o.barCount&&(this.bar=0,-1!=this.loopRepeatCount&&(h=!0,this.pause()))),this.syncSongState(),(null==this.tempMonoInstrumentSampleBuffer||this.tempMonoInstrumentSampleBuffer.length=o.barCount&&(this.nextBar=null);const p=s-f,d=Math.ceil(this.tickSampleCountdown),m=Math.min(d,p),y=f+m;for(let s=0;s=Math.abs(l.getFadeOutTicks())){this.freeReleasedTone(c,i),i--;continue}const h=t>=e.maximumTonesPerChannel;this.computeTone(o,s,r,n,!0,h),t++}c.awake&&(c.computed||c.compute(this,l,r,Math.ceil(r),null),c.computed=!1)}for(let t=0;t4&&o.beatsPerBar%2==0&&this.beat==o.beatsPerBar/2,e=0==this.beat?8:t?6:4,i=0==this.beat?1600:t?1200:800,s=0==this.beat?.06:t?.05:.04,n=this.samplesPerSecond/i,r=2*Math.PI/n;this.metronomeSamplesRemaining=Math.floor(n*e),this.metronomeFilter=2*Math.cos(r),this.metronomeAmplitude=s*Math.sin(r),this.metronomePrevAmplitude=0,this.startedMetronome=!0}if(this.metronomeSamplesRemaining>0){const e=Math.min(y,f+this.metronomeSamplesRemaining);this.metronomeSamplesRemaining-=e-f;for(let s=f;s=1?1.05*u:.8*u+.25);t[e]=s*r,i[e]=n*r}if(f+=m,this.isAtStartOfTick=!1,this.tickSampleCountdown-=m,this.tickSampleCountdown<=0){this.isAtStartOfTick=!0;for(const t of this.channels)for(const e of t.instruments){for(let t=0;t0&&this.loopRepeatCount--,this.bar>=o.barCount&&(this.bar=0,-1!=this.loopRepeatCount&&(h=!0,this.resetEffects(),this.pause())))))))}}(!Number.isFinite(u)||Math.abs(u)0){const t=this.tonePool.popBack();return t.freshlyAllocated=!0,t}return new Mt}releaseTone(t,e){t.releasedTones.pushFront(e),e.atNoteStart=!1,e.passedEndOfNote=!0}freeReleasedTone(t,e){this.freeTone(t.releasedTones.get(e)),t.releasedTones.remove(e)}freeAllTones(){for(const t of this.channels)for(const e of t.instruments){for(;e.activeTones.count()>0;)this.freeTone(e.activeTones.popBack());for(;e.releasedTones.count()>0;)this.freeTone(e.releasedTones.popBack());for(;e.liveInputTones.count()>0;)this.freeTone(e.liveInputTones.popBack())}}determineLiveInputTones(t,e,i){const s=t.channels[e],n=this.channels[e],o=this.liveInputPitches;for(let r=0;r0&&e==this.liveInputChannel&&o.length>0&&-1!=this.liveInputInstruments.indexOf(r)){const n=s.instruments[r];if(n.getChord().singleTone){let s;a.count()<=l?(s=this.newTone(),a.pushBack(s)):!n.getTransition().isSeamless&&this.liveInputStarted?(this.releaseTone(h,a.get(l)),s=this.newTone(),a.set(l,s)):s=a.get(l),l++;for(let t=0;tl;)this.releaseTone(h,a.popBack());this.clearTempMatchedPitchTones(l,h)}this.liveInputStarted=!1}adjacentPatternHasCompatibleInstrumentTransition(t,e,i,s,n,o,r,h,a,l){if(t.patternInstruments&&-1==s.instruments.indexOf(n)){if(i.instruments.length>1||s.instruments.length>1)return null;const t=e.instruments[s.instruments[0]];if(l)return t.getChord();const n=t.getTransition();return o.includeAdjacentPatterns&&n.includeAdjacentPatterns&&n.slides==o.slides?t.getChord():null}return l||o.includeAdjacentPatterns?r:null}static adjacentNotesHaveMatchingPitches(t,e){if(t.pitches.length!=e.pitches.length)return!1;const i=t.pins[t.pins.length-1].interval;for(const s of t.pitches)if(-1==e.pitches.indexOf(s+i))return!1;return!0}moveTonesIntoOrderedTempMatchedList(t,e){for(let i=0;i0;){const e=t.popFront();for(let t=0;ta)c=h.notes[t];else if(h.notes[t].start>a){f=h.notes[t];break}null!=c&&(null!=u&&u.end!=c.start&&(u=null),null!=f&&f.start!=c.end&&(f=null))}if(null!=h&&(!t.layeredInstruments||1==o.instruments.length||t.patternInstruments&&1==h.instruments.length)){const e=t.patternInstruments?h.instruments[0]:0;if(null!=r.singleSeamlessInstrument&&r.singleSeamlessInstrument!=e&&r.singleSeamlessInstrument0;)i.activeTones.pushFront(t.activeTones.popBack())}r.singleSeamlessInstrument=e}else r.singleSeamlessInstrument=null;for(let n=0;nr?y:null,f=c,b=S>r?g:null,w=f.start+h,F=!1;if(w>a){if(!(d.count()>r&&(o.isSeamless||k)&&null!=u))break;b=f,f=u,u=null,w=f.start+h,F=!0}let P=f.end;(o.isSeamless||k)&&null!=b&&(P=Math.min(e.partsPerBeat*this.song.beatsPerBar,P+h)),(o.continues||k)&&null!=u||(h+=v.strumParts);const I=e.ticksPerPart*w==l;let T;if(null!=this.tempMatchedPitchTones[m])T=this.tempMatchedPitchTones[m],this.tempMatchedPitchTones[m]=null,d.pushBack(T);else if(d.count()<=m)T=this.newTone(),d.pushBack(T);else if(!I||(o.isSeamless||k)&&null!=u)T=d.get(m);else{const t=d.get(m);t.isOnLastTick?this.freeTone(t):this.releaseTone(p,t),T=this.newTone(),d.set(m,T)}m++,T.pitches[0]=f.pitches[r],T.pitchCount=1,T.chordSize=f.pitches.length,T.instrumentIndex=n,T.note=f,T.noteStartPart=w,T.noteEndPart=P,T.prevNote=u,T.nextNote=b,T.prevNotePitchIndex=r,T.nextNotePitchIndex=r,T.atNoteStart=I,T.passedEndOfNote=F,T.forceContinueAtStart=k&&null!=u,T.forceContinueAtEnd=M&&null!=b,this.computeTone(t,i,s,T,!1,!1)}}}for(;d.count()>m;){const e=d.popBack(),s=t.channels[i];if(e.instrumentIndex=s&&(C=!0)}else if(null==o.note)D=A=1,o.lastInterval=0,o.ticksSinceReleased=0,o.liveInputSamplesHeld+=l;else{const t=o.note,i=o.nextNote,s=o.noteStartPart,n=o.noteEndPart,r=t.getEndPinIndex(q),h=t.pins[r-1],a=t.pins[r],l=s*e.ticksPerPart,c=n*e.ticksPerPart,u=(t.start+h.time)*e.ticksPerPart,f=(t.start+a.time)*e.ticksPerPart;o.ticksSinceReleased=0;const p=q*e.ticksPerPart+this.tick,d=p+1,m=p-l,g=d-l,b=Math.min(1,(p-u)/(f-u)),v=Math.min(1,(d-u)/(f-u));if(D=1,A=1,L=h.interval+(a.interval-h.interval)*b,z=h.interval+(a.interval-h.interval)*v,o.lastInterval=z,!w.isSeamless&&!o.forceContinueAtEnd||null==i){const t=-y.getFadeOutTicks();if(t>0){const e=c-l;D*=Math.min(1,(e-m)/t),A*=Math.min(1,(e-g)/t),d>=l+e&&(C=!0)}}}o.isOnLastTick=C;const $=o.envelopeComputer;$.computeEnvelopes(y,q,e.ticksPerPart*I,s/this.samplesPerSecond,o);const _=o.envelopeComputer.envelopeStarts,U=o.envelopeComputer.envelopeEnds;if(null!=o.note&&w.slides){const t=o.prevNote,e=o.nextNote;if(null!=t){const e=t.pitches[o.prevNotePitchIndex]+t.pins[t.pins.length-1].interval-o.pitches[0];if($.prevSlideStart&&(L+=e*$.prevSlideRatioStart),$.prevSlideEnd&&(z+=e*$.prevSlideRatioEnd),!v.singleTone){const e=t.pitches.length-o.chordSize;$.prevSlideStart&&(B=Ft.computeChordExpression(o.chordSize+e*$.prevSlideRatioStart)),$.prevSlideEnd&&(O=Ft.computeChordExpression(o.chordSize+e*$.prevSlideRatioEnd))}}if(null!=e){const t=e.pitches[o.nextNotePitchIndex]-(o.pitches[0]+o.note.pins[o.note.pins.length-1].interval);if($.nextSlideStart&&(L+=t*$.nextSlideRatioStart),$.nextSlideEnd&&(z+=t*$.nextSlideRatioEnd),!v.singleTone){const t=e.pitches.length-o.chordSize;$.nextSlideStart&&(B=Ft.computeChordExpression(o.chordSize+t*$.nextSlideRatioStart)),$.nextSlideEnd&&(O=Ft.computeChordExpression(o.chordSize+t*$.nextSlideRatioEnd))}}}if(u(y.effects)){const t=e.justIntonationSemitones[y.pitchShift]/M;L+=t*_[14],z+=t*U[14]}if(f(y.effects)){const t=_[15],i=U[15];L+=Ft.detuneToCents((y.detune-e.detuneCenter)*t)*e.pitchesPerOctave/1200,z+=Ft.detuneToCents((y.detune-e.detuneCenter)*i)*e.pitchesPerOctave/1200}if(p(y.effects)){const t=e.vibratos[y.vibrato].delayTicks,i=e.vibratos[y.vibrato].amplitude;let s;if(null!=o.prevVibrato)s=o.prevVibrato;else{if(s=i*Ft.getLFOAmplitude(y,x*I)*_[16],t>0){const e=t-$.noteTicksStart;s*=Math.max(0,Math.min(1,1-e/2))}}let n=i*Ft.getLFOAmplitude(y,x*T)*U[16];if(t>0){const e=t-$.noteTicksEnd;n*=Math.max(0,Math.min(1,1-e/2))}o.prevVibrato=n,L+=s,z+=n}if(!w.isSeamless&&!o.forceContinueAtStart||null==o.prevNote){const t=y.getFadeInSeconds();t>0&&(D*=Math.min(1,$.noteSecondsStart/t),A*=Math.min(1,$.noteSecondsEnd/t))}4==y.type&&null==o.drumsetPitch&&(o.drumsetPitch=o.pitches[0],null!=o.note&&(o.drumsetPitch+=o.note.pickMainInterval()),o.drumsetPitch=Math.max(0,Math.min(e.drumCount-1,o.drumsetPitch)));let V=$.lowpassCutoffDecayVolumeCompensation;if(d(y.effects)){const t=y.noteFilter,e=_[1],i=U[1];for(let s=0;s1&&r){const i=Math.floor((this.tick+this.part*e.ticksPerPart)/e.rhythms[t.rhythm].ticksPerArpeggio);n=o.pitches[h(o.pitchCount,t.rhythm,i)]-o.pitches[0]}const a=e.algorithms[y.algorithm].carrierCount;for(let t=0;t1&&(v.arpeggiates||v.customInterval)){const i=Math.floor((this.tick+this.part*e.ticksPerPart)/e.rhythms[t.rhythm].ticksPerArpeggio);if(v.customInterval){const e=o.pitches[1+h(o.pitchCount-1,t.rhythm,i)]-o.pitches[0];E=Math.pow(2,e/12),o.specialIntervalExpressionMult=Math.pow(2,-e/G)}else r=o.pitches[h(o.pitchCount,t.rhythm,i)]}const a=R+(r+L)*M,c=R+(r+z)*M;let u;u=null!=o.prevPitchExpressions[0]?o.prevPitchExpressions[0]:Math.pow(2,-(a-N)/G);const f=Math.pow(2,-(c-N)/G);o.prevPitchExpressions[0]=f;let p=H*V;if(2==y.type&&(p*=e.chipNoises[y.chipNoise].expression),0==y.type&&(p*=e.chipWaves[y.chipWave].expression),6==y.type){const t=n(y.pulseWidth),e=t*_[2],i=t*U[2];o.pulseWidth=e,o.pulseWidthDelta=(i-e)/l}7==y.type&&(p*=Math.pow(2,.7*(1-y.stringSustain/(e.stringSustainRange-1))));const d=gt.frequencyFromPitch(a);if(0==y.type||5==y.type||7==y.type){const t=e.unisons[y.unison],i=7==y.type?1:t.voices/2;p*=t.expression*i;const n=_[4],r=U[4],h=Math.pow(2,(t.offset+t.spread)*n/12),a=Math.pow(2,(t.offset+t.spread)*r/12),c=Math.pow(2,(t.offset-t.spread)*n/12)*E,u=Math.pow(2,(t.offset-t.spread)*r/12)*E;o.phaseDeltas[0]=d*S*h,o.phaseDeltas[1]=d*S*c,o.phaseDeltaScales[0]=s*Math.pow(a/h,1/l),o.phaseDeltaScales[1]=s*Math.pow(u/c,1/l)}else o.phaseDeltas[0]=d*S,o.phaseDeltaScales[0]=s;let m=1,b=1;if(8==y.type){const t=1/Math.sqrt(e.supersawVoiceCount),s=y.supersawDynamism/e.supersawDynamismMax,r=1-Math.pow(Math.max(0,1-s*_[33]),.2),h=1-Math.pow(Math.max(0,1-s*U[33]),.2),a=Math.pow(2,Math.log2(t)*r),c=Math.pow(2,Math.log2(t)*h),u=Math.sqrt((1/Math.pow(a,2)-1)/(e.supersawVoiceCount-1)),f=Math.sqrt((1/Math.pow(c,2)-1)/(e.supersawVoiceCount-1));o.supersawDynamism=u,o.supersawDynamismDelta=(f-u)/l;const p=-1==o.supersawDelayIndex;if(p){let t=0;for(let i=0;i=0;t--){const e=1-o.phases[t],h=e-r;if(s<0){const t=-s/i;if(t>1)-.5+.025*((2&t)-1))/(e.supersawVoiceCount>>1),1.1)*(2*(1&t)-1);o.supersawUnisonDetunes[t]=Math.pow(2,v*i/12)}const k=y.supersawShape/e.supersawShapeMax,M=k*_[35],x=k*U[35];o.supersawShape=M,o.supersawShapeDelta=(x-M)/l;const F=n(y.pulseWidth),P=F*_[2],I=F*U[2],T=null!=o.supersawPrevPhaseDelta?o.supersawPrevPhaseDelta:d*S,q=d*S*i;o.supersawPrevPhaseDelta=q;const E=P/T,C=I/q;o.supersawDelayLength=E,o.supersawDelayLengthDelta=(C-E)/l;const L=Math.ceil(Math.max(E,C))+2;if(null==o.supersawDelayLine||o.supersawDelayLine.length<=L){const t=Math.ceil(.5*this.samplesPerSecond/gt.frequencyFromPitch(24)),e=new Float32Array(Ft.fittingPowerOfTwo(Math.max(t,L)));if(!p&&null!=o.supersawDelayLine){const t=o.supersawDelayLine.length-1>>0,i=o.supersawDelayIndex;for(let s=0;s=0;i--)for(const n of Ft.operatorSourceTemplate)if(-1!=n.indexOf("/* + operator@Scaled*/")){let o="";for(const s of e.algorithms[t.algorithm].modulatedBy[i])o+=" + operator"+(s-1)+"Scaled";const r=e.feedbacks[t.feedbackType].indices[i];if(r.length>0){o+=" + feedbackMult * (";const t=[];for(const e of r)t.push("operator"+(e-1)+"Output");o+=t.join(" + ")+")"}s.push(n.replace(/\#/g,i+"").replace("/* + operator@Scaled*/",o))}else s.push(n.replace(/\#/g,i+""));else if(-1!=i.indexOf("#"))for(let t=0;t{const e=[];for(let i=0;i0,c=g(r.effects),u=b(r.effects),f=w(r.effects),p=v(r.effects);let d=0;h&&(d|=1),d<<=1,a&&(d|=1),d<<=1,l&&(d|=1),d<<=1,c&&(d|=1),d<<=1,u&&(d|=1),d<<=1,f&&(d|=1),d<<=1,p&&(d|=1);let k=Ft.effectsFunctionCache[d];if(null==k){let t="return (synth, outputDataL, outputDataR, bufferIndex, runLength, instrumentState) => {";const i=u||p||f;t+="\n\t\t\t\tconst tempMonoInstrumentSampleBuffer = synth.tempMonoInstrumentSampleBuffer;\n\t\t\t\t\n\t\t\t\tlet mixVolume = +instrumentState.mixVolume;\n\t\t\t\tconst mixVolumeDelta = +instrumentState.mixVolumeDelta;",i&&(t+="\n\t\t\t\t\n\t\t\t\tlet delayInputMult = +instrumentState.delayInputMult;\n\t\t\t\tconst delayInputMultDelta = +instrumentState.delayInputMultDelta;"),h&&(t+="\n\t\t\t\t\n\t\t\t\tconst distortionBaseVolume = +Config.distortionBaseVolume;\n\t\t\t\tlet distortion = instrumentState.distortion;\n\t\t\t\tconst distortionDelta = instrumentState.distortionDelta;\n\t\t\t\tlet distortionDrive = instrumentState.distortionDrive;\n\t\t\t\tconst distortionDriveDelta = instrumentState.distortionDriveDelta;\n\t\t\t\tconst distortionFractionalResolution = 4.0;\n\t\t\t\tconst distortionOversampleCompensation = distortionBaseVolume / distortionFractionalResolution;\n\t\t\t\tconst distortionFractionalDelay1 = 1.0 / distortionFractionalResolution;\n\t\t\t\tconst distortionFractionalDelay2 = 2.0 / distortionFractionalResolution;\n\t\t\t\tconst distortionFractionalDelay3 = 3.0 / distortionFractionalResolution;\n\t\t\t\tconst distortionFractionalDelayG1 = (1.0 - distortionFractionalDelay1) / (1.0 + distortionFractionalDelay1); // Inlined version of FilterCoefficients.prototype.allPass1stOrderFractionalDelay\n\t\t\t\tconst distortionFractionalDelayG2 = (1.0 - distortionFractionalDelay2) / (1.0 + distortionFractionalDelay2); // Inlined version of FilterCoefficients.prototype.allPass1stOrderFractionalDelay\n\t\t\t\tconst distortionFractionalDelayG3 = (1.0 - distortionFractionalDelay3) / (1.0 + distortionFractionalDelay3); // Inlined version of FilterCoefficients.prototype.allPass1stOrderFractionalDelay\n\t\t\t\tconst distortionNextOutputWeight1 = Math.cos(Math.PI * distortionFractionalDelay1) * 0.5 + 0.5;\n\t\t\t\tconst distortionNextOutputWeight2 = Math.cos(Math.PI * distortionFractionalDelay2) * 0.5 + 0.5;\n\t\t\t\tconst distortionNextOutputWeight3 = Math.cos(Math.PI * distortionFractionalDelay3) * 0.5 + 0.5;\n\t\t\t\tconst distortionPrevOutputWeight1 = 1.0 - distortionNextOutputWeight1;\n\t\t\t\tconst distortionPrevOutputWeight2 = 1.0 - distortionNextOutputWeight2;\n\t\t\t\tconst distortionPrevOutputWeight3 = 1.0 - distortionNextOutputWeight3;\n\t\t\t\t\n\t\t\t\tlet distortionFractionalInput1 = +instrumentState.distortionFractionalInput1;\n\t\t\t\tlet distortionFractionalInput2 = +instrumentState.distortionFractionalInput2;\n\t\t\t\tlet distortionFractionalInput3 = +instrumentState.distortionFractionalInput3;\n\t\t\t\tlet distortionPrevInput = +instrumentState.distortionPrevInput;\n\t\t\t\tlet distortionNextOutput = +instrumentState.distortionNextOutput;"),a&&(t+="\n\t\t\t\t\n\t\t\t\tlet bitcrusherPrevInput = +instrumentState.bitcrusherPrevInput;\n\t\t\t\tlet bitcrusherCurrentOutput = +instrumentState.bitcrusherCurrentOutput;\n\t\t\t\tlet bitcrusherPhase = +instrumentState.bitcrusherPhase;\n\t\t\t\tlet bitcrusherPhaseDelta = +instrumentState.bitcrusherPhaseDelta;\n\t\t\t\tconst bitcrusherPhaseDeltaScale = +instrumentState.bitcrusherPhaseDeltaScale;\n\t\t\t\tlet bitcrusherScale = +instrumentState.bitcrusherScale;\n\t\t\t\tconst bitcrusherScaleScale = +instrumentState.bitcrusherScaleScale;\n\t\t\t\tlet bitcrusherFoldLevel = +instrumentState.bitcrusherFoldLevel;\n\t\t\t\tconst bitcrusherFoldLevelScale = +instrumentState.bitcrusherFoldLevelScale;"),l&&(t+="\n\t\t\t\t\n\t\t\t\tlet filters = instrumentState.eqFilters;\n\t\t\t\tconst filterCount = instrumentState.eqFilterCount|0;\n\t\t\t\tlet initialFilterInput1 = +instrumentState.initialEqFilterInput1;\n\t\t\t\tlet initialFilterInput2 = +instrumentState.initialEqFilterInput2;\n\t\t\t\tconst applyFilters = Synth.applyFilters;"),t+="\n\t\t\t\t\n\t\t\t\tlet eqFilterVolume = +instrumentState.eqFilterVolume;\n\t\t\t\tconst eqFilterVolumeDelta = +instrumentState.eqFilterVolumeDelta;",c&&(t+="\n\t\t\t\t\n\t\t\t\tconst panningMask = synth.panningDelayBufferMask >>> 0;\n\t\t\t\tconst panningDelayLine = instrumentState.panningDelayLine;\n\t\t\t\tlet panningDelayPos = instrumentState.panningDelayPos & panningMask;\n\t\t\t\tlet panningVolumeL = +instrumentState.panningVolumeL;\n\t\t\t\tlet panningVolumeR = +instrumentState.panningVolumeR;\n\t\t\t\tconst panningVolumeDeltaL = +instrumentState.panningVolumeDeltaL;\n\t\t\t\tconst panningVolumeDeltaR = +instrumentState.panningVolumeDeltaR;\n\t\t\t\tlet panningOffsetL = +instrumentState.panningOffsetL;\n\t\t\t\tlet panningOffsetR = +instrumentState.panningOffsetR;\n\t\t\t\tconst panningOffsetDeltaL = 1.0 - instrumentState.panningOffsetDeltaL;\n\t\t\t\tconst panningOffsetDeltaR = 1.0 - instrumentState.panningOffsetDeltaR;"),u&&(t+="\n\t\t\t\t\n\t\t\t\tconst chorusMask = synth.chorusDelayBufferMask >>> 0;\n\t\t\t\tconst chorusDelayLineL = instrumentState.chorusDelayLineL;\n\t\t\t\tconst chorusDelayLineR = instrumentState.chorusDelayLineR;\n\t\t\t\tinstrumentState.chorusDelayLineDirty = true;\n\t\t\t\tlet chorusDelayPos = instrumentState.chorusDelayPos & chorusMask;\n\t\t\t\t\n\t\t\t\tlet chorusVoiceMult = +instrumentState.chorusVoiceMult;\n\t\t\t\tconst chorusVoiceMultDelta = +instrumentState.chorusVoiceMultDelta;\n\t\t\t\tlet chorusCombinedMult = +instrumentState.chorusCombinedMult;\n\t\t\t\tconst chorusCombinedMultDelta = +instrumentState.chorusCombinedMultDelta;\n\t\t\t\t\n\t\t\t\tconst chorusDuration = +Config.chorusPeriodSeconds;\n\t\t\t\tconst chorusAngle = Math.PI * 2.0 / (chorusDuration * synth.samplesPerSecond);\n\t\t\t\tconst chorusRange = synth.samplesPerSecond * Config.chorusDelayRange;\n\t\t\t\tconst chorusOffset0 = synth.chorusDelayBufferSize - Config.chorusDelayOffsets[0][0] * chorusRange;\n\t\t\t\tconst chorusOffset1 = synth.chorusDelayBufferSize - Config.chorusDelayOffsets[0][1] * chorusRange;\n\t\t\t\tconst chorusOffset2 = synth.chorusDelayBufferSize - Config.chorusDelayOffsets[0][2] * chorusRange;\n\t\t\t\tconst chorusOffset3 = synth.chorusDelayBufferSize - Config.chorusDelayOffsets[1][0] * chorusRange;\n\t\t\t\tconst chorusOffset4 = synth.chorusDelayBufferSize - Config.chorusDelayOffsets[1][1] * chorusRange;\n\t\t\t\tconst chorusOffset5 = synth.chorusDelayBufferSize - Config.chorusDelayOffsets[1][2] * chorusRange;\n\t\t\t\tlet chorusPhase = instrumentState.chorusPhase % (Math.PI * 2.0);\n\t\t\t\tlet chorusTap0Index = chorusDelayPos + chorusOffset0 - chorusRange * Math.sin(chorusPhase + Config.chorusPhaseOffsets[0][0]);\n\t\t\t\tlet chorusTap1Index = chorusDelayPos + chorusOffset1 - chorusRange * Math.sin(chorusPhase + Config.chorusPhaseOffsets[0][1]);\n\t\t\t\tlet chorusTap2Index = chorusDelayPos + chorusOffset2 - chorusRange * Math.sin(chorusPhase + Config.chorusPhaseOffsets[0][2]);\n\t\t\t\tlet chorusTap3Index = chorusDelayPos + chorusOffset3 - chorusRange * Math.sin(chorusPhase + Config.chorusPhaseOffsets[1][0]);\n\t\t\t\tlet chorusTap4Index = chorusDelayPos + chorusOffset4 - chorusRange * Math.sin(chorusPhase + Config.chorusPhaseOffsets[1][1]);\n\t\t\t\tlet chorusTap5Index = chorusDelayPos + chorusOffset5 - chorusRange * Math.sin(chorusPhase + Config.chorusPhaseOffsets[1][2]);\n\t\t\t\tchorusPhase += chorusAngle * runLength;\n\t\t\t\tconst chorusTap0End = chorusDelayPos + chorusOffset0 - chorusRange * Math.sin(chorusPhase + Config.chorusPhaseOffsets[0][0]) + runLength;\n\t\t\t\tconst chorusTap1End = chorusDelayPos + chorusOffset1 - chorusRange * Math.sin(chorusPhase + Config.chorusPhaseOffsets[0][1]) + runLength;\n\t\t\t\tconst chorusTap2End = chorusDelayPos + chorusOffset2 - chorusRange * Math.sin(chorusPhase + Config.chorusPhaseOffsets[0][2]) + runLength;\n\t\t\t\tconst chorusTap3End = chorusDelayPos + chorusOffset3 - chorusRange * Math.sin(chorusPhase + Config.chorusPhaseOffsets[1][0]) + runLength;\n\t\t\t\tconst chorusTap4End = chorusDelayPos + chorusOffset4 - chorusRange * Math.sin(chorusPhase + Config.chorusPhaseOffsets[1][1]) + runLength;\n\t\t\t\tconst chorusTap5End = chorusDelayPos + chorusOffset5 - chorusRange * Math.sin(chorusPhase + Config.chorusPhaseOffsets[1][2]) + runLength;\n\t\t\t\tconst chorusTap0Delta = (chorusTap0End - chorusTap0Index) / runLength;\n\t\t\t\tconst chorusTap1Delta = (chorusTap1End - chorusTap1Index) / runLength;\n\t\t\t\tconst chorusTap2Delta = (chorusTap2End - chorusTap2Index) / runLength;\n\t\t\t\tconst chorusTap3Delta = (chorusTap3End - chorusTap3Index) / runLength;\n\t\t\t\tconst chorusTap4Delta = (chorusTap4End - chorusTap4Index) / runLength;\n\t\t\t\tconst chorusTap5Delta = (chorusTap5End - chorusTap5Index) / runLength;"),f&&(t+="\n\t\t\t\t\n\t\t\t\tlet echoMult = +instrumentState.echoMult;\n\t\t\t\tconst echoMultDelta = +instrumentState.echoMultDelta;\n\t\t\t\t\n\t\t\t\tconst echoDelayLineL = instrumentState.echoDelayLineL;\n\t\t\t\tconst echoDelayLineR = instrumentState.echoDelayLineR;\n\t\t\t\tconst echoMask = (echoDelayLineL.length - 1) >>> 0;\n\t\t\t\tinstrumentState.echoDelayLineDirty = true;\n\t\t\t\t\n\t\t\t\tlet echoDelayPos = instrumentState.echoDelayPos & echoMask;\n\t\t\t\tconst echoDelayOffsetStart = (echoDelayLineL.length - instrumentState.echoDelayOffsetStart) & echoMask;\n\t\t\t\tconst echoDelayOffsetEnd = (echoDelayLineL.length - instrumentState.echoDelayOffsetEnd) & echoMask;\n\t\t\t\tlet echoDelayOffsetRatio = +instrumentState.echoDelayOffsetRatio;\n\t\t\t\tconst echoDelayOffsetRatioDelta = +instrumentState.echoDelayOffsetRatioDelta;\n\t\t\t\t\n\t\t\t\tconst echoShelfA1 = +instrumentState.echoShelfA1;\n\t\t\t\tconst echoShelfB0 = +instrumentState.echoShelfB0;\n\t\t\t\tconst echoShelfB1 = +instrumentState.echoShelfB1;\n\t\t\t\tlet echoShelfSampleL = +instrumentState.echoShelfSampleL;\n\t\t\t\tlet echoShelfSampleR = +instrumentState.echoShelfSampleR;\n\t\t\t\tlet echoShelfPrevInputL = +instrumentState.echoShelfPrevInputL;\n\t\t\t\tlet echoShelfPrevInputR = +instrumentState.echoShelfPrevInputR;"),p&&(t+="\n\t\t\t\t\n\t\t\t\tconst reverbMask = Config.reverbDelayBufferMask >>> 0; //TODO: Dynamic reverb buffer size.\n\t\t\t\tconst reverbDelayLine = instrumentState.reverbDelayLine;\n\t\t\t\tinstrumentState.reverbDelayLineDirty = true;\n\t\t\t\tlet reverbDelayPos = instrumentState.reverbDelayPos & reverbMask;\n\t\t\t\t\n\t\t\t\tlet reverb = +instrumentState.reverbMult;\n\t\t\t\tconst reverbDelta = +instrumentState.reverbMultDelta;\n\t\t\t\t\n\t\t\t\tconst reverbShelfA1 = +instrumentState.reverbShelfA1;\n\t\t\t\tconst reverbShelfB0 = +instrumentState.reverbShelfB0;\n\t\t\t\tconst reverbShelfB1 = +instrumentState.reverbShelfB1;\n\t\t\t\tlet reverbShelfSample0 = +instrumentState.reverbShelfSample0;\n\t\t\t\tlet reverbShelfSample1 = +instrumentState.reverbShelfSample1;\n\t\t\t\tlet reverbShelfSample2 = +instrumentState.reverbShelfSample2;\n\t\t\t\tlet reverbShelfSample3 = +instrumentState.reverbShelfSample3;\n\t\t\t\tlet reverbShelfPrevInput0 = +instrumentState.reverbShelfPrevInput0;\n\t\t\t\tlet reverbShelfPrevInput1 = +instrumentState.reverbShelfPrevInput1;\n\t\t\t\tlet reverbShelfPrevInput2 = +instrumentState.reverbShelfPrevInput2;\n\t\t\t\tlet reverbShelfPrevInput3 = +instrumentState.reverbShelfPrevInput3;"),t+="\n\t\t\t\t\n\t\t\t\tconst stopIndex = bufferIndex + runLength;\n\t\t\t\tfor (let sampleIndex = bufferIndex; sampleIndex < stopIndex; sampleIndex++) {\n\t\t\t\t\tlet sample = tempMonoInstrumentSampleBuffer[sampleIndex];\n\t\t\t\t\ttempMonoInstrumentSampleBuffer[sampleIndex] = 0.0;",h&&(t+="\n\t\t\t\t\t\n\t\t\t\t\tconst distortionReverse = 1.0 - distortion;\n\t\t\t\t\tconst distortionNextInput = sample * distortionDrive;\n\t\t\t\t\tsample = distortionNextOutput;\n\t\t\t\t\tdistortionNextOutput = distortionNextInput / (distortionReverse * Math.abs(distortionNextInput) + distortion);\n\t\t\t\t\tdistortionFractionalInput1 = distortionFractionalDelayG1 * distortionNextInput + distortionPrevInput - distortionFractionalDelayG1 * distortionFractionalInput1;\n\t\t\t\t\tdistortionFractionalInput2 = distortionFractionalDelayG2 * distortionNextInput + distortionPrevInput - distortionFractionalDelayG2 * distortionFractionalInput2;\n\t\t\t\t\tdistortionFractionalInput3 = distortionFractionalDelayG3 * distortionNextInput + distortionPrevInput - distortionFractionalDelayG3 * distortionFractionalInput3;\n\t\t\t\t\tconst distortionOutput1 = distortionFractionalInput1 / (distortionReverse * Math.abs(distortionFractionalInput1) + distortion);\n\t\t\t\t\tconst distortionOutput2 = distortionFractionalInput2 / (distortionReverse * Math.abs(distortionFractionalInput2) + distortion);\n\t\t\t\t\tconst distortionOutput3 = distortionFractionalInput3 / (distortionReverse * Math.abs(distortionFractionalInput3) + distortion);\n\t\t\t\t\tdistortionNextOutput += distortionOutput1 * distortionNextOutputWeight1 + distortionOutput2 * distortionNextOutputWeight2 + distortionOutput3 * distortionNextOutputWeight3;\n\t\t\t\t\tsample += distortionOutput1 * distortionPrevOutputWeight1 + distortionOutput2 * distortionPrevOutputWeight2 + distortionOutput3 * distortionPrevOutputWeight3;\n\t\t\t\t\tsample *= distortionOversampleCompensation;\n\t\t\t\t\tdistortionPrevInput = distortionNextInput;\n\t\t\t\t\tdistortion += distortionDelta;\n\t\t\t\t\tdistortionDrive += distortionDriveDelta;"),a&&(t+="\n\t\t\t\t\t\n\t\t\t\t\tbitcrusherPhase += bitcrusherPhaseDelta;\n\t\t\t\t\tif (bitcrusherPhase < 1.0) {\n\t\t\t\t\t\tbitcrusherPrevInput = sample;\n\t\t\t\t\t\tsample = bitcrusherCurrentOutput;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbitcrusherPhase = bitcrusherPhase % 1.0;\n\t\t\t\t\t\tconst ratio = bitcrusherPhase / bitcrusherPhaseDelta;\n\t\t\t\t\t\t\n\t\t\t\t\t\tconst lerpedInput = sample + (bitcrusherPrevInput - sample) * ratio;\n\t\t\t\t\t\tbitcrusherPrevInput = sample;\n\t\t\t\t\t\t\n\t\t\t\t\t\tconst bitcrusherWrapLevel = bitcrusherFoldLevel * 4.0;\n\t\t\t\t\t\tconst wrappedSample = (((lerpedInput + bitcrusherFoldLevel) % bitcrusherWrapLevel) + bitcrusherWrapLevel) % bitcrusherWrapLevel;\n\t\t\t\t\t\tconst foldedSample = bitcrusherFoldLevel - Math.abs(bitcrusherFoldLevel * 2.0 - wrappedSample);\n\t\t\t\t\t\tconst scaledSample = foldedSample / bitcrusherScale;\n\t\t\t\t\t\tconst oldValue = bitcrusherCurrentOutput;\n\t\t\t\t\t\tconst newValue = (((scaledSample > 0 ? scaledSample + 1 : scaledSample)|0)-.5) * bitcrusherScale;\n\t\t\t\t\t\t\n\t\t\t\t\t\tsample = oldValue + (newValue - oldValue) * ratio;\n\t\t\t\t\t\tbitcrusherCurrentOutput = newValue;\n\t\t\t\t\t}\n\t\t\t\t\tbitcrusherPhaseDelta *= bitcrusherPhaseDeltaScale;\n\t\t\t\t\tbitcrusherScale *= bitcrusherScaleScale;\n\t\t\t\t\tbitcrusherFoldLevel *= bitcrusherFoldLevelScale;"),l&&(t+="\n\t\t\t\t\t\n\t\t\t\t\tconst inputSample = sample;\n\t\t\t\t\tsample = applyFilters(inputSample, initialFilterInput1, initialFilterInput2, filterCount, filters);\n\t\t\t\t\tinitialFilterInput2 = initialFilterInput1;\n\t\t\t\t\tinitialFilterInput1 = inputSample;"),t+="\n\t\t\t\t\t\n\t\t\t\t\tsample *= eqFilterVolume;\n\t\t\t\t\teqFilterVolume += eqFilterVolumeDelta;",t+=c?"\n\t\t\t\t\t\n\t\t\t\t\tpanningDelayLine[panningDelayPos] = sample;\n\t\t\t\t\tconst panningRatioL = panningOffsetL % 1;\n\t\t\t\t\tconst panningRatioR = panningOffsetR % 1;\n\t\t\t\t\tconst panningTapLA = panningDelayLine[(panningOffsetL) & panningMask];\n\t\t\t\t\tconst panningTapLB = panningDelayLine[(panningOffsetL + 1) & panningMask];\n\t\t\t\t\tconst panningTapRA = panningDelayLine[(panningOffsetR) & panningMask];\n\t\t\t\t\tconst panningTapRB = panningDelayLine[(panningOffsetR + 1) & panningMask];\n\t\t\t\t\tconst panningTapL = panningTapLA + (panningTapLB - panningTapLA) * panningRatioL;\n\t\t\t\t\tconst panningTapR = panningTapRA + (panningTapRB - panningTapRA) * panningRatioR;\n\t\t\t\t\tlet sampleL = panningTapL * panningVolumeL;\n\t\t\t\t\tlet sampleR = panningTapR * panningVolumeR;\n\t\t\t\t\tpanningDelayPos = (panningDelayPos + 1) & panningMask;\n\t\t\t\t\tpanningVolumeL += panningVolumeDeltaL;\n\t\t\t\t\tpanningVolumeR += panningVolumeDeltaR;\n\t\t\t\t\tpanningOffsetL += panningOffsetDeltaL;\n\t\t\t\t\tpanningOffsetR += panningOffsetDeltaR;":"\n\t\t\t\t\t\n\t\t\t\t\tlet sampleL = sample;\n\t\t\t\t\tlet sampleR = sample;",u&&(t+="\n\t\t\t\t\t\n\t\t\t\t\tconst chorusTap0Ratio = chorusTap0Index % 1;\n\t\t\t\t\tconst chorusTap1Ratio = chorusTap1Index % 1;\n\t\t\t\t\tconst chorusTap2Ratio = chorusTap2Index % 1;\n\t\t\t\t\tconst chorusTap3Ratio = chorusTap3Index % 1;\n\t\t\t\t\tconst chorusTap4Ratio = chorusTap4Index % 1;\n\t\t\t\t\tconst chorusTap5Ratio = chorusTap5Index % 1;\n\t\t\t\t\tconst chorusTap0A = chorusDelayLineL[(chorusTap0Index) & chorusMask];\n\t\t\t\t\tconst chorusTap0B = chorusDelayLineL[(chorusTap0Index + 1) & chorusMask];\n\t\t\t\t\tconst chorusTap1A = chorusDelayLineL[(chorusTap1Index) & chorusMask];\n\t\t\t\t\tconst chorusTap1B = chorusDelayLineL[(chorusTap1Index + 1) & chorusMask];\n\t\t\t\t\tconst chorusTap2A = chorusDelayLineL[(chorusTap2Index) & chorusMask];\n\t\t\t\t\tconst chorusTap2B = chorusDelayLineL[(chorusTap2Index + 1) & chorusMask];\n\t\t\t\t\tconst chorusTap3A = chorusDelayLineR[(chorusTap3Index) & chorusMask];\n\t\t\t\t\tconst chorusTap3B = chorusDelayLineR[(chorusTap3Index + 1) & chorusMask];\n\t\t\t\t\tconst chorusTap4A = chorusDelayLineR[(chorusTap4Index) & chorusMask];\n\t\t\t\t\tconst chorusTap4B = chorusDelayLineR[(chorusTap4Index + 1) & chorusMask];\n\t\t\t\t\tconst chorusTap5A = chorusDelayLineR[(chorusTap5Index) & chorusMask];\n\t\t\t\t\tconst chorusTap5B = chorusDelayLineR[(chorusTap5Index + 1) & chorusMask];\n\t\t\t\t\tconst chorusTap0 = chorusTap0A + (chorusTap0B - chorusTap0A) * chorusTap0Ratio;\n\t\t\t\t\tconst chorusTap1 = chorusTap1A + (chorusTap1B - chorusTap1A) * chorusTap1Ratio;\n\t\t\t\t\tconst chorusTap2 = chorusTap2A + (chorusTap2B - chorusTap2A) * chorusTap2Ratio;\n\t\t\t\t\tconst chorusTap3 = chorusTap3A + (chorusTap3B - chorusTap3A) * chorusTap3Ratio;\n\t\t\t\t\tconst chorusTap4 = chorusTap4A + (chorusTap4B - chorusTap4A) * chorusTap4Ratio;\n\t\t\t\t\tconst chorusTap5 = chorusTap5A + (chorusTap5B - chorusTap5A) * chorusTap5Ratio;\n\t\t\t\t\tchorusDelayLineL[chorusDelayPos] = sampleL * delayInputMult;\n\t\t\t\t\tchorusDelayLineR[chorusDelayPos] = sampleR * delayInputMult;\n\t\t\t\t\tsampleL = chorusCombinedMult * (sampleL + chorusVoiceMult * (chorusTap1 - chorusTap0 - chorusTap2));\n\t\t\t\t\tsampleR = chorusCombinedMult * (sampleR + chorusVoiceMult * (chorusTap4 - chorusTap3 - chorusTap5));\n\t\t\t\t\tchorusDelayPos = (chorusDelayPos + 1) & chorusMask;\n\t\t\t\t\tchorusTap0Index += chorusTap0Delta;\n\t\t\t\t\tchorusTap1Index += chorusTap1Delta;\n\t\t\t\t\tchorusTap2Index += chorusTap2Delta;\n\t\t\t\t\tchorusTap3Index += chorusTap3Delta;\n\t\t\t\t\tchorusTap4Index += chorusTap4Delta;\n\t\t\t\t\tchorusTap5Index += chorusTap5Delta;\n\t\t\t\t\tchorusVoiceMult += chorusVoiceMultDelta;\n\t\t\t\t\tchorusCombinedMult += chorusCombinedMultDelta;"),f&&(t+="\n\t\t\t\t\t\n\t\t\t\t\tconst echoTapStartIndex = (echoDelayPos + echoDelayOffsetStart) & echoMask;\n\t\t\t\t\tconst echoTapEndIndex = (echoDelayPos + echoDelayOffsetEnd ) & echoMask;\n\t\t\t\t\tconst echoTapStartL = echoDelayLineL[echoTapStartIndex];\n\t\t\t\t\tconst echoTapEndL = echoDelayLineL[echoTapEndIndex];\n\t\t\t\t\tconst echoTapStartR = echoDelayLineR[echoTapStartIndex];\n\t\t\t\t\tconst echoTapEndR = echoDelayLineR[echoTapEndIndex];\n\t\t\t\t\tconst echoTapL = (echoTapStartL + (echoTapEndL - echoTapStartL) * echoDelayOffsetRatio) * echoMult;\n\t\t\t\t\tconst echoTapR = (echoTapStartR + (echoTapEndR - echoTapStartR) * echoDelayOffsetRatio) * echoMult;\n\t\t\t\t\t\n\t\t\t\t\techoShelfSampleL = echoShelfB0 * echoTapL + echoShelfB1 * echoShelfPrevInputL - echoShelfA1 * echoShelfSampleL;\n\t\t\t\t\techoShelfSampleR = echoShelfB0 * echoTapR + echoShelfB1 * echoShelfPrevInputR - echoShelfA1 * echoShelfSampleR;\n\t\t\t\t\techoShelfPrevInputL = echoTapL;\n\t\t\t\t\techoShelfPrevInputR = echoTapR;\n\t\t\t\t\tsampleL += echoShelfSampleL;\n\t\t\t\t\tsampleR += echoShelfSampleR;\n\t\t\t\t\t\n\t\t\t\t\techoDelayLineL[echoDelayPos] = sampleL * delayInputMult;\n\t\t\t\t\techoDelayLineR[echoDelayPos] = sampleR * delayInputMult;\n\t\t\t\t\techoDelayPos = (echoDelayPos + 1) & echoMask;\n\t\t\t\t\techoDelayOffsetRatio += echoDelayOffsetRatioDelta;\n\t\t\t\t\techoMult += echoMultDelta;"),p&&(t+="\n\t\t\t\t\t\n\t\t\t\t\t// Reverb, implemented using a feedback delay network with a Hadamard matrix and lowpass filters.\n\t\t\t\t\t// good ratios: 0.555235 + 0.618033 + 0.818 + 1.0 = 2.991268\n\t\t\t\t\t// Delay lengths: 3041 + 3385 + 4481 + 5477 = 16384 = 2^14\n\t\t\t\t\t// Buffer offsets: 3041 -> 6426 -> 10907 -> 16384\n\t\t\t\t\tconst reverbDelayPos1 = (reverbDelayPos + 3041) & reverbMask;\n\t\t\t\t\tconst reverbDelayPos2 = (reverbDelayPos + 6426) & reverbMask;\n\t\t\t\t\tconst reverbDelayPos3 = (reverbDelayPos + 10907) & reverbMask;\n\t\t\t\t\tconst reverbSample0 = (reverbDelayLine[reverbDelayPos]);\n\t\t\t\t\tconst reverbSample1 = reverbDelayLine[reverbDelayPos1];\n\t\t\t\t\tconst reverbSample2 = reverbDelayLine[reverbDelayPos2];\n\t\t\t\t\tconst reverbSample3 = reverbDelayLine[reverbDelayPos3];\n\t\t\t\t\tconst reverbTemp0 = -(reverbSample0 + sampleL) + reverbSample1;\n\t\t\t\t\tconst reverbTemp1 = -(reverbSample0 + sampleR) - reverbSample1;\n\t\t\t\t\tconst reverbTemp2 = -reverbSample2 + reverbSample3;\n\t\t\t\t\tconst reverbTemp3 = -reverbSample2 - reverbSample3;\n\t\t\t\t\tconst reverbShelfInput0 = (reverbTemp0 + reverbTemp2) * reverb;\n\t\t\t\t\tconst reverbShelfInput1 = (reverbTemp1 + reverbTemp3) * reverb;\n\t\t\t\t\tconst reverbShelfInput2 = (reverbTemp0 - reverbTemp2) * reverb;\n\t\t\t\t\tconst reverbShelfInput3 = (reverbTemp1 - reverbTemp3) * reverb;\n\t\t\t\t\treverbShelfSample0 = reverbShelfB0 * reverbShelfInput0 + reverbShelfB1 * reverbShelfPrevInput0 - reverbShelfA1 * reverbShelfSample0;\n\t\t\t\t\treverbShelfSample1 = reverbShelfB0 * reverbShelfInput1 + reverbShelfB1 * reverbShelfPrevInput1 - reverbShelfA1 * reverbShelfSample1;\n\t\t\t\t\treverbShelfSample2 = reverbShelfB0 * reverbShelfInput2 + reverbShelfB1 * reverbShelfPrevInput2 - reverbShelfA1 * reverbShelfSample2;\n\t\t\t\t\treverbShelfSample3 = reverbShelfB0 * reverbShelfInput3 + reverbShelfB1 * reverbShelfPrevInput3 - reverbShelfA1 * reverbShelfSample3;\n\t\t\t\t\treverbShelfPrevInput0 = reverbShelfInput0;\n\t\t\t\t\treverbShelfPrevInput1 = reverbShelfInput1;\n\t\t\t\t\treverbShelfPrevInput2 = reverbShelfInput2;\n\t\t\t\t\treverbShelfPrevInput3 = reverbShelfInput3;\n\t\t\t\t\treverbDelayLine[reverbDelayPos1] = reverbShelfSample0 * delayInputMult;\n\t\t\t\t\treverbDelayLine[reverbDelayPos2] = reverbShelfSample1 * delayInputMult;\n\t\t\t\t\treverbDelayLine[reverbDelayPos3] = reverbShelfSample2 * delayInputMult;\n\t\t\t\t\treverbDelayLine[reverbDelayPos ] = reverbShelfSample3 * delayInputMult;\n\t\t\t\t\treverbDelayPos = (reverbDelayPos + 1) & reverbMask;\n\t\t\t\t\tsampleL += reverbSample1 + reverbSample2 + reverbSample3;\n\t\t\t\t\tsampleR += reverbSample0 + reverbSample2 - reverbSample3;\n\t\t\t\t\treverb += reverbDelta;"),t+="\n\t\t\t\t\t\n\t\t\t\t\toutputDataL[sampleIndex] += sampleL * mixVolume;\n\t\t\t\t\toutputDataR[sampleIndex] += sampleR * mixVolume;\n\t\t\t\t\tmixVolume += mixVolumeDelta;",i&&(t+="\n\t\t\t\t\t\n\t\t\t\t\tdelayInputMult += delayInputMultDelta;"),t+="\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tinstrumentState.mixVolume = mixVolume;\n\t\t\t\tinstrumentState.eqFilterVolume = eqFilterVolume;\n\t\t\t\t\n\t\t\t\t// Avoid persistent denormal or NaN values in the delay buffers and filter history.\n\t\t\t\tconst epsilon = (1.0e-24);",i&&(t+="\n\t\t\t\t\n\t\t\t\tinstrumentState.delayInputMult = delayInputMult;"),h&&(t+="\n\t\t\t\t\n\t\t\t\tinstrumentState.distortion = distortion;\n\t\t\t\tinstrumentState.distortionDrive = distortionDrive;\n\t\t\t\t\n\t\t\t\tif (!Number.isFinite(distortionFractionalInput1) || Math.abs(distortionFractionalInput1) < epsilon) distortionFractionalInput1 = 0.0;\n\t\t\t\tif (!Number.isFinite(distortionFractionalInput2) || Math.abs(distortionFractionalInput2) < epsilon) distortionFractionalInput2 = 0.0;\n\t\t\t\tif (!Number.isFinite(distortionFractionalInput3) || Math.abs(distortionFractionalInput3) < epsilon) distortionFractionalInput3 = 0.0;\n\t\t\t\tif (!Number.isFinite(distortionPrevInput) || Math.abs(distortionPrevInput) < epsilon) distortionPrevInput = 0.0;\n\t\t\t\tif (!Number.isFinite(distortionNextOutput) || Math.abs(distortionNextOutput) < epsilon) distortionNextOutput = 0.0;\n\t\t\t\t\n\t\t\t\tinstrumentState.distortionFractionalInput1 = distortionFractionalInput1;\n\t\t\t\tinstrumentState.distortionFractionalInput2 = distortionFractionalInput2;\n\t\t\t\tinstrumentState.distortionFractionalInput3 = distortionFractionalInput3;\n\t\t\t\tinstrumentState.distortionPrevInput = distortionPrevInput;\n\t\t\t\tinstrumentState.distortionNextOutput = distortionNextOutput;"),a&&(t+="\n\t\t\t\t\t\n\t\t\t\tif (Math.abs(bitcrusherPrevInput) < epsilon) bitcrusherPrevInput = 0.0;\n\t\t\t\tif (Math.abs(bitcrusherCurrentOutput) < epsilon) bitcrusherCurrentOutput = 0.0;\n\t\t\t\tinstrumentState.bitcrusherPrevInput = bitcrusherPrevInput;\n\t\t\t\tinstrumentState.bitcrusherCurrentOutput = bitcrusherCurrentOutput;\n\t\t\t\tinstrumentState.bitcrusherPhase = bitcrusherPhase;\n\t\t\t\tinstrumentState.bitcrusherPhaseDelta = bitcrusherPhaseDelta;\n\t\t\t\tinstrumentState.bitcrusherScale = bitcrusherScale;\n\t\t\t\tinstrumentState.bitcrusherFoldLevel = bitcrusherFoldLevel;"),l&&(t+="\n\t\t\t\t\t\n\t\t\t\tsynth.sanitizeFilters(filters);\n\t\t\t\t// The filter input here is downstream from another filter so we\n\t\t\t\t// better make sure it's safe too.\n\t\t\t\tif (!(initialFilterInput1 < 100) || !(initialFilterInput2 < 100)) {\n\t\t\t\t\tinitialFilterInput1 = 0.0;\n\t\t\t\t\tinitialFilterInput2 = 0.0;\n\t\t\t\t}\n\t\t\t\tif (Math.abs(initialFilterInput1) < epsilon) initialFilterInput1 = 0.0;\n\t\t\t\tif (Math.abs(initialFilterInput2) < epsilon) initialFilterInput2 = 0.0;\n\t\t\t\tinstrumentState.initialEqFilterInput1 = initialFilterInput1;\n\t\t\t\tinstrumentState.initialEqFilterInput2 = initialFilterInput2;"),c&&(t+="\n\t\t\t\t\n\t\t\t\tSynth.sanitizeDelayLine(panningDelayLine, panningDelayPos, panningMask);\n\t\t\t\tinstrumentState.panningDelayPos = panningDelayPos;\n\t\t\t\tinstrumentState.panningVolumeL = panningVolumeL;\n\t\t\t\tinstrumentState.panningVolumeR = panningVolumeR;\n\t\t\t\tinstrumentState.panningOffsetL = panningOffsetL;\n\t\t\t\tinstrumentState.panningOffsetR = panningOffsetR;"),u&&(t+="\n\t\t\t\t\n\t\t\t\tSynth.sanitizeDelayLine(chorusDelayLineL, chorusDelayPos, chorusMask);\n\t\t\t\tSynth.sanitizeDelayLine(chorusDelayLineR, chorusDelayPos, chorusMask);\n\t\t\t\tinstrumentState.chorusPhase = chorusPhase;\n\t\t\t\tinstrumentState.chorusDelayPos = chorusDelayPos;\n\t\t\t\tinstrumentState.chorusVoiceMult = chorusVoiceMult;\n\t\t\t\tinstrumentState.chorusCombinedMult = chorusCombinedMult;"),f&&(t+="\n\t\t\t\t\n\t\t\t\tSynth.sanitizeDelayLine(echoDelayLineL, echoDelayPos, echoMask);\n\t\t\t\tSynth.sanitizeDelayLine(echoDelayLineR, echoDelayPos, echoMask);\n\t\t\t\tinstrumentState.echoDelayPos = echoDelayPos;\n\t\t\t\tinstrumentState.echoMult = echoMult;\n\t\t\t\tinstrumentState.echoDelayOffsetRatio = echoDelayOffsetRatio;\n\t\t\t\t\n\t\t\t\tif (!Number.isFinite(echoShelfSampleL) || Math.abs(echoShelfSampleL) < epsilon) echoShelfSampleL = 0.0;\n\t\t\t\tif (!Number.isFinite(echoShelfSampleR) || Math.abs(echoShelfSampleR) < epsilon) echoShelfSampleR = 0.0;\n\t\t\t\tif (!Number.isFinite(echoShelfPrevInputL) || Math.abs(echoShelfPrevInputL) < epsilon) echoShelfPrevInputL = 0.0;\n\t\t\t\tif (!Number.isFinite(echoShelfPrevInputR) || Math.abs(echoShelfPrevInputR) < epsilon) echoShelfPrevInputR = 0.0;\n\t\t\t\tinstrumentState.echoShelfSampleL = echoShelfSampleL;\n\t\t\t\tinstrumentState.echoShelfSampleR = echoShelfSampleR;\n\t\t\t\tinstrumentState.echoShelfPrevInputL = echoShelfPrevInputL;\n\t\t\t\tinstrumentState.echoShelfPrevInputR = echoShelfPrevInputR;"),p&&(t+="\n\t\t\t\t\n\t\t\t\tSynth.sanitizeDelayLine(reverbDelayLine, reverbDelayPos , reverbMask);\n\t\t\t\tSynth.sanitizeDelayLine(reverbDelayLine, reverbDelayPos + 3041, reverbMask);\n\t\t\t\tSynth.sanitizeDelayLine(reverbDelayLine, reverbDelayPos + 6426, reverbMask);\n\t\t\t\tSynth.sanitizeDelayLine(reverbDelayLine, reverbDelayPos + 10907, reverbMask);\n\t\t\t\tinstrumentState.reverbDelayPos = reverbDelayPos;\n\t\t\t\tinstrumentState.reverbMult = reverb;\n\t\t\t\t\n\t\t\t\tif (!Number.isFinite(reverbShelfSample0) || Math.abs(reverbShelfSample0) < epsilon) reverbShelfSample0 = 0.0;\n\t\t\t\tif (!Number.isFinite(reverbShelfSample1) || Math.abs(reverbShelfSample1) < epsilon) reverbShelfSample1 = 0.0;\n\t\t\t\tif (!Number.isFinite(reverbShelfSample2) || Math.abs(reverbShelfSample2) < epsilon) reverbShelfSample2 = 0.0;\n\t\t\t\tif (!Number.isFinite(reverbShelfSample3) || Math.abs(reverbShelfSample3) < epsilon) reverbShelfSample3 = 0.0;\n\t\t\t\tif (!Number.isFinite(reverbShelfPrevInput0) || Math.abs(reverbShelfPrevInput0) < epsilon) reverbShelfPrevInput0 = 0.0;\n\t\t\t\tif (!Number.isFinite(reverbShelfPrevInput1) || Math.abs(reverbShelfPrevInput1) < epsilon) reverbShelfPrevInput1 = 0.0;\n\t\t\t\tif (!Number.isFinite(reverbShelfPrevInput2) || Math.abs(reverbShelfPrevInput2) < epsilon) reverbShelfPrevInput2 = 0.0;\n\t\t\t\tif (!Number.isFinite(reverbShelfPrevInput3) || Math.abs(reverbShelfPrevInput3) < epsilon) reverbShelfPrevInput3 = 0.0;\n\t\t\t\tinstrumentState.reverbShelfSample0 = reverbShelfSample0;\n\t\t\t\tinstrumentState.reverbShelfSample1 = reverbShelfSample1;\n\t\t\t\tinstrumentState.reverbShelfSample2 = reverbShelfSample2;\n\t\t\t\tinstrumentState.reverbShelfSample3 = reverbShelfSample3;\n\t\t\t\tinstrumentState.reverbShelfPrevInput0 = reverbShelfPrevInput0;\n\t\t\t\tinstrumentState.reverbShelfPrevInput1 = reverbShelfPrevInput1;\n\t\t\t\tinstrumentState.reverbShelfPrevInput2 = reverbShelfPrevInput2;\n\t\t\t\tinstrumentState.reverbShelfPrevInput3 = reverbShelfPrevInput3;"),t+="}",k=new Function("Config","Synth",t)(e,Ft),Ft.effectsFunctionCache[d]=k}k(t,i,s,n,o,r)}static pulseWidthSynth(t,e,i,s,n){const o=t.tempMonoInstrumentSampleBuffer;let r=s.phaseDeltas[0];const h=+s.phaseDeltaScales[0];let a=+s.expression;const l=+s.expressionDelta;let c=s.phases[0]%1,u=s.pulseWidth;const f=s.pulseWidthDelta,p=s.noteFilters,d=0|s.noteFilterCount;let m=+s.initialNoteFilterInput1,y=+s.initialNoteFilterInput2;const g=Ft.applyFilters,b=e+i;for(let t=e;t1-r){s+=.5*((w=(e-1)/r)+w+w*w+1)}if(i1-r){var w;s-=.5*((w=(i-1)/r)+w+w*w+1)}const n=s,b=g(n,m,y,d,p);y=m,m=n,c+=r,r*=h,u+=f;const v=b*a;a+=l,o[t]+=v}s.phases[0]=c,s.phaseDeltas[0]=r,s.expression=a,s.pulseWidth=u,t.sanitizeFilters(p),s.initialNoteFilterInput1=m,s.initialNoteFilterInput2=y}static supersawSynth(t,i,s,n,o){const r=t.tempMonoInstrumentSampleBuffer,h=0|e.supersawVoiceCount;let a=n.phaseDeltas[0];const l=+n.phaseDeltaScales[0];let c=+n.expression;const u=+n.expressionDelta;let f=n.phases,p=+n.supersawDynamism;const d=+n.supersawDynamismDelta,m=n.supersawUnisonDetunes;let y=+n.supersawShape;const g=+n.supersawShapeDelta;let b=+n.supersawDelayLength;const w=+n.supersawDelayLengthDelta,v=n.supersawDelayLine,k=v.length-1>>0;let M=0|n.supersawDelayIndex;M=(M&k)+v.length;const x=n.noteFilters,S=0|n.noteFilterCount;let F=+n.initialNoteFilterInput1,P=+n.initialNoteFilterInput2;const I=Ft.applyFilters,T=i+s;for(let t=i;t1-a){var q;i-=.5*((q=(e-1)/a)+q+q*q+1)}f[0]=e;for(let t=1;t1-e){const t=(s-1)/e;i-=.5*(t+t+t*t+1)*p}f[t]=s}v[M&k]=i;const s=M-b,n=0|s,o=n+1,T=s-n,E=v[n&k];M++;const C=i-(E+(v[o&k]-E)*T)*y,L=I(C,F,P,S,x);P=F,F=C,a*=l,p+=d,y+=g,b+=w;const z=L*c;c+=u,r[t]+=z}n.phaseDeltas[0]=a,n.expression=c,n.supersawDynamism=p,n.supersawShape=y,n.supersawDelayLength=b,n.supersawDelayIndex=M,t.sanitizeFilters(x),n.initialNoteFilterInput1=F,n.initialNoteFilterInput2=P}static noiseSynth(t,i,s,n,o){const r=t.tempMonoInstrumentSampleBuffer,h=o.wave;let a=+n.phaseDeltas[0];const l=+n.phaseDeltaScales[0];let c=+n.expression;const u=+n.expressionDelta;let f=n.phases[0]%1*e.chipNoiseLength;0==n.phases[0]&&(f=Math.random()*e.chipNoiseLength);const p=e.chipNoiseLength-1;let d=+n.noiseSample;const m=n.noteFilters,y=0|n.noteFilterCount;let g=+n.initialNoteFilterInput1,b=+n.initialNoteFilterInput2;const w=Ft.applyFilters,v=Math.min(1,a*o.noisePitchFilterMult),k=i+s;for(let t=i;t0;r--){const r=n+16&s,h=t[r];if(o*h<=0){for(let r=0;r<16;r++){const r=n+1&s,h=t[r];if(o*h<=0){const t=h-o;i=n,Math.abs(t)>1e-8&&(i+=-o/t),i=Math.max(0,i)%e;break}n=r,o=h}break}n=r,o=h}return i}static instrumentVolumeToVolumeMult(t){return t==e.volumeRange-1?0:Math.pow(2,e.volumeLogScale*t)}static volumeMultToInstrumentVolume(t){return t<=0?e.volumeRange-1:Math.min(e.volumeRange-2,Math.log2(t)/e.volumeLogScale)}static noteSizeToVolumeMult(t){return Math.pow(Math.max(0,t)/e.noteSizeMax,1.5)}static volumeMultToNoteSize(t){return Math.pow(Math.max(0,t),1/1.5)*e.noteSizeMax}static fadeInSettingToSeconds(t){return.0125*(.95*t+.05*t*t)}static secondsToFadeInSetting(t){return tt(0,e.fadeInRange,Math.round((-.95+Math.sqrt(.9025+.2*t/.0125))/.1))}static fadeOutSettingToTicks(t){return e.fadeOutTicks[t]}static ticksToFadeOutSetting(t){let i=e.fadeOutTicks[0];if(t<=i)return 0;for(let s=1;s=Z))break;t[s]=0}}static applyFilters(t,e,i,s,n){for(let o=0;o{this.j.undo()},this.cleanUp=()=>{this.W.removeEventListener("click",this.K)},e){case"scale":i=It(qt("Scale"),Tt("This setting limits the available pitches for adding notes. You may think that there's no point in limiting your choices, but the set of pitches you use has a strong influence on the mood and feel of your song, and these scales serve as guides to help you choose appropriate pitches. Don't worry, you can change the scale at any time, so you're not locked into it. Try making little melodies using all the available pitches of a scale to get a sense for how it sounds."),Tt('Most of the scales have a major version, and a minor version. Assuming your song uses all pitches in the scale and especially "tonic" pitches (the brown rows in the pattern editor) then major scales tend to sound more playful or optimistic, whereas minor scales sound more serious or sad.'));break;case"key":i=It(qt("Song Key"),Tt('This setting can shift the frequency of every note in your entire song up or down, keeping the "tonic" pitches (the brown rows in the pattern editor) aligned with the selected "key" pitch.'),Tt('If you\'ve already placed some notes but they don\'t emphasize "tonic" pitches then the selected key isn\'t very meaningful. You can select the "Detect Key" option in the key menu to automatically align the most emphasized notes with "tonic" pitches.'));break;case"tempo":i=It(qt("Song Tempo"),Tt('This setting controls the speed of your song, measured in beats-per-minute. A "beat" is the duration of the little gray rectangles in the pattern editor. (In conventional music notation, a "quarter note" is usually equivalent to "beat".)'));break;case"reverb":i=It(qt("Reverb"),Tt('Reverb is like a continuous echo effect. A little bit helps instruments sound more natural. Adding a lot of reverb can add sense of depth or mystery, but too much reverb can kinda "smear" sounds so that it\'s harder to distinguish notes or instruments, especially for lower "bass" notes.'));break;case"rhythm":i=It(qt("Rhythm"),Tt("This setting determines how beats are divided. The pattern editor helps you align notes to fractions of a beat based on this setting."),Tt("If you've already placed some notes but they don't align with the selected rhythm, you can select the \"Snap Notes To Rhythm\" option in the rhythm menu to force the notes in the currently selected pattern(s) to align with the selected rhythm."));break;case"instrumentIndex":i=It(qt("Instrument Number"),Tt('In the "Channel Settings" option from BeepBox\'s "Edit" menu, there are a few ways to enable multiple instruments per channel.'),Tt("First, you could enable multiple simultaneous instruments per channel. All of the channel's instruments will play all of the notes in the channel at the same time, and you can click an instrument number to view and edit its settings."),Tt("Second, you could enable different instruments per pattern. Only one of the instruments will play at any given time, but you can click the instrument number to change which instrument is used for the currently selected pattern(s)."),Tt("Finally, you can enable them both, in which case you can click an instrument number once to view it, and again to toggle whether the instrument is used for the currently selected pattern(s)."),Tt("Either way, you can click the + button to add more instruments to a channel, and you can press shift and a number key on your keyboard to select an instrument as if you had clicked the corresponding button here."));break;case"instrumentVolume":i=It(qt("Instrument Volume"),Tt("This setting controls the volume of the selected instrument without affecting the volume of the other instruments. This allows you to balance the loudness of each instrument relative to each other."));break;case"pan":i=It(qt("Instrument Panning"),Tt("If you're listening through headphones or some other stereo sound system, this controls the position of the instrument and where the sound is coming from, ranging from left to right."),Tt("As a suggestion, composers often put lead melodies, drums, and basses in the center, and spread other instruments toward either side. If too many instruments seem like they're coming from the same place, it can feel crowded and harder to distinguish individual sounds, especially if they cover a similar pitch range."));break;case"instrumentType":i=It(qt("Instrument Type"),Tt("BeepBox comes with many instrument presets, try them out! You can also create your own custom instruments!"),Tt("There are also options for copying and pasting instrument settings and for generating random instruments at the top of the instrument type menu."));break;case"eqFilter":i=It(qt("EQ Filter"),Tt("Filters are a way of emphasizing or diminishing different parts of a sound. Musical notes have a fundamental (base) frequency, but the sound of a musical note also has parts at higher frequencies and filters can adjust the volume of each of these parts based on their frequency."),Tt("Click in the filter editor to insert, delete, or drag a filter control point. The horizontal position of the point determines which frequencies it affects, and the vertical position determines how the volume is affected at that frequency."),Tt('Insert a new point on the left side of the filter editor to add a "high-pass" filter point, which additionally reduces the volume of lower frequencies, or insert a new point on the right side to add a "low-pass" filter point which reduces the volume of higher frequencies.'),Tt('You can also enable a "Note Filter" as an effect. EQ and note filters are mostly the same, but have different purposes. EQ filters are for overall adjustments, whereas note filters are for dynamic control and can be moved with envelopes. Note filters also change how the distortion effect sounds.'));break;case"noteFilter":i=It(qt("Note Filter"),Tt("Note filters are mostly the same as EQ filters, but have a different purpose. EQ filters are for overall adjustments, whereas note filters are for dynamic control and can be moved with envelopes. Note filters also change how the distortion effect sounds."),Tt("Filters are a way of emphasizing or diminishing different parts of a sound. Musical notes have a fundamental (base) frequency, but the sound of a musical note also has parts at higher frequencies and filters can adjust the volume of each of these parts based on their frequency."),Tt("Click in the filter editor to insert, delete, or drag a filter control point. The horizontal position of the point determines which frequencies it affects, and the vertical position determines how the volume is affected at that frequency."),Tt('Insert a new point on the left side of the filter editor to add a "high-pass" filter point, which additionally reduces the volume of lower frequencies, or insert a new point on the right side to add a "low-pass" filter point which reduces the volume of higher frequencies.'));break;case"fadeInOut":i=It(qt("Fade In/Out"),Tt("This setting controls how long it takes for notes to reach full volume at the beginning or decay to silence at the end."),Tt("An instant fade-in sounds like instruments that are played by hitting or plucking, whereas slower fade-ins sound like instruments that are played by blowing air."),Tt("You can also make the fade-out start before the note ends to leave a gap before the next note starts, or after the note ends to allow the sound of the end of the note to overlap with the start of the next note."));break;case"transition":i=It(qt("Transition"),Tt("Usually, when one note ends at the same time another begins, the old note will fade out and the new note will fade in based on the fade in/out settings, but this setting can override that, connecting the end of one note to the beginning of the next."),Tt('The "interrupt" transition makes the wave suddenly change from the old note\'s frequency to the new note\'s frequency without any fading, but still restarts envelopes at the beginning of the new note. The "continue" transition is similar but it doesn\'t even restart envelopes, and can be used to make each of the notes in a chord start or stop at different times!'),Tt('The "slide" transition makes the pitch shift quickly but not instantaneously from the old note\'s frequency to the new note\'s frequency, and softly restarts envelopes. The "slide in pattern" transition is the same except it doesn\'t connect the last note in a pattern to the first note in the next pattern.'));break;case"chipWave":i=It(qt("Chip Wave"),Tt("BeepBox comes with some sound waves based on classic electronic sound chips, as well as several unique waves. This is the basic source of the sound of the instrument, which is modified by the other instrument settings."));break;case"chipNoise":i=It(qt("Noise"),Tt("BeepBox comes with several basic noise sounds. These do not have any distinct musical pitch, and can be used like drums to create beats and emphasize your song's rhythm."));break;case"supersawDynamism":i=It(qt("Supersaw Dynamism"),Tt("A supersaw is a combination of many sawtooth waves, and this setting controls the contribution of extra sawtooth waves."),Tt('At the low end of the slider, only the first wave is contributing to the sound, which sounds like an ordinary static sawtooth wave. At the maximum setting, all of the waves are contributing equally and the resulting tone can randomly shift depending on how the waves line up with each other, similar to the "unison" and "chorus" settings.'));break;case"supersawSpread":i=It(qt("Supersaw Spread"),Tt("A supersaw is a combination of many sawtooth waves, and this setting controls the distance between their frequencies. The dynamism setting must be used for the extra waves to have any effect."),Tt('At the low end of the spread slider, all of the voices have the same frequency but random phase, resulting in a different sound every time a note starts. In the middle, the waves all have slightly different frequencies that shift in and out of phase over time similar to the "unison" and "chorus" settings, creating a classic supersaw sound. At the extreme end, the frequencies are so far apart they sound dissonant.'));break;case"supersawShape":i=It(qt("Supersaw Shape"),Tt("This supersaw instrument includes an option to change the shape of the waves from sawtooth waves to pulse waves. Use this setting to morph between the two shapes."),Tt("When a pulse wave shape is used, you can also control the pulse width with a separate setting."));break;case"pulseWidth":i=It(qt("Pulse Wave Width"),Tt("This setting controls the shape and sound of a pulse wave. At the minimum width, it sounds light and buzzy. At the maximum width, it is shaped like a classic square wave."));break;case"unison":i=It(qt("Unison"),Tt("This instrument can play two identical waves at different frequencies. When two waves play at slightly different frequencies, they move in and out of phase with each other over time as different parts of the waves line up. This creates a dynamic, shifting sound. Pianos are a common example of this kind of sound, because each piano key strikes multiple strings that are tuned to slightly different frequencies."),Tt('The distance between two frequencies is called an "interval", and this setting controls how large it is. If the interval is too wide, then the waves may sound out-of-tune and "dissonant". However, if the interval is even larger, then the two frequencies can even be distinct pitches.'));break;case"chords":i=It(qt("Chords"),Tt("When multiple different notes occur at the same time, this is called a chord. Chords can be created in BeepBox's pattern editor by adding notes above or below another note."),Tt('This setting determines how chords are played. The standard option is "simultaneous" which starts playing all of the pitches in a chord at the same instant. The "strum" option is similar, but plays the notes starting at slightly different times. The "arpeggio" option is used in "chiptune" style music and plays a single tone that rapidly alternates between all of the pitches in the chord.'),Tt('Some BeepBox instruments have an option called "custom interval" which uses the chord notes to control the interval between the waves of a single tone. This can create strange sound effects when combined with FM modulators.'));break;case"vibrato":i=It(qt("Vibrato"),Tt("This setting causes the frequency of a note to wobble slightly. Singers and violinists often use vibrato."));break;case"algorithm":i=It(qt("FM Algorithm"),Tt("FM Synthesis is a mysterious but powerful technique for crafting sounds, popularized by Yamaha keyboards and the Sega Genesis/Mega Drive. It may seem confusing, but try playing around with the options until you get a feel for it, or check out some of the preset examples!"),Tt("This FM synthesizer uses up to four waves, numbered 1, 2, 3, and 4. Each wave may have its own frequency and volume."),Tt('There are two kinds of waves: "carrier" waves play a tone out loud, but "modulator" waves distort other waves instead. Wave 1 is always a carrier and plays a tone, but other waves may distort it. The "Algorithm" setting determines which waves are modulators, and which other waves those modulators distort. For example, "1←2" means that wave 2 modulates wave 1, and wave 1 plays out loud.'));break;case"feedbackType":i=It(qt("Feedback Type"),Tt("Modulators distort in one direction (like 1←2), but you can also use the feedback setting to make any wave distort in the opposite direction (1→2), or even itself (1⟲)."));break;case"feedbackVolume":i=It(qt("Feedback Distortion"),Tt("This setting controls the amount of feedback distortion based on the feedback type setting."));break;case"operatorFrequency":i=It(qt("Operator Frequency"),Tt('This setting controls the frequency of an individual FM wave, relative to the fundamental frequency of the note. The multiplier 1× is the same as the fundamental frequency, whereas 2x would be an octave (12 semitones) above it. The frequencies with a "~" are slightly detuned and shift in and out of phase over time compared to the other frequencies.'),Tt('Try different combinations of a "carrier" wave and a "modulator" wave with different frequencies to get a feel for how they sound together.'));break;case"operatorVolume":i=It(qt("Operator Volume"),Tt('This setting controls the volume of "carrier" waves, or the amount of distortion that "modulator" waves apply to other waves.'));break;case"spectrum":i=It(qt("Spectrum"),Tt("This setting allows you to draw your own noise spectrum! This is good for making drum sounds."),Tt("If you only use certain frequencies and a soft fade in/out, it's also possible to make howling wind sounds or even musical wind instruments."),Tt("The left side of the spectrum editor controls the noise energy at lower frequencies, and the right side controls higher frequencies."));break;case"harmonics":i=It(qt("Harmonics"),Tt("This setting allows you to design your own sound wave! Most musical waves are actually a combination of sine waves at certain frequencies, and this lets you control the volume of each sine wave individually."),Tt("The left side of the harmonics editor controls the sine wave volumes at lower frequencies, and the right side controls higher frequencies."));break;case"effects":i=It(qt("Effects"),Tt("BeepBox has many different kinds of special effects you can add to instruments. You can turn on multiple effects at once, and they can be configured individually. Try them all out!"));break;case"drumsetEnvelope":i=It(qt("Drumset Envelope"),Tt("This drumset comes with a low-pass filter, and this setting can dynamically change the low-pass filter frequency over time. Each row in the pattern editor can have a different envelope shape."));break;case"drumsetSpectrum":i=It(qt("Drumset Spectrum"),Tt("This setting allows you to draw your own noise spectrum! This is good for making drumsets. Each row in the pattern editor gets its own spectrum."),Tt("The left side of the spectrum editor controls the noise energy at lower frequencies, and the right side controls higher frequencies."));break;case"chorus":i=It(qt("Chorus"),Tt("The chorus effect combines multiple copies of the instrument's sound and adds a bit of vibrato to simulate an ensemble of instruments or voices. Drag the slider to control how much chorus is added."));break;case"echoSustain":i=It(qt("Echo Volume"),Tt("The echo effect repeats the instrument's sound after a delay. Each echo is a little bit quieter than the last, and this setting controls how much quieter."));break;case"echoDelay":i=It(qt("Echo Delay"),Tt("The echo effect repeats the instrument's sound after a delay, and this setting controls how long the delay is."));break;case"pitchShift":i=It(qt("Pitch Shift"),Tt("This setting makes instruments play higher or lower pitches than the ones displayed in the pattern editor. Be careful that you don't confuse yourself!"),Tt("You can combine this with envelopes to bend pitch over time, or play multiple simultaneous instruments with different pitch shifts for interesting layered sounds."),Tt('The intervals created by this setting are in "just intonation" which means they stay in phase with the original pitch instead of shifting in and out of phase over time. If you want the shifting, add the detune effect!'));break;case"detune":i=It(qt("Detune"),Tt('This setting slightly adjusts the frequency of notes played by the instrument. You can use a little bit to add a pleasing shifting sound similar to the "unison" feature when combined with other instruments. If you use too much, then the instrument may sound unpleasantly out-of-tune.'));break;case"distortion":i=It(qt("Distortion"),Tt("This is the famous electric guitar effect! However, there are some things to be aware of."),Tt('First, most chords don\'t sound right when combined with heavy distortion. The only chords commonly used with distorted electric guitars are "power chords" which consist of a root note, a "fifth" note above that, and/or any octaves of those two notes.'),Tt("Second, the distortion sound depends a lot on filtering. In particular, I recommend enabling the note filter effect, and adding both high-pass and low-pass points to the note filter. (Note filters are applied first, then distortion which transforms the sound based on that filtering, then the EQ filter is applied last.)"),Tt("Finally, I recommend adjusting the fade-out setting to allow the end of each note to overlap a little bit with the beginning of the next, but not too much!"));break;case"bitcrusherQuantization":i=It(qt("Bitcrusher Quantization"),Tt("This effect makes stuff sounds harsher, artificial, and \"low quality\", which is great if that's what you're going for!"));break;case"bitcrusherFreq":i=It(qt("Frequency Quantization"),Tt("The bitcrusher effect comes with an additional frequency quantization effect! This is a fun one to play with, especially when combined with the note filter effect."),Tt("Every other notch on this slider is aligned with the currently selected key of the song, and the in-between notches are aligned with the tritones of the key."));break;case"envelopes":i=It(qt("Envelopes"),Tt("Envelopes are a way to dynamically adjust various other settings over time, usually based on how long the note lasts. Press the + button to add an envelope, then use the menus below to select which setting to control and the curve of the envelope. Try different combinations to see how they sound!"),Tt('Most envelope curves restart from the beginning every time a new note plays. The "note size" option is based on the note width as drawn in the pattern editor.'),Tt("Envelope curves move in the range from 0 to 1 (or vice versa), where 0 means as quiet as possible and 1 is the same as the corresponding position selected in the instrument settings above. If multiple envelopes are targetting the same setting, they are multiplied before applying to the setting."));break;default:throw new Error("Unhandled TipPrompt type: "+e)}this.container=It({class:"prompt",style:"width: 300px;"},i,this.W),setTimeout((()=>this.W.focus())),this.W.addEventListener("click",this.K)}}class Ct{constructor(){this.Y=!0}J(){this.Y=!1}isNoop(){return this.Y}commit(){}}class Lt extends Ct{constructor(t){super(),this.X=t,this.Z=!t}undo(){this.X?(this.tt(),this.Z=!0):(this.et(),this.Z=!1)}redo(){this.X?(this.et(),this.Z=!1):(this.tt(),this.Z=!0)}it(){return this.Z}tt(){throw new Error("Change.doForwards(): Override me.")}et(){throw new Error("Change.doBackwards(): Override me.")}}class zt extends Ct{constructor(){super()}append(t){t.isNoop()||this.J()}}class Dt extends Lt{constructor(t){super(!1),this.st=null==t?[]:t.concat()}append(t){t.isNoop()||(this.st[this.st.length]=t,this.J())}tt(){for(let t=0;t=0;t--)this.st[t].undo()}}function At(t,e){const i=t.every((t=>-1!=e.indexOf(t))),s=e.every((e=>-1!=t.indexOf(e)));return i&&s&&e.length==t.length}function Bt(t,e,i){const s=new Set(t);t.length=0,t.push(...s);for(let s=0;s=e.channels[i].instruments.length&&(t.splice(s,1),s--);t.length>e.getMaxInstrumentsPerPattern(i)&&(t.length=e.getMaxInstrumentsPerPattern(i)),t.length<=0&&(t[0]=0)}function Ot(t,e){for(const i of t.notes)for(const t of i.pitches)for(const s of i.pins){const i=(t+s.interval)%12;e[i]||(e[i]=!0)}}function Nt(t){for(let e=1;e=t.pins.length)throw new Error("Error converting pins in note overflow.");const o=t.pins[e+1],h=o.time+i;if(h>0){const t=-n/(h-n);r.pins.push(rt(Math.round(s.interval+t*(o.interval-s.interval)),0,Math.round(s.size+t*(o.size-s.size))))}}else if(n<=h)r.pins.push(rt(s.interval,n,s.size));else{if(e<1)throw new Error("Error converting pins in note overflow.");const o=t.pins[e-1],a=o.time+i;if(a0&&t.continuesLastPattern){const t=o[o.length-1];if(t.end==r.start&&Ft.adjacentNotesHaveMatchingPitches(t,r)){l=!0;const e=t.pins[t.pins.length-1].interval,i=t.end-t.start;for(let s=1;s=this.ut[t+1].time?this.ut.splice(t,1):t++;Nt(this.ut);const e=this.ut[0].interval,i=this.ut[0].time;for(let t=0;to.chance)continue;const i=new dt;i.type=o.type,i.freq=s(o.minFreq,o.maxFreq,dt.getRoundedSettingValueFromHz(o.centerHz),1/e.filterFreqStep),i.gain=s(0,e.filterGainRange-1,e.filterGainCenter+o.centerGain,2/e.filterGainStep),2==i.type&&i.gain==e.filterGainCenter||(n.includes(i.freq)||(n.push(i.freq),t.controlPoints[t.controlPointCount]=i,t.controlPointCount++))}}const r=t.song.getChannelIsNoise(t.channel),h=t.song.channels[t.channel].instruments[t.getCurrentInstrument()];h.effects&=4,h.envelopeCount=0;const a=dt.getRoundedSettingValueFromHz(700),l=e.filterFreqRange-1;if(o(h.eqFilter,[new n(.8,0,a,l,4e3,-1),new n(.4,1,0,a-1,250,-1),new n(.5,2,0,l,2e3,0),new n(.4,2,0,l,1400,0),new n(.3,2,0,l,1e3,0),new n(.2,2,0,l,500,0)]),r){const t=i([{item:2,weight:1},{item:3,weight:3}]);function r(t){let i=0;for(const e of t)e>i&&(i=e);for(let s=0;s>1,2),h.vibrato=e.vibratos.dictionary[i([{item:"light",weight:2},{item:"delayed",weight:2},{item:"heavy",weight:1},{item:"shaky",weight:2}])].index),Math.random()<.8&&(h.effects|=32,o(h.noteFilter,[new n(1,0,a,l,8e3,-1)]),h.addEnvelope(e.instrumentAutomationTargets.dictionary.noteFilterAllFreqs.index,0,e.envelopes.dictionary[i([{item:"punch",weight:4},{item:"flare 1",weight:2},{item:"flare 2",weight:2},{item:"flare 3",weight:2},{item:"twang 1",weight:8},{item:"twang 2",weight:8},{item:"twang 3",weight:8},{item:"swell 1",weight:2},{item:"swell 2",weight:2},{item:"swell 3",weight:1},{item:"tremolo1",weight:1},{item:"tremolo2",weight:1},{item:"tremolo3",weight:1},{item:"tremolo4",weight:1},{item:"tremolo5",weight:1},{item:"tremolo6",weight:1},{item:"decay 1",weight:4},{item:"decay 2",weight:4},{item:"decay 3",weight:4}])].index)),Math.random()<.1&&(h.effects|=8,h.distortion=s(1,e.distortionRange-1,e.distortionRange-1,2)),Math.random()<.1&&(h.effects|=16,h.bitcrusherFreq=s(0,e.bitcrusherFreqRange-1,e.bitcrusherFreqRange>>1,2),h.bitcrusherQuantization=s(0,e.bitcrusherQuantizationRange-1,e.bitcrusherQuantizationRange>>1,2)),Math.random()<.1&&(h.effects|=2,h.chorus=s(1,e.chorusRange-1,e.chorusRange-1,1)),Math.random()<.1&&(h.echoSustain=s(0,e.echoSustainRange-1,e.echoSustainRange>>1,2),h.echoDelay=s(0,e.echoDelayRange-1,e.echoDelayRange>>1,2),0==h.echoSustain&&0==h.echoDelay||(h.effects|=64)),Math.random()<.5&&(h.effects|=1,h.reverb=s(1,e.reverbRange-1,1,1)),t){case 2:h.chipNoise=Math.random()*e.chipNoises.length|0;break;case 3:{const t=[()=>{const t=[];for(let i=0;i{let t=1;const i=[t];for(let s=1;s{let t=1;const i=[t];for(let s=1;si&&(i=e);for(let s=0;s>1,2),h.vibrato=e.vibratos.dictionary[i([{item:"light",weight:2},{item:"delayed",weight:2},{item:"heavy",weight:1},{item:"shaky",weight:2}])].index),Math.random()<.1&&(h.effects|=8,h.distortion=s(1,e.distortionRange-1,e.distortionRange-1,2)),m(h.effects)&&Math.random()<.8?(h.effects|=32,o(h.noteFilter,[new n(1,0,a,l,2e3,-1),new n(.9,1,0,a-1,500,-1),new n(.4,2,0,l,1400,0)])):Math.random()<.5&&(h.effects|=32,o(h.noteFilter,[new n(1,0,a,l,8e3,-1)]),h.addEnvelope(e.instrumentAutomationTargets.dictionary.noteFilterAllFreqs.index,0,e.envelopes.dictionary[i([{item:"punch",weight:6},{item:"flare 1",weight:2},{item:"flare 2",weight:4},{item:"flare 3",weight:2},{item:"twang 1",weight:2},{item:"twang 2",weight:4},{item:"twang 3",weight:4},{item:"swell 1",weight:4},{item:"swell 2",weight:2},{item:"swell 3",weight:1},{item:"tremolo1",weight:1},{item:"tremolo2",weight:1},{item:"tremolo3",weight:1},{item:"tremolo4",weight:1},{item:"tremolo5",weight:1},{item:"tremolo6",weight:1},{item:"decay 1",weight:1},{item:"decay 2",weight:2},{item:"decay 3",weight:2}])].index)),Math.random()<.1&&(h.effects|=16,h.bitcrusherFreq=s(0,e.bitcrusherFreqRange-1,0,2),h.bitcrusherQuantization=s(0,e.bitcrusherQuantizationRange-1,e.bitcrusherQuantizationRange>>1,2)),Math.random()<.1&&(h.effects|=2,h.chorus=s(1,e.chorusRange-1,e.chorusRange-1,1)),Math.random()<.1&&(h.echoSustain=s(0,e.echoSustainRange-1,e.echoSustainRange>>1,2),h.echoDelay=s(0,e.echoDelayRange-1,e.echoDelayRange>>1,2),0==h.echoSustain&&0==h.echoDelay||(h.effects|=64)),Math.random()<.5&&(h.effects|=1,h.reverb=s(1,e.reverbRange-1,1,1)),t){case 0:h.chipWave=Math.random()*e.chipWaves.length|0;break;case 6:case 8:8==t&&(h.supersawDynamism=s(0,e.supersawDynamismMax,e.supersawDynamismMax,2),h.supersawSpread=s(0,e.supersawSpreadMax,Math.ceil(e.supersawSpreadMax/3),4),h.supersawShape=s(0,e.supersawShapeMax,0,4)),h.pulseWidth=s(0,e.pulseWidthRange-1,e.pulseWidthRange-1,2),Math.random()<.6&&h.addEnvelope(e.instrumentAutomationTargets.dictionary.pulseWidth.index,0,e.envelopes.dictionary[i([{item:"punch",weight:6},{item:"flare 1",weight:2},{item:"flare 2",weight:4},{item:"flare 3",weight:2},{item:"twang 1",weight:2},{item:"twang 2",weight:4},{item:"twang 3",weight:4},{item:"swell 1",weight:4},{item:"swell 2",weight:2},{item:"swell 3",weight:1},{item:"tremolo1",weight:1},{item:"tremolo2",weight:1},{item:"tremolo3",weight:1},{item:"tremolo4",weight:1},{item:"tremolo5",weight:1},{item:"tremolo6",weight:1},{item:"decay 1",weight:1},{item:"decay 2",weight:2},{item:"decay 3",weight:2}])].index);break;case 7:case 5:{7==t&&(h.stringSustain=Math.random()*e.stringSustainRange|0);const i=[()=>{const t=[];for(let i=0;i{let t=1;const i=[t];for(let s=1;s{let t=1;const i=[t];for(let s=1;st.song.patternsPerChannel)throw new Error("invalid pattern");for(let r=i;re&&s.bars.splice(0,t.song.barCount-e)}else{for(;s.bars.length0)&&(t.barScrollPos=Math.max(0,t.barScrollPos+i)),t.song.loopStart=Math.max(0,t.song.loopStart+i)}t.bar=Math.min(t.bar,e-1),t.song.loopLength=Math.min(e,t.song.loopLength),t.song.loopStart=Math.min(e-t.song.loopLength,t.song.loopStart),t.song.barCount=e,t.notifier.changed(),this.J()}}}class Yt extends Ct{constructor(t,i,s){super();const n=Math.min(e.barCountMax,t.song.barCount+s);if(0!=(s=n-t.song.barCount)){for(const e of t.song.channels)for(;e.bars.length=i?t.song.loopStart+=s:t.song.loopStart+t.song.loopLength>=i&&(t.song.loopLength+=s),t.notifier.changed(),this.J()}}}class Jt extends Ct{constructor(t,e,i){super();for(const s of t.song.channels)s.bars.splice(e,i),0==s.bars.length&&s.bars.push(0);t.song.barCount=Math.max(1,t.song.barCount-i),t.bar=Math.max(0,t.bar-i),t.barScrollPos=Math.max(0,t.barScrollPos-i),t.song.loopStart>=e?t.song.loopStart=Math.max(0,t.song.loopStart-i):t.song.loopStart+t.song.loopLength>e&&(t.song.loopLength-=i),t.song.loopLength=Math.max(1,Math.min(t.song.barCount-t.song.loopStart,t.song.loopLength)),t.notifier.changed(),this.J()}}class Qt extends Ct{constructor(t,e,i,s){super(),t.song.channels.splice(e+s,0,...t.song.channels.splice(e,i-e+1)),t.notifier.changed(),this.J()}}class Xt extends Ct{constructor(t,i,s){if(super(),t.song.pitchChannelCount!=i||t.song.noiseChannelCount!=s){const n=[];function o(i,s,o,r,h,a){for(let l=0;l=i;){const e=t.song.getChannelIsNoise(s);t.song.channels.splice(s,1),e?t.song.noiseChannelCount--:t.song.pitchChannelCount--,s--}t.song.pitchChannelCountn&&h--:i.controlPointCount<=1&&(s=e.instrumentAutomationTargets.dictionary.none.index,h=0))}this.Mt.push(s),this.xt.push(h)}this.J(),this.redo()}tt(){this.Pt.controlPoints.splice(this.I,0,this.It),this.Pt.controlPointCount++,this.Pt.controlPoints.length=this.Pt.controlPointCount,this.wt.preset=this.St;for(let t=0;t=s)return;const n=Je(i),o=x.valueToPreset(n),r=new gt(i);r.fromJsonObject(o.settings,i,1),r.preset=n,r.volume=1,e.instruments.push(r),t.viewedInstrument[t.channel]=e.instruments.length-1,t.notifier.changed(),this.J()}}class qe extends Ct{constructor(t){super();const i=t.song.channels[t.channel];if(i.instruments.length<=e.instrumentCountMin)return;const s=t.viewedInstrument[t.channel];if(i.instruments.splice(s,1),t.song.patternInstruments)for(const t of i.patterns){for(let e=0;es&&t.instruments[e]--;t.instruments.length<=0&&(t.instruments[0]=0)}t.notifier.changed(),this.J()}}class Ee extends Ct{constructor(t,e){super(),t.viewedInstrument[t.channel]!=e&&(t.viewedInstrument[t.channel]=e,t.notifier.changed(),this.J())}}class Ce extends Ct{constructor(t,e,i){super();const s=t.song.layeredInstruments,n=t.song.patternInstruments;if(s!=e||n!=i){t.song.layeredInstruments=e,t.song.patternInstruments=i;for(let e=0;et.song.getMaxInstrumentsPerChannel()&&(s.instruments.length=t.song.getMaxInstrumentsPerChannel());for(let o=0;os)throw new Error;r=t+1}else if(e.notes[t].start=n)break;const a=new ht(o.pitches[0],i,h,o.pins[0].size,!1);a.pitches.length=0;for(const t of o.pitches)a.pitches.push(t);a.pins.length=0;for(const t of o.pins)a.pins.push(rt(t.interval,t.time,t.size));a.continuesLastPattern=!0===o.continuesLastPattern&&0==a.start,e.notes.splice(r++,0,a),a.end>n&&this.append(new li(t,a,a.start,n))}s+=o}t.notifier.changed(),this.J()}}class Ne extends zt{constructor(t,e,i){super(),e.fromJsonObject(i,i.isDrum),t.notifier.changed(),this.J()}}class Re extends Ct{constructor(t,e,i,s){super(),At(i,s.instruments)||(s.instruments.length=0,s.instruments.push(...i),Bt(s.instruments,t.song,e),this.J(),t.notifier.changed())}}class He extends Ct{constructor(t,e){if(super(),t.song.patternsPerChannel!=e){for(let i=0;ie&&(s[t]=0);for(let t=n.length;th&&(a||(this.ut.length>0&&(n=e.continuesLastPattern),this.ut.push(rt(this.ct[i].interval,s,this.ct[i].size)),a=!0),this.ut.push(rt(o.interval,l,o.size)))}a||(n=e.continuesLastPattern,this.ut.push(rt(this.ct[i].interval,s,this.ct[i].size))),this.bt(n)}}class _e extends Gt{constructor(t,i,s,n,o,r){super(t,i),s-=this.ot,n-=this.ot,o-=i.pitches[r];let h,a,l,c,u=!1,f=!1,p=0,d=e.noteSizeMax,m=!0;for(n>s?(h=0,a=1,l=i.pins.length,c=t=>{this.ut.push(t)}):(h=i.pins.length-1,a=-1,l=-1,c=t=>{this.ut.unshift(t)});h!=l;h+=a){const t=i.pins[h],e=t.time;for(;;)if(u){if(f){if(e*a==n*a)break;t.interval!=p&&(m=!1),c(rt(m?o:t.interval,e,t.size));break}if(e*a<=n*a&&(p=t.interval,d=t.size),e*a=t))break;r+=s}return r}return Math.round(i/s)*s};let o=0;for(;o=n(e.end)?this.append(new ai(t,i,e,o,!0)):(this.append(new Ve(t,e,n)),o++)}}}class Ve extends Gt{constructor(t,e,i){super(t,e);for(const t of this.ct)this.ut.push(rt(t.interval,i(t.time+this.ot)-this.ot,t.size));this.bt()}}class je extends zt{constructor(t,i,s){super();let n=Math.round(i%t.song.beatsPerBar*e.partsPerBeat);if(n<0&&(n+=t.song.beatsPerBar*e.partsPerBeat),0!=n){switch(s){case"wrapAround":{const i=e.partsPerBeat*t.song.beatsPerBar;for(const e of t.song.channels)for(const t of e.patterns){const e=[];for(let s=1;s>=0;s--){const o=s*i;for(const s of t.notes){const t=s.start+n,r=s.end+n,h=Math.max(0,t-o),a=Math.min(i,r-o);hi){const s=new Dt;for(let n=0;n=e(i.end)?this.append(new ai(t,n,i,o,!0)):(this.append(new Ve(t,i,e)),o++)}}this.append(new si(t,t.song.tempo,t.song.tempo*i/t.song.beatsPerBar))}break;case"overflow":this.append(new Ht(t,i,0)),t.song.loopStart=0,t.song.loopLength=t.song.barCount;break;default:throw new Error("Unrecognized beats-per-bar conversion strategy.")}t.song.beatsPerBar=i,t.notifier.changed(),this.J()}}}class Ke extends zt{constructor(t,e){super(),t.song.scale!=e&&(t.song.scale=e,t.notifier.changed(),this.J())}}class Ye extends zt{constructor(t){super();const i=t.song,s=e.keys[i.key].basePitch,n=[0,0,0,0,0,0,0,0,0,0,0,0];for(let t=0;t0,!0));i.key=o,t.notifier.changed(),this.J()}}}function Je(t){const e=[];for(let i=0;i.5?"chip noise":"standard drumset"):Je(s),o=x.valueToPreset(n);i.fromJsonObject(o.settings,s,1),i.preset=n,i.volume=1}}class Xe extends zt{constructor(t,e){if(super(),t.song.fromBase64String(e),""==e){this.append(new mi(t,0,0)),t.selection.resetBoxSelection(),Qe(t.song),t.song.scale=t.prefs.defaultScale;for(let e=0;e<=t.song.channels.length;e++)t.viewedInstrument[e]=0,t.recentPatternInstruments[e]=[0];t.viewedInstrument.length=t.song.channels.length}else this.append(new Ze(t));t.notifier.changed(),this.J()}}class Ze extends Ct{constructor(t){super();const e=Math.min(t.channel,t.song.getChannelCount()-1),i=Math.max(0,Math.min(t.song.barCount-1,t.bar));t.channel==e&&t.bar==i||(t.bar=i,t.channel=e,this.J()),t.selection.scrollToSelectedPattern(),t.notifier.changed()}}class ti extends zt{constructor(t,i,s){super();const n=t.song;function o(t,e){for(;t.length>e;){let e=t.length-1,i=0;for(let s=0;s=i&&(e=s,i=n)}t.splice(e,1)}}for(o(i,e.pitchChannelCountMax),o(s,e.noiseChannelCountMax);i.lengthn.patternsPerChannel||e.bars[t]<0)&&(e.bars[t]=0);for(;e.bars.lengthn.getMaxInstrumentsPerChannel()&&(e.instruments.length=n.getMaxInstrumentsPerChannel());for(const i of e.patterns)Bt(i.instruments,n,t);for(;e.patterns.lengthi&&!r&&(this.ut.push(rt(a,i,h)),r=!0),!(t.time<=s))break;if(this.ut.push(rt(t.interval,t.time,t.size)),t.time==s){l=!1;break}}}l&&this.ut.push(rt(this.ct[o].interval,s,this.ct[o].size)),this.bt(n)}}class ci extends Dt{constructor(t,e,i,s,n){super();let o=0;for(;o=s)break;if(r.starts){const n=r.clone();this.append(new li(t,r,r.start,i)),o++,this.append(new ai(t,e,n,o,!1)),this.append(new li(t,n,s,n.end)),o++}else r.starts?(this.append(new li(t,r,s,r.end)),o++):this.append(new ai(t,e,r,o,!0))}}}}class ui extends Dt{constructor(t,e){super();let i=0;for(;i=0;i--)if(h||o||e.scales[t.song.scale].flags[i%12]){s=i;break}let l=!1;for(let t=0;te+a&&(c=e+a)}for(const i of this.ct){let s=i.interval+this.ft[0];if(sc&&(s=c),r&&!h)s=n?Math.min(c,s+12):Math.max(l,s-12);else if(n){for(let i=s+1;i<=c;i++)if(h||o||e.scales[t.song.scale].flags[i%12]){s=i;break}}else for(let i=s-1;i>=l;i--)if(h||o||e.scales[t.song.scale].flags[i%12]){s=i;break}s-=this.dt[0],this.ut.push(rt(s,i.time,i.size))}if(0!=this.ut[0].interval)throw new Error("wrong pin start interval");for(let t=1;t=t.selection.patternSelectionEnd)||this.append(new fi(t,e,r,s,n,o))}}class di extends Ct{constructor(t,e,i,s,n){super(),t.selection.boxSelectionX0=e,t.selection.boxSelectionX1=i,t.selection.boxSelectionY0=s,t.selection.boxSelectionY1=n,t.notifier.changed(),this.J()}}class mi extends Lt{constructor(t,e,i){super(!1),this.j=t,this.ot=t.selection.patternSelectionStart,this.rt=t.selection.patternSelectionEnd,this.jt=t.selection.patternSelectionActive,this.ht=e,this.lt=i,this.Wt=e=h?(f++,e.end<=a&&(u=f)):(c.push(e.clone()),this.append(new ai(t,s,e,f,!0)))}for(const e of c)if(e.start+=n,e.end+=n,!(e.end<=a||e.start>=l)){this.append(new ai(t,s,e,u++,!1)),this.append(new li(t,e,Math.max(e.start,a),Math.min(l,e.end)));for(let s=0;s0,t.prefs.notesOutsideScale))}}}class gi extends zt{constructor(t,i,s,n,o){super();for(let r=n;r=i+s)&&t.song.channels[r].bars[e]==h){a=!0;break}if(a){const i=t.song.getPattern(r,o);this.append(new Wt(t,0,o,r,1,1)),this.append(new Ge(t,r,o));const s=t.song.getPattern(r,o);if(null==s)throw new Error;this.append(new Oe(t,s,i.notes,0,e.partsPerBeat*t.song.beatsPerBar,e.partsPerBeat*t.song.beatsPerBar)),s.instruments.length=0,s.instruments.push(...i.instruments),n[String(h)]=t.song.channels[r].bars[o]}else n[String(h)]=h}this.append(new Wt(t,n[String(h)],o,r,1,1))}}}}}class bi extends Ct{constructor(t,i,s){super(),t.selection.patternSelectionActive&&new ui(t,i);const n=e.maxPitch;for(const e of i.notes){if(t.selection.patternSelectionActive&&(e.end<=t.selection.patternSelectionStart||e.start>=t.selection.patternSelectionEnd))continue;const i=[],o=[];for(let t=0;te+n&&(h=e+n)}for(const t of e.pins){let n=t.interval+e.pitches[0];nh&&(n=h);const a=s[n%12]+(n-n%12);o.push(rt(a-i[0],t.time,t.size))}if(0!=o[0].interval)throw new Error("wrong pin start interval");for(let t=1;t{const t=this._e();this.de.length=this.j.song.getChannelCount();for(let i=0;i{this.pe&&!this.be&&!this.ue&&this.le&&performance.now()>this.we+1e3&&this.Ee.valid&&this.j.lastChangeWas(this.Ie)&&(this.Ie.undo(),this.be=!0,this.Ve(),this.j.notifier.notifyWatchers());const e=Math.floor(this.j.synth.playhead);if(this.j.synth.playing&&(null!=this.Vt&&this.j.song.getPattern(this.j.channel,Math.floor(this.j.synth.playhead))==this.Vt||Math.floor(this.j.synth.playhead)==this.j.bar+this.Yt)){this.te.setAttribute("visibility","visible");const t=this.j.synth.playhead-e;Math.abs(t-this.Ce)>.1?this.Ce=t:this.Ce+=.2*(t-this.Ce),this.te.setAttribute("x",""+M(this.Ce*this.je-2))}else this.te.setAttribute("visibility","hidden");this.j.synth.playing&&(this.j.synth.recording||this.j.prefs.autoFollow)&&this.$e!=e&&(new ee(this.j,this.j.channel,e),this.j.notifier.notifyWatchers()),this.$e=e,this.j.currentPatternIsDirty&&this.We(),window.requestAnimationFrame(this.Ue)},this.Ke=t=>{this.ce||(this.ce=!0,this.pe=!1)},this.Ye=t=>{this.ce&&(this.ce=!1)},this.Je=t=>{t.preventDefault();const e=this.se.getBoundingClientRect();this.he=((t.clientX||t.pageX)-e.left)*this.je/(e.right-e.left),this.ae=((t.clientY||t.pageY)-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.pe=!1,this.ge=t.ctrlKey||t.metaKey,this.be=t.shiftKey,this.Ve()},this.Xe=t=>{t.preventDefault();const e=this.se.getBoundingClientRect();this.he=(t.touches[0].clientX-e.left)*this.je/(e.right-e.left),this.ae=(t.touches[0].clientY-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.pe=!0,this.ge=t.ctrlKey||t.metaKey,this.be=t.shiftKey,this.we=performance.now(),this.Ve()},this.Ze=t=>{const e=this.se.getBoundingClientRect();this.he=((t.clientX||t.pageX)-e.left)*this.je/(e.right-e.left),this.ae=((t.clientY||t.pageY)-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.pe=!1,this.ti()},this.ei=t=>{if(!this.le)return;t.preventDefault();const e=this.se.getBoundingClientRect();this.he=(t.touches[0].clientX-e.left)*this.je/(e.right-e.left),this.ae=(t.touches[0].clientY-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.ti()},this.ii=t=>{if(!this.Ee.valid)return;const i=this.j.lastChangeWas(this.Ie);if(this.le&&i&&null!=this.Ie)if(this.Me)this.j.record(this.Ie),this.Ie=null;else if(this.ve||this.ke||this.be)this.si(this.Ie),this.Ie=null;else if(this.ue||null==this.Ee.curNote||!this.Ie.isNoop()||this.ve||this.ke||this.Me||this.be)this.j.record(this.Ie),this.Ie=null;else{if(null==this.Vt)throw new Error;const t=new Dt;if(t.append(new mi(this.j,0,0)),-1==this.Ee.pitchIndex){if(this.Ee.curNote.pitches.length==e.maxChordSize&&t.append(new De(this.j,this.Ee.curNote,this.Ee.curNote.pitches[0],0,!0)),t.append(new De(this.j,this.Ee.curNote,this.Ee.pitch,this.Ee.curNote.pitches.length)),this.ni(this.Ee.curNote),this.j.prefs.enableNotePreview&&!this.j.synth.playing){const t=Math.min(e.partsPerBeat,this.Ee.end-this.Ee.start);this.j.performance.setTemporaryPitches(this.Ee.curNote.pitches,t)}}else 1==this.Ee.curNote.pitches.length?t.append(new ai(this.j,this.Vt,this.Ee.curNote,this.Ee.curIndex,!0)):t.append(new De(this.j,this.Ee.curNote,this.Ee.pitch,this.Ee.curNote.pitches.indexOf(this.Ee.pitch),!0));this.j.record(t)}this.le=!1,this.ue=!1,this.ve=!1,this.ke=!1,this.Me=!1,this.qe=!1,this.oi(),this.ri()};for(let t=0;tthis.je||this.ae<0||this.ae>this.Qe||this.re<=0)return;const t=this.ai();if(this.Ee.exactPart=this.he/this.ci,this.Ee.part=Math.floor(Math.max(0,Math.min(this.j.song.beatsPerBar*e.partsPerBeat-t,this.Ee.exactPart))/t)*t,null!=this.Vt)for(const t of this.Vt.notes)if(t.end<=this.Ee.exactPart)this.Ee.prevNote=t,this.Ee.curIndex++;else if(t.start<=this.Ee.exactPart&&t.end>this.Ee.exactPart)this.Ee.curNote=t;else if(t.start>this.Ee.exactPart){this.Ee.nextNote=t;break}let i=this.ui(this.ae);if(null!=this.Ee.curNote){this.Ee.start=this.Ee.curNote.start,this.Ee.end=this.Ee.curNote.end,this.Ee.pins=this.Ee.curNote.pins;let t,e=0,s=0,n=this.Ee.curNote.pins[0];for(let i=1;ir)continue;if(this.het.interval&&(o=t.interval),re&&(h=e,this.Ee.nearPinIndex=this.Ee.curNote.pins.indexOf(t))}if(i-=e,this.Ee.pitch=this.fi(i,-o,this.hi()-r),!this.j.song.getChannelIsNoise(this.j.channel)){let t=s;for(let e=0;et||(t=s,this.Ee.pitch=this.Ee.curNote.pitches[e])}}for(let t=0;te.partsPerBeat)this.Ee.start=s*e.partsPerBeat;else if(t==e.partsPerBeat)this.Ee.start=s*e.partsPerBeat,nn&&(this.Ee.start+=Math.floor(o/n)*n);else{this.Ee.start=s*e.partsPerBeat;let i=e.partsPerBeat%t==0?t:Math.min(t,n);for(;ih&&(this.Ee.end=h)):this.Ee.end>h&&(this.Ee.end=h,this.Ee.start=this.Ee.end-t,this.Ee.starts&&(t=s);const n=this.j.prefs.notesOutsideScale?e.scales.dictionary.expert.flags:e.scales[this.j.song.scale].flags;if(n[Math.floor(t)%e.pitchesPerOctave]||this.j.song.getChannelIsNoise(this.j.channel))return Math.floor(t);{let o=Math.floor(t)+1,r=Math.floor(t)-1;for(;!n[o%e.pitchesPerOctave];)o++;for(;!n[r%e.pitchesPerOctave];)r--;if(o>s)return rh-t?o:r}}ni(t){this.pi=[];for(const e of t.pins)this.pi.push(rt(0,e.time,e.size));for(let t=1;t5&&(this.ue=!0,this.fe=Math.abs(t)>=Math.abs(e))}if(this.ue&&this.le&&this.Ee.valid&&t){this.Ie.undo();const t=new Dt;this.Ie=t,this.j.setProspectiveChange(this.Ie);const i=this.ai(),s=this.li(this.he/this.ci);if(this.ve)t.append(new mi(this.j,Math.max(0,Math.min(this.j.song.beatsPerBar*e.partsPerBeat,s)),this.j.selection.patternSelectionEnd)),this.bi();else if(this.ke)t.append(new mi(this.j,this.j.selection.patternSelectionStart,Math.max(0,Math.min(this.j.song.beatsPerBar*e.partsPerBeat,s)))),this.bi();else if(this.Me){const t=this.j.getCurrentPattern(this.Yt);if(this.ue&&null!=t){this.Ie.undo();const s=new Dt;this.Ie=s,this.j.setProspectiveChange(this.Ie);const n=e.scales[this.j.song.scale].flags.filter((t=>t)).length,o=this.j.song.getChannelIsNoise(this.j.channel)?1:12/n,r=Math.round((this.he-this.me)/(this.ci*i))*i,h=Math.round((this.ye-this.ae)/(this.re*o));s.append(new yi(this.j,this.j.channel,t,r,h))}}else if(this.be){if(this.ue){let i=Math.max(0,Math.min((this.j.song.beatsPerBar-1)*e.partsPerBeat,Math.floor(this.Ee.exactPart/e.partsPerBeat)*e.partsPerBeat)),n=i+e.partsPerBeat;if(null!=this.Ee.curNote&&(i=Math.max(i,this.Ee.curNote.start),n=Math.min(n,this.Ee.curNote.end)),sn){n=e.partsPerBeat*this.j.song.beatsPerBar;const t=this.j.getCurrentPattern(this.Yt);if(null!=t)for(let e=0;e=s){n=t.notes[e].start;break}if(t.notes[e].end>=s){n=t.notes[e].end;break}}for(let t=0;t<=this.j.song.beatsPerBar;t++){const i=t*e.partsPerBeat;s=5*i&&t%e.partsPerBeat!=0&&t!=3*e.partsPerBeat/4&&t!=3*e.partsPerBeat/2&&t!=4*e.partsPerBeat/3)continue;const s=t;if(s==o){a=s;break}if(so){athis.j.song.beatsPerBar*e.partsPerBeat&&(h=this.j.song.beatsPerBar*e.partsPerBeat),r=h);s++);const o=new ht(this.Ee.pitch,r,h,e.noteSizeMax,this.j.song.getChannelIsNoise(this.j.channel));o.continuesLastPattern=l,t.append(new ai(this.j,i,o,s)),this.ni(o),this.xe=n?r:h,this.Se=this.Ee.pitch,this.Fe=o.pins[n?0:1].size,this.Pe=!0}this.Vt=this.j.getCurrentPattern(this.Yt)}else if(this.fe){t.append(new mi(this.j,0,0));const s=(this.he-this.me)/this.ci,n=this.Ee.curNote.pins[this.Ee.nearPinIndex];let o=Math.round((this.Ee.curNote.start+n.time+s)/i)*i;const r=o<0;if(o<0&&(o=0),o>this.j.song.beatsPerBar*e.partsPerBeat&&(o=this.j.song.beatsPerBar*e.partsPerBeat),null==this.Vt)throw new Error;if(o<=this.Ee.curNote.start&&this.Ee.nearPinIndex==this.Ee.curNote.pins.length-1||o>=this.Ee.curNote.end&&0==this.Ee.nearPinIndex)t.append(new ai(this.j,this.Vt,this.Ee.curNote,this.Ee.curIndex,!0)),this.Pe=!1;else{const e=Math.min(this.Ee.curNote.start,o),i=Math.max(this.Ee.curNote.end,o);this.xe=o,this.Se=this.Ee.curNote.pitches[-1==this.Ee.pitchIndex?0:this.Ee.pitchIndex]+this.Ee.curNote.pins[this.Ee.nearPinIndex].interval,this.Fe=this.Ee.curNote.pins[this.Ee.nearPinIndex].size,this.Pe=!0,t.append(new ci(this.j,this.Vt,e,i,this.Ee.curNote)),t.append(new $e(this.j,this.Ee.curNote,this.Ee.nearPinIndex,o,r)),this.ni(this.Ee.curNote)}}else if(-1==this.Ee.pitchIndex){t.append(new mi(this.j,0,0));const s=Math.max(this.Ee.curNote.start,Math.min(this.Ee.curNote.end,Math.round(this.he/(this.ci*i))*i))-this.Ee.curNote.start;let n,o=this.Ee.curNote.pins[0],r=0,h=0;for(let t=1;to.time)continue;if(se.noteSizeMax&&(r=e.noteSizeMax),h=this.fi(Math.round(n.interval*(1-i)+o.interval*i+this.Ee.curNote.pitches[0]),0,this.hi())-this.Ee.curNote.pitches[0];break}this.xe=this.Ee.curNote.start+s,this.Se=this.Ee.curNote.pitches[-1==this.Ee.pitchIndex?0:this.Ee.pitchIndex]+h,this.Fe=r,this.Pe=!0,t.append(new ki(this.j,this.Ee.curNote,s,r,h,this.ge)),this.ni(this.Ee.curNote)}else{if(t.append(new mi(this.j,0,0)),this.Fe=this.Ee.curNote.pins[this.Ee.nearPinIndex].size,null==this.Vt)throw new Error;let n,o;this.he>=this.me?(n=Math.max(this.Ee.curNote.start,this.Ee.part),o=s+i):(n=Math.min(this.Ee.curNote.end,this.Ee.part+i),o=s),o<0&&(o=0),o>this.j.song.beatsPerBar*e.partsPerBeat&&(o=this.j.song.beatsPerBar*e.partsPerBeat),o>this.Ee.curNote.end&&t.append(new ci(this.j,this.Vt,this.Ee.curNote.start,o,this.Ee.curNote)),ot&&(r=t),h=0;t--){if(t==this.j.channel)continue;if(this.j.song.getChannelIsNoise(t)!=this.j.song.getChannelIsNoise(this.j.channel))continue;const i=this.j.song.getPattern(t,this.j.bar+this.Yt);if(null==i)continue;const s=this.j.getBaseVisibleOctave(t)*e.pitchesPerOctave;for(const e of i.notes)for(const i of e.pitches){const n=A.path();n.setAttribute("fill",$.getChannelColor(this.j.song,t).secondaryNote),n.setAttribute("pointer-events","none"),this.vi(n,i,e.start,e.pins,.19*this.re,!1,s),this.Zt.appendChild(n)}}if(null!=this.Vt){const t=this.j.song.channels[this.j.channel].instruments[this.j.getCurrentInstrument()],e=t.getChord(),i=t.getTransition(),s=e.customInterval||e.arpeggiates||e.strumParts>0||i.slides;for(const t of this.Vt.notes)for(let e=0;e1&&s){const s=A.text();s.setAttribute("x",""+M(this.ci*t.start+o)),s.setAttribute("y",""+M(this.wi(i-this.Le))),s.setAttribute("width","30"),s.setAttribute("fill",$.invertedText),s.setAttribute("text-anchor","start"),s.setAttribute("dominant-baseline","central"),s.setAttribute("pointer-events","none"),s.textContent=""+(e+1),this.Zt.appendChild(s)}}}this.j.currentPatternIsDirty=!1}vi(t,i,s,n,o,r,h){const a=this.ci*(n[n.length-1].time+n[0].time),l=.5*Math.min(2,a-1);let c=n[0],u="M "+M(this.ci*(s+c.time)+l)+" "+M(this.wi(i-h)+o*(r?c.size/e.noteSizeMax:1))+" ";for(let t=1;tc.interval&&(u+="L "+M(f+1)+" "+M(d-o*y)+" "),a.interval=0;t--){let a=c;c=n[t];let f=this.ci*(s+a.time)-(t==n.length-2?l:0),p=this.ci*(s+c.time)+(0==t?l:0),d=this.wi(i+a.interval-h),m=this.wi(i+c.interval-h),y=r?a.size/e.noteSizeMax:1,g=r?c.size/e.noteSizeMax:1;u+="L "+M(f)+" "+M(d+o*y)+" ",a.intervalc.interval&&(u+="L "+M(p+1)+" "+M(m+o*g)+" "),u+="L "+M(p)+" "+M(m+o*g)+" "}u+="z",t.setAttribute("d",u)}wi(t){return this.re*(this.gi-t-.5)}}class Ei{constructor(t){this.j=t,this.container=D.div({class:"envelopeEditor"}),this.ki=[],this.Mi=[],this.xi=[],this.Si=[],this.Fi=0,this.Pi=-1,this.Ii=-1,this.Ti=0,this.qi=t=>{const i=this.Mi.indexOf(t.target),s=this.xi.indexOf(t.target);if(-1!=i){const t=parseInt(this.Mi[i].value),s=t%e.instrumentAutomationTargets.length,n=t/e.instrumentAutomationTargets.length>>>0;this.j.record(new Pi(this.j,i,s,n))}else-1!=s&&this.j.record(new Ii(this.j,s,this.xi[s].selectedIndex))},this.Ei=t=>{const e=this.Si.indexOf(t.target);-1!=e&&this.j.record(new Fi(this.j,e))},this.container.addEventListener("change",this.qi),this.container.addEventListener("click",this.Ei)}Ci(t,i){let s=e.instrumentAutomationTargets[t].displayName;return e.instrumentAutomationTargets[t].maxCount>1&&(-1!=s.indexOf("#")?s=s.replace("#",String(i+1)):s+=" "+(i+1)),D.option({value:t+i*e.instrumentAutomationTargets.length},s)}Li(t,i){for(let s=0;s>>0;n.hidden=!i.supportsEnvelopeTarget(r,h)}}render(){const t=this.j.song.channels[this.j.channel].instruments[this.j.getCurrentInstrument()];if(this.j.prefs.alwaysShowSettings||t.preset==t.type){for(let i=this.ki.length;i{t.preventDefault();const e=this.se.getBoundingClientRect();this.he=(t.clientX||t.pageX)-e.left,this.Ve()},this.Xe=t=>{t.preventDefault();const e=this.se.getBoundingClientRect();this.he=t.touches[0].clientX-e.left,this.Ve()},this.Ze=t=>{if(null==this.container.offsetParent)return;const e=this.se.getBoundingClientRect();this.he=(t.clientX||t.pageX)-e.left,isNaN(this.he)&&(this.he=0),this.ti()},this.ei=t=>{if(null==this.container.offsetParent)return;if(!this.le)return;t.preventDefault();const e=this.se.getBoundingClientRect();this.he=t.touches[0].clientX-e.left,isNaN(this.he)&&(this.he=0),this.ti()},this.ii=t=>{if(null!=this.container.offsetParent){if(this.le&&this.j.lastChangeWas(this.Ie)&&null!=this.Ie)if(this.ue)this.j.record(this.Ie);else{const t=this.j.song.channels[this.j.channel].instruments[this.j.getCurrentInstrument()];this.Oi?this.j.record(new Me(this.j,this.Hi(this.he),t.fadeOut)):this.j.record(new Me(this.j,t.fadeIn,this.Gi(this.he)))}this.Ie=null,this.ue=!1,this.le=!1}};const i=this.$i(e.fadeOutNeutral);this.Ai.setAttribute("d",`M ${i} 0 L ${i} ${this.Qe}`),this.container.addEventListener("mousedown",this.Je),document.addEventListener("mousemove",this.Ze),document.addEventListener("mouseup",this.ii),this.container.addEventListener("touchstart",this.Xe),this.container.addEventListener("touchmove",this.ei),this.container.addEventListener("touchend",this.ii),this.container.addEventListener("touchcancel",this.ii)}_i(t){return 1+.4*(this.je-2)*t/(e.fadeInRange-1)}Hi(t){return tt(0,e.fadeInRange,Math.round((t-1)*(e.fadeInRange-1)/(.4*this.je-2)))}$i(t){return 1+(this.je-2)*(.5+.5*t/(e.fadeOutTicks.length-1))}Gi(t){return tt(0,e.fadeOutTicks.length,Math.round((e.fadeOutTicks.length-1)*((t-1)/(this.je-2)-.5)/.5))}Ve(){isNaN(this.he)&&(this.he=0),this.me=this.he,this.le=!0,this.ue=!1;const t=this.j.song.channels[this.j.channel].instruments[this.j.getCurrentInstrument()],e=this._i(t.fadeIn),i=this.$i(t.fadeOut);this.Oi=this.me<(e+i)/2,this.Ie=new Dt,this.j.setProspectiveChange(this.Ie)}ti(){if(null!=this.Ie&&this.j.lastChangeWas(this.Ie)?this.Ie.undo():this.le=!1,this.Ie=null,this.le){const t=new Dt;if(this.Ie=t,this.j.setProspectiveChange(this.Ie),Math.abs(this.he-this.me)>4&&(this.ue=!0),this.ue){const e=this.j.song.channels[this.j.channel].instruments[this.j.getCurrentInstrument()];this.Oi?t.append(new Me(this.j,this.Hi(this._i(e.fadeIn)+this.he-this.me),e.fadeOut)):t.append(new Me(this.j,e.fadeIn,this.Gi(this.$i(e.fadeOut)+this.he-this.me)))}}}render(){const t=this.j.song.channels[this.j.channel].instruments[this.j.getCurrentInstrument()];if(this.Ni==t.fadeIn&&this.Ri==t.fadeOut)return;const i=this._i(t.fadeIn),s=this.$i(t.fadeOut);this.Bi.setAttribute("d",`M ${i} 0 L ${i} ${this.Qe} M ${s} 0 L ${s} ${this.Qe}`);const n=this.$i(e.fadeOutNeutral);let o="";o+=`M 0 ${this.Qe} `,o+=`L ${i} 0 `,Ft.fadeOutSettingToTicks(t.fadeOut)>0?(o+=`L ${n} 0 `,o+=`L ${s} ${this.Qe} `):(o+=`L ${s} 0 `,o+=`L ${n} ${this.Qe} `),o+="z",this.Di.setAttribute("d",o)}}class Li{constructor(t,e=!1){this.j=t,this.je=120,this.Qe=26,this.Ui=A.path({fill:$.uiWidgetBackground,"pointer-events":"none"}),this.Vi=A.path({fill:"currentColor","pointer-events":"none"}),this.Ai=A.path({fill:"none",stroke:"currentColor","stroke-width":1,"stroke-dasharray":"3, 2","pointer-events":"none"}),this.ji=A.circle({fill:"white",stroke:"none","pointer-events":"none",r:4}),this.se=A.svg({style:`background-color: ${$.editorBackground}; touch-action: none;`,width:"100%",height:"100%",viewBox:"0 0 "+this.je+" "+this.Qe,preserveAspectRatio:"none"},this.Ui,this.Ai,this.ji,this.Vi),this.Wi=D.div({style:"position: absolute; bottom: 0; left: 2px; font-size: 8px; line-height: 1; pointer-events: none;"}),this.container=D.div({class:"filterEditor",style:"height: 100%; position: relative;"},this.se,this.Wi),this.Ki=2,this.Yi=!1,this.Ji=!1,this.he=0,this.ae=0,this.ce=!1,this.le=!1,this.ue=!1,this.Qi=!1,this.Xi=!1,this.Zi=2,this.ts=0,this.es=0,this.ss=0,this.Ie=null,this.ns=-1,this.os=-1,this.rs=-1,this.hs=-1,this.ls=-1,this.Ke=t=>{this.ce=!0},this.Ye=t=>{this.ce=!1,this.cs()},this.Je=t=>{t.preventDefault(),this.Ji=!1;const e=this.se.getBoundingClientRect();this.he=((t.clientX||t.pageX)-e.left)*this.je/(e.right-e.left),this.ae=((t.clientY||t.pageY)-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.Ve()},this.Xe=t=>{t.preventDefault(),this.Ji=!0;const e=this.se.getBoundingClientRect();this.he=(t.touches[0].clientX-e.left)*this.je/(e.right-e.left),this.ae=(t.touches[0].clientY-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.Ve()},this.Ze=t=>{if(null==this.container.offsetParent)return;const e=this.se.getBoundingClientRect();this.he=((t.clientX||t.pageX)-e.left)*this.je/(e.right-e.left),this.ae=((t.clientY||t.pageY)-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.le||this.us(),this.ti()},this.ei=t=>{if(null==this.container.offsetParent)return;this.le&&t.preventDefault();const e=this.se.getBoundingClientRect();this.he=(t.touches[0].clientX-e.left)*this.je/(e.right-e.left),this.ae=(t.touches[0].clientY-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.le||this.us(),this.ti()},this.ii=t=>{if(null!=this.container.offsetParent){if(this.le&&this.j.lastChangeWas(this.Ie)&&null!=this.Ie){if(this.Qi||this.ue||this.Ji)this.j.record(this.Ie);else if(this.ts=e.filterMaxPoints)&&n=0&&s=this.Pt.controlPointCount||-1==this.ts)this.Ie=null,this.le=!1;else{const i=this.fs(this.he)-this.es,s=this.ds(this.ae)-this.ss,n=this.Pt.controlPoints[this.ts],o=Math.max(0,Math.min(e.filterGainRange-1,Math.round(n.gain+s))),r=this.gs(this.Pt,n.freq+i,this.ts);0==Math.round(i)&&0==Math.round(s)&&r==n.freq&&o==n.gain||(this.ue=!0),r>=0&&r{const e=this.Ss.indexOf(t.target);-1!=e&&(this.j.song.channels[e].muted=!this.j.song.channels[e].muted,this.j.notifier.changed())},this.container.addEventListener("click",this.Ei)}render(){if(this.j.prefs.enableChannelMuting){if(this.Ss.length!=this.j.song.getChannelCount()){for(let t=this.Ss.length;t{this.j.selection.setPattern(this.Es.selectedIndex)},this.Ue=t=>{const e=this.Os*this.j.synth.playhead-2;this.Gs!=e&&(this.Gs=e,this.Ps.setAttribute("x",""+e)),window.requestAnimationFrame(this.Ue)},this._s=t=>{this.Bs=!0,this.ue=!0,this.Us(t),this.Ls=this.Ds,this.zs=this.As},this.Vs=t=>{this.Us(t),this.Ls==this.Ds&&this.zs==this.As||t.preventDefault(),this.Bs&&this.js(),this.ri()},this.Ws=t=>{this.Bs=!1,this.ue=!1,this.ri()},this.Ke=t=>{this.ce||(this.ce=!0)},this.Ye=t=>{this.ce&&(this.ce=!1)},this.Je=t=>{t.preventDefault(),this.Bs=!0,this.Ks(t),this.Ls=this.Ds,this.zs=this.As,t.shiftKey?(this.ue=!0,this.j.selection.setTrackSelection(this.j.selection.boxSelectionX0,this.Ds,this.j.selection.boxSelectionY0,this.As),this.j.selection.selectionUpdated()):(this.ue=!1,this.j.channel==this.As&&this.j.bar==this.Ds||(this.j.selection.setChannelBar(this.As,this.Ds),this.ue=!0),this.j.selection.resetBoxSelection())},this.Ze=t=>{this.Ks(t),this.Bs&&(this.Ls==this.Ds&&this.zs==this.As||(this.ue=!0),this.js()),this.ri()},this.Ys=t=>{if(this.Bs&&!this.ue&&this.j.channel==this.As&&this.j.bar==this.Ds){const t=this.ae%Di.patternHeight{e||(this.Ji=!1,this.ri()),e=!0}),!0),document.addEventListener("touchstart",(()=>{e||(this.Ji=!0,this.ri()),e=!0}),!0)}movePlayheadToMouse(){return!!this.ce&&(this.j.synth.playhead=this.Ds+this.he%this.Os/this.Os,!0)}js(){this.j.selection.setTrackSelection(this.j.selection.boxSelectionX0,this.Ds,this.j.selection.boxSelectionY0,this.As),this.j.selection.selectionUpdated()}Us(t){const e=this.se.getBoundingClientRect();this.he=t.touches[0].clientX-e.left,this.ae=t.touches[0].clientY-e.top,isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.Ds=Math.floor(Math.min(this.j.song.barCount-1,Math.max(0,this.he/this.Os))),this.As=Math.floor(Math.min(this.j.song.getChannelCount()-1,Math.max(0,this.ae/Di.patternHeight)))}Ks(t){const e=this.se.getBoundingClientRect();this.he=(t.clientX||t.pageX)-e.left,this.ae=(t.clientY||t.pageY)-e.top,this.Ds=Math.floor(Math.min(this.j.song.barCount-1,Math.max(0,this.he/this.Os))),this.As=Math.floor(Math.min(this.j.song.getChannelCount()-1,Math.max(0,this.ae/Di.patternHeight)))}ri(){let t=this.As,e=this.Ds;this.Ji&&(e=this.j.bar,t=this.j.channel);const i=e==this.j.bar&&t==this.j.channel;if(!this.ce||this.Bs||i?this.Is.style.visibility="hidden":(this.Is.setAttribute("x",""+(1+this.Os*e)),this.Is.setAttribute("y",""+(1+Di.patternHeight*t)),this.Is.setAttribute("height",""+(Di.patternHeight-2)),this.Is.setAttribute("width",""+(this.Os-2)),this.Is.style.visibility="visible"),(this.ce||this.Ji)&&i){const i=this.ae%Di.patternHeight\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t'),Ri("Small")),Ni({class:"layout-option"},$i({type:"radio",name:"layout",value:"long"}),A('\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t'),Ri("Long")),Ni({class:"layout-option"},$i({type:"radio",name:"layout",value:"tall"}),A('\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t'),Ri("Tall"))),this.container=Ri({class:"prompt noSelection",style:"width: 300px;"},Gi("Layout"),this.Zs,Ri({style:"display: flex; flex-direction: row-reverse; justify-content: space-between;"},this.Qs),this.Xs),this.K=()=>{this.j.undo()},this.cleanUp=()=>{this.Qs.removeEventListener("click",this.tn),this.Xs.removeEventListener("click",this.K),this.container.removeEventListener("keydown",this.en)},this.en=t=>{"BUTTON"!=t.target.tagName&&13==t.keyCode&&this.tn()},this.tn=()=>{this.j.prefs.layout=this.Zs.elements.layout.value,this.j.prefs.save(),U.setLayout(this.j.prefs.layout),this.K()},this.Js.select(),setTimeout((()=>this.Js.focus())),this.Qs.addEventListener("click",this.tn),this.Xs.addEventListener("click",this.K),this.container.addEventListener("keydown",this.en),this.Zs.elements.layout.value=this.j.prefs.layout}}class Ui{constructor(t){this.j=t,this.Qe=20,this.sn=0,this.nn=1,this.rn=2,this.hn=A.path({fill:"none",stroke:$.loopAccent,"stroke-width":4}),this.ji=A.path({fill:$.hoverPreview,"pointer-events":"none"}),this.se=A.svg({style:"touch-action: pan-y; position: absolute;",height:this.Qe},this.hn,this.ji),this.container=D.div({class:"loopEditor"},this.se),this.Os=32,this.an=null,this.Ee={startBar:-1,mode:-1},this.he=0,this.ln=0,this.cn=0,this.un=!1,this.fn=!1,this.le=!1,this.ce=!1,this.pn=-1,this.dn=-1,this.mn=0,this.ks=-1,this.Ke=t=>{this.ce||(this.ce=!0,this.ri())},this.Ye=t=>{this.ce&&(this.ce=!1,this.ri())},this.Je=t=>{t.preventDefault(),this.le=!0;const e=this.se.getBoundingClientRect();this.he=(t.clientX||t.pageX)-e.left,this.oi(),this.ri(),this.Ze(t)},this.Xe=t=>{this.le=!0;const e=this.se.getBoundingClientRect();this.he=t.touches[0].clientX-e.left,this.oi(),this.ri(),this.ln=t.touches[0].clientX,this.cn=t.touches[0].clientY,this.fn=!1,this.un=!1},this.Ze=t=>{const e=this.se.getBoundingClientRect();this.he=(t.clientX||t.pageX)-e.left,this.ti()},this.ei=t=>{if(!this.le)return;const e=this.se.getBoundingClientRect();this.he=t.touches[0].clientX-e.left,this.fn||this.un||(Math.abs(t.touches[0].clientY-this.cn)>10?this.un=!0:Math.abs(t.touches[0].clientX-this.ln)>10&&(this.fn=!0)),this.fn&&(this.ti(),t.preventDefault())},this.yn=t=>{t.preventDefault(),this.un||(this.ti(),this.ce=!1,this.ii(t),this.ri()),this.le=!1},this.ii=t=>{null!=this.an&&this.j.record(this.an),this.an=null,this.le=!1,this.oi(),this.gn()},this.bn=()=>{this.gn()},this.oi(),this.gn(),this.j.notifier.watch(this.bn),this.container.addEventListener("mousedown",this.Je),document.addEventListener("mousemove",this.Ze),document.addEventListener("mouseup",this.ii),this.container.addEventListener("mouseover",this.Ke),this.container.addEventListener("mouseout",this.Ye),this.container.addEventListener("touchstart",this.Xe),this.container.addEventListener("touchmove",this.ei),this.container.addEventListener("touchend",this.yn),this.container.addEventListener("touchcancel",this.yn)}oi(){const t=this.he/this.Os;this.Ee.startBar=t,t>this.j.song.loopStart-.25&&tthis.j.song.barCount&&(e-=i-this.j.song.barCount,i=this.j.song.barCount),{start:e,length:i-e}}ti(){if(this.le){let t=this.j.song.loopStart,e=this.j.song.loopStart+this.j.song.loopLength;null!=this.an&&this.j.lastChangeWas(this.an)&&(t=this.an.oldStart,e=t+this.an.oldLength);const i=this.he/this.Os;let s,n,o;if(this.Ee.mode==this.sn)s=t+Math.round(i-this.Ee.startBar),n=e,s<0&&(s=0),s>=this.j.song.barCount&&(s=this.j.song.barCount),s==n?s=n-1:s>n&&(o=s,s=n,n=o),this.an=new ze(this.j,t,e-t,s,n-s);else if(this.Ee.mode==this.nn)s=t,n=e+Math.round(i-this.Ee.startBar),n<0&&(n=0),n>=this.j.song.barCount&&(n=this.j.song.barCount),n==s?n=s+1:n{t.preventDefault(),this.le=!0;const e=this.se.getBoundingClientRect();this.he=((t.clientX||t.pageX)-e.left)*this.je/(e.right-e.left),this.ae=((t.clientY||t.pageY)-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.Pn=this.fs(this.he),this.In=this.qn(this.ae),this.ti()},this.Xe=t=>{t.preventDefault(),this.le=!0;const e=this.se.getBoundingClientRect();this.he=(t.touches[0].clientX-e.left)*this.je/(e.right-e.left),this.ae=(t.touches[0].clientY-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.Pn=this.fs(this.he),this.In=this.qn(this.ae),this.ti()},this.Ze=t=>{if(null==this.container.offsetParent)return;const e=this.se.getBoundingClientRect();this.he=((t.clientX||t.pageX)-e.left)*this.je/(e.right-e.left),this.ae=((t.clientY||t.pageY)-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.ti()},this.ei=t=>{if(null==this.container.offsetParent)return;if(!this.le)return;t.preventDefault();const e=this.se.getBoundingClientRect();this.he=(t.touches[0].clientX-e.left)*this.je/(e.right-e.left),this.ae=(t.touches[0].clientY-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.ti()},this.ii=t=>{this.le&&(this.j.record(this.an),this.an=null),this.le=!1};for(let t=0;t=e.spectrumControlPoints||(n.spectrum[t]=Math.max(0,Math.min(e.spectrumMax,Math.round(t*s+o))))}n.spectrum[Math.max(0,Math.min(e.spectrumControlPoints-1,Math.round(t)))]=Math.max(0,Math.min(e.spectrumMax,Math.round(i))),this.Pn=t,this.In=i,this.an=new oe(this.j,s,n),this.j.setProspectiveChange(this.an)}}render(){const t=this.j.song.channels[this.j.channel].instruments[this.j.getCurrentInstrument()],i=null==this.vn?t.spectrumWave:t.drumsetSpectrumWaves[this.vn],s=t=>(1-t/e.spectrumMax)*(this.Qe-1)+1;let n=0,o="M 0 "+M(this.Qe)+" ";for(let t=0;t0&&(o+="L "+(this.je-1)+" "+M(r)+" "),this.Tn!=o&&(this.Tn=o,this.Sn.setAttribute("d",o),this.kn.setAttribute("d",o+"L "+this.je+" "+M(r)+" L "+this.je+" "+M(this.Qe)+" L 0 "+M(this.Qe)+" z "),this.Fn.setAttribute("d","M "+this.je+" "+M(r)+" L "+(this.je-4)+" "+M(r-4)+" L "+(this.je-4)+" "+M(r+4)+" z"),this.Fn.style.display=n>0?"":"none"),this.Oe!=this.j.prefs.showFifth&&(this.Oe=this.j.prefs.showFifth,this.xn.style.display=this.j.prefs.showFifth?"":"none")}}class ji{constructor(t){this.j=t,this.je=120,this.Qe=26,this.Mn=A.svg({"pointer-events":"none"}),this.xn=A.svg({"pointer-events":"none"}),this.Sn=A.path({fill:"none",stroke:"currentColor","stroke-width":2,"pointer-events":"none"}),this.En=[],this.Cn=A.svg({"pointer-events":"none"}),this.se=A.svg({style:`background-color: ${$.editorBackground}; touch-action: none; cursor: crosshair;`,width:"100%",height:"100%",viewBox:"0 0 "+this.je+" "+this.Qe,preserveAspectRatio:"none"},this.Mn,this.xn,this.Sn,this.Cn),this.container=D.div({class:"harmonics",style:"height: 100%;"},this.se),this.he=0,this.ae=0,this.Pn=0,this.In=0,this.le=!1,this.an=null,this.Tn="",this.Oe=!0,this.Je=t=>{t.preventDefault(),this.le=!0;const e=this.se.getBoundingClientRect();this.he=((t.clientX||t.pageX)-e.left)*this.je/(e.right-e.left),this.ae=((t.clientY||t.pageY)-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.Pn=this.fs(this.he),this.In=this.qn(this.ae),this.ti()},this.Xe=t=>{t.preventDefault(),this.le=!0;const e=this.se.getBoundingClientRect();this.he=(t.touches[0].clientX-e.left)*this.je/(e.right-e.left),this.ae=(t.touches[0].clientY-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.Pn=this.fs(this.he),this.In=this.qn(this.ae),this.ti()},this.Ze=t=>{if(null==this.container.offsetParent)return;const e=this.se.getBoundingClientRect();this.he=((t.clientX||t.pageX)-e.left)*this.je/(e.right-e.left),this.ae=((t.clientY||t.pageY)-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.ti()},this.ei=t=>{if(null==this.container.offsetParent)return;if(!this.le)return;t.preventDefault();const e=this.se.getBoundingClientRect();this.he=(t.touches[0].clientX-e.left)*this.je/(e.right-e.left),this.ae=(t.touches[0].clientY-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.he)&&(this.he=0),isNaN(this.ae)&&(this.ae=0),this.ti()},this.ii=t=>{this.le&&(this.j.record(this.an),this.an=null),this.le=!1};for(let t=1;t<=e.harmonicsControlPoints;t*=2)this.Mn.appendChild(A.rect({fill:$.tonic,x:(t-.5)*(this.je-8)/(e.harmonicsControlPoints-1)-1,y:0,width:2,height:this.Qe}));for(let t=3;t<=e.harmonicsControlPoints;t*=2)this.xn.appendChild(A.rect({fill:$.fifthNote,x:(t-.5)*(this.je-8)/(e.harmonicsControlPoints-1)-1,y:0,width:2,height:this.Qe}));for(let t=0;t<4;t++){const e=A.rect({fill:"currentColor",x:this.je-2*t-1,y:0,width:1,height:this.Qe});this.En.push(e),this.Cn.appendChild(e)}this.container.addEventListener("mousedown",this.Je),document.addEventListener("mousemove",this.Ze),document.addEventListener("mouseup",this.ii),this.container.addEventListener("touchstart",this.Xe),this.container.addEventListener("touchmove",this.ei),this.container.addEventListener("touchend",this.ii),this.container.addEventListener("touchcancel",this.ii)}fs(t){return(e.harmonicsControlPoints-1)*t/(this.je-8)-.5}qn(t){return e.harmonicsMax*(1-t/this.Qe)}ti(){if(this.le){const t=this.fs(this.he),i=this.qn(this.ae),s=this.j.song.channels[this.j.channel].instruments[this.j.getCurrentInstrument()],n=s.harmonicsWave;if(t!=this.Pn){const s=(i-this.In)/(t-this.Pn),o=this.In-this.Pn*s,r=Math.ceil(Math.min(this.Pn,t)),h=Math.floor(Math.max(this.Pn,t));for(let t=r;t<=h;t++)t<0||t>=e.harmonicsControlPoints||(n.harmonics[t]=Math.max(0,Math.min(e.harmonicsMax,Math.round(t*s+o))))}n.harmonics[Math.max(0,Math.min(e.harmonicsControlPoints-1,Math.round(t)))]=Math.max(0,Math.min(e.harmonicsMax,Math.round(i))),this.Pn=t,this.In=i,this.an=new re(this.j,s,n),this.j.setProspectiveChange(this.an)}}render(){const t=this.j.song.channels[this.j.channel].instruments[this.j.getCurrentInstrument()].harmonicsWave,i=t=>(1-t/e.harmonicsMax)*this.Qe;let s=M(this.Qe),n="";for(let o=0;o{this.ce||(this.ce=!0,this.ri())},this.Ye=t=>{this.ce&&(this.ce=!1,this.ri())},this.Je=t=>{t.preventDefault(),this.le=!0;const e=this.se.getBoundingClientRect();this.he=(t.clientX||t.pageX)-e.left,this.ri(),this.he>=this.j.barScrollPos*this.Hn&&this.he<=(this.j.barScrollPos+this.j.trackVisibleBars)*this.Hn&&(this.On=!0,this.Gn=this.he)},this.Xe=t=>{t.preventDefault(),this.le=!0;const e=this.se.getBoundingClientRect();this.he=t.touches[0].clientX-e.left,this.ri(),this.he>=this.j.barScrollPos*this.Hn&&this.he<=(this.j.barScrollPos+this.j.trackVisibleBars)*this.Hn&&(this.On=!0,this.Gn=this.he)},this.Ze=t=>{const e=this.se.getBoundingClientRect();this.he=(t.clientX||t.pageX)-e.left,this.ti()},this.ei=t=>{if(!this.le)return;t.preventDefault();const e=this.se.getBoundingClientRect();this.he=t.touches[0].clientX-e.left,this.ti()},this.ii=t=>{!this.On&&this.le&&(this.he<(this.j.barScrollPos+8)*this.Hn?(this.j.barScrollPos>0&&this.j.barScrollPos--,this.j.notifier.changed()):(this.j.barScrollPos0;)this.j.barScrollPos--,this.Gn-=this.Hn,this.j.notifier.changed();for(;this.he-this.Gn>.5*this.Hn&&this.j.barScrollPos(this.j.barScrollPos+this.j.trackVisibleBars)*this.Hn?e=!0:i=!0),this.An.style.visibility=t?"visible":"hidden",this.Bn.style.visibility=e?"visible":"hidden",this.Dn.style.visibility=i?"visible":"hidden"}render(){this.Hn=(this.je-1)/Math.max(this.j.trackVisibleBars,this.j.song.barCount);const t=this.Nn!=this.j.song.barCount;if(t){for(this.Nn=this.j.song.barCount;this.Ln.firstChild;)this.Ln.removeChild(this.Ln.firstChild);for(let t=0;t<=this.j.song.barCount;t++){const e=t%16==0?0:t%4==0?this.Qe/8:this.Qe/3;this.Ln.appendChild(A.rect({fill:$.uiWidgetBackground,x:t*this.Hn-1,y:e,width:2,height:this.Qe-2*e}))}}(t||this.Rn!=this.j.barScrollPos)&&(this.Rn=this.j.barScrollPos,this.zn.setAttribute("x",String(this.Hn*this.j.barScrollPos)),this.zn.setAttribute("width",String(this.Hn*this.j.trackVisibleBars)),this.Dn.setAttribute("x",String(this.Hn*this.j.barScrollPos)),this.Dn.setAttribute("width",String(this.Hn*this.j.trackVisibleBars))),this.ri()}}class Ki{constructor(t){this.j=t,this.je=20,this.Qe=481,this.$n=4,this._n=e.pitchOctaves,this.Un=(this.Qe-this.$n)/this._n,this.zn=A.rect({fill:$.uiWidgetBackground,x:2,y:0,width:this.je-4}),this.Dn=A.rect({fill:"none",stroke:$.hoverPreview,"stroke-width":2,"pointer-events":"none",x:1,y:0,width:this.je-2}),this.Ts=A.path({fill:$.hoverPreview,"pointer-events":"none"}),this.qs=A.path({fill:$.hoverPreview,"pointer-events":"none"}),this.se=A.svg({style:`background-color: ${$.editorBackground}; touch-action: pan-x; position: absolute;`,width:this.je,height:"100%",viewBox:"0 0 20 481",preserveAspectRatio:"none"}),this.container=D.div({id:"octaveScrollBarContainer",style:"width: 20px; height: 100%; overflow: hidden; position: relative; flex-shrink: 0;"},this.se),this.ae=0,this.le=!1,this.ce=!1,this.On=!1,this.Vn=-1,this.jn=-1,this.an=null,this.Ke=t=>{this.ce||(this.ce=!0,this.ri())},this.Ye=t=>{this.ce&&(this.ce=!1,this.ri())},this.Je=t=>{t.preventDefault(),this.le=!0;const e=this.se.getBoundingClientRect();this.ae=((t.clientY||t.pageY)-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.ae)&&(this.ae=0),this.j.song.getChannelIsNoise(this.j.channel)||(this.ri(),this.ae>=this.Wn-this.Kn&&this.ae<=this.Wn&&(this.On=!0,this.an=null,this.Gn=this.ae))},this.Xe=t=>{t.preventDefault(),this.le=!0;const e=this.se.getBoundingClientRect();this.ae=(t.touches[0].clientY-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.ae)&&(this.ae=0),this.j.song.getChannelIsNoise(this.j.channel)||(this.ri(),this.ae>=this.Wn-this.Kn&&this.ae<=this.Wn&&(this.On=!0,this.an=null,this.Gn=this.ae))},this.Ze=t=>{const e=this.se.getBoundingClientRect();this.ae=((t.clientY||t.pageY)-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.ae)&&(this.ae=0),this.ti()},this.ei=t=>{if(!this.le)return;t.preventDefault();const e=this.se.getBoundingClientRect();this.ae=(t.touches[0].clientY-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.ae)&&(this.ae=0),this.ti()},this.ii=t=>{if(!this.j.song.getChannelIsNoise(this.j.channel)&&this.le)if(this.On)null!=this.an&&this.j.record(this.an);else{const t=this.j.getVisibleOctaveCount(),i=e.pitchOctaves-t,s=this.j.lastChangeWas(this.an),n=s?this.an.oldValue:this.j.song.channels[this.j.channel].octave,o=this.j.getBaseVisibleOctave(this.j.channel);this.ae0&&(this.an=new Ae(this.j,n,Math.floor(o-1+.5*t)),this.j.record(this.an,s))}this.le=!1,this.On=!1,this.ri()},this.bn=()=>{this.Wn=this.Qe-this.Un*this.j.getBaseVisibleOctave(this.j.channel),this.se.style.visibility=this.j.song.getChannelIsNoise(this.j.channel)?"hidden":"visible";const t=this.j.getVisibleOctaveCount();this.Vn==this.Wn&&this.jn==t||(this.Vn=this.Wn,this.jn=t,this.Kn=this.Un*t+this.$n,this.zn.setAttribute("height",String(this.Kn)),this.Dn.setAttribute("height",String(this.Kn)),this.zn.setAttribute("y",String(this.Wn-this.Kn)),this.Dn.setAttribute("y",String(this.Wn-this.Kn))),this.ri()},this.j.notifier.watch(this.bn),this.bn(),this.se.appendChild(this.zn);for(let t=0;t<=this._n;t++)this.se.appendChild(A.rect({fill:$.tonic,x:0,y:t*this.Un,width:this.je,height:this.$n}));this.se.appendChild(this.Dn),this.se.appendChild(this.Ts),this.se.appendChild(this.qs);const i=.5*this.je;this.Ts.setAttribute("d",`M ${i} 9 L ${i+6} 20 L ${i-6} 20 z`),this.qs.setAttribute("d",`M ${i} ${this.Qe-9} L ${i+6} ${this.Qe-20} L ${i-6} ${this.Qe-20} z`),this.container.addEventListener("mousedown",this.Je),document.addEventListener("mousemove",this.Ze),document.addEventListener("mouseup",this.ii),this.container.addEventListener("mouseover",this.Ke),this.container.addEventListener("mouseout",this.Ye),this.container.addEventListener("touchstart",this.Xe),this.container.addEventListener("touchmove",this.ei),this.container.addEventListener("touchend",this.ii),this.container.addEventListener("touchcancel",this.ii)}ti(){if(!this.j.song.getChannelIsNoise(this.j.channel)){if(this.On){const t=this.j.getVisibleOctaveCount(),i=e.pitchOctaves-t,s=this.j.lastChangeWas(this.an)?this.an.oldValue:this.j.song.channels[this.j.channel].octave;let n=this.j.getBaseVisibleOctave(this.j.channel);for(;this.ae-this.Gn<.5*-this.Un&&n.5*this.Un&&n>0;)n--,this.Gn+=this.Un;this.an=new Ae(this.j,s,Math.floor(n+.5*t)),this.j.setProspectiveChange(this.an)}this.ce&&this.ri()}}ri(){let t=!1,e=!1,i=!1;this.ce&&!this.le&&(this.aethis.Wn?e=!0:i=!0),this.Ts.style.visibility=t?"inherit":"hidden",this.qs.style.visibility=e?"inherit":"hidden",this.Dn.style.visibility=i?"inherit":"hidden"}}const Yi=8192,Ji={35:{frequency:0,duration:2,volume:3},36:{frequency:0,duration:2,volume:3},37:{frequency:5,duration:1,volume:3},38:{frequency:4,duration:2,volume:3},39:{frequency:5,duration:2,volume:3},40:{frequency:4,duration:2,volume:3},41:{frequency:1,duration:2,volume:3},42:{frequency:8,duration:1,volume:3},43:{frequency:1,duration:2,volume:3},44:{frequency:8,duration:1,volume:2},45:{frequency:2,duration:2,volume:3},46:{frequency:8,duration:4,volume:3},47:{frequency:2,duration:2,volume:3},48:{frequency:3,duration:2,volume:3},49:{frequency:7,duration:4,volume:3},50:{frequency:3,duration:2,volume:3},51:{frequency:6,duration:4,volume:2},52:{frequency:7,duration:4,volume:3},53:{frequency:6,duration:2,volume:3},54:{frequency:11,duration:2,volume:3},55:{frequency:9,duration:4,volume:3},56:{frequency:7,duration:1,volume:2},57:{frequency:7,duration:4,volume:3},58:{frequency:10,duration:2,volume:2},59:{frequency:6,duration:4,volume:3},69:{frequency:10,duration:2,volume:3},70:{frequency:10,duration:2,volume:3},73:{frequency:10,duration:1,volume:2},74:{frequency:10,duration:2,volume:2}};function Qi(t){return Math.pow(t/127,4)/.3844015376046128}var Xi=t&&t.Yn||function(t,e,i,s){return new(i||(i=Promise))((function(n,o){function r(t){try{a(s.next(t))}catch(t){o(t)}}function h(t){try{a(s.throw(t))}catch(t){o(t)}}function a(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i((function(t){t(e)}))).then(r,h)}a((s=s.apply(t,e||[])).next())}))};const Zi=(4294967295*Math.random()>>>0).toString(16);class ts{constructor(t){this.j=t,this.Jn=t=>{localStorage.setItem("midiHandlerId",Zi)},this.Qn=t=>{if("input"===t.port.type)switch(t.port.state){case"connected":this.Xn(t.port);break;case"disconnected":this.Zn(t.port)}},this.Xn=t=>{t.addEventListener("midimessage",this.eo)},this.Zn=t=>{t.removeEventListener("midimessage",this.eo),this.j.performance.clearAllPitches()},this.eo=t=>{if(!this.j.prefs.enableMidi||localStorage.getItem("midiHandlerId")!=Zi)return;const i=this.j.song.getChannelIsNoise(this.j.channel);let[s,n,o]=t.data;if(s&=240,i){const t=Ji[n];if(null==t)return;n=t.frequency}else if(n-=e.keys[this.j.song.key].basePitch,n<0||n>e.maxPitch)return;switch(144==s&&0==o&&(s=128),s){case 144:this.j.synth.preferLowerLatency=!0,this.j.performance.addPerformedPitch(n);break;case 128:this.j.performance.removePerformedPitch(n)}},this.registerMidiAccessHandler()}registerMidiAccessHandler(){return Xi(this,void 0,void 0,(function*(){if(null!=navigator.requestMIDIAccess)try{const t=yield navigator.requestMIDIAccess();t.inputs.forEach(this.Xn),t.addEventListener("statechange",this.Qn),this.Jn(),window.addEventListener("focus",this.Jn)}catch(t){console.error("Failed to get MIDI access",t)}}))}}class es{constructor(t){this.j=t,this.io=!1,this.so=t=>{this.io&&(this.j.performance.clearAllPitches(),this.io=!1)},window.addEventListener("blur",this.so)}static keyPosToPitch(t,i,s,n){let o=null,r=null;switch(n){case"wickiHayden":o=5*s+2*i-2;break;case"songScale":const n=e.scales[t.song.scale].flags.map(((t,e)=>t?e:null)).filter((t=>null!=t));o=(s-1+Math.floor(i/n.length))*e.pitchesPerOctave+n[(i+n.length)%n.length];break;case"pianoAtC":o=es.no[s][i],r=e.keys.dictionary.C.basePitch;break;case"pianoAtA":o=es.oo[s][i],r=e.keys.dictionary.A.basePitch;break;case"pianoTransposingC":o=es.no[s][i];break;case"pianoTransposingA":o=es.oo[s][i]}if(null==o)return null;const h=Math.max(0,t.song.channels[t.channel].octave-1)*e.pitchesPerOctave;let a=0;if(null!=r){a=(r-e.keys[t.song.key].basePitch+144)%12}const l=h+a+o;return l<0||l>e.maxPitch?null:l}handleKeyEvent(t,e){switch(t.code){case"Backquote":this.handleKey(-1,3,e);break;case"Digit1":this.handleKey(0,3,e);break;case"Digit2":this.handleKey(1,3,e);break;case"Digit3":this.handleKey(2,3,e);break;case"Digit4":this.handleKey(3,3,e);break;case"Digit5":this.handleKey(4,3,e);break;case"Digit6":this.handleKey(5,3,e);break;case"Digit7":this.handleKey(6,3,e);break;case"Digit8":this.handleKey(7,3,e);break;case"Digit9":this.handleKey(8,3,e);break;case"Digit0":this.handleKey(9,3,e);break;case"Minus":this.handleKey(10,3,e);break;case"Equal":this.handleKey(11,3,e);break;case"IntlYen":this.handleKey(12,3,e);break;case"KeyQ":this.handleKey(0,2,e);break;case"KeyW":this.handleKey(1,2,e);break;case"KeyE":this.handleKey(2,2,e);break;case"KeyR":this.handleKey(3,2,e);break;case"KeyT":this.handleKey(4,2,e);break;case"KeyY":this.handleKey(5,2,e);break;case"KeyU":this.handleKey(6,2,e);break;case"KeyI":this.handleKey(7,2,e);break;case"KeyO":this.handleKey(8,2,e);break;case"KeyP":this.handleKey(9,2,e);break;case"BracketLeft":this.handleKey(10,2,e);break;case"BracketRight":this.handleKey(11,2,e);break;case"Backslash":"\\"==t.key||"|"==t.key?this.handleKey(12,2,e):this.handleKey(11,1,e);break;case"KeyA":this.handleKey(0,1,e);break;case"KeyS":this.handleKey(1,1,e);break;case"KeyD":this.handleKey(2,1,e);break;case"KeyF":this.handleKey(3,1,e);break;case"KeyG":this.handleKey(4,1,e);break;case"KeyH":this.handleKey(5,1,e);break;case"KeyJ":this.handleKey(6,1,e);break;case"KeyK":this.handleKey(7,1,e);break;case"KeyL":this.handleKey(8,1,e);break;case"Semicolon":this.handleKey(9,1,e);break;case"Quote":this.handleKey(10,1,e);break;case"IntlHash":this.handleKey(11,1,e);break;case"IntlBackslash":this.handleKey(-1,0,e);break;case"KeyZ":this.handleKey(0,0,e);break;case"KeyX":this.handleKey(1,0,e);break;case"KeyC":this.handleKey(2,0,e);break;case"KeyV":this.handleKey(3,0,e);break;case"KeyB":this.handleKey(4,0,e);break;case"KeyN":this.handleKey(5,0,e);break;case"KeyM":this.handleKey(6,0,e);break;case"Comma":this.handleKey(7,0,e);break;case"Period":this.handleKey(8,0,e);break;case"Slash":this.handleKey(9,0,e);break;case"IntlRo":this.handleKey(10,0,e);break;default:return}t.preventDefault()}handleKey(t,i,s){if(this.j.song.getChannelIsNoise(this.j.channel))return void(t>=0&&t{this.ce||(this.ce=!0,this.ri())},this.Ye=t=>{this.ce&&(this.ce=!1,this.ri())},this.Je=t=>{t.preventDefault(),this.j.synth.maintainLiveInput(),this.le=!0;const e=this.container.getBoundingClientRect();this.ae=((t.clientY||t.pageY)-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.ae)&&(this.ae=0),this.yo(),this.bo(),this.ri()},this.Ze=t=>{(this.le||this.ce)&&this.j.synth.maintainLiveInput();const e=this.container.getBoundingClientRect();this.ae=((t.clientY||t.pageY)-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.ae)&&(this.ae=0),this.yo(),this.le&&this.bo(),this.ri()},this.Ys=t=>{this.le&&this.wo(),this.le=!1,this.ri()},this.Xe=t=>{t.preventDefault(),this.j.synth.maintainLiveInput(),this.le=!0;const e=this.container.getBoundingClientRect();this.ae=(t.touches[0].clientY-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.ae)&&(this.ae=0),this.yo(),this.bo()},this.ei=t=>{t.preventDefault(),this.j.synth.maintainLiveInput();const e=this.container.getBoundingClientRect();this.ae=(t.touches[0].clientY-e.top)*this.Qe/(e.bottom-e.top),isNaN(this.ae)&&(this.ae=0),this.yo(),this.le&&this.bo()},this.yn=t=>{t.preventDefault(),this.le=!1,this.wo()},this.vo=()=>{window.requestAnimationFrame(this.vo);let t=!1;const e=this.j.performance.pitchesAreTemporary()?0:this.j.synth.liveInputPitches.length;this.mo.length!=e&&(t=!0);for(let i=0;i{const t=this.j.song.getChannelIsNoise(this.j.channel);if(this.gi=t?e.drumCount:this.j.getVisiblePitchCount(),this.re=this.Qe/this.gi,this.yo(),this.le&&this.bo(),this.j.prefs.showLetters&&(this.fo!=this.j.song.scale||this.po!=this.j.song.key||this.Ne!=t||this.do!=this.gi)){if(this.fo=this.j.song.scale,this.po=this.j.song.key,this.Ne=t,this.ro.style.display=t?"none":"flex",this.ho.style.display=t?"flex":"none",!t){if(this.do!=this.gi){this.ro.innerHTML="";for(let t=0;to-i?s:n}}bo(){const t=this.j.getBaseVisibleOctave(this.j.channel)*e.pitchesPerOctave,i=this.ko+t;this.uo!=i&&(this.j.performance.removePerformedPitch(this.uo),this.uo=i,this.j.performance.addPerformedPitch(i))}wo(){this.j.performance.removePerformedPitch(this.uo),this.uo=-1}ri(){if(this.ao.style.visibility=!this.ce||this.le?"hidden":"visible",this.ce&&!this.le){const t=this.container.getBoundingClientRect(),e=this.re/(this.Qe/(t.bottom-t.top));this.ao.style.left="0px",this.ao.style.top=e*(this.gi-this.ko-1)+"px",this.ao.style.height=e+"px"}const t=this.j.getBaseVisibleOctave(this.j.channel)*e.pitchesPerOctave,i=(this.j.song.getChannelIsNoise(this.j.channel)?this.ho:this.ro).children;for(let e=0;e{this.j.undo()},this.cleanUp=()=>{this.Qs.removeEventListener("click",this.So),this.Xs.removeEventListener("click",this.K),this.Mo.removeEventListener("keypress",us.Fo),this.Mo.removeEventListener("blur",us.Po),this.container.removeEventListener("keydown",this.en)},this.en=t=>{"BUTTON"!=t.target.tagName&&13==t.keyCode&&this.So()},this.So=()=>{window.localStorage.setItem("beatCountStrategy",this.xo.value),this.j.prompt=null,this.j.record(new We(this.j,us.Io(this.Mo),this.xo.value),!0)},this.Mo.value=this.j.song.beatsPerBar+"",this.Mo.min=e.beatsPerBarMin+"",this.Mo.max=e.beatsPerBarMax+"";const i=window.localStorage.getItem("beatCountStrategy");null!=i&&(this.xo.value=i),this.Mo.select(),setTimeout((()=>this.Mo.focus())),this.Qs.addEventListener("click",this.So),this.Xs.addEventListener("click",this.K),this.Mo.addEventListener("keypress",us.Fo),this.Mo.addEventListener("blur",us.Po),this.container.addEventListener("keydown",this.en)}static Fo(t){const e=t.which?t.which:t.keyCode;return 46!=e&&e>31&&(e<48||e>57)&&(t.preventDefault(),!0)}static Po(t){const e=t.target;e.value=String(us.Io(e))}static Io(t){return Math.floor(Math.max(Number(t.min),Math.min(Number(t.max),Number(t.value))))}}const{button:fs,div:ps,span:ds,h2:ms,input:ys,br:gs,select:bs,option:ws}=D;class vs{constructor(t){this.j=t,this.Mo=ys({style:"width: 3em; margin-left: 1em;",type:"number",step:"0.01",value:"0"}),this.xo=bs({style:"width: 100%;"},ws({value:"overflow"},"Overflow notes across bars."),ws({value:"wrapAround"},"Wrap notes around within bars.")),this.Xs=fs({class:"cancelButton"}),this.Qs=fs({class:"okayButton",style:"width:45%;"},"Okay"),this.container=ps({class:"prompt noSelection",style:"width: 250px;"},ms("Move Notes Sideways"),ps({style:"display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},ps({style:"text-align: right;"},"Beats to move:",gs(),ds({style:`font-size: smaller; color: ${$.secondaryText};`},"(Negative is left, positive is right)")),this.Mo),ps({style:"display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},ps({class:"selectContainer",style:"width: 100%;"},this.xo)),ps({style:"display: flex; flex-direction: row-reverse; justify-content: space-between;"},this.Qs),this.Xs),this.K=()=>{this.j.undo()},this.cleanUp=()=>{this.Qs.removeEventListener("click",this.So),this.Xs.removeEventListener("click",this.K),this.Mo.removeEventListener("blur",vs.Po),this.container.removeEventListener("keydown",this.en)},this.en=t=>{"BUTTON"!=t.target.tagName&&13==t.keyCode&&this.So()},this.So=()=>{window.localStorage.setItem("moveNotesSidewaysStrategy",this.xo.value),this.j.prompt=null,this.j.record(new je(this.j,+this.Mo.value,this.xo.value),!0)},this.Mo.min=-this.j.song.beatsPerBar+"",this.Mo.max=this.j.song.beatsPerBar+"";const e=window.localStorage.getItem("moveNotesSidewaysStrategy");null!=e&&(this.xo.value=e),this.Mo.select(),setTimeout((()=>this.Mo.focus())),this.Qs.addEventListener("click",this.So),this.Xs.addEventListener("click",this.K),this.Mo.addEventListener("blur",vs.Po),this.container.addEventListener("keydown",this.en)}static Po(t){const i=t.target;let s=+i.value;s=Math.round(s*e.partsPerBeat)/e.partsPerBeat,s=Math.round(100*s)/100,i.value=Math.max(+i.min,Math.min(+i.max,s))+""}}const{button:ks,div:Ms,span:xs,h2:Ss,input:Fs,br:Ps,select:Is,option:Ts}=D;class qs{constructor(t){this.j=t,this.To=Fs({style:"width: 3em; margin-left: 1em;",type:"number",step:"1"}),this.qo=Is({style:"width: 100%;"},Ts({value:"end"},"Apply change at end of song."),Ts({value:"beginning"},"Apply change at beginning of song.")),this.Xs=ks({class:"cancelButton"}),this.Qs=ks({class:"okayButton",style:"width:45%;"},"Okay"),this.container=Ms({class:"prompt noSelection",style:"width: 250px;"},Ss("Song Length"),Ms({style:"display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},Ms({style:"display: inline-block; text-align: right;"},"Bars per song:",Ps(),xs({style:`font-size: smaller; color: ${$.secondaryText};`},"(Multiples of 4 are recommended)")),this.To),Ms({style:"display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},Ms({class:"selectContainer",style:"width: 100%;"},this.qo)),Ms({style:"display: flex; flex-direction: row-reverse; justify-content: space-between;"},this.Qs),this.Xs),this.K=()=>{this.j.undo()},this.cleanUp=()=>{this.Qs.removeEventListener("click",this.So),this.Xs.removeEventListener("click",this.K),this.To.removeEventListener("keypress",qs.Fo),this.To.removeEventListener("blur",qs.Po),this.container.removeEventListener("keydown",this.en)},this.en=t=>{"BUTTON"!=t.target.tagName&&13==t.keyCode&&this.So()},this.So=()=>{window.localStorage.setItem("barCountPosition",this.qo.value);const t=new zt;t.append(new Kt(this.j,qs.Io(this.To),"beginning"==this.qo.value)),this.j.prompt=null,this.j.record(t,!0)},this.To.value=this.j.song.barCount+"",this.To.min=e.barCountMin+"",this.To.max=e.barCountMax+"";const i=window.localStorage.getItem("barCountPosition");null!=i&&(this.qo.value=i),this.To.select(),setTimeout((()=>this.To.focus())),this.Qs.addEventListener("click",this.So),this.Xs.addEventListener("click",this.K),this.To.addEventListener("keypress",qs.Fo),this.To.addEventListener("blur",qs.Po),this.container.addEventListener("keydown",this.en)}static Fo(t){const e=t.which?t.which:t.keyCode;return 46!=e&&e>31&&(e<48||e>57)&&(t.preventDefault(),!0)}static Po(t){const e=t.target;e.value=String(qs.Io(e))}static Io(t){return Math.floor(Math.max(Number(t.min),Math.min(Number(t.max),Number(t.value))))}}const{button:Es,div:Cs,h2:Ls,p:zs,select:Ds,option:As}=D;class Bs{constructor(t){this.j=t,this.Eo=Ds({style:"width: 100%;"},As({value:"acoustic"},"(A) Acoustic"),As({value:"bright"},"(B) Bright")),this.Xs=Es({class:"cancelButton"}),this.Qs=Es({class:"okayButton",style:"width:45%;"},"Okay"),this.container=Cs({class:"prompt",style:"width: 300px;"},Cs(Ls("String Sustain"),zs("This setting controls how quickly the picked string vibration decays."),zs('Unlike most of BeepBox\'s instrument synthesizer features, a picked string cannot change frequency suddenly while maintaining its decay. If a tone\'s pitch changes suddenly (e.g. if the chord type is set to "arpeggio" or the transition type is set to "continues") then the string will be re-picked and start decaying from the beginning again, even if the envelopes don\'t otherwise restart.')),Cs({style:{display:e.enableAcousticSustain?void 0:"none"}},zs('BeepBox comes with two slightly different sustain designs. You can select one here and press "Okay" to confirm it.'),Cs({class:"selectContainer",style:"width: 100%;"},this.Eo)),Cs({style:{display:e.enableAcousticSustain?"flex":"none","flex-direction":"row-reverse","justify-content":"space-between"}},this.Qs),this.Xs),this.K=()=>{this.j.undo()},this.cleanUp=()=>{this.Qs.removeEventListener("click",this.So),this.Xs.removeEventListener("click",this.K),this.container.removeEventListener("keydown",this.en)},this.en=t=>{"BUTTON"!=t.target.tagName&&13==t.keyCode&&this.So()},this.So=()=>{if(e.enableAcousticSustain){const t=new zt;t.append(new we(this.j,e.sustainTypeNames.indexOf(this.Eo.value))),this.j.prompt=null,this.j.record(t,!0)}else this.K()};const i=this.j.song.channels[this.j.channel].instruments[this.j.getCurrentInstrument()];this.Eo.value=e.sustainTypeNames[i.stringSustainType],setTimeout((()=>this.Xs.focus())),this.Qs.addEventListener("click",this.So),this.Xs.addEventListener("click",this.K),this.container.addEventListener("keydown",this.en)}}const{button:Os,div:Ns,label:Rs,br:Hs,h2:Gs,input:$s}=D;class _s{constructor(t){this.j=t,this.Co=$s({style:"width: 3em; margin-left: 1em;",type:"number",step:"1"}),this.Lo=$s({style:"width: 3em; margin-left: 1em;",type:"number",step:"1"}),this.zo=$s({style:"width: 3em; margin-left: 1em;",type:"number",step:"1"}),this.Do=$s({style:"width: 3em; margin-left: 1em;",type:"checkbox"}),this.Ao=$s({style:"width: 3em; margin-left: 1em;",type:"checkbox"}),this.Xs=Os({class:"cancelButton"}),this.Qs=Os({class:"okayButton",style:"width:45%;"},"Okay"),this.container=Ns({class:"prompt noSelection",style:"width: 250px; text-align: right;"},Gs("Channel Settings"),Rs({style:"display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},"Pitch channels:",this.Lo),Rs({style:"display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},"Drum channels:",this.zo),Rs({style:"display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},"Available patterns per channel:",this.Co),Rs({style:"display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},"Simultaneous instruments",Hs(),"per channel:",this.Do),Rs({style:"display: flex; flex-direction: row; align-items: center; height: 2em; justify-content: flex-end;"},"Different instruments",Hs(),"per pattern:",this.Ao),Ns({style:"display: flex; flex-direction: row-reverse; justify-content: space-between;"},this.Qs),this.Xs),this.K=()=>{this.j.undo()},this.cleanUp=()=>{this.Qs.removeEventListener("click",this.So),this.Xs.removeEventListener("click",this.K),this.Co.removeEventListener("keypress",_s.Fo),this.Lo.removeEventListener("keypress",_s.Fo),this.zo.removeEventListener("keypress",_s.Fo),this.Co.removeEventListener("blur",this.Po),this.Lo.removeEventListener("blur",this.Po),this.zo.removeEventListener("blur",this.Po),this.container.removeEventListener("keydown",this.en)},this.en=t=>{"BUTTON"!=t.target.tagName&&13==t.keyCode&&this.So()},this.Po=t=>{const e=t.target;e.value=String(_s.Io(e))},this.So=()=>{const t=new zt;t.append(new Ce(this.j,this.Do.checked,this.Ao.checked)),t.append(new He(this.j,_s.Io(this.Co))),t.append(new Xt(this.j,_s.Io(this.Lo),_s.Io(this.zo))),this.j.prompt=null,this.j.record(t,!0)},this.Co.value=this.j.song.patternsPerChannel+"",this.Co.min="1",this.Co.max=e.barCountMax+"",this.Lo.value=this.j.song.pitchChannelCount+"",this.Lo.min=e.pitchChannelCountMin+"",this.Lo.max=e.pitchChannelCountMax+"",this.zo.value=this.j.song.noiseChannelCount+"",this.zo.min=e.noiseChannelCountMin+"",this.zo.max=e.noiseChannelCountMax+"",this.Do.checked=this.j.song.layeredInstruments,this.Ao.checked=this.j.song.patternInstruments,this.Lo.select(),setTimeout((()=>this.Lo.focus())),this.Qs.addEventListener("click",this.So),this.Xs.addEventListener("click",this.K),this.Co.addEventListener("keypress",_s.Fo),this.Lo.addEventListener("keypress",_s.Fo),this.zo.addEventListener("keypress",_s.Fo),this.Co.addEventListener("blur",this.Po),this.Lo.addEventListener("blur",this.Po),this.zo.addEventListener("blur",this.Po),this.container.addEventListener("keydown",this.en)}static Fo(t){const e=t.which?t.which:t.keyCode;return 46!=e&&e>31&&(e<48||e>57)&&(t.preventDefault(),!0)}static Io(t){return Math.floor(Math.max(Number(t.min),Math.min(Number(t.max),Number(t.value))))}}function Us(t,e){const i=new ArrayBuffer(e);let s=0,n=Math.min(t.byteLength,i.byteLength);const o=[8,4,2,1];for(const e of o)if(n>=e){const o=r(e,t,i,s,n);s=o.nextOffset,n=o.leftBytes}return i;function r(t,e,i,s,n){let o=Uint8Array;switch(t){case 8:o=Float64Array;break;case 4:o=Float32Array;break;case 2:o=Uint16Array;break;default:o=Uint8Array}const r=new o(e,s,n/t|0),h=new o(i,s,n/t|0);for(let t=0;tthis.No.byteLength&&(this.No=Us(this.No,Math.max(2*this.No.byteLength,this.Oo)),this.Ro=new DataView(this.No))}getWriteIndex(){return this.Bo}rewriteUint32(t,e){this.Ro.setUint32(t,e>>>0,!1)}writeUint32(t){t>>>=0,this.Ho(4),this.Ro.setUint32(this.Bo,t,!1),this.Bo=this.Oo}writeUint24(t){t>>>=0,this.Ho(3),this.Ro.setUint8(this.Bo,t>>16&255),this.Ro.setUint8(this.Bo+1,t>>8&255),this.Ro.setUint8(this.Bo+2,255&t),this.Bo=this.Oo}writeUint16(t){t>>>=0,this.Ho(2),this.Ro.setUint16(this.Bo,t,!1),this.Bo=this.Oo}writeUint8(t){t>>>=0,this.Ho(1),this.Ro.setUint8(this.Bo,t),this.Bo=this.Oo}writeInt8(t){t|=0,this.Ho(1),this.Ro.setInt8(this.Bo,t),this.Bo=this.Oo}writeMidi7Bits(t){if((t>>>=0)>=128)throw new Error("7 bit value contained 8th bit!");this.Ho(1),this.Ro.setUint8(this.Bo,t),this.Bo=this.Oo}writeMidiVariableLength(t){if((t>>>=0)>268435455)throw new Error("writeVariableLength value too big.");let e=!1;for(let i=0;i<4;i++){const s=t>>>21-7*i&127;0==s&&3!=i||(e=!0),e&&this.writeUint8((3==i?0:128)|s)}}writeMidiAscii(t){this.writeMidiVariableLength(t.length);for(let e=0;e127)throw new Error("Trying to write unicode character as ascii.");this.writeUint8(i)}}toCompactArrayBuffer(){return Us(this.No,this.Oo)}}const{button:js,div:Ws,h2:Ks,input:Ys,select:Js,option:Qs}=D;function Xs(t,e,i){return t+i*(e-t)}function Zs(t,e){if(navigator.msSaveOrOpenBlob)return void navigator.msSaveOrOpenBlob(t,e);const i=document.createElement("a");if(null!=i.download){const s=URL.createObjectURL(t);setTimeout((function(){URL.revokeObjectURL(s)}),6e4),i.href=s,i.download=e,setTimeout((function(){i.dispatchEvent(new MouseEvent("click"))}),0)}else{const e=URL.createObjectURL(t);setTimeout((function(){URL.revokeObjectURL(e)}),6e4),window.open(e,"_blank")||(window.location.href=e)}}class tn{constructor(t){this.j=t,this.Go=Ys({type:"text",style:"width: 10em;",value:"BeepBox-Song",maxlength:250,autofocus:"autofocus"}),this.$o=Ys({type:"checkbox"}),this._o=Ys({style:"width: 2em;",type:"number",min:"1",max:"4",step:"1"}),this.Uo=Ys({type:"checkbox"}),this.Vo=Js({style:"width: 100%;"},Qs({value:"wav"},".wav"),Qs({value:"mp3"},".mp3"),Qs({value:"midi"},".mid"),Qs({value:"json"},".json (for any BeepBox version)"),Qs({value:"html"},".html (opens BeepBox)")),this.Xs=js({class:"cancelButton"}),this.jo=js({class:"exportButton",style:"width:45%;"},"Export"),this.container=Ws({class:"prompt noSelection",style:"width: 200px;"},Ks("Export Options"),Ws({style:"display: flex; flex-direction: row; align-items: center; justify-content: space-between;"},"File name:",this.Go),Ws({style:"display: table; width: 100%;"},Ws({style:"display: table-row;"},Ws({style:"display: table-cell;"},"Intro:"),Ws({style:"display: table-cell;"},"Loop Count:"),Ws({style:"display: table-cell;"},"Outro:")),Ws({style:"display: table-row;"},Ws({style:"display: table-cell; vertical-align: middle;"},this.$o),Ws({style:"display: table-cell; vertical-align: middle;"},this._o),Ws({style:"display: table-cell; vertical-align: middle;"},this.Uo))),Ws({style:"text-align: left;"},"File Type:"),Ws({class:"selectContainer",style:"width: 100%;"},this.Vo),Ws({style:"text-align: left;"},"(Be patient, exporting may take some time...)"),Ws({style:"display: flex; flex-direction: row-reverse; justify-content: space-between;"},this.jo),this.Xs),this.K=()=>{this.j.undo()},this.cleanUp=()=>{this.Go.removeEventListener("input",tn.Wo),this._o.removeEventListener("blur",tn.Po),this.jo.removeEventListener("click",this.Ko),this.Xs.removeEventListener("click",this.K),this.container.removeEventListener("keydown",this.en)},this.en=t=>{"BUTTON"!=t.target.tagName&&13==t.keyCode&&this.Ko()},this.Ko=()=>{switch(window.localStorage.setItem("exportFormat",this.Vo.value),this.Vo.value){case"wav":this.Yo();break;case"mp3":this.Jo();break;case"midi":this.Qo();break;case"json":this.Xo();break;case"html":this.Zo();break;default:throw new Error("Unhandled file export type.")}},this._o.value="1",0==this.j.song.loopStart?(this.$o.checked=!1,this.$o.disabled=!0):(this.$o.checked=!0,this.$o.disabled=!1),this.j.song.loopStart+this.j.song.loopLength==this.j.song.barCount?(this.Uo.checked=!1,this.Uo.disabled=!0):(this.Uo.checked=!0,this.Uo.disabled=!1);const e=window.localStorage.getItem("exportFormat");null!=e&&(this.Vo.value=e),this.Go.select(),setTimeout((()=>this.Go.focus())),this.Go.addEventListener("input",tn.Wo),this._o.addEventListener("blur",tn.Po),this.jo.addEventListener("click",this.Ko),this.Xs.addEventListener("click",this.K),this.container.addEventListener("keydown",this.en)}static Wo(t){const e=t.target,i=/[\+\*\$\?\|\{\}\\\/<>#%!`&'"=:@]/gi;if(i.test(e.value)){let t=e.selectionStart;e.value=e.value.replace(i,""),t--,e.setSelectionRange(t,t)}}static Po(t){const e=t.target;e.value=Math.floor(Math.max(Number(e.min),Math.min(Number(e.max),Number(e.value))))+""}tr(t){const e=new Ft(this.j.song);if(e.samplesPerSecond=t,e.loopRepeatCount=Number(this._o.value)-1,!this.$o.checked)for(let t=0;t{const{recordedSamplesL:t,recordedSamplesR:e}=this.tr(44100),i=1152,s=new window.lamejs.Mp3Encoder(2,44100,192),n=[],o=new Int16Array(t.length),r=new Int16Array(e.length);for(let i=0;i0&&n.push(a)}const h=s.flush();h.length>0&&n.push(h);Zs(new Blob(n,{type:"audio/mp3"}),this.Go.value.trim()+".mp3"),this.K()};if("lamejs"in window)t();else{var e=document.createElement("script");e.src="https://cdn.jsdelivr.net/npm/lamejs@1.2.0/lame.min.js",e.onload=t,document.head.appendChild(e)}}Qo(){const t=this.j.song,i=2*e.ticksPerPart*e.partsPerBeat,s=2*e.ticksPerPart,n=t.getBeatsPerMinute(),o=Math.round(6e7/n),r=i*t.beatsPerBar,a=24,l=[];if(this.$o.checked)for(let e=0;e=16)continue;c.push({isMeta:!1,channel:t,midiChannel:u++,isNoise:this.j.song.getChannelIsNoise(t),isDrumset:!1}),9==u&&u++}else c.push({isMeta:!1,channel:t,midiChannel:9,isNoise:!0,isDrumset:!0}),f=!0;const p=new Vs(1024);p.writeUint32(1297377380),p.writeUint32(6),p.writeUint16(1),p.writeUint16(c.length),p.writeUint16(i);for(const n of c){p.writeUint32(1297379947);const{isMeta:c,channel:u,midiChannel:f,isNoise:m,isDrumset:y}=n,g=p.getWriteIndex();p.writeUint32(0);let b=0,w=0;const v=function(t){if(t=0&&e<=127))throw new Error("Midi control event value out of range: "+e);p.writeUint8(176|f),p.writeMidi7Bits(t),p.writeMidi7Bits(0|e)};if(c){v(0),p.writeUint8(255),p.writeMidi7Bits(1),p.writeMidiAscii("Composed with https://www.beepbox.co"),v(0),p.writeUint8(255),p.writeMidi7Bits(81),p.writeMidiVariableLength(3),p.writeUint24(o),v(0),p.writeUint8(255),p.writeMidi7Bits(88),p.writeMidiVariableLength(4),p.writeUint8(t.beatsPerBar),p.writeUint8(2),p.writeUint8(24),p.writeUint8(8);const i=e.scales[t.scale].flags[3]&&!e.scales[t.scale].flags[4],s=t.key;let n=s;for(1==(1&s)&&(n+=6),i&&(n+=9);n>6;)n-=12;v(0),p.writeUint8(255),p.writeMidi7Bits(89),p.writeMidiVariableLength(2),p.writeInt8(n),p.writeUint8(i?1:0),this.$o.checked&&(w+=r*t.loopStart),v(w),p.writeUint8(255),p.writeMidi7Bits(6),p.writeMidiAscii("Loop Start");for(let e=0;es.chipWave&&(t=tn.midiChipInstruments[s.chipWave]);else if(6==s.type||1==s.type||5==s.type||8==s.type)t=81;else{if(7!=s.type)throw new Error("Unrecognized instrument type.");t=25}v(w),p.writeUint8(192|f),p.writeMidi7Bits(t)}v(w);let t=(r=Ft.instrumentVolumeToVolumeMult(s.volume),127*Math.pow(.3844015376046128*r,.25));k(7,Math.min(127,Math.round(t))),v(w);let h=63*(s.pan/e.panCenter-1)+64;k(10,Math.min(127,Math.round(h)))}var r}null==t.getPattern(u,0)&&c(0);let g=Yi,b=127,M=!1;const S=m?e.spectrumBasePitch:e.keys[t.key].basePitch,F=m?e.noiseInterval:1;for(const n of l){const o=t.getPattern(u,n);if(null!=o){const n=o.instruments[0],r=t.channels[u].instruments[n],l=x.valueToPreset(r.preset);c(n);let P=r.getChord().arpeggiates,I=P?1:e.maxChordSize;r.getChord().customInterval&&(0==r.type||5==r.type?(I=2,P=!0):1==r.type?I=e.operatorCount:console.error("Unrecognized instrument type for harmonizing arpeggio: "+r.type));for(let n=0;n>7&127),g=R),H==b||y||(v(o),k(11,H),b=H);const G=o==c;for(let n=0;n=t.length)throw new Error("Could not find corresponding drumset pitch. "+a);a=t[a]}else{if(P&&r.pitches.length>n+1&&n==L-1){const l=(o-w)%i,c=e.rhythms[t.rhythm].ticksPerArpeggio*s/e.ticksPerPart,u=Math.floor(l/c);a=r.pitches[n+h(r.pitches.length-n,t.rhythm,u)]}a=S+a*F+A,null!=l&&null!=l.midiSubharmonicOctaves?a+=12*l.midiSubharmonicOctaves:m&&(a+=12*+x.presetCategories.dictionary["Drum Presets"].presets.dictionary["taiko drum"].midiSubharmonicOctaves),m&&(a*=2)}a=Math.max(0,Math.min(127,a)),C[n]=a,G||E[n]==C[n]||(v(o),p.writeUint8(128|f),p.writeMidi7Bits(E[n]),p.writeMidi7Bits(z))}for(let t=0;t>7&127)));w+=r}}v(w),p.writeUint8(255),p.writeMidi7Bits(47),p.writeMidiVariableLength(0),p.rewriteUint32(g,p.getWriteIndex()-g-4)}var d;Zs(new Blob([p.toCompactArrayBuffer()],{type:"audio/midi"}),this.Go.value.trim()+".mid"),this.K()}Xo(){const t=this.j.song.toJsonObject(this.$o.checked,Number(this._o.value),this.Uo.checked),e=JSON.stringify(t,null,"\t");Zs(new Blob([e],{type:"application/json"}),this.Go.value.trim()+".json"),this.K()}Zo(){const t=`\n\nYou should be redirected to the song at:

\n\n\n\n\n\n