diff --git a/README.md b/README.md index c2882401..65e3372e 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,18 @@
-**SpessaSynth** is a SoundFont2-based real-time synthesizer and MIDI player written in vanilla JavaScript. -It’s a powerful and versatile library that allows you to read, write, or play MIDI files, -read DLS files and read/write SF2/SF3 files with ease. +**SpessaSynth** is a SoundFont2-based real-time synthesizer and MIDI library written in vanilla JavaScript. +It’s a powerful and versatile library that allows you to: +- Play MIDI files using SF2/SF3/DLS files +- Write MIDI files +- Write SF2/SF3 files +- Convert DLS to SF2 +- [and more!](#easy-integration) ```shell npm install --save spessasynth_lib ``` -### DLS Support now available! ->2];)BA=BA<=536870912?gt(2*BA,i):Math.min(gt((3*BA+2147483648)/4,i),E);var f=I.reallocBuffer(BA);return f&&f.byteLength==BA?(zt(f),Ct(),!0):(BA=B,!1)}u=l=y=k=F=q=M=0,D=!1,I.reallocBuffer||(I.reallocBuffer=function(i){try{if(ArrayBuffer.transfer)E=ArrayBuffer.transfer(s,i);else{var E,B=n;E=new ArrayBuffer(i),new Int8Array(E).set(B)}}catch{return!1}return!!So(E)&&E});try{(v=Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype,"byteLength").get))(new ArrayBuffer(4))}catch{v=function(E){return E.byteLength}}var Et=I.TOTAL_STACK||5242880,BA=I.TOTAL_MEMORY||16777216;function Qo(){return BA}function fe(i){for(;i.length>0;){var E=i.shift();if(typeof E=="function"){E();continue}var B=E.func;typeof B=="number"?E.arg===void 0?I.dynCall_v(B):I.dynCall_vi(B,E.arg):B(E.arg===void 0?null:E.arg)}}BA=0?i:E<=32?2*Math.abs(1< =f&&(E<=32||i>f)&&(i=-2*f+i),i}var fo=Math.abs,mo=Math.ceil,ss=Math.floor,po=Math.min,Ae=0,Qt=null,me=null;function rr(i){return i}I.preloadedImages={},I.preloadedAudios={};var ns="data:application/octet-stream;base64,";function Te(i){return String.prototype.startsWith?i.startsWith(ns):i.indexOf(ns)===0}(function(){var E="main.wast",B="main.wasm",f="main.temp.asm.js";Te(E)||(E=GA(E)),Te(B)||(B=GA(B)),Te(f)||(f=GA(f));var R={global:null,env:null,asm2wasm:Eo,parent:I},P=null;function W(sA){return sA}function x(){try{if(I.wasmBinary)return new Uint8Array(I.wasmBinary);if(I.readBinary)return I.readBinary(B);throw"both async and sync fetching of the wasm failed"}catch(sA){ZA(sA)}}I.asmPreload=I.asm;var hA=I.reallocBuffer,rA=function(sA){sA=gt(sA,I.usingWasm?65536:16777216);var J=I.buffer.byteLength;if(I.usingWasm)try{var fA=I.wasmMemory.grow((sA-J)/65536);return fA!==-1?I.buffer=I.wasmMemory.buffer:null}catch{return null}};I.reallocBuffer=function(sA){return iA==="asmjs"?hA(sA):rA(sA)};var iA="";I.asm=function(sA,J,fA){var MA;if(!(J=MA=J).table){var NA,bA=I.wasmTableSize;bA===void 0&&(bA=1024);var ee=I.wasmMaxTableSize;typeof WebAssembly=="object"&&typeof WebAssembly.Table=="function"?ee!==void 0?J.table=new WebAssembly.Table({initial:bA,maximum:ee,element:"anyfunc"}):J.table=new WebAssembly.Table({initial:bA,element:"anyfunc"}):J.table=Array(bA),I.wasmTable=J.table}return J.memoryBase||(J.memoryBase=I.STATIC_BASE),J.tableBase||(J.tableBase=0),NA=function(Se,oe,dt){if(typeof WebAssembly!="object")return xA("no native wasm support detected"),!1;if(!(I.wasmMemory instanceof WebAssembly.Memory))return xA("no native wasm Memory in use"),!1;function Je(JA,qA){if((P=JA.exports).memory){var ye,ft,is;ye=P.memory,ft=I.buffer,ye.byteLength 0?B:Ue(i)+1,R=Array(f),P=Le(i,R,0,R.length);return E&&(R.length=P),R}function gr(i){for(var E=[],B=0;B 255&&(f&=255),E.push(String.fromCharCode(f))}return E.join("")}l+=16,M=Me(4),F=(y=k=Kt(l))+Et,q=Kt(F),Q[M>>2]=q,D=!0,I.wasmTableSize=4,I.wasmMaxTableSize=4,I.asmGlobalArg={},I.asmLibraryArg={abort:ZA,assert:_A,enlargeMemory:jt,getTotalMemory:Qo,abortOnCannotGrowMemory:function(){ZA("Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value "+BA+", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ")},invoke_iii:function(E,B,f){var R=lt();try{return I.dynCall_iii(E,B,f)}catch(P){if(ct(R),typeof P!="number"&&P!=="longjmp")throw P;I.setThrew(1,0)}},___assert_fail:function(E,B,f,R){ZA("Assertion failed: "+be(E)+", at: "+[B?be(B):"unknown filename",f,R?be(R):"unknown function"])},___setErrNo:function(E){return I.___errno_location&&(Q[I.___errno_location()>>2]=E),E},_abort:function(){I.abort()},_emscripten_memcpy_big:function(E,B,f){return o.set(o.subarray(B,B+f),E),E},_llvm_floor_f64:ss,DYNAMICTOP_PTR:M,tempDoublePtr:kA,ABORT:Ne,STACKTOP:k,STACK_MAX:F};var os=I.asm(I.asmGlobalArg,I.asmLibraryArg,s);I.asm=os,I.___errno_location=function(){return I.asm.___errno_location.apply(null,arguments)};var So=I._emscripten_replace_memory=function(){return I.asm._emscripten_replace_memory.apply(null,arguments)};I._free=function(){return I.asm._free.apply(null,arguments)};var He=I._malloc=function(){return I.asm._malloc.apply(null,arguments)};I._memcpy=function(){return I.asm._memcpy.apply(null,arguments)},I._memset=function(){return I.asm._memset.apply(null,arguments)},I._sbrk=function(){return I.asm._sbrk.apply(null,arguments)},I._stb_vorbis_js_channels=function(){return I.asm._stb_vorbis_js_channels.apply(null,arguments)},I._stb_vorbis_js_close=function(){return I.asm._stb_vorbis_js_close.apply(null,arguments)},I._stb_vorbis_js_decode=function(){return I.asm._stb_vorbis_js_decode.apply(null,arguments)},I._stb_vorbis_js_open=function(){return I.asm._stb_vorbis_js_open.apply(null,arguments)},I._stb_vorbis_js_sample_rate=function(){return I.asm._stb_vorbis_js_sample_rate.apply(null,arguments)},I.establishStackSpace=function(){return I.asm.establishStackSpace.apply(null,arguments)},I.getTempRet0=function(){return I.asm.getTempRet0.apply(null,arguments)},I.runPostSets=function(){return I.asm.runPostSets.apply(null,arguments)},I.setTempRet0=function(){return I.asm.setTempRet0.apply(null,arguments)},I.setThrew=function(){return I.asm.setThrew.apply(null,arguments)};var Ye=I.stackAlloc=function(){return I.asm.stackAlloc.apply(null,arguments)},ct=I.stackRestore=function(){return I.asm.stackRestore.apply(null,arguments)},lt=I.stackSave=function(){return I.asm.stackSave.apply(null,arguments)};function pe(i){this.name="ExitStatus",this.message="Program terminated with exit("+i+")",this.status=i}function ut(i){i=i||I.arguments,!(Ae>0)&&(function(){if(I.preRun)for(typeof I.preRun=="function"&&(I.preRun=[I.preRun]);I.preRun.length;)lo(I.preRun.shift());fe($t)}(),!(Ae>0)&&(I.calledRun||(I.setStatus?(I.setStatus("Running..."),setTimeout(function(){setTimeout(function(){I.setStatus("")},1),E()},1)):E())));function E(){!I.calledRun&&(I.calledRun=!0,Ne||(ht||(ht=!0,fe(Bt)),fe(As),I.onRuntimeInitialized&&I.onRuntimeInitialized(),function(){if(I.postRun)for(typeof I.postRun=="function"&&(I.postRun=[I.postRun]);I.postRun.length;)uo(I.postRun.shift());fe(ts)}()))}}function Cr(i,E){(!E||!I.noExitRuntime||i!==0)&&(I.noExitRuntime||(Ne=!0,Pt=i,k=T,fe(es),co=!0,I.onExit&&I.onExit(i)),I.quit(i,new pe(i)))}function ZA(i){throw I.onAbort&&I.onAbort(i),i!==void 0?(xe(i),xA(i),i=JSON.stringify(i)):i="",Ne=!0,Pt=1,"abort("+i+"). Build with -s ASSERTIONS=1 for more info."}if(I.dynCall_iii=function(){return I.asm.dynCall_iii.apply(null,arguments)},I.asm=os,I.ccall=Zt,I.cwrap=function(E,B,f,R){var P=(f=f||[]).every(function(W){return W==="number"});return B!=="string"&&P&&!R?Vt(E):function(){return Zt(E,B,f,arguments,R)}},pe.prototype=Error(),pe.prototype.constructor=pe,me=function i(){I.calledRun||ut(),I.calledRun||(me=i)},I.run=ut,I.abort=ZA,I.preInit)for(typeof I.preInit=="function"&&(I.preInit=[I.preInit]);I.preInit.length>0;)I.preInit.pop()();I.noExitRuntime=!0,ut(),I.onRuntimeInitialized=()=>{_s=!0,zs()},OA.decode=function(i){return function(B){if(!_s)throw Error("Not initialized");var f={};function R(oe){return new Int32Array(I.HEAPU8.buffer,oe,1)[0]}function P(oe,dt){var Je=new ArrayBuffer(dt*Float32Array.BYTES_PER_ELEMENT),re=new Float32Array(Je);return re.set(new Float32Array(I.HEAPU8.buffer,oe,dt)),re}f.open=I.cwrap("stb_vorbis_js_open","number",[]),f.close=I.cwrap("stb_vorbis_js_close","void",["number"]),f.channels=I.cwrap("stb_vorbis_js_channels","number",["number"]),f.sampleRate=I.cwrap("stb_vorbis_js_sample_rate","number",["number"]),f.decode=I.cwrap("stb_vorbis_js_decode","number",["number","number","number","number","number"]);var W,x,hA,rA,iA=f.open(),sA=(W=B,x=B.byteLength,hA=I._malloc(x),(rA=new Uint8Array(I.HEAPU8.buffer,hA,x)).set(new Uint8Array(W,0,x)),rA),J=I._malloc(4),fA=I._malloc(4),MA=f.decode(iA,sA.byteOffset,sA.byteLength,J,fA);if(I._free(sA.byteOffset),MA<0)throw f.close(iA),I._free(J),Error("stbvorbis decode failed: "+MA);for(var NA=f.channels(iA),bA=Array(NA),ee=new Int32Array(I.HEAPU32.buffer,R(J),NA),LA=0;LA =0&&(s=this.workletProcessorChannels[e]),t.messageType){case tA.noteOn:this.noteOn(e,A[0],A[1],A[2]);break;case tA.noteOff:this.noteOff(e,A);break;case tA.pitchWheel:this.pitchWheel(e,A[0],A[1]);break;case tA.ccChange:this.controllerChange(e,A[0],A[1],A[2]);break;case tA.customcCcChange:s.customControllers[A[0]]=A[1];break;case tA.killNote:this.killNote(e,A);break;case tA.programChange:this.programChange(e,A[0],A[1]);break;case tA.channelPressure:this.channelPressure(e,A);break;case tA.polyPressure:this.polyPressure(e,A[0],A[1]);break;case tA.ccReset:e===TA?this.resetAllControllers():this.resetControllers(e);break;case tA.systemExclusive:this.systemExclusive(A);break;case tA.setChannelVibrato:if(e===TA)for(let g=0;g {let e=(A.midiControllers[CA+V.pitchWheelRange]>>7)+(A.midiControllers[CA+V.pitchWheelRange]&127)/127;return{voicesAmount:A.voices.length,pitchBend:A.midiControllers[CA+V.pitchWheel],pitchBendRangeSemitones:e,isMuted:A.isMuted,isDrum:A.drumChannel}});this.post({messageType:mA.channelProperties,messageData:t})}function Go(t,A,e){let s=t,n=A<<7|e;return t===127&&A===127&&e===127?{midiNote:-1,centTuning:null}:{midiNote:s,centTuning:n*.0061}}function en(t,A=0){let e=t[0];if(!(this.deviceID!==TA&&t[1]!==127&&this.deviceID!==t[1]))switch(e){default:N(`%cUnrecognized SysEx: %c${QA(t)}`,r.warn,r.unrecognized);break;case 126:case 127:switch(t[2]){case 4:let n;switch(t[3]){case 1:let o=t[5]<<7|t[4];this.setMIDIVolume(o/16384),m(`%cMaster Volume. Volume: %c${o}`,r.info,r.value);break;case 2:let C=((t[5]<<7|t[4])-8192)/8192;this.setMasterPan(C),m(`%cMaster Pan. Pan: %c${C}`,r.info,r.value);break;case 3:let Q=(t[5]<<7|t[6])-8192;n=Math.floor(Q/81.92),this.setMasterTuning(n),m(`%cMaster Fine Tuning. Cents: %c${n}`,r.info,r.value);break;case 4:n=(t[5]-64)*100,this.setMasterTuning(n),m(`%cMaster Coarse Tuning. Cents: %c${n}`,r.info,r.value);break;default:N(`%cUnrecognized MIDI Device Control Real-time message: %c${QA(t)}`,r.warn,r.unrecognized)}break;case 9:t[3]===1?(m("%cGM system on",r.info),this.system="gm"):t[3]===3?(m("%cGM2 system on",r.info),this.system="gm2"):(m("%cGM system off, defaulting to GS",r.info),this.system="gs");break;case 8:switch(t[3]){case 2:case 7:let o=4;t[3]===7&&o++;let g=t[o++],C=t[o++];for(let h=0;h >1&1)===1&&this.setOctaveTuning(15+A,Q);for(let h=0;h<7;h++)(t[5]>>h&1)===1&&this.setOctaveTuning(7+h+A,Q);for(let h=0;h<7;h++)(t[6]>>h&1)===1&&this.setOctaveTuning(h+A,Q);m(`%cMIDI Octave Scale ${t[3]===8?"(1 byte)":"(2 bytes)"} tuning via Tuning: %c${Q.join(" ")}`,r.info,r.value);break;default:N(`%cUnrecognized MIDI Tuning standard message: %c${QA(t)}`,r.warn,r.unrecognized);break}break;default:N(`%cUnrecognized MIDI Realtime/non realtime message: %c${QA(t)}`,r.warn,r.unrecognized)}break;case 65:let s=function(){N(`%cUnrecognized Roland %cGS %cSysEx: %c${QA(t)}`,r.warn,r.recognized,r.warn,r.unrecognized)};if(t[2]===66&&t[3]===18){let n=t[7];if(t[6]===127){n===0?(m("%cGS system on",r.info),this.system="gs"):n===127&&(m("%cGS system off, switching to GM2",r.info),this.system="gm2");return}else if(t[4]===64){if((t[5]&16)>0){let o=[9,0,1,2,3,4,5,6,7,8,10,11,12,13,14,15][t[5]&15]+A;switch(t[6]){default:s();break;case 21:let g=n>0&&t[5]>>4;this.setDrums(o,g),m(`%cChannel %c${o}%c ${g?"is now a drum channel":"now isn't a drum channel"}%c via: %c${QA(t)}`,r.info,r.value,r.recognized,r.info,r.value);return;case 22:let C=n-64;this.transposeChannel(o,C),m(`%cChannel %c${o}%c pitch shift. Semitones %c${C}%c, with %c${QA(t)}`,r.info,r.recognized,r.info,r.value,r.info,r.value);return;case 64:case 65:case 66:case 67:case 68:case 69:case 70:case 71:case 72:case 73:case 74:case 75:let Q=n-64;m(`%cChannel %c${o}%c scale tuning. Cents %c${Q}%c, with %c${QA(t)}`,r.info,r.recognized,r.info,r.value,r.info,r.value),this.setChannelTuning(o,Q);break}return}else if(t[5]===0&&t[6]===6){m(`%cRoland GS Master Pan set to: %c${n}%c with: %c${QA(t)}`,r.info,r.value,r.info,r.value),this.setMasterPan((n-64)/64);return}else if(t[5]===0&&t[6]===5){let o=n-64;m(`%cRoland GS Master Key-Shift set to: %c${o}%c with: %c${QA(t)}`,r.info,r.value,r.info,r.value),this.setMasterTuning(o*100);return}else if(t[5]===0&&t[6]===4){m(`%cRoland GS Master Volume set to: %c${n}%c with: %c${QA(t)}`,r.info,r.value,r.info,r.value),this.setMIDIVolume(n/127);return}}s();return}else if(t[2]===22&&t[3]===18&&t[4]===16){this.setMIDIVolume(t[7]/100),m(`%cRoland Master Volume control set to: %c${t[7]}%c via: %c${QA(t)}`,r.info,r.value,r.info,r.value);return}else{N(`%cUnrecognized Roland SysEx: %c${QA(t)}`,r.warn,r.unrecognized);return}case 67:if(t[2]===76)if(t[3]===0&&t[4]===0)switch(t[5]){case 4:let n=t[6];this.setMIDIVolume(n/127),m(`%cXG master volume. Volume: %c${n}`,r.info,r.recognized);break;case 6:let o=t[6]-64;this.transposeAllChannels(o),m(`%cXG master transpose. Volume: %c${o}`,r.info,r.recognized);break;case 126:m("%cXG system on",r.info),this.system="xg";break}else if(t[3]===8){if(this.system!=="xg")return;let n=t[4]+A;if(n>=this.workletProcessorChannels.length)return;let o=t[6];switch(t[5]){case 1:this.controllerChange(n,p.bankSelect,o);break;case 2:this.controllerChange(n,p.lsbForControl0BankSelect,o);break;case 3:this.programChange(n,o);break;case 8:let g=this.workletProcessorChannels[n];if(g.drumChannel)return;let C=o-64;g.channelTransposeKeyShift=C;break;case 11:this.controllerChange(n,p.mainVolume,o);break;case 14:let Q=o;Q===0&&(Q=Math.floor(Math.random()*127)),this.controllerChange(n,p.pan,Q);break;case 19:this.controllerChange(n,p.effects1Depth,o);break;case 18:this.controllerChange(n,p.effects3Depth,o);break;default:N(`%cUnrecognized Yamaha XG Part Setup: %c${t[5].toString(16).toUpperCase()}`,r.warn,r.unrecognized)}}else this.system==="xg"&&N(`%cUnrecognized Yamaha XG SysEx: %c${QA(t)}`,r.warn,r.unrecognized);else this.system==="xg"&&N(`%cUnrecognized Yamaha SysEx: %c${QA(t)}`,r.warn,r.unrecognized);break}}function tn(t,A,e){if(A.transformAmount===0)return 0;let s;if(A.sourceUsesCC)s=t[A.sourceIndex];else{let Q=A.sourceIndex+CA;switch(A.sourceIndex){case V.noController:s=16383;break;case V.noteOnKeyNum:s=e.midiNote<<7;break;case V.noteOnVelocity:s=e.velocity<<7;break;case V.polyPressure:s=e.pressure<<7;break;default:s=t[Q];break}}let n=dA[A.sourceCurveType][A.sourcePolarity][A.sourceDirection][s],o;if(A.secSrcUsesCC)o=t[A.secSrcIndex];else{let Q=A.secSrcIndex+CA;switch(A.secSrcIndex){case V.noController:o=16383;break;case V.noteOnKeyNum:o=e.midiNote<<7;break;case V.noteOnVelocity:o=e.velocity<<7;break;case V.polyPressure:o=e.pressure<<7;break;default:o=t[Q]}}let g=dA[A.secSrcCurveType][A.secSrcPolarity][A.secSrcDirection][o],C=n*g*A.transformAmount;return A.transformType===2?Math.abs(C):C}function XA(t,A,e=-1,s=0){let{modulators:n,generators:o,modulatedGenerators:g}=t;if(YA.recalculate(t),e===-1){g.set(o),n.forEach(h=>{g[h.modulatorDestination]+=tn(A,h,t)}),RA.recalculate(t);return}let C=new Set([a.initialAttenuation,a.delayVolEnv,a.attackVolEnv,a.holdVolEnv,a.decayVolEnv,a.sustainVolEnv,a.releaseVolEnv,a.keyNumToVolEnvHold,a.keyNumToVolEnvDecay]),Q=new Set;n.forEach(h=>{if(h.sourceUsesCC===e&&h.sourceIndex===s||h.secSrcUsesCC===e&&h.secSrcIndex===s){let d=h.modulatorDestination;Q.has(d)||(g[d]=o[d],n.forEach(c=>{c.modulatorDestination===d&&(g[d]+=tn(A,c,t))}),Q.add(d))}}),[...Q].some(h=>C.has(h))&&RA.recalculate(t)}var dA=[];for(let t=0;t<4;t++){dA[t]=[[new Float32Array(IA),new Float32Array(IA)],[new Float32Array(IA),new Float32Array(IA)]];for(let A=0;A 200&&e<40||this.highPerformanceMode&&e<10||g.isMuted)return;let C=A+g.channelTransposeKeyShift;if(A>127||A<0)return;let Q=g.preset.program;this.tunings[Q]?.[A]?.midiNote>=0&&(C=this.tunings[Q]?.[A].midiNote);let h=this.getWorkletVoices(t,C,e,g,o,s),d=g.voices;h.forEach(c=>{let u=c.generators[a.exclusiveClass];u!==0&&d.forEach(l=>{l.generators[a.exclusiveClass]===u&&(this.releaseVoice(l),l.modulatedGenerators[a.releaseVolEnv]=-7e3,l.modulatedGenerators[a.releaseModEnv]=-7e3,RA.recalculate(l),YA.recalculate(l))}),XA(c,g.midiControllers),RA.intialize(c),c.currentPan=(Math.max(-500,Math.min(500,c.modulatedGenerators[a.pan]))+500)/1e3}),this.totalVoicesAmount+=h.length,this.totalVoicesAmount>this.voiceCap&&this.voiceKilling(h.length),d.push(...h),n&&(this.sendChannelProperties(),this.callEvent("noteon",{midiNote:A,channel:t,velocity:e}))}function nn(t,A){if(A>127||A<0){N("Received a noteOn for note",A,"Ignoring.");return}let e=A+this.workletProcessorChannels[t].channelTransposeKeyShift,s=this.workletProcessorChannels[t].preset.program;if(this.tunings[s]?.[A]?.midiNote>=0&&(e=this.tunings[s]?.[A].midiNote),this.highPerformanceMode&&!this.workletProcessorChannels[t].drumChannel){this.killNote(t,e);return}this.workletProcessorChannels[t].voices.forEach(o=>{o.midiNote!==e||o.isInRelease===!0||(this.workletProcessorChannels[t].holdPedal?this.workletProcessorChannels[t].sustainedVoices.push(o):this.releaseVoice(o))}),this.callEvent("noteoff",{midiNote:A,channel:t})}function on(t,A){this.workletProcessorChannels[t].voices.forEach(e=>{e.midiNote===A&&(e.modulatedGenerators[a.releaseVolEnv]=-12e3,this.releaseVoice(e))})}function rn(t,A=!1){let e=this.workletProcessorChannels[t].voices;A?(e.length=0,this.workletProcessorChannels[t].sustainedVoices.length=0,this.sendChannelProperties()):(e.forEach(s=>{s.isInRelease||this.releaseVoice(s)}),this.workletProcessorChannels[t].sustainedVoices.forEach(s=>{this.releaseVoice(s)}))}function an(t=!1){m("%cStop all received!",r.info);for(let A=0;A XA(n,this.workletProcessorChannels[t].midiControllers,0,V.pitchWheel)),this.sendChannelProperties()}function cn(t,A){let e=this.workletProcessorChannels[t];e.midiControllers[CA+V.channelPressure]=A<<7,this.workletProcessorChannels[t].voices.forEach(s=>XA(s,e.midiControllers,0,V.channelPressure)),this.callEvent("channelpressure",{channel:t,pressure:A})}function ln(t,A,e){this.workletProcessorChannels[t].voices.forEach(s=>{s.midiNote===A&&(s.pressure=e,XA(s,this.workletProcessorChannels[t].midiControllers,0,V.polyPressure))}),this.callEvent("polypressure",{channel:t,midiNote:A,pressure:e})}function un(t,A){if(A.length!==12)throw new Error("Tuning is not the length of 12.");this.workletProcessorChannels[t].channelOctaveTuning=A}function dn(t,A,e,s=!1){let n=this.workletProcessorChannels[t];if(n===void 0){N(`Trying to access channel ${t} which does not exist... ignoring!`);return}if(A>=p.lsbForControl1ModulationWheel&&A<=p.lsbForControl13EffectControl2&&A!==p.lsbForControl6DataEntry){let o=A-32;if(n.lockedControllers[o])return;n.midiControllers[o]=n.midiControllers[o]&16256|e&127,n.voices.forEach(g=>XA(g,n.midiControllers,1,o))}switch(A){case p.allNotesOff:this.stopAll(t);break;case p.allSoundOff:this.stopAll(t,!0);break;case p.bankSelect:let o=e;if(!s){switch(this.system){case"gm":m(`%cIgnoring the Bank Select (${e}), as the synth is in GM mode.`,r.info);return;case"xg":o===120||o===126||o===127?this.setDrums(t,!0):t%16!==SA&&this.setDrums(t,!1);break;case"gm2":o===120&&(n.drumChannel=!0,this.callEvent("drumchange",{channel:t,isDrumChannel:!0}))}n.drumChannel&&(o=128),o===128&&!n.drumChannel&&(o=n.midiControllers[p.bankSelect])}n.midiControllers[p.bankSelect]=o;break;case p.lsbForControl0BankSelect:this.system==="xg"?n.drumChannel||e!==127&&(n.midiControllers[p.bankSelect]=e):this.system==="gm2"&&(n.midiControllers[p.bankSelect]=e);break;case p.RPNLsb:n.RPValue=n.RPValue<<7|e,n.dataEntryState=uA.RPFine;break;case p.RPNMsb:n.RPValue=e,n.dataEntryState=uA.RPCoarse;break;case p.NRPNMsb:n.NRPCoarse=e,n.dataEntryState=uA.NRPCoarse;break;case p.NRPNLsb:n.NRPFine=e,n.dataEntryState=uA.NRPFine;break;case p.dataEntryMsb:this.dataEntryCoarse(t,e);break;case p.lsbForControl6DataEntry:this.dataEntryFine(t,e);break;case p.resetAllControllers:this.resetControllers(t);break;case p.sustainPedal:e>=64?n.holdPedal=!0:(n.holdPedal=!1,n.sustainedVoices.forEach(g=>{this.releaseVoice(g)}),n.sustainedVoices=[]);break;default:if(n.lockedControllers[A])return;n.midiControllers[A]=e<<7,n.voices.forEach(g=>XA(g,n.midiControllers,1,A)),this.callEvent("controllerchange",{channel:t,controllerNumber:A,controllerValue:e});break}}function fn(t){this.midiVolume=t,this.setMasterPan(this.pan)}function mn(t){this.masterGain=t*Lt,this.setMasterPan(this.pan)}function pn(t){this.pan=t,t=t/2+.5,this.panLeft=(1-t)*this.currentGain,this.panRight=t*this.currentGain}function Sn(t,A){A&&this.stopAll(t,!0),this.workletProcessorChannels[t].isMuted=A,this.sendChannelProperties(),this.callEvent("mutechannel",{channel:t,isMuted:A})}function yn(t){this.workletProcessorChannels[t].lockGSNRPNParams=!0,this.workletProcessorChannels[t].channelVibrato.rate=0,this.workletProcessorChannels[t].channelVibrato.delay=0,this.workletProcessorChannels[t].channelVibrato.depth=0}function Dn(t,A,e,s){this.workletProcessorChannels[t].lockGSNRPNParams||(this.workletProcessorChannels[t].channelVibrato.rate=e,this.workletProcessorChannels[t].channelVibrato.delay=s,this.workletProcessorChannels[t].channelVibrato.depth=A)}function kn(t,A){let e=this.workletProcessorChannels[t],s=()=>{e.channelVibrato.delay===0&&e.channelVibrato.rate===0&&e.channelVibrato.depth===0&&(e.channelVibrato.depth=50,e.channelVibrato.rate=8,e.channelVibrato.delay=.6)};switch(e.dataEntryState){default:case uA.Idle:break;case uA.NRPFine:if(this.system!=="gs"||e.lockGSNRPNParams)return;switch(e.NRPCoarse){default:if(A===64)return;N(`%cUnrecognized NRPN for %c${t}%c: %c(0x${e.NRPCoarse.toString(16).toUpperCase()} 0x${e.NRPFine.toString(16).toUpperCase()})%c data value: %c${A}`,r.warn,r.recognized,r.warn,r.unrecognized,r.warn,r.value);break;case 1:switch(e.NRPFine){default:if(A===64)return;N(`%cUnrecognized NRPN for %c${t}%c: %c(0x${e.NRPCoarse.toString(16)} 0x${e.NRPFine.toString(16)})%c data value: %c${A}`,r.warn,r.recognized,r.warn,r.unrecognized,r.warn,r.value);break;case 8:if(A===64)return;s(),e.channelVibrato.rate=A/64*8,m(`%cVibrato rate for %c${t}%c is now set to %c${A} = ${e.channelVibrato.rate}%cHz.`,r.info,r.recognized,r.info,r.value,r.info);break;case 9:if(A===64)return;s(),e.channelVibrato.depth=A/2,m(`%cVibrato depth for %c${t}%c is now set to %c${A} = ${e.channelVibrato.depth}%c cents range of detune.`,r.info,r.recognized,r.info,r.value,r.info);break;case 10:if(A===64)return;s(),e.channelVibrato.delay=A/64/3,m(`%cVibrato delay for %c${t}%c is now set to %c${A} = ${e.channelVibrato.delay}%c seconds.`,r.info,r.recognized,r.info,r.value,r.info);break;case 32:let g=A;this.controllerChange(t,p.brightness,A),m(`%cFilter cutoff for %c${t}%c is now set to %c${g}`,r.info,r.recognized,r.info,r.value)}break;case 24:let n=A-64;e.keyCentTuning[e.NRPFine]=n*100,m(`%cGS drum key tuning. MIDI note: %c${e.NRPFine}%c semitones: %c${n}`,r.info,r.recognized,r.info,r.value);break;case 29:let o=A;this.controllerChange(t,p.effects1Depth,o),m(`%cGS Drum reverb for %c${t}%c: %c${o}`,r.info,r.recognized,r.info,r.value);break}break;case uA.RPCoarse:case uA.RPFine:switch(e.RPValue){default:N(`%cUnrecognized RPN for %c${t}%c: %c(0x${e.RPValue.toString(16)})%c data value: %c${A}`,r.warn,r.recognized,r.warn,r.unrecognized,r.warn,r.value);break;case 0:e.midiControllers[CA+V.pitchWheelRange]=A<<7,m(`%cChannel ${t} bend range. Semitones: %c${A}`,r.info,r.value);break;case 2:this.setChannelTuningSemitones(t,A-64);break;case 1:this.setChannelTuning(t,A-64,!1);break;case 5:this.setModulationDepth(t,A*100);break;case 16383:this.resetParameters(t);break}}}function wn(t,A){let e=this.workletProcessorChannels[t];switch(e.dataEntryState){default:break;case uA.RPCoarse:case uA.RPFine:switch(e.RPValue){default:break;case 0:if(A===0)break;e.midiControllers[CA+V.pitchWheelRange]|=A;let s=(e.midiControllers[CA+V.pitchWheelRange]>>7)+A/127;m(`%cChannel ${t} bend range. Semitones: %c${s}`,r.info,r.value);break;case 1:let o=e.customControllers[aA.channelTuning]<<7|A;this.setChannelTuning(t,o*.01220703125);break;case 5:let C=e.customControllers[aA.modulationMultiplier]*50+A/128*100;this.setModulationDepth(t,C);break;case 16383:this.resetParameters(t);break}}}function Fn(){m("%cResetting all controllers!",r.info),this.callEvent("allcontrollerreset",void 0);for(let t=0;t {this.workletProcessorChannels[t].lockedControllers[s]&&this.callEvent("controllerchange",{channel:t,controllerNumber:s,controllerValue:this.workletProcessorChannels[t].midiControllers[s]>>7})};if(e(p.mainVolume),e(p.pan),e(p.expressionController),e(p.modulationWheel),e(p.effects3Depth),e(p.effects1Depth),this.workletProcessorChannels[t].lockedControllers[CA+V.pitchWheel]){let s=this.workletProcessorChannels[t].midiControllers[CA+V.pitchWheel],n=s>>7,o=s&127;this.callEvent("pitchwheel",{channel:t,MSB:n,LSB:o})}}this.tunings=[],this.tunings=[];for(let t=0;t<127;t++)this.tunings.push([]);this.setMIDIVolume(1),this.system=Ke}function Rn(t){let A=this.workletProcessorChannels[t],s=A.lockedControllers.reduce((o,g,C)=>(g&&o.push(C),o),[]).map(o=>({ccNum:o,ccVal:A.midiControllers[o]}));A.channelOctaveTuning.fill(0),A.keyCentTuning.fill(0),A.midiControllers.set(KA),A.channelVibrato={rate:0,depth:0,delay:0},A.holdPedal=!1,s.forEach(o=>{A.midiControllers[o.ccNum]=o.ccVal});let n=A.customControllers[aA.channelTransposeFine];A.customControllers.set(wt),A.customControllers[aA.channelTransposeFine]=n,this.resetParameters(t)}function Gn(t){let A=this.workletProcessorChannels[t];A.NRPCoarse=0,A.NRPFine=0,A.RPValue=0,A.dataEntryState=uA.Idle}function xn(){let t=4;for(let s of this.instruments)t+=s.instrumentZones.reduce((n,o)=>(o.generators=o.generators.filter(g=>g.generatorType!==a.sampleID&&g.generatorType!==a.keyRange&&g.generatorType!==a.velRange),(o.velRange.max!==127||o.velRange.min!==0)&&o.generators.unshift({generatorType:a.velRange,generatorValue:o.velRange.max<<8|o.velRange.min}),(o.keyRange.max!==127||o.keyRange.min!==0)&&o.generators.unshift({generatorType:a.keyRange,generatorValue:o.keyRange.max<<8|o.keyRange.min}),o.isGlobal||o.generators.push({generatorType:a.sampleID,generatorValue:this.samples.indexOf(o.sample)}),o.generators.length*4+n),0);let A=new H(t),e=0;for(let s of this.instruments)for(let n of s.instrumentZones){n.generatorZoneStartIndex=e;for(let o of n.generators)Y(A,o.generatorType),Y(A,o.generatorValue),e++}return cA(A,0),nA(new $("igen",A.length,A))}function Mn(t,A,e,s,n){let o=this.samples.map((h,d)=>{e&&h.compressSample(s,n);let c=h.getRawData();return m(`%cEncoded sample %c${d}. ${h.sampleName}%c of %c${this.samples.length}`,r.info,r.recognized,r.info,r.recognized),c}),g=this.samples.reduce((h,d,c)=>h+o[c].length+46,0),C=new H(g);this.samples.forEach((h,d)=>{let c=o[d],u,l,D=c.length;h.isCompressed?(u=C.currentIndex,l=u+c.length):(u=C.currentIndex/2,l=u+c.length/2,D+=46),t.push(u),C.set(c,C.currentIndex),C.currentIndex+=D,A.push(l)});let Q=nA(new $("smpl",C.length,C),new H([115,100,116,97]));return nA(new $("LIST",Q.length,Q))}function Nn(t,A){let s=new H(46*(this.samples.length+1));return this.samples.forEach((n,o)=>{FA(s,n.sampleName,20);let g=t[o];cA(s,g);let C=A[o];cA(s,C);let Q=n.sampleLoopStartIndex/2+g,h=n.sampleLoopEndIndex/2+g;n.isCompressed&&(Q-=g,h-=g),cA(s,Q),cA(s,h),cA(s,n.sampleRate),s[s.currentIndex++]=n.samplePitch,s[s.currentIndex++]=n.samplePitchCorrection,Y(s,n.sampleLink),Y(s,n.sampleType)}),FA(s,"EOS",46),nA(new $("shdr",s.length,s))}function bn(){let t=10;for(let s of this.instruments)t+=s.instrumentZones.reduce((n,o)=>o.modulators.length*10+n,0);let A=new H(t),e=0;for(let s of this.instruments)for(let n of s.instrumentZones){n.modulatorZoneStartIndex=e;for(let o of n.modulators)Y(A,o.sourceEnum),Y(A,o.modulatorDestination),Y(A,o.transformAmount),Y(A,o.secondarySourceEnum),Y(A,o.transformType),e++}return ge(A,0,10),nA(new $("imod",A.length,A))}function Ln(){let t=this.instruments.reduce((o,g)=>g.instrumentZones.length*4+o,4),A=new H(t),e=0,s=0,n=0;for(let o of this.instruments){o.instrumentZoneIndex=e;for(let g of o.instrumentZones)g.zoneID=e,Y(A,s),Y(A,n),s+=g.generators.length,n+=g.modulators.length,e++}return Y(A,s),Y(A,n),nA(new $("ibag",A.length,A))}function Un(){let t=this.instruments.length*22+22,A=new H(t),e=0,s=0;for(let n of this.instruments)FA(A,n.instrumentName,20),Y(A,e),e+=n.instrumentZones.length,n.instrumentID=s,s++;return FA(A,"EOI",20),Y(A,e),nA(new $("inst",A.length,A))}function Tn(){let t=4;for(let s of this.presets)t+=s.presetZones.reduce((n,o)=>(o.generators=o.generators.filter(g=>g.generatorType!==a.instrument&&g.generatorType!==a.keyRange&&g.generatorType!==a.velRange),(o.velRange.max!==127||o.velRange.min!==0)&&o.generators.unshift({generatorType:a.velRange,generatorValue:o.velRange.max<<8|o.velRange.min}),(o.keyRange.max!==127||o.keyRange.min!==0)&&o.generators.unshift({generatorType:a.keyRange,generatorValue:o.keyRange.max<<8|o.keyRange.min}),o.isGlobal||o.generators.push({generatorType:a.instrument,generatorValue:this.instruments.indexOf(o.instrument)}),o.generators.length*4+n),0);let A=new H(t),e=0;for(let s of this.presets)for(let n of s.presetZones){n.generatorZoneStartIndex=e;for(let o of n.generators)Y(A,o.generatorType),Y(A,o.generatorValue);e+=n.generators.length}return Y(A,0),Y(A,0),nA(new $("pgen",A.length,A))}function Hn(){let t=10;for(let s of this.presets)t+=s.presetZones.reduce((n,o)=>o.modulators.length*10+n,0);let A=new H(t),e=0;for(let s of this.presets)for(let n of s.presetZones){n.modulatorZoneStartIndex=e;for(let o of n.modulators)Y(A,o.sourceEnum),Y(A,o.modulatorDestination),Y(A,o.transformAmount),Y(A,o.secondarySourceEnum),Y(A,o.transformType),e++}return ge(A,0,10),nA(new $("pmod",A.length,A))}function Yn(){let t=this.presets.reduce((o,g)=>g.presetZones.length*4+o,4),A=new H(t),e=0,s=0,n=0;for(let o of this.presets){o.presetZoneStartIndex=e;for(let g of o.presetZones)g.zoneID=e,Y(A,s),Y(A,n),s+=g.generators.length,n+=g.modulators.length,e++}return Y(A,s),Y(A,n),nA(new $("pbag",A.length,A))}function Jn(){let t=this.presets.length*38+38,A=new H(t),e=0;for(let s of this.presets)FA(A,s.presetName,20),Y(A,s.program),Y(A,s.bank),Y(A,e),cA(A,s.library),cA(A,s.genre),cA(A,s.morphology),e+=s.presetZones.length;return FA(A,"EOP",20),Y(A,0),Y(A,0),Y(A,e),cA(A,0),cA(A,0),cA(A,0),nA(new $("phdr",A.length,A))}var xo={compress:!1,compressionQuality:.5,compressionFunction:void 0};function qn(t=xo){if(t.compress&&typeof t.compressionFunction!="function")throw new TypeError("No compression function supplied but compression enabled.");pA("%cSaving soundfont...",r.info),m(`%cCompression: %c${t?.compress||"false"}%c quality: %c${t?.compressionQuality||"none"}`,r.info,r.recognized,r.info,r.recognized),m("%cWriting INFO...",r.info);let A=[];this.soundFontInfo.ISFT="SpessaSynth",t?.compress&&(this.soundFontInfo.ifil="3.0");for(let[v,T]of Object.entries(this.soundFontInfo))if(v==="ifil"||v==="iver"){let I=parseInt(T.split(".")[0]),AA=parseInt(T.split(".")[1]),K=new H(4);Y(K,I),Y(K,AA),A.push(nA(new $(v,4,K)))}else if(v==="DMOD")A.push(nA(new $(v,T.length,T)));else{let I=new H(T.length);FA(I,T),A.push(nA(new $(v,T.length,I)))}let e=De([new H([73,78,70,79]),...A]),s=nA(new $("LIST",e.length,e));m("%cWriting SDTA...",r.info);let n=[],o=[],g=Mn.call(this,n,o,t?.compress,t?.compressionQuality||.5,t.compressionFunction);m("%cWriting PDTA...",r.info),m("%cWriting SHDR...",r.info);let C=Nn.call(this,n,o);m("%cWriting IGEN...",r.info);let Q=xn.call(this);m("%cWriting IMOD...",r.info);let h=bn.call(this);m("%cWriting IBAG...",r.info);let d=Ln.call(this);m("%cWriting INST...",r.info);let c=Un.call(this),u=Tn.call(this);m("%cWriting PMOD...",r.info);let l=Hn.call(this);m("%cWriting PBAG...",r.info);let D=Yn.call(this);m("%cWriting PHDR...",r.info);let y=Jn.call(this),k=De([new H([112,100,116,97]),y,D,l,u,c,d,h,Q,C]),F=nA(new $("LIST",k.length,k));m("%cWriting the output file...",r.info);let q=De([new H([115,102,98,107]),s,g,F]),M=nA(new $("RIFF",q.length,q));return m(`%cSaved succesfully! Final file size: %c${M.length}`,r.info,r.recognized),X(),M}var ne=class t{constructor(A=void 0){this.soundFontInfo={},this.presets=[],this.samples=[],this.instruments=[],this.defaultModulators=Oe.map(e=>eA.copy(e)),A?.presets&&(this.presets.push(...A.presets),this.soundFontInfo=A.info)}removeUnusedElements(){this.instruments.forEach(A=>{A.useCount<1&&A.instrumentZones.forEach(e=>{e.isGlobal||e.sample.useCount--})}),this.instruments=this.instruments.filter(A=>A.useCount>0),this.samples=this.samples.filter(A=>A.useCount>0)}deleteInstrument(A){if(A.useCount>0)throw new Error(`Cannot delete an instrument that has ${A.useCount} usages.`);this.instruments.splice(this.instruments.indexOf(A),1),A.deleteInstrument(),this.removeUnusedElements()}deleteSample(A){if(A.useCount>0)throw new Error(`Cannot delete sample that has ${A.useCount} usages.`);this.samples.splice(this.samples.indexOf(A),1),this.removeUnusedElements()}deletePreset(A){A.deletePreset(),this.presets.splice(this.presets.indexOf(A),1),this.removeUnusedElements()}getPresetNoFallback(A,e,s=!1){let n=this.presets.find(o=>o.bank===A&&o.program===e);if(n)return n;if(s!==!1)return A===128?this.presets.find(o=>o.bank===128):this.presets.find(o=>o.program===e)}setSampleIDOffset(A){this.presets.forEach(e=>e.sampleIDOffset=A)}getPreset(A,e){let s=this.presets.find(n=>n.bank===A&&n.program===e);return s||(A===128?(s=this.presets.find(n=>n.bank===128&&n.program===e),s||(s=this.presets.find(n=>n.bank===128))):s=this.presets.find(n=>n.program===e&&n.bank!==128),s&&N(`%cPreset ${A}.${e} not found. Replaced with %c${s.presetName} (${s.bank}.${s.program})`,r.warn,r.recognized)),s||(N(`Preset ${e} not found. Defaulting to`,this.presets[0].presetName),s=this.presets[0]),s}getPresetByName(A){let e=this.presets.find(s=>s.presetName===A);return e||(N("Preset not found. Defaulting to:",this.presets[0].presetName),e=this.presets[0]),e}static mergeSoundfonts(...A){let e=A.shift(),s=e.presets;for(;A.length;)A.shift().presets.forEach(o=>{s.find(g=>g.bank===o.bank&&g.program===o.program)===void 0&&s.push(o)});return new t({presets:s,info:e.soundFontInfo})}};ne.prototype.write=qn;function vn(t){pA("%cLoading instruments...",r.info);for(let A=0;A A.deleteZone()),this.presetZones.length=0}deleteZone(A){this.presetZones[A].deleteZone(),this.presetZones.splice(A,1)}preload(A,e){for(let s=A;s {o.sample.isSampleLoaded||o.sample.getAudioData()})}preloadSpecific(A,e){this.getSamplesAndGenerators(A,e).forEach(s=>{s.sample.isSampleLoaded||s.sample.getAudioData()})}getSamplesAndGenerators(A,e){let s=this.foundSamplesAndGenerators[A][e];if(s)return s;if(this.presetZones.length<1)return[];function n(c,u,l){return l>=c&&l<=u}function o(c,u){c.push(...u.filter(l=>!c.find(D=>D.generatorType===l.generatorType)))}function g(c,u){c.push(...u.filter(l=>!c.find(D=>eA.isIdentical(l,D))))}let C=[],Q=this.presetZones[0].isGlobal?[...this.presetZones[0].generators]:[],h=this.presetZones[0].isGlobal?[...this.presetZones[0].modulators]:[];return this.presetZones.filter(c=>n(c.keyRange.min,c.keyRange.max,A)&&n(c.velRange.min,c.velRange.max,e)&&!c.isGlobal).forEach(c=>{if(c.instrument.instrumentZones.length<1)return;let u=c.generators,l=c.modulators,D=c.instrument.instrumentZones[0].isGlobal?[...c.instrument.instrumentZones[0].generators]:[],y=c.instrument.instrumentZones[0].isGlobal?[...c.instrument.instrumentZones[0].modulators]:[];c.instrument.instrumentZones.filter(F=>n(F.keyRange.min,F.keyRange.max,A)&&n(F.velRange.min,F.velRange.max,e)&&!F.isGlobal).forEach(F=>{let q=[...F.generators],M=[...F.modulators];o(u,Q),o(q,D),g(l,h),g(M,y),g(M,this.defaultModulators);let v=[...M];for(let T=0;T eA.isIdentical(I,K));AA!==-1?v[AA]=v[AA].sumTransform(I):v.push(I)}C.push({instrumentGenerators:q,presetGenerators:u,modulators:v,sample:F.sample,sampleID:F.generators.find(T=>T.generatorType===a.sampleID).generatorValue})})}),this.foundSamplesAndGenerators[A][e]=C,C}};var Fe=class{velRange={min:0,max:127};keyRange={min:0,max:127};isGlobal=!1;generators=[];modulators=[]};var $A=class extends Fe{sample=void 0;useCount=0;deleteZone(){this.useCount--,!this.isGlobal&&this.sample.useCount--}},ce=class extends Fe{instrument=void 0;deleteZone(){this.isGlobal||this.instrument.removeUseCount()}};var le=class{constructor(){this.instrumentName="",this.instrumentZones=[],this._useCount=0}addUseCount(){this._useCount++,this.instrumentZones.forEach(A=>A.useCount++)}removeUseCount(){this._useCount--;for(let A=0;A A.deleteZone()),this.instrumentZones.length=0}safeDeleteZone(A){return this.instrumentZones[A].useCount--,this.instrumentZones[A].useCount<1?(this.deleteZone(A),!0):!1}deleteZone(A){this.instrumentZones[A].deleteZone(),this.instrumentZones.splice(A,1)}};var et=class extends Qe{constructor(A,e){super(Oe),this.program=e&127,this.bank=A>>8&127,A>>31&&(this.bank=128),this.DLSInstrument=new le,this.DLSInstrument.addUseCount();let n=new ce;n.instrument=this.DLSInstrument,this.presetZones=[n]}};function Kn(t){this.verifyHeader(t,"LIST"),this.verifyText(O(t.chunkData,4),"ins ");let A=[];for(;t.chunkData.length>t.chunkData.currentIndex;)A.push(Z(t.chunkData));let e=A.find(l=>l.header==="insh");if(!e)throw X(),new Error("No instrument header!");let s=S(e.chunkData,4),n=S(e.chunkData,4),o=S(e.chunkData,4),g=new et(n,o),C="unnamedPreset",Q=yA(A,"INFO");if(Q){let l=Z(Q.chunkData);for(;l.header!=="INAM";)l=Z(Q.chunkData);C=O(l.chunkData,l.chunkData.length).trim()}g.presetName=C,g.DLSInstrument.instrumentName=C,te(`%cParsing %c"${C}"%c...`,r.info,r.recognized,r.info);let h=yA(A,"lrgn");if(!h)throw X(),new Error("No region list!");let d=new $A;d.isGlobal=!0;let c=yA(A,"lart"),u=yA(A,"lar2");this.readLart(c,u,d),g.DLSInstrument.instrumentZones.push(d);for(let l=0;l >10&15;F===lA.linear&&k!==lA.linear&&(F=k);let q=s>>14&1,M=s>>15&1;g===a.initialAttenuation&&(M=!M),c=vA(F,q,M,C.isCC,C.enum)}let u=s>>4&15,l=s>>8&1,D=s>>9&1,y=vA(u,l,D,d.isCC,d.enum);if(Q){let k=y;y=c,c=k}return new eA({srcEnum:c,secSrcEnum:y,dest:g,transform:0,amt:n})}function Ut(t,A){let e=t.chunkData,s=[],n=[];S(e,4);let o=S(e,4);for(let g=0;g>16;if(C===0&&Q===0&&d===0){let l;switch(h){case G.pan:l=new b(a.pan,u);break;case G.gain:l=new b(a.initialAttenuation,-u*10/.4);break;case G.filterCutoff:l=new b(a.initialFilterFc,u);break;case G.filterQ:l=new b(a.initialFilterQ,u);break;case G.modLfoFreq:l=new b(a.freqModLFO,u);break;case G.modLfoDelay:l=new b(a.delayModLFO,u);break;case G.vibLfoFreq:l=new b(a.freqVibLFO,u);break;case G.vibLfoDelay:l=new b(a.delayVibLFO,u);break;case G.volEnvDelay:l=new b(a.delayVolEnv,u);break;case G.volEnvAttack:l=new b(a.attackVolEnv,u);break;case G.volEnvHold:l=new b(a.holdVolEnv,u);break;case G.volEnvDecay:l=new b(a.decayVolEnv,u);break;case G.volEnvRelease:l=new b(a.releaseVolEnv,u);break;case G.volEnvSustain:let D=(1e3-u)/10;l=new b(a.sustainVolEnv,D*10);break;case G.modEnvDelay:l=new b(a.delayModEnv,u);break;case G.modEnvAttack:l=new b(a.attackModEnv,u);break;case G.modEnvHold:l=new b(a.holdModEnv,u);break;case G.modEnvDecay:l=new b(a.decayModEnv,u);break;case G.modEnvRelease:l=new b(a.releaseModEnv,u);break;case G.modEnvSustain:let y=1e3-u;l=new b(a.sustainModEnv,y);break;case G.reverbSend:l=new b(a.reverbEffectsSend,u);break;case G.chorusSend:l=new b(a.chorusEffectsSend,u);break;case G.pitch:let k=Math.floor(u/100),F=Math.floor(u-k*100);l=new b(a.fineTune,F),s.push(new b(a.coarseTune,k));break}l&&s.push(l)}else{let l=!0;if(Q===_.none)if(C===_.modLfo&&h===G.pitch)s.push(new b(a.modLfoToPitch,u));else if(C===_.modLfo&&h===G.gain)s.push(new b(a.modLfoToVolume,u));else if(C===_.modLfo&&h===G.filterCutoff)s.push(new b(a.modLfoToFilterFc,u));else if(C===_.vibratoLfo&&h===G.pitch)s.push(new b(a.vibLfoToPitch,u));else if(C===_.modEnv&&h===G.pitch)s.push(new b(a.modEnvToPitch,u));else if(C===_.modEnv&&h===G.filterCutoff)s.push(new b(a.modEnvToFilterFc,u));else if(C===_.keyNum&&h===G.volEnvHold){s.push(new b(a.keyNumToVolEnvHold,u/-128));let D=Math.round(60/128*u);s.forEach(y=>{y.generatorType===a.holdVolEnv&&(y.generatorValue+=D)})}else if(C===_.keyNum&&h===G.volEnvDecay){s.push(new b(a.keyNumToVolEnvDecay,u/-128));let D=Math.round(60/128*u);s.forEach(y=>{y.generatorType===a.decayVolEnv&&(y.generatorValue+=D)})}else if(C===_.keyNum&&h===G.modEnvHold){s.push(new b(a.keyNumToModEnvHold,u/-128));let D=Math.round(60/128*u);s.forEach(y=>{y.generatorType===a.holdModEnv&&(y.generatorValue+=D)})}else if(C===_.keyNum&&h===G.modEnvDecay){s.push(new b(a.keyNumToModEnvDecay,u/-128));let D=Math.round(60/128*u);s.forEach(y=>{y.generatorType===a.decayModEnv&&(y.generatorValue+=D)})}else l=!1;else l=!1;if(l===!1){let D=Vn(C,Q,h,d,u);D?(n.push(D),m("%cSucceeded converting to SF2 Modulator!",r.recognized)):N("Failed converting to SF2 Modulator!")}}}return n.find(g=>g.modulatorDestination===a.reverbEffectsSend)===void 0&&n.push(new eA({srcEnum:219,dest:a.reverbEffectsSend,amt:1e3,secSrcEnum:0,transform:0})),n.find(g=>g.modulatorDestination===a.chorusEffectsSend)===void 0&&n.push(new eA({srcEnum:221,dest:a.chorusEffectsSend,amt:1e3,secSrcEnum:0,transform:0})),A&&n.push(new eA({srcEnum:129,dest:a.vibLfoToPitch,amt:0,secSrcEnum:0,transform:0}),new eA({srcEnum:13,dest:a.vibLfoToPitch,amt:0,secSrcEnum:0,transform:0})),{modulators:n,generators:s}}function On(t,A,e){if(t)for(;t.chunkData.currentIndex t.chunkData.currentIndex;)A.push(Z(t.chunkData));let e=A.find(AA=>AA.header==="rgnh"),s=S(e.chunkData,2),n=S(e.chunkData,2),o=S(e.chunkData,2),g=S(e.chunkData,2),C=new tt({min:s,max:n},{min:o,max:g});S(e.chunkData,2);let Q=S(e.chunkData,2);Q!==0&&C.generators.push(new b(a.exclusiveClass,Q));let h=yA(A,"lart"),d=yA(A,"lar2");this.readLart(h,d,C),C.isGlobal=!1;let c=A.find(AA=>AA.header==="wsmp");S(c.chunkData,4);let u=S(c.chunkData,2),l=jA(c.chunkData[c.chunkData.currentIndex++],c.chunkData[c.chunkData.currentIndex++]),k=(S(c.chunkData,4)|0)/-655360*10/.4;S(c.chunkData,4);let F=S(c.chunkData,4),q,M={start:0,end:0};if(F===0)q=0;else{S(c.chunkData,4),S(c.chunkData,4)===0?q=1:q=3,M.start=S(c.chunkData,4);let K=S(c.chunkData,4);M.end=M.start+K}let v=A.find(AA=>AA.header==="wlnk");if(v===void 0)return;S(v.chunkData,2),S(v.chunkData,2),S(v.chunkData,4);let T=S(v.chunkData,4),I=this.samples[T];if(I===void 0)throw new Error("Invalid sample ID!");return C.setWavesample(k,q,M,u,I,T,l),C}var ue=class{constructor(A,e,s,n,o,g,C,Q){this.sampleName=A,this.sampleRate=e,this.samplePitch=s,this.samplePitchCorrection=n,this.sampleLink=o,this.sampleType=g,this.sampleLoopStartIndex=C,this.sampleLoopEndIndex=Q,this.isCompressed=(g&16)>0,this.compressedData=void 0,this.useCount=0}getRawData(){let A=new Error("Not implemented");throw A.name="NotImplementedError",A}compressSample(A,e){if(!this.isCompressed)try{this.compressedData=e([this.getAudioData()],1,this.sampleRate,A),this.sampleType|=16,this.isCompressed=!0}catch{N(`Failed to compress ${this.sampleName}. Leaving as uncompressed!`),this.isCompressed=!1,this.compressedData=void 0,this.sampleType&=-17}}getAudioData(){let A=new Error("Not implemented");throw A.name="NotImplementedError",A}};var st=class extends ue{constructor(A,e,s,n,o,g,C){super(A,e,s,n,0,1,o*2,(g-1)*2),this.sampleData=C}getAudioData(){return this.sampleData}sampleData;getRawData(){if(this.isCompressed){if(!this.compressedData)throw new Error("Compressed but no data??");return this.compressedData}let A=new Uint8Array(this.sampleData.length*2);for(let e=0;e >8&255}return A}};function Xn(t){pA("%cLoading Wave samples...",r.recognized);let A=0;for(;t.chunkData.currentIndex K.header==="fmt ");if(!n)throw new Error("No fmt chunk in the wave file!");if(S(n.chunkData,2)!==1)throw new Error("Only PCM format in WAVE is supported.");if(S(n.chunkData,2)!==1)throw new Error("Only mono samples are supported.");let C=S(n.chunkData,4);S(n.chunkData,4),S(n.chunkData,2);let Q=S(n.chunkData,2),h=Q/8,d=Math.pow(2,h*8-1),c=Math.pow(2,h*8),u,l=!1;Q===8?(u=255,l=!0):u=d;let D=s.find(K=>K.header==="data");if(!D)throw new Error("No data chunk in the wave chunk!");let y=D.size/h,k=new Float32Array(y);for(let K=0;K =d&&(j-=c),k[K]=j/u)}let F=60,q=0,M=0,v=k.length-1,T=s.find(K=>K.header==="wsmp");if(T){if(S(T.chunkData,4),F=S(T.chunkData,2),q=jA(T.chunkData[T.chunkData.currentIndex++],T.chunkData[T.chunkData.currentIndex++]),S(T.chunkData,4),S(T.chunkData,4),S(T.chunkData,4)===1){S(T.chunkData,8),M=S(T.chunkData,4);let j=S(T.chunkData,4);v=M+j}}else N("No wsmp chunk in wave... using sane defaults.");let I=yA(s,"INFO"),AA=`Unnamed ${A}`;if(I){let K=Z(I.chunkData);for(;K.header!=="INAM"&&I.chunkData.currentIndex c.header==="colh");if(!o)throw X(),new Error("No colh chunk!");this.instrumentAmount=S(o.chunkData,4),m(`%cInstruments amount: %c${this.instrumentAmount}`,r.info,r.recognized);let g=yA(s,"wvpl");this.readDLSSamples(g);let C=yA(s,"lins");if(!C)throw X(),new Error("No lins chunk!");this.readDLSInstrumentList(C),this.presets.sort((c,h)=>c.program-h.program+(c.bank-h.bank)),m(`%cParsing finished! %c"${this.soundFontInfo.INAM||"UNNAMED"}"%c has %c${this.presets.length} %cpresets, - %c${this.instruments.length}%c instruments and %c${this.samples.length}%c samples.`,r.info,r.recognized,r.info,r.recognized,r.info,r.recognized,r.info,r.recognized,r.info),X()}verifyHeader(A,t){if(A.header.toLowerCase()!==t.toLowerCase())throw X(),new SyntaxError(`Invalid DLS chunk header! Expected "${t.toLowerCase()}" got "${A.header.toLowerCase()}"`)}verifyText(A,t){if(A.toLowerCase()!==t.toLowerCase())throw X(),new SyntaxError(`Invalid DLS soundfont! Expected "${t.toLowerCase()}" got "${A.toLowerCase()}"`)}};WA.prototype.readDLSInstrumentList=vn;WA.prototype.readDLSInstrument=Kn;WA.prototype.readRegion=Zn;WA.prototype.readLart=On;WA.prototype.readDLSSamples=Xn;var Ut=class extends ue{constructor(A,t,s,n,o,g,C,c,h,d,Q,u,l){super(A,g,C,c,h,d,n-t,o-t),this.sampleName=A,this.sampleStartIndex=t,this.sampleEndIndex=s,this.isSampleLoaded=!1,this.sampleID=u,this.sampleLength=this.sampleEndIndex-this.sampleStartIndex,this.sampleDataArray=Q,this.sampleData=new Float32Array(0),this.isCompressed&&(this.sampleLoopStartIndex+=this.sampleStartIndex,this.sampleLoopEndIndex+=this.sampleStartIndex,this.sampleLength=99999999),this.isDataRaw=l}getRawData(){let A=this.sampleDataArray;if(this.isCompressed){if(this.compressedData)return this.compressedData;let t=A.currentIndex;return A.slice(this.sampleStartIndex/2+t,this.sampleEndIndex/2+t)}else{if(!this.isDataRaw)throw new Error("Writing SF2Pack samples is not supported.");let t=A.currentIndex;return A.slice(t+this.sampleStartIndex,t+this.sampleEndIndex)}}decodeVorbis(){if(this.sampleLength<1)return;let A=this.sampleDataArray,t=A.currentIndex,s=A.slice(this.sampleStartIndex/2+t,this.sampleEndIndex/2+t);this.sampleData=new Float32Array(0);let n=OA.decode(s.buffer);this.sampleData=n.data[0]}getAudioData(){return this.isSampleLoaded?this.sampleData:this.sampleLength<1?new Float32Array(1):this.isCompressed?(this.decodeVorbis(),this.isSampleLoaded=!0,this.sampleData):this.isDataRaw?this.loadUncompressedData():this.getUncompressedReadyData()}loadUncompressedData(){if(this.isCompressed)return N("Trying to load a compressed sample via loadUncompressedData()... aborting!"),new Float32Array(0);let A=new Float32Array(this.sampleLength/2),t=this.sampleDataArray.currentIndex,s=new Int16Array(this.sampleDataArray.slice(t+this.sampleStartIndex,t+this.sampleEndIndex).buffer);for(let n=0;n e.chunkData.currentIndex;){let o=bo(n,e.chunkData,A,t);s.push(o),n++}return s.length>1&&s.pop(),s}function bo(e,A,t,s){let n=O(A,20),o=S(A,4)*2,g=S(A,4)*2,C=S(A,4)*2,c=S(A,4)*2,h=S(A,4),d=A[A.currentIndex++];d===255&&(d=60);let Q=ps(A[A.currentIndex++]),u=S(A,2),l=S(A,2);return new Ut(n,o,g,C,c,h,d,Q,u,l,t,e,s)}var Tt=class extends le{constructor(A){super(),this.instrumentName=O(A.chunkData,20).trim(),this.instrumentZoneIndex=S(A.chunkData,2),this.instrumentZonesAmount=0}getInstrumentZones(A,t){this.instrumentZonesAmount=A;for(let s=this.instrumentZoneIndex;s e.chunkData.currentIndex;){let s=new Tt(e);if(t.length>0){let n=s.instrumentZoneIndex-t[t.length-1].instrumentZoneIndex;t[t.length-1].getInstrumentZones(n,A)}t.push(s)}return t.length>1&&t.pop(),t}var Ht=class extends $A{constructor(A){super(),this.generatorZoneStartIndex=S(A,2),this.modulatorZoneStartIndex=S(A,2),this.modulatorZoneSize=0,this.generatorZoneSize=0,this.isGlobal=!0}setZoneSize(A,t){this.modulatorZoneSize=A,this.generatorZoneSize=t}getGenerators(A){for(let t=this.generatorZoneStartIndex;t s.generatorType===a.sampleID);t&&(this.sample=A[t.generatorValue],this.isGlobal=!1,this.sample.useCount++)}getKeyRange(){let A=this.generators.find(t=>t.generatorType===a.keyRange);A&&(this.keyRange.min=A.generatorValue&127,this.keyRange.max=A.generatorValue>>8&127)}getVelRange(){let A=this.generators.find(t=>t.generatorType===a.velRange);A&&(this.velRange.min=A.generatorValue&127,this.velRange.max=A.generatorValue>>8&127)}};function zn(e,A,t,s){let n=[];for(;e.chunkData.length>e.chunkData.currentIndex;){let o=new Ht(e.chunkData);if(n.length>0){let g=o.modulatorZoneStartIndex-n[n.length-1].modulatorZoneStartIndex,C=o.generatorZoneStartIndex-n[n.length-1].generatorZoneStartIndex;n[n.length-1].setZoneSize(g,C),n[n.length-1].getGenerators(A),n[n.length-1].getModulators(t),n[n.length-1].getSample(s),n[n.length-1].getKeyRange(),n[n.length-1].getVelRange()}n.push(o)}return n.length>1&&n.pop(),n}var Yt=class extends ce{constructor(A){super(),this.generatorZoneStartIndex=S(A,2),this.modulatorZoneStartIndex=S(A,2),this.modulatorZoneSize=0,this.generatorZoneSize=0,this.isGlobal=!0}setZoneSize(A,t){this.modulatorZoneSize=A,this.generatorZoneSize=t}getGenerators(A){for(let t=this.generatorZoneStartIndex;t s.generatorType===a.instrument);t&&(this.instrument=A[t.generatorValue],this.instrument.addUseCount(),this.isGlobal=!1)}getKeyRange(){let A=this.generators.find(t=>t.generatorType===a.keyRange);A&&(this.keyRange.min=A.generatorValue&127,this.keyRange.max=A.generatorValue>>8&127)}getVelRange(){let A=this.generators.find(t=>t.generatorType===a.velRange);A&&(this.velRange.min=A.generatorValue&127,this.velRange.max=A.generatorValue>>8&127)}};function jn(e,A,t,s){let n=[];for(;e.chunkData.length>e.chunkData.currentIndex;){let o=new Yt(e.chunkData);if(n.length>0){let g=o.modulatorZoneStartIndex-n[n.length-1].modulatorZoneStartIndex,C=o.generatorZoneStartIndex-n[n.length-1].generatorZoneStartIndex;n[n.length-1].setZoneSize(g,C),n[n.length-1].getGenerators(A),n[n.length-1].getModulators(t),n[n.length-1].getInstrument(s),n[n.length-1].getKeyRange(),n[n.length-1].getVelRange()}n.push(o)}return n.length>1&&n.pop(),n}var Jt=class extends Qe{constructor(A,t){super(t),this.presetName=O(A.chunkData,20).trim().replace(/\d{3}:\d{3}/,""),this.program=S(A.chunkData,2),this.bank=S(A.chunkData,2),this.presetZoneStartIndex=S(A.chunkData,2),this.library=S(A.chunkData,4),this.genre=S(A.chunkData,4),this.morphology=S(A.chunkData,4),this.presetZonesAmount=0}getPresetZones(A,t){this.presetZonesAmount=A;for(let s=this.presetZoneStartIndex;s e.chunkData.currentIndex;){let n=new Jt(e,t);if(s.length>0){let o=n.presetZoneStartIndex-s[s.length-1].presetZoneStartIndex;s[s.length-1].getPresetZones(o,A)}s.push(n)}return s.length>1&&s.pop(),s}var st=class extends ne{constructor(A,t=!0){if(super(),t&&console.warn("Using the constructor directly is deprecated. Use loadSoundFont instead."),this.dataArray=new H(A),te("%cParsing SoundFont...",r.info),!this.dataArray)throw X(),new TypeError("No data!");let s=Z(this.dataArray,!1);this.verifyHeader(s,"riff");let n=O(this.dataArray,4).toLowerCase();if(n!=="sfbk"&&n!=="sfpk")throw X(),new SyntaxError(`Invalid soundFont! Expected "sfbk" or "sfpk" got "${n}"`);let o=n==="sfpk",g=Z(this.dataArray);for(this.verifyHeader(g,"list"),O(g.chunkData,4);g.chunkData.length>g.chunkData.currentIndex;){let z=Z(g.chunkData),gA;switch(z.header.toLowerCase()){case"ifil":case"iver":gA=`${S(z.chunkData,2)}.${S(z.chunkData,2)}`,this.soundFontInfo[z.header]=gA;break;case"icmt":gA=O(z.chunkData,z.chunkData.length,void 0,!1),this.soundFontInfo[z.header]=gA;break;case"dmod":let oA=Ze(z);oA.pop(),gA=`Modulators: ${oA.length}`;let GA=this.defaultModulators;this.defaultModulators=oA,this.defaultModulators.push(...GA.filter(xe=>!this.defaultModulators.find(xA=>eA.isIdentical(xe,xA)))),this.soundFontInfo[z.header]=z.chunkData;break;default:gA=O(z.chunkData,z.chunkData.length),this.soundFontInfo[z.header]=gA}m(`%c"${z.header}": %c"${gA}"`,r.info,r.recognized)}let C=Z(this.dataArray,!1);this.verifyHeader(C,"list"),this.verifyText(O(this.dataArray,4),"sdta"),m("%cVerifying smpl chunk...",r.warn);let c=Z(this.dataArray,!1);this.verifyHeader(c,"smpl");let h;if(o){m("%cSF2Pack detected, attempting to decode the smpl chunk...",r.info);try{h=OA.decode(this.dataArray.buffer.slice(this.dataArray.currentIndex,this.dataArray.currentIndex+C.size-12)).data[0]}catch(z){throw X(),new Error(`SF2Pack Ogg Vorbis decode error: ${z}`)}m(`%cDecoded the smpl chunk! Length: %c${h.length}`,r.info,r.value)}else h=this.dataArray,this.sampleDataStartIndex=this.dataArray.currentIndex;m(`%cSkipping sample chunk, length: %c${C.size-12}`,r.info,r.value),this.dataArray.currentIndex+=C.size-12,m("%cLoading preset data chunk...",r.warn);let d=Z(this.dataArray);this.verifyHeader(d,"list"),O(d.chunkData,4);let Q=Z(d.chunkData);this.verifyHeader(Q,"phdr");let u=Z(d.chunkData);this.verifyHeader(u,"pbag");let l=Z(d.chunkData);this.verifyHeader(l,"pmod");let D=Z(d.chunkData);this.verifyHeader(D,"pgen");let y=Z(d.chunkData);this.verifyHeader(y,"inst");let k=Z(d.chunkData);this.verifyHeader(k,"ibag");let F=Z(d.chunkData);this.verifyHeader(F,"imod");let q=Z(d.chunkData);this.verifyHeader(q,"igen");let M=Z(d.chunkData);this.verifyHeader(M,"shdr"),this.dataArray.currentIndex=this.sampleDataStartIndex,this.samples.push(...Wn(M,h,!o));let v=pt(q),T=Ze(F),I=zn(k,v,T,this.samples);this.instruments=_n(y,I);let AA=pt(D),K=Ze(l),j=jn(u,AA,K,this.instruments);this.presets.push(...$n(Q,j,this.defaultModulators)),this.presets.sort((z,gA)=>z.program-gA.program+(z.bank-gA.bank)),m(`%cParsing finished! %c"${this.soundFontInfo.INAM}"%c has %c${this.presets.length} %cpresets, - %c${this.instruments.length}%c instruments and %c${this.samples.length}%c samples.`,r.info,r.recognized,r.info,r.recognized,r.info,r.recognized,r.info,r.recognized,r.info),X(),o&&delete this.dataArray}verifyHeader(A,t){if(A.header.toLowerCase()!==t.toLowerCase())throw X(),new SyntaxError(`Invalid chunk header! Expected "${t.toLowerCase()}" got "${A.header.toLowerCase()}"`)}verifyText(A,t){if(A.toLowerCase()!==t.toLowerCase())throw X(),new SyntaxError(`Invalid soundFont! Expected "${t.toLowerCase()}" got "${A.toLowerCase()}"`)}};function Re(e){let A=e.slice(8,12),t=new H(A);return O(t,4,void 0,!1).toLowerCase()==="dls "?new WA(e):new st(e,!1)}function Ao(e,A,t=!1){let s=this.workletProcessorChannels[e];if(s===void 0){N(`Trying to access channel ${e} which does not exist... ignoring!`);return}if(s.lockPreset)return;let n=s.drumChannel?128:s.midiControllers[p.bankSelect],o,g;if(this.overrideSoundfont){let C=n===128?128:n-this.soundfontBankOffset,c=this.overrideSoundfont.getPresetNoFallback(C,A);c?(o=n,g=c,s.presetUsesOverride=!0):(g=this.soundfontManager.getPreset(n,A),o=g.bank,s.presetUsesOverride=!1)}else g=this.soundfontManager.getPreset(n,A),o=g.bank,s.presetUsesOverride=!1;this.setPreset(e,g),this.callEvent("programchange",{channel:e,program:g.program,bank:o,userCalled:t})}function eo(e,A){if(this.overrideSoundfont){let t=e===128?128:e-this.soundfontBankOffset,s=this.overrideSoundfont.getPresetNoFallback(t,A);if(s)return s}return this.soundfontManager.getPreset(e,A)}function to(e,A){if(!this.workletProcessorChannels[e].lockPreset){delete this.workletProcessorChannels[e].preset,this.workletProcessorChannels[e].preset=A,this.workletProcessorChannels[e].cachedVoices=[];for(let t=0;t<128;t++)this.workletProcessorChannels[e].cachedVoices.push([])}}function so(e,A){let t=this.workletProcessorChannels[e];t.lockPreset||t.drumChannel!==A&&(A?(t.channelTransposeKeyShift=0,t.drumChannel=!0,this.setPreset(e,this.getPreset(128,t.preset.program))):(t.drumChannel=!1,this.setPreset(e,this.getPreset(t.midiControllers[p.bankSelect],t.preset.program))),t.presetUsesOverride=!1,this.callEvent("drumchange",{channel:e,isDrumChannel:t.drumChannel}),this.sendChannelProperties())}function no(){let e=this.soundfontManager.getPresetList();this.overrideSoundfont!==void 0&&this.overrideSoundfont.presets.forEach(A=>{let t=A.bank===128?128:A.bank+this.soundfontBankOffset,s=e.find(n=>n.bank===t&&n.program===A.program);s!==void 0?s.presetName=A.presetName:e.push({presetName:A.presetName,bank:t,program:A.program})}),this.callEvent("presetlistchange",e)}function oo(e=!0,A=!0){this.stopAllChannels(!0),A&&(delete this.overrideSoundfont,this.overrideSoundfont=void 0),this.defaultPreset=this.getPreset(0,0),this.drumPreset=this.getPreset(128,0);for(let t=0;t {this.programChange(s,t.preset.program)}),this.post({messageType:mA.ready,messageData:void 0}),this.sendPresetList(),m("%cSpessaSynth is ready!",r.recognized)}function io(e,A){this.soundfontBankOffset=A,this.reloadSoundFont(e,!0),this.overrideSoundfont.samples.forEach(t=>t.getAudioData()),this._snapshot!==void 0&&(this.applySynthesizerSnapshot(this._snapshot),this.resetAllControllers())}function ao(){let A={channelSnapshots:this.workletProcessorChannels.map(t=>({program:t.preset.program,bank:t.preset.bank,lockPreset:t.lockPreset,patchName:t.preset.presetName,midiControllers:t.midiControllers,lockedControllers:t.lockedControllers,customControllers:t.customControllers,channelVibrato:t.channelVibrato,lockVibrato:t.lockGSNRPNParams,channelTransposeKeyShift:t.channelTransposeKeyShift,channelOctaveTuning:t.channelOctaveTuning,keyCentTuning:t.keyCentTuning,isMuted:t.isMuted,drumChannel:t.drumChannel})),mainVolume:this.midiVolume,pan:this.pan,transposition:this.transposition,system:this.system,interpolation:this.interpolationType};this.post({messageType:mA.synthesizerSnapshot,messageData:A})}function Io(e){for(this.system=e.system,this.setMasterGain(e.mainVolume),this.setMasterPan(e.pan),this.transposeAllChannels(e.transposition),this.interpolationType=e.interpolation;this.workletProcessorChannels.length {let s=this.workletProcessorChannels[t];this.muteChannel(t,A.isMuted),this.setDrums(t,A.drumChannel),s.midiControllers=A.midiControllers,s.lockedControllers=A.lockedControllers,s.customControllers=A.customControllers,s.channelVibrato=A.channelVibrato,s.lockGSNRPNParams=A.lockVibrato,s.channelTransposeKeyShift=A.channelTransposeKeyShift,s.channelOctaveTuning=A.channelOctaveTuning,s.lockPreset=!1,s.midiControllers[p.bankSelect]=A.bank,this.programChange(t,A.program),s.lockPreset=A.lockPreset}),m("%cFinished restoring controllers!",r.info)}var nt=class{constructor(A,t){this.ready=t,this.totalSoundfontOffset=0,this.reloadManager(A)}_assingSampleOffsets(){let A=0;this.soundfontList.forEach(t=>{t.soundfont.setSampleIDOffset(A),A+=t.soundfont.samples.length}),this.totalSoundfontOffset=A}generatePresetList(){this._assingSampleOffsets();let A={};for(let t=this.soundfontList.length-1;t>=0;t--){let s=this.soundfontList[t],n=new Set;for(let o of s.soundfont.presets){let g=`${o.bank+s.bankOffset}-${o.program}`;n.has(g)||(n.add(g),A[g]=o.presetName)}}this.presetList=[];for(let[t,s]of Object.entries(A)){let n=t.split("-");this.presetList.push({presetName:s,program:parseInt(n[1]),bank:parseInt(n[0])})}}handleMessage(A,t){switch(A){case Ie.addNewSoundFont:this.addNewSoundFont(t[0],t[1],t[2]);break;case Ie.reloadSoundFont:this.reloadManager(t);break;case Ie.deleteSoundFont:this.deleteSoundFont(t);break;case Ie.rearrangeSoundFonts:this.rearrangeSoundFonts(t)}}getPresetList(){return this.presetList.slice()}reloadManager(A){let t=Re(A);this.soundfontList=[],this.soundfontList.push({id:"main",bankOffset:0,soundfont:t}),this.generatePresetList(),this.ready()}deleteSoundFont(A){if(this.soundfontList.length===0){N("1 soundfont left. Aborting!");return}let t=this.soundfontList.findIndex(s=>s.id===A);if(t===-1){N(`No soundfont with id of "${A}" found. Aborting!`);return}delete this.soundfontList[t].soundfont.presets,delete this.soundfontList[t].soundfont.instruments,delete this.soundfontList[t].soundfont.samples,this.soundfontList.splice(t,1),this.generatePresetList()}addNewSoundFont(A,t,s){if(this.soundfontList.find(n=>n.id===t)!==void 0)throw new Error("Cannot overwrite the existing soundfont. Use soundfontManager.delete(id) instead.");this.soundfontList.push({id:t,soundfont:Re(A),bankOffset:s}),this.generatePresetList(),this.ready()}rearrangeSoundFonts(A){this.soundfontList.sort((t,s)=>A.indexOf(t.id)-A.indexOf(s.id)),this.generatePresetList()}getPreset(A,t){if(this.soundfontList.length<1)throw new Error("No soundfonts! This should never happen.");for(let s of this.soundfontList){let n=s.soundfont.getPresetNoFallback(A-s.bankOffset,t);if(n!==void 0)return n}if(A!==128){for(let s of this.soundfontList){let n=s.soundfont.presets.find(o=>o.program===t);if(n)return n}return this.soundfontList[0].soundfont.presets[0]}else{for(let s of this.soundfontList){let n=s.soundfont.presets.find(o=>o.bank===128);if(n)return n}return this.soundfontList[0].soundfont.presets[0]}}};var ot=class{constructor(A,t,s,n,o,g,C,c){this.sampleData=A,this.playbackStep=t,this.cursor=s,this.rootKey=n,this.loopStart=o,this.loopEnd=g,this.end=C,this.loopingMode=c}sampleData;playbackStep=0;cursor=0;rootKey=0;loopStart=0;loopEnd=0;end=0;loopingMode=0},Ge=class e{constructor(A,t,s,n,o,g,C,c,h){this.sample=t,this.generators=c,this.modulatedGenerators=new Int16Array(c),this.modulators=h,this.velocity=n,this.midiNote=s,this.channelNumber=o,this.startTime=g,this.targetKey=C,this.volumeEnvelope=new RA(A)}sample;filter=new he;generators;modulators=[];modulatedGenerators;finished=!1;isInRelease=!1;channelNumber=0;velocity=0;midiNote=0;pressure=0;targetKey=0;modulationEnvelope=new YA;volumeEnvelope;startTime=0;releaseStartTime=1/0;currentTuningCents=0;currentTuningCalculated=1;currentPan=.5;static copy(A,t){let s=A.sample,n=new ot(s.sampleData,s.playbackStep,s.cursor,s.rootKey,s.loopStart,s.loopEnd,s.end,s.loopingMode);return new e(A.volumeEnvelope.sampleRate,n,A.midiNote,A.velocity,A.channelNumber,t,A.targetKey,A.generators,A.modulators.slice())}};function go(e,A,t,s,n,o=!1){let g,C=s.cachedVoices[A][t];return C!==void 0?g=C.map(c=>Ge.copy(c,n)):(g=s.preset.getSamplesAndGenerators(A,t).reduce((h,d)=>{if(d.sample.sampleData===void 0)return N(`Discarding invalid sample: ${d.sample.sampleName}`),h;let Q=new Int16Array(60);for(let M=0;M<60;M++)Q[M]=Ss(M,d.presetGenerators,d.instrumentGenerators);Q[a.initialAttenuation]=Math.floor(Q[a.initialAttenuation]*.4);let u=d.sample.samplePitch;Q[a.overridingRootKey]>-1&&(u=Q[a.overridingRootKey]);let l=A;Q[a.keyNum]>-1&&(l=Q[a.keyNum]);let D=d.sample.sampleLoopStartIndex/2+(Q[a.startloopAddrsOffset]+Q[a.startloopAddrsCoarseOffset]*32768),y=d.sample.sampleLoopEndIndex/2+(Q[a.endloopAddrsOffset]+Q[a.endloopAddrsCoarseOffset]*32768),k=Q[a.sampleModes],F=d.sample.getAudioData().length;D=Math.min(Math.max(0,D),F),y=Math.min(Math.max(0,y),F),y-D<1&&(k=0);let q=new ot(d.sample.getAudioData(),d.sample.sampleRate/sampleRate*Math.pow(2,d.sample.samplePitchCorrection/1200),Q[a.startAddrsOffset]+Q[a.startAddrsCoarseOffset]*32768,u,D,y,Math.floor(d.sample.sampleData.length)-1+(Q[a.endAddrOffset]+Q[a.endAddrsCoarseOffset]*32768),k);return Q[a.velocity]>-1&&(t=Q[a.velocity]),o&&Qs([{Sample:d.sample.sampleName,Generators:Q,Modulators:d.modulators.map(M=>M.debugString()),Velocity:t,TargetKey:l,MidiNote:A,WorkletSample:q}]),h.push(new Ge(sampleRate,q,A,t,e,n,l,Q,d.modulators)),h},[]),s.cachedVoices[A][t]=g.map(h=>Ge.copy(h,n))),g}var Nt=.07,bt=1,L=class extends AudioWorkletProcessor{constructor(A){super(),this.oneOutputMode=A.processorOptions?.startRenderingData?.oneOutput===!0,this._outputsAmount=this.oneOutputMode?1:A.processorOptions.midiChannels,this.enableEventSystem=A.processorOptions.enableEventSystem,this.deviceID=TA,this.interpolationType=$e.linear,this.processTickCallback=void 0,this.sequencer=new EA(this),this.transposition=0,this.tunings=[];for(let t=0;t<127;t++)this.tunings.push([]);this.soundfontBankOffset=0,this.masterGain=bt,this.midiVolume=1,this.voiceCap=ls,this.pan=0,this.panLeft=.5*this.currentGain,this.highPerformanceMode=!1,this.overrideSoundfont=void 0,this.panRight=.5*this.currentGain;try{this.soundfontManager=new nt(A.processorOptions.soundfont,this.postReady.bind(this))}catch(t){throw this.post({messageType:mA.soundfontError,messageData:t}),t}this.sendPresetList(),this.defaultPreset=this.getPreset(0,0),this.drumPreset=this.getPreset(128,0),this.workletProcessorChannels=[];for(let t=0;t this.handleMessage(t.data),A.processorOptions.startRenderingData&&(this._snapshot!==void 0&&(this.applySynthesizerSnapshot(this._snapshot),this.resetAllControllers()),m("%cRendering enabled! Starting render.",r.info),A.processorOptions.startRenderingData.parsedMIDI&&(A.processorOptions.startRenderingData?.loopCount!==void 0?(this.sequencer.loopCount=A.processorOptions.startRenderingData?.loopCount,this.sequencer.loop=!0):this.sequencer.loop=!1,this.sequencer.loadNewSongList([A.processorOptions.startRenderingData.parsedMIDI]))),OA.isInitialized.then(()=>{this.postReady(),m("%cSpessaSynth is ready!",r.recognized)})}post(A){this.enableEventSystem&&this.port.postMessage(A)}postReady(){this.enableEventSystem&&this.port.postMessage({messageType:mA.ready,messageData:void 0})}get currentGain(){return this.masterGain*this.midiVolume}debugMessage(){m({channels:this.workletProcessorChannels,voicesAmount:this.totalVoicesAmount,outputAmount:this._outputsAmount,dumpedSamples:this.workletDumpedSamplesList})}process(A,t){this.processTickCallback&&this.processTickCallback();let s=0;return this.workletProcessorChannels.forEach((n,o)=>{if(n.voices.length<1||n.isMuted)return;let g,C,c,h,d;if(this.oneOutputMode){let u=t[0];g=o%16*2,C=u[g],c=u[g+1]}else g=o%this._outputsAmount+2,C=t[g][0],c=t[g][1],h=t[0],d=t[1];let Q=n.voices;n.voices=[],Q.forEach(u=>{this.renderVoice(n,u,C,c,h,d),u.finished||n.voices.push(u)}),s+=n.voices.length}),s!==this.totalVoicesAmount&&(this.totalVoicesAmount=s,this.sendChannelProperties()),!0}};L.prototype.renderVoice=Zs;L.prototype.releaseVoice=Ws;L.prototype.voiceKilling=Xs;L.prototype.getWorkletVoices=go;L.prototype.handleMessage=js;L.prototype.sendChannelProperties=An;L.prototype.callEvent=$s;L.prototype.systemExclusive=en;L.prototype.noteOn=sn;L.prototype.noteOff=nn;L.prototype.polyPressure=ln;L.prototype.killNote=on;L.prototype.stopAll=rn;L.prototype.stopAllChannels=an;L.prototype.muteChannel=Sn;L.prototype.setVibrato=Dn;L.prototype.disableAndLockGSNRPN=yn;L.prototype.dataEntryCoarse=kn;L.prototype.dataEntryFine=wn;L.prototype.createWorkletChannel=ys;L.prototype.controllerChange=dn;L.prototype.channelPressure=cn;L.prototype.resetAllControllers=Fn;L.prototype.resetControllers=Rn;L.prototype.resetParameters=Gn;L.prototype.setMasterGain=mn;L.prototype.setMasterPan=pn;L.prototype.setMIDIVolume=fn;L.prototype.transposeAllChannels=In;L.prototype.transposeChannel=gn;L.prototype.setChannelTuning=Cn;L.prototype.setChannelTuningSemitones=En;L.prototype.setMasterTuning=Bn;L.prototype.setModulationDepth=hn;L.prototype.pitchWheel=Qn;L.prototype.setOctaveTuning=un;L.prototype.programChange=Ao;L.prototype.getPreset=eo;L.prototype.setPreset=to;L.prototype.setDrums=so;L.prototype.reloadSoundFont=ro;L.prototype.clearSoundFont=oo;L.prototype.setEmbeddedSoundFont=io;L.prototype.sendPresetList=no;L.prototype.sendSynthesizerSnapshot=ao;L.prototype.applySynthesizerSnapshot=Io;registerProcessor(cs,L);m("%cProcessor succesfully registered!",r.recognized); +`+this.soundFontInfo.ISBJ,delete this.soundFontInfo.ISBJ);for(let[Q,h]of Object.entries(this.soundFontInfo))m(`%c"${Q}": %c"${h}"`,r.info,r.recognized);let o=s.find(Q=>Q.header==="colh");if(!o)throw X(),new Error("No colh chunk!");this.instrumentAmount=S(o.chunkData,4),m(`%cInstruments amount: %c${this.instrumentAmount}`,r.info,r.recognized);let g=yA(s,"wvpl");this.readDLSSamples(g);let C=yA(s,"lins");if(!C)throw X(),new Error("No lins chunk!");this.readDLSInstrumentList(C),this.presets.sort((Q,h)=>Q.program-h.program+(Q.bank-h.bank)),m(`%cParsing finished! %c"${this.soundFontInfo.INAM||"UNNAMED"}"%c has %c${this.presets.length} %cpresets, + %c${this.instruments.length}%c instruments and %c${this.samples.length}%c samples.`,r.info,r.recognized,r.info,r.recognized,r.info,r.recognized,r.info,r.recognized,r.info),X()}verifyHeader(A,e){if(A.header.toLowerCase()!==e.toLowerCase())throw X(),new SyntaxError(`Invalid DLS chunk header! Expected "${e.toLowerCase()}" got "${A.header.toLowerCase()}"`)}verifyText(A,e){if(A.toLowerCase()!==e.toLowerCase())throw X(),new SyntaxError(`Invalid DLS soundfont! Expected "${e.toLowerCase()}" got "${A.toLowerCase()}"`)}};WA.prototype.readDLSInstrumentList=vn;WA.prototype.readDLSInstrument=Kn;WA.prototype.readRegion=Zn;WA.prototype.readLart=On;WA.prototype.readDLSSamples=Xn;var Tt=class extends ue{constructor(A,e,s,n,o,g,C,Q,h,d,c,u,l){super(A,g,C,Q,h,d,n-e,o-e),this.sampleName=A,this.sampleStartIndex=e,this.sampleEndIndex=s,this.isSampleLoaded=!1,this.sampleID=u,this.sampleLength=this.sampleEndIndex-this.sampleStartIndex,this.sampleDataArray=c,this.sampleData=new Float32Array(0),this.isCompressed&&(this.sampleLoopStartIndex+=this.sampleStartIndex,this.sampleLoopEndIndex+=this.sampleStartIndex,this.sampleLength=99999999),this.isDataRaw=l}getRawData(){let A=this.sampleDataArray;if(this.isCompressed){if(this.compressedData)return this.compressedData;let e=A.currentIndex;return A.slice(this.sampleStartIndex/2+e,this.sampleEndIndex/2+e)}else{if(!this.isDataRaw)throw new Error("Writing SF2Pack samples is not supported.");let e=A.currentIndex;return A.slice(e+this.sampleStartIndex,e+this.sampleEndIndex)}}decodeVorbis(){if(this.sampleLength<1)return;let A=this.sampleDataArray,e=A.currentIndex,s=A.slice(this.sampleStartIndex/2+e,this.sampleEndIndex/2+e);this.sampleData=new Float32Array(0);let n=OA.decode(s.buffer);this.sampleData=n.data[0]}getAudioData(){return this.isSampleLoaded?this.sampleData:this.sampleLength<1?new Float32Array(1):this.isCompressed?(this.decodeVorbis(),this.isSampleLoaded=!0,this.sampleData):this.isDataRaw?this.loadUncompressedData():this.getUncompressedReadyData()}loadUncompressedData(){if(this.isCompressed)return N("Trying to load a compressed sample via loadUncompressedData()... aborting!"),new Float32Array(0);let A=new Float32Array(this.sampleLength/2),e=this.sampleDataArray.currentIndex,s=new Int16Array(this.sampleDataArray.slice(e+this.sampleStartIndex,e+this.sampleEndIndex).buffer);for(let n=0;n t.chunkData.currentIndex;){let o=bo(n,t.chunkData,A,e);s.push(o),n++}return s.length>1&&s.pop(),s}function bo(t,A,e,s){let n=O(A,20),o=S(A,4)*2,g=S(A,4)*2,C=S(A,4)*2,Q=S(A,4)*2,h=S(A,4),d=A[A.currentIndex++];d===255&&(d=60);let c=Ss(A[A.currentIndex++]),u=S(A,2),l=S(A,2);return new Tt(n,o,g,C,Q,h,d,c,u,l,e,t,s)}var Ht=class extends le{constructor(A){super(),this.instrumentName=O(A.chunkData,20).trim(),this.instrumentZoneIndex=S(A.chunkData,2),this.instrumentZonesAmount=0}getInstrumentZones(A,e){this.instrumentZonesAmount=A;for(let s=this.instrumentZoneIndex;s t.chunkData.currentIndex;){let s=new Ht(t);if(e.length>0){let n=s.instrumentZoneIndex-e[e.length-1].instrumentZoneIndex;e[e.length-1].getInstrumentZones(n,A)}e.push(s)}return e.length>1&&e.pop(),e}var Yt=class extends $A{constructor(A){super(),this.generatorZoneStartIndex=S(A,2),this.modulatorZoneStartIndex=S(A,2),this.modulatorZoneSize=0,this.generatorZoneSize=0,this.isGlobal=!0}setZoneSize(A,e){this.modulatorZoneSize=A,this.generatorZoneSize=e}getGenerators(A){for(let e=this.generatorZoneStartIndex;e s.generatorType===a.sampleID);e&&(this.sample=A[e.generatorValue],this.isGlobal=!1,this.sample.useCount++)}getKeyRange(){let A=this.generators.find(e=>e.generatorType===a.keyRange);A&&(this.keyRange.min=A.generatorValue&127,this.keyRange.max=A.generatorValue>>8&127)}getVelRange(){let A=this.generators.find(e=>e.generatorType===a.velRange);A&&(this.velRange.min=A.generatorValue&127,this.velRange.max=A.generatorValue>>8&127)}};function zn(t,A,e,s){let n=[];for(;t.chunkData.length>t.chunkData.currentIndex;){let o=new Yt(t.chunkData);if(n.length>0){let g=o.modulatorZoneStartIndex-n[n.length-1].modulatorZoneStartIndex,C=o.generatorZoneStartIndex-n[n.length-1].generatorZoneStartIndex;n[n.length-1].setZoneSize(g,C),n[n.length-1].getGenerators(A),n[n.length-1].getModulators(e),n[n.length-1].getSample(s),n[n.length-1].getKeyRange(),n[n.length-1].getVelRange()}n.push(o)}return n.length>1&&n.pop(),n}var Jt=class extends ce{constructor(A){super(),this.generatorZoneStartIndex=S(A,2),this.modulatorZoneStartIndex=S(A,2),this.modulatorZoneSize=0,this.generatorZoneSize=0,this.isGlobal=!0}setZoneSize(A,e){this.modulatorZoneSize=A,this.generatorZoneSize=e}getGenerators(A){for(let e=this.generatorZoneStartIndex;e s.generatorType===a.instrument);e&&(this.instrument=A[e.generatorValue],this.instrument.addUseCount(),this.isGlobal=!1)}getKeyRange(){let A=this.generators.find(e=>e.generatorType===a.keyRange);A&&(this.keyRange.min=A.generatorValue&127,this.keyRange.max=A.generatorValue>>8&127)}getVelRange(){let A=this.generators.find(e=>e.generatorType===a.velRange);A&&(this.velRange.min=A.generatorValue&127,this.velRange.max=A.generatorValue>>8&127)}};function jn(t,A,e,s){let n=[];for(;t.chunkData.length>t.chunkData.currentIndex;){let o=new Jt(t.chunkData);if(n.length>0){let g=o.modulatorZoneStartIndex-n[n.length-1].modulatorZoneStartIndex,C=o.generatorZoneStartIndex-n[n.length-1].generatorZoneStartIndex;n[n.length-1].setZoneSize(g,C),n[n.length-1].getGenerators(A),n[n.length-1].getModulators(e),n[n.length-1].getInstrument(s),n[n.length-1].getKeyRange(),n[n.length-1].getVelRange()}n.push(o)}return n.length>1&&n.pop(),n}var qt=class extends Qe{constructor(A,e){super(e),this.presetName=O(A.chunkData,20).trim().replace(/\d{3}:\d{3}/,""),this.program=S(A.chunkData,2),this.bank=S(A.chunkData,2),this.presetZoneStartIndex=S(A.chunkData,2),this.library=S(A.chunkData,4),this.genre=S(A.chunkData,4),this.morphology=S(A.chunkData,4),this.presetZonesAmount=0}getPresetZones(A,e){this.presetZonesAmount=A;for(let s=this.presetZoneStartIndex;s t.chunkData.currentIndex;){let n=new qt(t,e);if(s.length>0){let o=n.presetZoneStartIndex-s[s.length-1].presetZoneStartIndex;s[s.length-1].getPresetZones(o,A)}s.push(n)}return s.length>1&&s.pop(),s}var nt=class extends ne{constructor(A,e=!0){if(super(),e&&console.warn("Using the constructor directly is deprecated. Use loadSoundFont instead."),this.dataArray=new H(A),te("%cParsing SoundFont...",r.info),!this.dataArray)throw X(),new TypeError("No data!");let s=Z(this.dataArray,!1);this.verifyHeader(s,"riff");let n=O(this.dataArray,4).toLowerCase();if(n!=="sfbk"&&n!=="sfpk")throw X(),new SyntaxError(`Invalid soundFont! Expected "sfbk" or "sfpk" got "${n}"`);let o=n==="sfpk",g=Z(this.dataArray);for(this.verifyHeader(g,"list"),O(g.chunkData,4);g.chunkData.length>g.chunkData.currentIndex;){let z=Z(g.chunkData),gA;switch(z.header.toLowerCase()){case"ifil":case"iver":gA=`${S(z.chunkData,2)}.${S(z.chunkData,2)}`,this.soundFontInfo[z.header]=gA;break;case"icmt":gA=O(z.chunkData,z.chunkData.length,void 0,!1),this.soundFontInfo[z.header]=gA;break;case"dmod":let oA=Ze(z);oA.pop(),gA=`Modulators: ${oA.length}`;let GA=this.defaultModulators;this.defaultModulators=oA,this.defaultModulators.push(...GA.filter(xe=>!this.defaultModulators.find(xA=>eA.isIdentical(xe,xA)))),this.soundFontInfo[z.header]=z.chunkData;break;default:gA=O(z.chunkData,z.chunkData.length),this.soundFontInfo[z.header]=gA}m(`%c"${z.header}": %c"${gA}"`,r.info,r.recognized)}let C=Z(this.dataArray,!1);this.verifyHeader(C,"list"),this.verifyText(O(this.dataArray,4),"sdta"),m("%cVerifying smpl chunk...",r.warn);let Q=Z(this.dataArray,!1);this.verifyHeader(Q,"smpl");let h;if(o){m("%cSF2Pack detected, attempting to decode the smpl chunk...",r.info);try{h=OA.decode(this.dataArray.buffer.slice(this.dataArray.currentIndex,this.dataArray.currentIndex+C.size-12)).data[0]}catch(z){throw X(),new Error(`SF2Pack Ogg Vorbis decode error: ${z}`)}m(`%cDecoded the smpl chunk! Length: %c${h.length}`,r.info,r.value)}else h=this.dataArray,this.sampleDataStartIndex=this.dataArray.currentIndex;m(`%cSkipping sample chunk, length: %c${C.size-12}`,r.info,r.value),this.dataArray.currentIndex+=C.size-12,m("%cLoading preset data chunk...",r.warn);let d=Z(this.dataArray);this.verifyHeader(d,"list"),O(d.chunkData,4);let c=Z(d.chunkData);this.verifyHeader(c,"phdr");let u=Z(d.chunkData);this.verifyHeader(u,"pbag");let l=Z(d.chunkData);this.verifyHeader(l,"pmod");let D=Z(d.chunkData);this.verifyHeader(D,"pgen");let y=Z(d.chunkData);this.verifyHeader(y,"inst");let k=Z(d.chunkData);this.verifyHeader(k,"ibag");let F=Z(d.chunkData);this.verifyHeader(F,"imod");let q=Z(d.chunkData);this.verifyHeader(q,"igen");let M=Z(d.chunkData);this.verifyHeader(M,"shdr"),this.dataArray.currentIndex=this.sampleDataStartIndex,this.samples.push(...Wn(M,h,!o));let v=St(q),T=Ze(F),I=zn(k,v,T,this.samples);this.instruments=_n(y,I);let AA=St(D),K=Ze(l),j=jn(u,AA,K,this.instruments);this.presets.push(...$n(c,j,this.defaultModulators)),this.presets.sort((z,gA)=>z.program-gA.program+(z.bank-gA.bank)),m(`%cParsing finished! %c"${this.soundFontInfo.INAM}"%c has %c${this.presets.length} %cpresets, + %c${this.instruments.length}%c instruments and %c${this.samples.length}%c samples.`,r.info,r.recognized,r.info,r.recognized,r.info,r.recognized,r.info,r.recognized,r.info),X(),o&&delete this.dataArray}verifyHeader(A,e){if(A.header.toLowerCase()!==e.toLowerCase())throw X(),new SyntaxError(`Invalid chunk header! Expected "${e.toLowerCase()}" got "${A.header.toLowerCase()}"`)}verifyText(A,e){if(A.toLowerCase()!==e.toLowerCase())throw X(),new SyntaxError(`Invalid soundFont! Expected "${e.toLowerCase()}" got "${A.toLowerCase()}"`)}};function Re(t){let A=t.slice(8,12),e=new H(A);return O(e,4,void 0,!1).toLowerCase()==="dls "?new WA(t):new nt(t,!1)}function Ao(t,A,e=!1){let s=this.workletProcessorChannels[t];if(s===void 0){N(`Trying to access channel ${t} which does not exist... ignoring!`);return}if(s.lockPreset)return;let n=s.drumChannel?128:s.midiControllers[p.bankSelect],o,g;if(this.overrideSoundfont){let C=n===128?128:n-this.soundfontBankOffset,Q=this.overrideSoundfont.getPresetNoFallback(C,A);Q?(o=n,g=Q,s.presetUsesOverride=!0):(g=this.soundfontManager.getPreset(n,A),o=g.bank,s.presetUsesOverride=!1)}else g=this.soundfontManager.getPreset(n,A),o=g.bank,s.presetUsesOverride=!1;this.setPreset(t,g),this.callEvent("programchange",{channel:t,program:g.program,bank:o,userCalled:e})}function eo(t,A){if(this.overrideSoundfont){let e=t===128?128:t-this.soundfontBankOffset,s=this.overrideSoundfont.getPresetNoFallback(e,A);if(s)return s}return this.soundfontManager.getPreset(t,A)}function to(t,A){if(!this.workletProcessorChannels[t].lockPreset){delete this.workletProcessorChannels[t].preset,this.workletProcessorChannels[t].preset=A,this.workletProcessorChannels[t].cachedVoices=[];for(let e=0;e<128;e++)this.workletProcessorChannels[t].cachedVoices.push([])}}function so(t,A){let e=this.workletProcessorChannels[t];e.lockPreset||e.drumChannel!==A&&(A?(e.channelTransposeKeyShift=0,e.drumChannel=!0,this.setPreset(t,this.getPreset(128,e.preset.program))):(e.drumChannel=!1,this.setPreset(t,this.getPreset(e.midiControllers[p.bankSelect],e.preset.program))),e.presetUsesOverride=!1,this.callEvent("drumchange",{channel:t,isDrumChannel:e.drumChannel}),this.sendChannelProperties())}function no(){let t=this.soundfontManager.getPresetList();this.overrideSoundfont!==void 0&&this.overrideSoundfont.presets.forEach(A=>{let e=A.bank===128?128:A.bank+this.soundfontBankOffset,s=t.find(n=>n.bank===e&&n.program===A.program);s!==void 0?s.presetName=A.presetName:t.push({presetName:A.presetName,bank:e,program:A.program})}),this.callEvent("presetlistchange",t)}function oo(t=!0,A=!0){this.stopAllChannels(!0),A&&(delete this.overrideSoundfont,this.overrideSoundfont=void 0),this.defaultPreset=this.getPreset(0,0),this.drumPreset=this.getPreset(128,0);for(let e=0;e {this.programChange(s,e.preset.program)}),this.post({messageType:mA.ready,messageData:void 0}),this.sendPresetList(),m("%cSpessaSynth is ready!",r.recognized)}function io(t,A){this.soundfontBankOffset=A,this.reloadSoundFont(t,!0),this.overrideSoundfont.samples.forEach(e=>e.getAudioData()),this._snapshot!==void 0&&(this.applySynthesizerSnapshot(this._snapshot),this.resetAllControllers())}function ao(){let A={channelSnapshots:this.workletProcessorChannels.map(e=>({program:e.preset.program,bank:e.preset.bank,lockPreset:e.lockPreset,patchName:e.preset.presetName,midiControllers:e.midiControllers,lockedControllers:e.lockedControllers,customControllers:e.customControllers,channelVibrato:e.channelVibrato,lockVibrato:e.lockGSNRPNParams,channelTransposeKeyShift:e.channelTransposeKeyShift,channelOctaveTuning:e.channelOctaveTuning,keyCentTuning:e.keyCentTuning,isMuted:e.isMuted,drumChannel:e.drumChannel})),mainVolume:this.midiVolume,pan:this.pan,transposition:this.transposition,system:this.system,interpolation:this.interpolationType};this.post({messageType:mA.synthesizerSnapshot,messageData:A})}function Io(t){for(this.system=t.system,this.setMasterGain(t.mainVolume),this.setMasterPan(t.pan),this.transposeAllChannels(t.transposition),this.interpolationType=t.interpolation;this.workletProcessorChannels.length {let s=this.workletProcessorChannels[e];this.muteChannel(e,A.isMuted),this.setDrums(e,A.drumChannel),s.midiControllers=A.midiControllers,s.lockedControllers=A.lockedControllers,s.customControllers=A.customControllers,s.channelVibrato=A.channelVibrato,s.lockGSNRPNParams=A.lockVibrato,s.channelTransposeKeyShift=A.channelTransposeKeyShift,s.channelOctaveTuning=A.channelOctaveTuning,s.lockPreset=!1,s.midiControllers[p.bankSelect]=A.bank,this.programChange(e,A.program),s.lockPreset=A.lockPreset}),m("%cFinished restoring controllers!",r.info)}var ot=class{constructor(A,e){this.ready=e,this.totalSoundfontOffset=0,this.reloadManager(A)}_assingSampleOffsets(){let A=0;this.soundfontList.forEach(e=>{e.soundfont.setSampleIDOffset(A),A+=e.soundfont.samples.length}),this.totalSoundfontOffset=A}generatePresetList(){this._assingSampleOffsets();let A={};for(let e=this.soundfontList.length-1;e>=0;e--){let s=this.soundfontList[e],n=new Set;for(let o of s.soundfont.presets){let g=`${o.bank+s.bankOffset}-${o.program}`;n.has(g)||(n.add(g),A[g]=o.presetName)}}this.presetList=[];for(let[e,s]of Object.entries(A)){let n=e.split("-");this.presetList.push({presetName:s,program:parseInt(n[1]),bank:parseInt(n[0])})}}handleMessage(A,e){switch(A){case Ie.addNewSoundFont:this.addNewSoundFont(e[0],e[1],e[2]);break;case Ie.reloadSoundFont:this.reloadManager(e);break;case Ie.deleteSoundFont:this.deleteSoundFont(e);break;case Ie.rearrangeSoundFonts:this.rearrangeSoundFonts(e)}}getPresetList(){return this.presetList.slice()}reloadManager(A){let e=Re(A);this.soundfontList=[],this.soundfontList.push({id:"main",bankOffset:0,soundfont:e}),this.generatePresetList(),this.ready()}deleteSoundFont(A){if(this.soundfontList.length===0){N("1 soundfont left. Aborting!");return}let e=this.soundfontList.findIndex(s=>s.id===A);if(e===-1){N(`No soundfont with id of "${A}" found. Aborting!`);return}delete this.soundfontList[e].soundfont.presets,delete this.soundfontList[e].soundfont.instruments,delete this.soundfontList[e].soundfont.samples,this.soundfontList.splice(e,1),this.generatePresetList()}addNewSoundFont(A,e,s){if(this.soundfontList.find(n=>n.id===e)!==void 0)throw new Error("Cannot overwrite the existing soundfont. Use soundfontManager.delete(id) instead.");this.soundfontList.push({id:e,soundfont:Re(A),bankOffset:s}),this.generatePresetList(),this.ready()}rearrangeSoundFonts(A){this.soundfontList.sort((e,s)=>A.indexOf(e.id)-A.indexOf(s.id)),this.generatePresetList()}getPreset(A,e){if(this.soundfontList.length<1)throw new Error("No soundfonts! This should never happen.");for(let s of this.soundfontList){let n=s.soundfont.getPresetNoFallback(A-s.bankOffset,e);if(n!==void 0)return n}if(A!==128){for(let s of this.soundfontList){let n=s.soundfont.presets.find(o=>o.program===e);if(n)return n}return this.soundfontList[0].soundfont.presets[0]}else{for(let s of this.soundfontList){let n=s.soundfont.presets.find(o=>o.bank===128);if(n)return n}return this.soundfontList[0].soundfont.presets[0]}}};var rt=class{constructor(A,e,s,n,o,g,C,Q){this.sampleData=A,this.playbackStep=e,this.cursor=s,this.rootKey=n,this.loopStart=o,this.loopEnd=g,this.end=C,this.loopingMode=Q}sampleData;playbackStep=0;cursor=0;rootKey=0;loopStart=0;loopEnd=0;end=0;loopingMode=0},Ge=class t{constructor(A,e,s,n,o,g,C,Q,h){this.sample=e,this.generators=Q,this.modulatedGenerators=new Int16Array(Q),this.modulators=h,this.velocity=n,this.midiNote=s,this.channelNumber=o,this.startTime=g,this.targetKey=C,this.volumeEnvelope=new RA(A,Q[a.sustainVolEnv])}sample;filter=new he;generators;modulators=[];modulatedGenerators;finished=!1;isInRelease=!1;channelNumber=0;velocity=0;midiNote=0;pressure=0;targetKey=0;modulationEnvelope=new YA;volumeEnvelope;startTime=0;releaseStartTime=1/0;currentTuningCents=0;currentTuningCalculated=1;currentPan=.5;static copy(A,e){let s=A.sample,n=new rt(s.sampleData,s.playbackStep,s.cursor,s.rootKey,s.loopStart,s.loopEnd,s.end,s.loopingMode);return new t(A.volumeEnvelope.sampleRate,n,A.midiNote,A.velocity,A.channelNumber,e,A.targetKey,A.generators,A.modulators.slice())}};function go(t,A,e,s,n,o=!1){let g,C=s.cachedVoices[A][e];return C!==void 0?g=C.map(Q=>Ge.copy(Q,n)):(g=s.preset.getSamplesAndGenerators(A,e).reduce((h,d)=>{if(d.sample.sampleData===void 0)return N(`Discarding invalid sample: ${d.sample.sampleName}`),h;let c=new Int16Array(60);for(let M=0;M<60;M++)c[M]=ys(M,d.presetGenerators,d.instrumentGenerators);c[a.initialAttenuation]=Math.floor(c[a.initialAttenuation]*.4);let u=d.sample.samplePitch;c[a.overridingRootKey]>-1&&(u=c[a.overridingRootKey]);let l=A;c[a.keyNum]>-1&&(l=c[a.keyNum]);let D=d.sample.sampleLoopStartIndex/2+(c[a.startloopAddrsOffset]+c[a.startloopAddrsCoarseOffset]*32768),y=d.sample.sampleLoopEndIndex/2+(c[a.endloopAddrsOffset]+c[a.endloopAddrsCoarseOffset]*32768),k=c[a.sampleModes],F=d.sample.getAudioData().length;D=Math.min(Math.max(0,D),F),y=Math.min(Math.max(0,y),F),y-D<1&&(k=0);let q=new rt(d.sample.getAudioData(),d.sample.sampleRate/sampleRate*Math.pow(2,d.sample.samplePitchCorrection/1200),c[a.startAddrsOffset]+c[a.startAddrsCoarseOffset]*32768,u,D,y,Math.floor(d.sample.sampleData.length)-1+(c[a.endAddrOffset]+c[a.endAddrsCoarseOffset]*32768),k);return c[a.velocity]>-1&&(e=c[a.velocity]),o&&cs([{Sample:d.sample.sampleName,Generators:c,Modulators:d.modulators.map(M=>M.debugString()),Velocity:e,TargetKey:l,MidiNote:A,WorkletSample:q}]),h.push(new Ge(sampleRate,q,A,e,t,n,l,c,d.modulators)),h},[]),s.cachedVoices[A][e]=g.map(h=>Ge.copy(h,n))),g}var bt=.07,Lt=1,L=class extends AudioWorkletProcessor{constructor(A){super(),this.oneOutputMode=A.processorOptions?.startRenderingData?.oneOutput===!0,this._outputsAmount=this.oneOutputMode?1:A.processorOptions.midiChannels,this.enableEventSystem=A.processorOptions.enableEventSystem,this.deviceID=TA,this.interpolationType=$e.linear,this.processTickCallback=void 0,this.sequencer=new EA(this),this.transposition=0,this.tunings=[];for(let e=0;e<127;e++)this.tunings.push([]);this.soundfontBankOffset=0,this.masterGain=Lt,this.midiVolume=1,this.voiceCap=us,this.pan=0,this.panLeft=.5*this.currentGain,this.highPerformanceMode=!1,this.overrideSoundfont=void 0,this.panRight=.5*this.currentGain;try{this.soundfontManager=new ot(A.processorOptions.soundfont,this.postReady.bind(this))}catch(e){throw this.post({messageType:mA.soundfontError,messageData:e}),e}this.sendPresetList(),this.defaultPreset=this.getPreset(0,0),this.drumPreset=this.getPreset(128,0),this.workletProcessorChannels=[];for(let e=0;e this.handleMessage(e.data),A.processorOptions.startRenderingData&&(this._snapshot!==void 0&&(this.applySynthesizerSnapshot(this._snapshot),this.resetAllControllers()),m("%cRendering enabled! Starting render.",r.info),A.processorOptions.startRenderingData.parsedMIDI&&(A.processorOptions.startRenderingData?.loopCount!==void 0?(this.sequencer.loopCount=A.processorOptions.startRenderingData?.loopCount,this.sequencer.loop=!0):this.sequencer.loop=!1,this.sequencer.loadNewSongList([A.processorOptions.startRenderingData.parsedMIDI]))),OA.isInitialized.then(()=>{this.postReady(),m("%cSpessaSynth is ready!",r.recognized)})}post(A){this.enableEventSystem&&this.port.postMessage(A)}postReady(){this.enableEventSystem&&this.port.postMessage({messageType:mA.ready,messageData:void 0})}get currentGain(){return this.masterGain*this.midiVolume}debugMessage(){m({channels:this.workletProcessorChannels,voicesAmount:this.totalVoicesAmount,outputAmount:this._outputsAmount,dumpedSamples:this.workletDumpedSamplesList})}process(A,e){this.processTickCallback&&this.processTickCallback();let s=0;return this.workletProcessorChannels.forEach((n,o)=>{if(n.voices.length<1||n.isMuted)return;let g,C,Q,h,d;if(this.oneOutputMode){let u=e[0];g=o%16*2,C=u[g],Q=u[g+1]}else g=o%this._outputsAmount+2,C=e[g][0],Q=e[g][1],h=e[0],d=e[1];let c=n.voices;n.voices=[],c.forEach(u=>{this.renderVoice(n,u,C,Q,h,d),u.finished||n.voices.push(u)}),s+=n.voices.length}),s!==this.totalVoicesAmount&&(this.totalVoicesAmount=s,this.sendChannelProperties()),!0}};L.prototype.renderVoice=Zs;L.prototype.releaseVoice=Ws;L.prototype.voiceKilling=Xs;L.prototype.getWorkletVoices=go;L.prototype.handleMessage=js;L.prototype.sendChannelProperties=An;L.prototype.callEvent=$s;L.prototype.systemExclusive=en;L.prototype.noteOn=sn;L.prototype.noteOff=nn;L.prototype.polyPressure=ln;L.prototype.killNote=on;L.prototype.stopAll=rn;L.prototype.stopAllChannels=an;L.prototype.muteChannel=Sn;L.prototype.setVibrato=Dn;L.prototype.disableAndLockGSNRPN=yn;L.prototype.dataEntryCoarse=kn;L.prototype.dataEntryFine=wn;L.prototype.createWorkletChannel=Ds;L.prototype.controllerChange=dn;L.prototype.channelPressure=cn;L.prototype.resetAllControllers=Fn;L.prototype.resetControllers=Rn;L.prototype.resetParameters=Gn;L.prototype.setMasterGain=mn;L.prototype.setMasterPan=pn;L.prototype.setMIDIVolume=fn;L.prototype.transposeAllChannels=In;L.prototype.transposeChannel=gn;L.prototype.setChannelTuning=Cn;L.prototype.setChannelTuningSemitones=En;L.prototype.setMasterTuning=Bn;L.prototype.setModulationDepth=hn;L.prototype.pitchWheel=Qn;L.prototype.setOctaveTuning=un;L.prototype.programChange=Ao;L.prototype.getPreset=eo;L.prototype.setPreset=to;L.prototype.setDrums=so;L.prototype.reloadSoundFont=ro;L.prototype.clearSoundFont=oo;L.prototype.setEmbeddedSoundFont=io;L.prototype.sendPresetList=no;L.prototype.sendSynthesizerSnapshot=ao;L.prototype.applySynthesizerSnapshot=Io;registerProcessor(ls,L);m("%cProcessor succesfully registered!",r.recognized); diff --git a/src/spessasynth_lib/synthetizer/worklet_system/worklet_utilities/volume_envelope.js b/src/spessasynth_lib/synthetizer/worklet_system/worklet_utilities/volume_envelope.js index 39a0414a..c1781179 100644 --- a/src/spessasynth_lib/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +++ b/src/spessasynth_lib/synthetizer/worklet_system/worklet_utilities/volume_envelope.js @@ -9,7 +9,7 @@ import { generatorTypes } from '../../../soundfont/read_sf2/generators.js' export const VOLUME_ENVELOPE_SMOOTHING_FACTOR = 0.001; const DB_SILENCE = 100; -const PERCEIVED_DB_SILENCE = 96; +const PERCEIVED_DB_SILENCE = 90; /** * VOL ENV STATES: @@ -25,10 +25,18 @@ export class WorkletVolumeEnvelope { /** * @param sampleRate {number} Hz + * @param initialDecay {number} cb */ - constructor(sampleRate) + constructor(sampleRate, initialDecay) { this.sampleRate = sampleRate; + /** + * if sustain stge is silent, + * then we can turn off the voice when it is silent. + * We can't do that with modulated as it can silence the volume and then raise it again and the voice must keep playing + * @type {boolean} + */ + this.canEndOnSilentSustain = initialDecay / 10 >= PERCEIVED_DB_SILENCE; } /** @@ -383,6 +391,10 @@ export class WorkletVolumeEnvelope // fallthrough case 4: + if(env.canEndOnSilentSustain && env.sustainDbRelative >= PERCEIVED_DB_SILENCE) + { + voice.finished = true; + } // sustain phase: stay at sustain while(true) { diff --git a/src/spessasynth_lib/synthetizer/worklet_system/worklet_utilities/worklet_voice.js b/src/spessasynth_lib/synthetizer/worklet_system/worklet_utilities/worklet_voice.js index 91c05914..20df5474 100644 --- a/src/spessasynth_lib/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +++ b/src/spessasynth_lib/synthetizer/worklet_system/worklet_utilities/worklet_voice.js @@ -142,7 +142,7 @@ class WorkletVoice this.channelNumber = channel; this.startTime = currentTime; this.targetKey = targetKey; - this.volumeEnvelope = new WorkletVolumeEnvelope(sampleRate); + this.volumeEnvelope = new WorkletVolumeEnvelope(sampleRate, generators[generatorTypes.sustainVolEnv]); } /** * Sample ID for voice.