midiwire 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -230,6 +230,30 @@ export function createMIDIDeviceManager(options?: MIDIDeviceManagerOptions): Pro
230
230
  * });
231
231
  */
232
232
  export function createMIDIController(options?: MIDIControlsOptions): Promise<MIDIController>;
233
+ /**
234
+ * Check if the browser supports the Web MIDI API.
235
+ * Returns true if `navigator.requestMIDIAccess` is available.
236
+ *
237
+ * @returns {boolean} True if Web MIDI is supported, false otherwise
238
+ *
239
+ * @example
240
+ * // Check before initializing
241
+ * if (isMIDISupported()) {
242
+ * const midi = await createMIDIController()
243
+ * } else {
244
+ * alert("Please use Chrome, Edge, or Opera for Web MIDI support")
245
+ * }
246
+ *
247
+ * @example
248
+ * // Conditional UI rendering
249
+ * const midiSection = document.getElementById("midi-controls")
250
+ * if (isMIDISupported()) {
251
+ * midiSection.style.display = "block"
252
+ * } else {
253
+ * midiSection.innerHTML = "<p>MIDI not supported in this browser</p>"
254
+ * }
255
+ */
256
+ export function isMIDISupported(): boolean;
233
257
  export { DataAttributeBinder } from './bindings/DataAttributeBinder.js';
234
258
  export { EventEmitter } from './core/EventEmitter.js';
235
259
  export { MIDIDeviceManager } from './core/MIDIDeviceManager.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"AAwEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AACH,kDAzEW,wBAAwB,GACtB,OAAO,CAAC,iBAAiB,CAAC,CA0HtC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,+CAnDW,mBAAmB,GACjB,OAAO,CAAC,cAAc,CAAC,CAoEnC;;;;;;;;;;;;;;;;;;;;;;mBAvSa,MAAM;;;;oBACN,MAAM;;;;aACN,MAAM,GAAC,MAAM;;;;YACb,OAAO;;;;;;;;;;;;eAGP,MAAM;;;;eACN,OAAO;;;;YACP,MAAM,GAAC,MAAM;;;;;;;;;eAgLb,MAAM;;;;mBACN,MAAM;;;;oBACN,MAAM;;;;aACN,MAAM,GAAC,MAAM;;;;YACb,OAAO;;;;kBACP,OAAO;;;;eACP,OAAO;;;;;;;;;;;;YAGP,MAAM,GAAC,MAAM;;kCAxMO,6BAA6B;+BADhC,0BAA0B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"AAwEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6EG;AACH,kDAzEW,wBAAwB,GACtB,OAAO,CAAC,iBAAiB,CAAC,CA0HtC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,+CAnDW,mBAAmB,GACjB,OAAO,CAAC,cAAc,CAAC,CAoEnC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,mCAnBa,OAAO,CAqBnB;;;;;;;;;;;;;;;;;;;;;;mBAlUa,MAAM;;;;oBACN,MAAM;;;;aACN,MAAM,GAAC,MAAM;;;;YACb,OAAO;;;;;;;;;;;;eAGP,MAAM;;;;eACN,OAAO;;;;YACP,MAAM,GAAC,MAAM;;;;;;;;;eAgLb,MAAM;;;;mBACN,MAAM;;;;oBACN,MAAM;;;;aACN,MAAM,GAAC,MAAM;;;;YACb,OAAO;;;;kBACP,OAAO;;;;eACP,OAAO;;;;;;;;;;;;YAGP,MAAM,GAAC,MAAM;;kCAxMO,6BAA6B;+BADhC,0BAA0B"}
@@ -3614,6 +3614,9 @@ async function j(c = {}) {
3614
3614
  }
3615
3615
  return e;
3616
3616
  }
3617
+ function Tt() {
3618
+ return typeof navigator < "u" && typeof navigator.requestMIDIAccess == "function";
3619
+ }
3617
3620
  export {
3618
3621
  p as CONN,
3619
3622
  p as CONNECTION_EVENTS,
@@ -3646,6 +3649,7 @@ export {
3646
3649
  ct as encode7Bit,
3647
3650
  nt as frequencyToNote,
3648
3651
  Et as getCCName,
3652
+ Tt as isMIDISupported,
3649
3653
  at as isSysEx,
3650
3654
  ut as isValid14BitCC,
3651
3655
  Pt as isValidCC,
@@ -1 +1 @@
1
- (function(l,I){typeof exports=="object"&&typeof module<"u"?I(exports):typeof define=="function"&&define.amd?define(["exports"],I):(l=typeof globalThis<"u"?globalThis:l||self,I(l.MIDIControls={}))})(this,(function(l){"use strict";var Ot=Object.defineProperty;var dt=(l,I,K)=>I in l?Ot(l,I,{enumerable:!0,configurable:!0,writable:!0,value:K}):l[I]=K;var _=(l,I,K)=>dt(l,typeof I!="symbol"?I+"":I,K);class I{constructor(e,i="[data-midi-cc]"){this.controller=e,this.selector=i,this.observer=null}bindAll(){document.querySelectorAll(this.selector==="[data-midi-cc]"?"[data-midi-cc], [data-midi-msb][data-midi-lsb]":this.selector).forEach(i=>{if(i.hasAttribute("data-midi-bound"))return;const n=this._parseAttributes(i);n&&(this.controller.bind(i,n),i.setAttribute("data-midi-bound","true"))})}enableAutoBinding(){if(this.observer)return;const e=this.selector==="[data-midi-cc]"?"[data-midi-cc], [data-midi-msb][data-midi-lsb]":this.selector;this.observer=new MutationObserver(i=>{i.forEach(n=>{n.addedNodes.forEach(s=>{if(s.nodeType===Node.ELEMENT_NODE){if(s.matches?.(e)){const r=this._parseAttributes(s);r&&!s.hasAttribute("data-midi-bound")&&(this.controller.bind(s,r),s.setAttribute("data-midi-bound","true"))}s.querySelectorAll&&s.querySelectorAll(e).forEach(E=>{if(!E.hasAttribute("data-midi-bound")){const o=this._parseAttributes(E);o&&(this.controller.bind(E,o),E.setAttribute("data-midi-bound","true"))}})}}),n.removedNodes.forEach(s=>{s.nodeType===Node.ELEMENT_NODE&&(s.hasAttribute?.("data-midi-bound")&&this.controller.unbind(s),s.querySelectorAll&&s.querySelectorAll("[data-midi-bound]").forEach(E=>{this.controller.unbind(E)}))})})}),this.observer.observe(document.body,{childList:!0,subtree:!0})}disableAutoBinding(){this.observer&&(this.observer.disconnect(),this.observer=null)}_parseAttributes(e){const i=parseInt(e.dataset.midiMsb,10),n=parseInt(e.dataset.midiLsb,10);if(!Number.isNaN(i)&&!Number.isNaN(n)&&i>=0&&i<=127&&n>=0&&n<=127){const r=parseInt(e.dataset.midiCc,10);return!Number.isNaN(r)&&r>=0&&r<=127&&console.warn(`Element has both 7-bit (data-midi-cc="${r}") and 14-bit (data-midi-msb="${i}" data-midi-lsb="${n}") CC attributes. 14-bit takes precedence.`,e),{msb:i,lsb:n,is14Bit:!0,channel:parseInt(e.dataset.midiChannel,10)||void 0,min:parseFloat(e.getAttribute("min"))||0,max:parseFloat(e.getAttribute("max"))||127,invert:e.dataset.midiInvert==="true",label:e.dataset.midiLabel}}const s=parseInt(e.dataset.midiCc,10);return!Number.isNaN(s)&&s>=0&&s<=127?{cc:s,channel:parseInt(e.dataset.midiChannel,10)||void 0,min:parseFloat(e.getAttribute("min"))||0,max:parseFloat(e.getAttribute("max"))||127,invert:e.dataset.midiInvert==="true",label:e.dataset.midiLabel}:((e.dataset.midiCc!==void 0||e.dataset.midiMsb!==void 0&&e.dataset.midiLsb!==void 0)&&console.warn("Invalid MIDI configuration on element:",e),null)}destroy(){this.disableAutoBinding()}}class K extends Error{constructor(e,i){super(e),this.name="MIDIError",this.code=i,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}}class F extends K{constructor(e,i){super(e,"MIDI_ACCESS_ERROR"),this.name="MIDIAccessError",this.reason=i}}class y extends K{constructor(e){super(e,"MIDI_CONNECTION_ERROR"),this.name="MIDIConnectionError"}}class R extends K{constructor(e,i,n){super(e,"MIDI_DEVICE_ERROR"),this.name="MIDIDeviceError",this.deviceType=i,this.deviceId=n}}class M extends K{constructor(e,i){super(e,"MIDI_VALIDATION_ERROR"),this.name="MIDIValidationError",this.validationType=i}}class H extends Error{constructor(e,i){super(e),this.name="DX7Error",this.code=i,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}}class g extends H{constructor(e,i,n){super(e,"DX7_PARSE_ERROR"),this.name="DX7ParseError",this.parseType=i,this.offset=n}}class d extends H{constructor(e,i,n){super(e,"DX7_VALIDATION_ERROR"),this.name="DX7ValidationError",this.validationType=i,this.value=n}}function O(c,e,i){return Math.max(e,Math.min(i,c))}function w(c,e,i,n=!1){const s=(c-e)/(i-e),E=(n?1-s:s)*127;return O(Math.round(E),0,127)}function J(c,e,i,n=!1){let s=O(c,0,127)/127;return n&&(s=1-s),e+s*(i-e)}function k(c){const e={C:0,"C#":1,DB:1,D:2,"D#":3,EB:3,E:4,F:5,"F#":6,GB:6,G:7,"G#":8,AB:8,A:9,"A#":10,BB:10,B:11},i=c.match(/^([A-G][#b]?)(-?\d+)$/i);if(!i)throw new M(`Invalid note name: ${c}`,"note",c);const[,n,s]=i,r=e[n.toUpperCase()];if(r===void 0)throw new M(`Invalid note: ${n}`,"note",n);const E=(parseInt(s,10)+1)*12+r;return O(E,0,127)}function j(c,e=!1){const s=e?["C","Db","D","Eb","E","F","Gb","G","Ab","A","Bb","B"]:["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],r=Math.floor(c/12)-1;return`${s[c%12]}${r}`}function X(c){const e=69+12*Math.log2(c/440);return O(Math.round(e),0,127)}function tt(c){return 440*2**((c-69)/12)}function et(c){return{0:"Bank Select",1:"Modulation",2:"Breath Controller",4:"Foot Controller",5:"Portamento Time",7:"Volume",8:"Balance",10:"Pan",11:"Expression",64:"Sustain Pedal",65:"Portamento",66:"Sostenuto",67:"Soft Pedal",68:"Legato",71:"Resonance",72:"Release Time",73:"Attack Time",74:"Cutoff",75:"Decay Time",76:"Vibrato Rate",77:"Vibrato Depth",78:"Vibrato Delay",84:"Portamento Control",91:"Reverb",92:"Tremolo",93:"Chorus",94:"Detune",95:"Phaser",120:"All Sound Off",121:"Reset All Controllers",123:"All Notes Off"}[c]||`CC ${c}`}function B(c){const e=O(Math.round(c),0,16383);return{msb:e>>7&127,lsb:e&127}}function Y(c,e){return O(c,0,127)<<7|O(e,0,127)}function x(c,e,i,n=!1){const s=(c-e)/(i-e),E=(n?1-s:s)*16383;return B(E)}function it(c,e,i,n,s=!1){let E=Y(c,e)/16383;return s&&(E=1-E),i+E*(n-i)}class v{constructor(){this.events=new Map}on(e,i){return this.events.has(e)||this.events.set(e,[]),this.events.get(e).push(i),()=>this.off(e,i)}once(e,i){const n=(...s)=>{i(...s),this.off(e,n)};this.on(e,n)}off(e,i){if(!this.events.has(e))return;const n=this.events.get(e),s=n.indexOf(i);s>-1&&n.splice(s,1),n.length===0&&this.events.delete(e)}emit(e,i){if(!this.events.has(e))return;[...this.events.get(e)].forEach(s=>{try{s(i)}catch(r){console.error(`Error in event handler for "${e}":`,r)}})}removeAllListeners(e){e?this.events.delete(e):this.events.clear()}}const p={DEVICE_CHANGE:"device-change",IN_DEV_CONNECTED:"in-dev-connected",IN_DEV_DISCONNECTED:"in-dev-disconnected",OUT_DEV_CONNECTED:"out-dev-connected",OUT_DEV_DISCONNECTED:"out-dev-disconnected"};class $ extends v{constructor(e={}){super(),this.options={sysex:!1,...e},this.midiAccess=null,this.output=null,this.input=null}async requestAccess(){if(!navigator.requestMIDIAccess)throw new F("Web MIDI API is not supported in this browser","unsupported");try{this.midiAccess=await navigator.requestMIDIAccess({sysex:this.options.sysex}),this.midiAccess.onstatechange=e=>{const i=e.port,n=e.port.state;this.emit(p.DEVICE_CHANGE,{port:i,state:n,type:i.type,device:{id:i.id,name:i.name,manufacturer:i.manufacturer||"Unknown"}}),n==="disconnected"?i.type==="input"?(this.emit(p.IN_DEV_DISCONNECTED,{device:i}),this.input&&this.input.id===i.id&&(this.input=null)):i.type==="output"&&(this.emit(p.OUT_DEV_DISCONNECTED,{device:i}),this.output&&this.output.id===i.id&&(this.output=null)):n==="connected"&&(i.type==="input"?this.emit(p.IN_DEV_CONNECTED,{device:i}):i.type==="output"&&this.emit(p.OUT_DEV_CONNECTED,{device:i}))}}catch(e){throw e.name==="SecurityError"?new F("MIDI access denied. SysEx requires user permission.","denied"):new F(`Failed to get MIDI access: ${e.message}`,"failed")}}async connect(e){if(!this.midiAccess)throw new y("MIDI access not initialized. Call requestAccess() first.");const i=Array.from(this.midiAccess.outputs.values());if(i.length===0)throw new R("No MIDI output devices available","output");if(e===void 0){this.output=i[0];return}if(typeof e=="number"){if(e<0||e>=i.length)throw new R(`Output index ${e} out of range (0-${i.length-1})`,"output",e);this.output=i[e];return}if(this.output=i.find(n=>n.name===e||n.id===e),!this.output){const n=i.map(s=>s.name).join(", ");throw new R(`MIDI output "${e}" not found. Available: ${n}`,"output",e)}}async connectInput(e,i){if(!this.midiAccess)throw new y("MIDI access not initialized. Call requestAccess() first.");if(typeof i!="function")throw new M("onMessage callback must be a function","callback");const n=Array.from(this.midiAccess.inputs.values());if(n.length===0)throw new R("No MIDI input devices available","input");if(this.input&&(this.input.onmidimessage=null),e===void 0)this.input=n[0];else if(typeof e=="number"){if(e<0||e>=n.length)throw new R(`Input index ${e} out of range (0-${n.length-1})`,"input",e);this.input=n[e]}else if(this.input=n.find(s=>s.name===e||s.id===e),!this.input){const s=n.map(r=>r.name).join(", ");throw new R(`MIDI input "${e}" not found. Available: ${s}`,"input",e)}this.input.onmidimessage=s=>{i(s)}}disconnectOutput(){this.output=null}disconnectInput(){this.input&&(this.input.onmidimessage=null,this.input=null)}disconnect(){this.disconnectOutput(),this.disconnectInput()}isConnected(){return this.output!==null}getCurrentOutput(){return this.output?{id:this.output.id,name:this.output.name,manufacturer:this.output.manufacturer||"Unknown"}:null}getCurrentInput(){return this.input?{id:this.input.id,name:this.input.name,manufacturer:this.input.manufacturer||"Unknown"}:null}getOutputs(){if(!this.midiAccess)return[];const e=[];return this.midiAccess.outputs.forEach(i=>{i.state==="connected"&&e.push({id:i.id,name:i.name,manufacturer:i.manufacturer||"Unknown"})}),e}getInputs(){if(!this.midiAccess)return[];const e=[];return this.midiAccess.inputs.forEach(i=>{i.state==="connected"&&e.push({id:i.id,name:i.name,manufacturer:i.manufacturer||"Unknown"})}),e}send(e,i=null){if(!this.output){console.warn("No MIDI output connected. Call connect() first.");return}try{const n=new Uint8Array(e);i===null?this.output.send(n):this.output.send(n,i)}catch(n){console.error("Failed to send MIDI message:",n)}}sendSysEx(e,i=!1){if(!this.options.sysex){console.warn("SysEx not enabled. Initialize with sysex: true");return}let n;i?n=[240,...e,247]:n=e,this.send(n)}}const A={READY:"ready",ERROR:"error",DESTROYED:"destroyed",DEV_OUT_CONNECTED:"dev-out-connected",DEV_OUT_DISCONNECTED:"dev-out-disconnected",DEV_IN_CONNECTED:"dev-in-connected",DEV_IN_DISCONNECTED:"dev-in-disconnected",CH_CC_SEND:"ch-cc-send",CH_CC_RECV:"ch-cc-recv",CH_NOTE_ON_SEND:"ch-note-on-send",CH_NOTE_ON_RECV:"ch-note-on-recv",CH_NOTE_OFF_SEND:"ch-note-off-send",CH_NOTE_OFF_RECV:"ch-note-off-recv",CH_PC_SEND:"ch-pc-send",CH_PC_RECV:"ch-pc-recv",CH_PITCH_BEND_SEND:"ch-pitch-bend-send",CH_PITCH_BEND_RECV:"ch-pitch-bend-recv",CH_MONO_PRESS_SEND:"ch-mono-press-send",CH_MONO_PRESS_RECV:"ch-mono-press-recv",CH_POLY_PRESS_SEND:"ch-poly-press-send",CH_POLY_PRESS_RECV:"ch-poly-press-recv",CH_ALL_SOUNDS_OFF_SEND:"ch-all-sounds-off-send",CH_RESET_CONTROLLERS_SEND:"ch-reset-controllers-send",CH_LOCAL_CONTROL_SEND:"ch-local-control-send",CH_ALL_NOTES_OFF_SEND:"ch-all-notes-off-send",CH_OMNI_OFF_SEND:"ch-omni-off-send",CH_OMNI_ON_SEND:"ch-omni-on-send",CH_MONO_ON_SEND:"ch-mono-on-send",CH_POLY_ON_SEND:"ch-poly-on-send",SYS_EX_SEND:"sys-ex-send",SYS_EX_RECV:"sys-ex-recv",SYS_CLOCK_RECV:"sys-clock-recv",SYS_START_RECV:"sys-start-recv",SYS_CONTINUE_RECV:"sys-continue-recv",SYS_STOP_RECV:"sys-stop-recv",SYS_MTC_RECV:"sys-mtc-recv",SYS_SONG_POS_RECV:"sys-song-pos-recv",SYS_SONG_SEL_RECV:"sys-song-sel-recv",SYS_TUNE_REQ_RECV:"sys-tune-req-recv",SYS_ACT_SENSE_RECV:"sys-act-sense-recv",SYS_RESET_RECV:"sys-reset-recv",MIDI_RAW:"midi-raw",PATCH_SAVED:"patch-saved",PATCH_LOADED:"patch-loaded",PATCH_DELETED:"patch-deleted"};class Z extends v{constructor(e={}){super(),this.options={inputChannel:1,outputChannel:1,autoConnect:!0,sysex:!1,...e},this.connection=null,this.bindings=new Map,this.state={controlChange:new Map,programChange:new Map,pitchBend:new Map,monoPressure:new Map,polyPressure:new Map},this.initialized=!1,this._initNamespaces()}async init(){if(this.initialized){console.warn("MIDI Controller already initialized");return}try{this.connection=new $({sysex:this.options.sysex}),await this.connection.requestAccess(),this.connection.on(p.DEVICE_CHANGE,async({state:e,type:i,device:n})=>{try{if(e==="connected")i==="output"?this.emit(A.DEV_OUT_CONNECTED,n):i==="input"&&this.emit(A.DEV_IN_CONNECTED,n);else if(e==="disconnected"){if(i==="output"&&n){const s=this.connection.getCurrentOutput();s&&s.id===n.id?await this._disconnectOutput():this.emit(A.DEV_OUT_DISCONNECTED,n)}if(i==="input"&&n){const s=this.connection.getCurrentInput();s&&s.id===n.id?await this._disconnectInput():this.emit(A.DEV_IN_DISCONNECTED,n)}}}catch(s){console.error("Error in device change handler:",s),this.emit(A.ERROR,s)}}),this.options.autoConnect&&await this.connection.connect(this.options.output),this.options.input!==void 0&&await this._connectInput(this.options.input),this.initialized=!0,this.emit(A.READY,this),this.options.onReady?.(this)}catch(e){throw this.emit(A.ERROR,e),this.options.onError?.(e),e}}_initNamespaces(){this.device={connect:this._connect.bind(this),disconnect:this._disconnect.bind(this),connectInput:this._connectInput.bind(this),disconnectInput:this._disconnectInput.bind(this),connectOutput:this._connectOutput.bind(this),disconnectOutput:this._disconnectOutput.bind(this),getCurrentOutput:this._getCurrentOutput.bind(this),getCurrentInput:this._getCurrentInput.bind(this),getOutputs:this._getOutputs.bind(this),getInputs:this._getInputs.bind(this)},this.channel={sendNoteOn:this._sendNoteOn.bind(this),sendNoteOff:this._sendNoteOff.bind(this),sendCC:this._sendCC.bind(this),getCC:this._getCC.bind(this),sendPC:this._sendPC.bind(this),getPC:this._getPC.bind(this),sendPitchBend:this._sendPitchBend.bind(this),getPitchBend:this._getPitchBend.bind(this),sendMonoPressure:this._sendMonoPressure.bind(this),getMonoPressure:this._getMonoPressure.bind(this),sendPolyPressure:this._sendPolyPressure.bind(this),getPolyPressure:this._getPolyPressure.bind(this),allSoundsOff:this._allSoundsOff.bind(this),resetControllers:this._resetControllers.bind(this),localControl:this._localControl.bind(this),allNotesOff:this._allNotesOff.bind(this),omniOff:this._omniOff.bind(this),omniOn:this._omniOn.bind(this),monoOn:this._monoOn.bind(this),polyOn:this._polyOn.bind(this)},this.system={sendEx:function(e,i=!1){return this._sendSysEx(e,i)}.bind(this),sendClock:this._sendClock.bind(this),start:this._sendStart.bind(this),continue:this._sendContinue.bind(this),stop:this._sendStop.bind(this),sendMTC:this._sendMTC.bind(this),sendSongPosition:this._sendSongPosition.bind(this),sendSongSelect:this._sendSongSelect.bind(this),sendTuneRequest:this._sendTuneRequest.bind(this),sendActiveSensing:this._sendActiveSensing.bind(this),sendSystemReset:this._sendSystemReset.bind(this)},this.patch={get:this._getPatch.bind(this),set:this._setPatch.bind(this),save:this._savePatch.bind(this),load:this._loadPatch.bind(this),delete:this._deletePatch.bind(this),list:this._listPatches.bind(this)}}bind(e,i,n={}){if(!e)return console.warn("Cannot bind: element is null or undefined"),()=>{};const s=this._createBinding(e,i,n);return this.bindings.set(e,s),this.initialized&&this.connection?.isConnected()&&s.handler({target:e}),()=>this.unbind(e)}_createBinding(e,i,n={}){const{min:s=parseFloat(e.getAttribute("min"))||0,max:r=parseFloat(e.getAttribute("max"))||127,channel:E,invert:o=!1,onInput:h=void 0}=i,{debounce:N=0}=n,u={...i,min:s,max:r,invert:o,onInput:h};if(E!==void 0&&(u.channel=E),i.is14Bit){const{msb:T,lsb:f}=i,U=V=>{const W=parseFloat(V.target.value);if(Number.isNaN(W))return;const{msb:Nt,lsb:Dt}=x(W,s,r,o),Q=E||this.options.outputChannel;this._sendCC(T,Nt,Q),this._sendCC(f,Dt,Q)};let L=null;const b=N>0?V=>{L&&clearTimeout(L),L=setTimeout(()=>{U(V),L=null},N)}:U;return e.addEventListener("input",b),e.addEventListener("change",b),{element:e,config:u,handler:U,destroy:()=>{L&&clearTimeout(L),e.removeEventListener("input",b),e.removeEventListener("change",b)}}}const{cc:a}=i,C=T=>{const f=parseFloat(T.target.value);if(Number.isNaN(f))return;const U=w(f,s,r,o),L=E===void 0?this.options.outputChannel:E;this._sendCC(a,U,L)};let S=null;const D=N>0?T=>{S&&clearTimeout(S),S=setTimeout(()=>{C(T),S=null},N)}:C;return e.addEventListener("input",D),e.addEventListener("change",D),{element:e,config:u,handler:C,destroy:()=>{S&&clearTimeout(S),e.removeEventListener("input",D),e.removeEventListener("change",D)}}}unbind(e){const i=this.bindings.get(e);i&&(i.destroy(),this.bindings.delete(e))}async destroy(){for(const e of this.bindings.values())e.destroy();this.bindings.clear(),this.state.controlChange.clear(),this.state.programChange.clear(),this.state.pitchBend.clear(),this.state.monoPressure.clear(),this.state.polyPressure.clear(),await this._disconnect(),this.initialized=!1,this.emit(A.DESTROYED),this.removeAllListeners()}async _connect(e){e?await this.connection.connect(e):this.options.output!==void 0?await this.connection.connect(this.options.output):this.options.autoConnect&&await this.connection.connect()}async _disconnect(){this.connection.disconnect()}async _connectInput(e){await this.connection.connectInput(e,i=>{this._handleMIDIMessage(i)}),this.emit(A.DEV_IN_CONNECTED,this.connection.getCurrentInput())}async _disconnectInput(){const e=this.connection.getCurrentInput();this.connection.disconnectInput(),this.emit(A.DEV_IN_DISCONNECTED,e)}async _connectOutput(e){await this.connection.connect(e),this.emit(A.DEV_OUT_CONNECTED,this.connection.getCurrentOutput())}async _disconnectOutput(){const e=this.connection.getCurrentOutput();this.connection.disconnectOutput(),this.emit(A.DEV_OUT_DISCONNECTED,e)}_getCurrentOutput(){return this.connection?.getCurrentOutput()||null}_getCurrentInput(){return this.connection?.getCurrentInput()||null}_getOutputs(){return this.connection?.getOutputs()||[]}_getInputs(){return this.connection?.getInputs()||[]}send(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send(e)}_sendNoteOn(e,i=64,n=this.options.outputChannel){if(!this.initialized)return;e=O(Math.round(e),0,127),i=O(Math.round(i),0,127),n=O(Math.round(n),1,16);const s=144+(n-1);this.connection.send([s,e,i]),this.emit(A.CH_NOTE_ON_SEND,{note:e,velocity:i,channel:n})}_sendNoteOff(e,i=this.options.outputChannel,n=0){if(!this.initialized)return;e=O(Math.round(e),0,127),n=O(Math.round(n),0,127),i=O(Math.round(i),1,16);const s=144+(i-1);this.connection.send([s,e,n]),this.emit(A.CH_NOTE_OFF_SEND,{note:e,channel:i,velocity:n})}_sendCC(e,i,n=this.options.outputChannel){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}e=O(Math.round(e),0,127),i=O(Math.round(i),0,127),n=O(Math.round(n),1,16);const s=176+(n-1);this.connection.send([s,e,i]);const r=`${n}:${e}`;this.state.controlChange.set(r,i),this.emit(A.CH_CC_SEND,{cc:e,value:i,channel:n})}_sendPC(e,i=this.options.outputChannel){if(!this.initialized)return;e=O(Math.round(e),0,127),i=O(Math.round(i),1,16);const n=192+(i-1);this.connection.send([n,e]),this.state.programChange.set(i.toString(),e),this.emit(A.CH_PC_SEND,{program:e,channel:i})}_getPC(e=this.options.inputChannel){return this.state.programChange.get(e.toString())}_getCC(e,i=this.options.inputChannel){const n=`${i}:${e}`;return this.state.controlChange.get(n)}_sendPitchBend(e,i=this.options.outputChannel){if(!this.initialized)return;e=O(Math.round(e),0,16383),i=O(Math.round(i),1,16);const n=224+(i-1),s=e&127,r=e>>7&127;this.connection.send([n,s,r]),this.state.pitchBend.set(i.toString(),e),this.emit(A.CH_PITCH_BEND_SEND,{value:e,channel:i})}_getPitchBend(e=this.options.inputChannel){return this.state.pitchBend.get(e.toString())}_sendMonoPressure(e,i=this.options.outputChannel){if(!this.initialized)return;e=O(Math.round(e),0,127),i=O(Math.round(i),1,16);const n=208+(i-1);this.connection.send([n,e]),this.state.monoPressure.set(i.toString(),e),this.emit(A.CH_MONO_PRESS_SEND,{pressure:e,channel:i})}_getMonoPressure(e=this.options.inputChannel){return this.state.monoPressure.get(e.toString())}_sendPolyPressure(e,i,n=this.options.outputChannel){if(!this.initialized)return;e=O(Math.round(e),0,127),i=O(Math.round(i),0,127),n=O(Math.round(n),1,16);const s=160+(n-1);this.connection.send([s,e,i]);const r=`${n}:${e}`;this.state.polyPressure.set(r,i),this.emit(A.CH_POLY_PRESS_SEND,{note:e,pressure:i,channel:n})}_getPolyPressure(e,i=this.options.inputChannel){const n=`${i}:${e}`;return this.state.polyPressure.get(n)}_allSoundsOff(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e!==void 0){e=O(Math.round(e),1,16);const i=176+(e-1);this.connection.send([i,120,0]),this.emit(A.CH_ALL_SOUNDS_OFF_SEND,{channel:e})}else{for(let i=1;i<=16;i++){const n=176+(i-1);this.connection.send([n,120,0])}this.emit(A.CH_ALL_SOUNDS_OFF_SEND,{channel:null})}}_resetControllers(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e!==void 0){e=O(Math.round(e),1,16);const i=176+(e-1);this.connection.send([i,121,0]),this.emit(A.CH_RESET_CONTROLLERS_SEND,{channel:e})}else{for(let i=1;i<=16;i++){const n=176+(i-1);this.connection.send([n,121,0])}this.emit(A.CH_RESET_CONTROLLERS_SEND,{channel:null})}}_localControl(e,i){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}const n=e?127:0;if(i!==void 0){i=O(Math.round(i),1,16);const s=176+(i-1);this.connection.send([s,122,n]),this.emit(A.CH_LOCAL_CONTROL_SEND,{enabled:e,channel:i})}else{for(let s=1;s<=16;s++){const r=176+(s-1);this.connection.send([r,122,n])}this.emit(A.CH_LOCAL_CONTROL_SEND,{enabled:e,channel:null})}}_allNotesOff(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e!==void 0){e=O(Math.round(e),1,16);const i=176+(e-1);this.connection.send([i,123,0]),this.emit(A.CH_ALL_NOTES_OFF_SEND,{channel:e})}else{for(let i=1;i<=16;i++){const n=176+(i-1);this.connection.send([n,123,0])}this.emit(A.CH_ALL_NOTES_OFF_SEND,{channel:null})}}_omniOff(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e!==void 0){e=O(Math.round(e),1,16);const i=176+(e-1);this.connection.send([i,124,0]),this.emit(A.CH_OMNI_OFF_SEND,{channel:e})}else{for(let i=1;i<=16;i++){const n=176+(i-1);this.connection.send([n,124,0])}this.emit(A.CH_OMNI_OFF_SEND,{channel:null})}}_omniOn(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e!==void 0){e=O(Math.round(e),1,16);const i=176+(e-1);this.connection.send([i,125,0]),this.emit(A.CH_OMNI_ON_SEND,{channel:e})}else{for(let i=1;i<=16;i++){const n=176+(i-1);this.connection.send([n,125,0])}this.emit(A.CH_OMNI_ON_SEND,{channel:null})}}_monoOn(e=1,i){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e=Math.max(0,Math.min(16,Math.round(e))),i!==void 0){i=O(Math.round(i),1,16);const n=176+(i-1);this.connection.send([n,126,e]),this.emit(A.CH_MONO_ON_SEND,{channels:e,channel:i})}else{for(let n=1;n<=16;n++){const s=176+(n-1);this.connection.send([s,126,e])}this.emit(A.CH_MONO_ON_SEND,{channels:e,channel:null})}}_polyOn(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e!==void 0){e=O(Math.round(e),1,16);const i=176+(e-1);this.connection.send([i,127,0]),this.emit(A.CH_POLY_ON_SEND,{channel:e})}else{for(let i=1;i<=16;i++){const n=176+(i-1);this.connection.send([n,127,0])}this.emit(A.CH_POLY_ON_SEND,{channel:null})}}_sendSysEx(e,i=!1){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(!this.options.sysex){console.warn("SysEx not enabled. Initialize with sysex: true");return}this.connection.sendSysEx(e,i),this.emit(A.SYS_EX_SEND,{data:e,includeWrapper:i})}_sendClock(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([248])}_sendStart(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([250])}_sendContinue(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([251])}_sendStop(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([252])}_sendMTC(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}e=O(Math.round(e),0,127),this.connection.send([241,e])}_sendSongPosition(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}e=O(Math.round(e),0,16383);const i=e&127,n=e>>7&127;this.connection.send([242,i,n])}_sendSongSelect(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}e=O(Math.round(e),0,127),this.connection.send([243,e])}_sendTuneRequest(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([246])}_sendActiveSensing(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([254])}_sendSystemReset(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([255])}_handleMIDIMessage(e){const[i,n,s]=e.data,r=i&240,E=(i&15)+1;if(i===248){this.emit(A.SYS_CLOCK_RECV,{timestamp:e.midiwire});return}if(i===250){this.emit(A.SYS_START_RECV,{timestamp:e.midiwire});return}if(i===251){this.emit(A.SYS_CONTINUE_RECV,{timestamp:e.midiwire});return}if(i===252){this.emit(A.SYS_STOP_RECV,{timestamp:e.midiwire});return}if(i===254){this.emit(A.SYS_ACT_SENSE_RECV,{timestamp:e.midiwire});return}if(i===255){this.emit(A.SYS_RESET_RECV,{timestamp:e.midiwire});return}if(i===240){this.emit(A.SYS_EX_RECV,{data:Array.from(e.data),timestamp:e.midiwire});return}if(i===241){this.emit(A.SYS_MTC_RECV,{data:n,timestamp:e.midiwire});return}if(i===242){const o=n+(s<<7);this.emit(A.SYS_SONG_POS_RECV,{position:o,timestamp:e.midiwire});return}if(i===243){this.emit(A.SYS_SONG_SEL_RECV,{song:n,timestamp:e.midiwire});return}if(i===246){this.emit(A.SYS_TUNE_REQ_RECV,{timestamp:e.midiwire});return}if(i===247){this.emit(A.MIDI_RAW,{status:i,data:[n,s],channel:E,timestamp:e.midiwire});return}if(r===176){const o=`${E}:${n}`;this.state.controlChange.set(o,s),this.emit(A.CH_CC_RECV,{cc:n,value:s,channel:E});return}if(r===192){this.state.programChange.set(E.toString(),n),this.emit(A.CH_PC_RECV,{program:n,channel:E});return}if(r===224){const o=n+(s<<7);this.state.pitchBend.set(E.toString(),o),this.emit(A.CH_PITCH_BEND_RECV,{value:o,channel:E});return}if(r===208){this.state.monoPressure.set(E.toString(),n),this.emit(A.CH_MONO_PRESS_RECV,{pressure:n,channel:E});return}if(r===160){const o=`${E}:${n}`;this.state.polyPressure.set(o,s),this.emit(A.CH_POLY_PRESS_RECV,{note:n,pressure:s,channel:E});return}if(r===144&&s>0){this.emit(A.CH_NOTE_ON_RECV,{note:n,velocity:s,channel:E});return}if(r===128||r===144&&s===0){this.emit(A.CH_NOTE_OFF_RECV,{note:n,channel:E});return}this.emit(A.MIDI_RAW,{status:i,data:[n,s],channel:E,timestamp:e.midiwire})}_getPatch(e="Unnamed Patch"){const i={name:e,device:this._getCurrentOutput()?.name||null,timestamp:new Date().toISOString(),version:"1.0",channels:{},settings:{}};for(const[n,s]of this.state.controlChange.entries()){const[r,E]=n.split(":").map(Number);i.channels[r]||(i.channels[r]={ccs:{},notes:{}}),i.channels[r].ccs[E]=s}for(const[n,s]of this.state.programChange.entries()){const r=parseInt(n,10);i.channels[r]||(i.channels[r]={ccs:{},notes:{}}),i.channels[r].program=s}for(const[n,s]of this.state.pitchBend.entries()){const r=parseInt(n,10);i.channels[r]||(i.channels[r]={ccs:{},notes:{}}),i.channels[r].pitchBend=s}for(const[n,s]of this.state.monoPressure.entries()){const r=parseInt(n,10);i.channels[r]||(i.channels[r]={ccs:{},notes:{}}),i.channels[r].monoPressure=s}for(const[n,s]of this.state.polyPressure.entries()){const[r,E]=n.split(":").map(Number),o=parseInt(r,10);i.channels[o]||(i.channels[o]={ccs:{},notes:{}}),i.channels[o].polyPressure||(i.channels[o].polyPressure={}),i.channels[o].polyPressure[E]=s}for(const[n,s]of this.bindings.entries()){const{config:r}=s;if(r.cc){const E=`cc${r.cc}`;i.settings[E]={min:r.min,max:r.max,invert:r.invert||!1,is14Bit:r.is14Bit||!1,label:n.getAttribute?.("data-midi-label")||null,elementId:n.id||null}}}return i}async _setPatch(e){if(!e||!e.channels)throw new M("Invalid patch format","patch");const i=e.version||"1.0";i==="1.0"?await this._applyPatchV1(e):(console.warn(`Unknown patch version: ${i}. Attempting to apply as v1.0`),await this._applyPatchV1(e)),this.emit(A.PATCH_LOADED,{patch:e})}async _applyPatchV1(e){for(const[i,n]of Object.entries(e.channels)){const s=parseInt(i,10);if(n.ccs)for(const[r,E]of Object.entries(n.ccs)){const o=parseInt(r,10);this._sendCC(o,E,s)}if(n.program!==void 0&&this._sendPC(n.program,s),n.pitchBend!==void 0&&this._sendPitchBend(n.pitchBend,s),n.monoPressure!==void 0&&this._sendMonoPressure(n.monoPressure,s),n.polyPressure)for(const[r,E]of Object.entries(n.polyPressure)){const o=parseInt(r,10);this._sendPolyPressure(o,E,s)}if(n.notes)for(const[r,E]of Object.entries(n.notes)){const o=parseInt(r,10);E>0?this._sendNoteOn(o,E,s):this._sendNoteOff(o,s)}}if(e.settings)for(const[i,n]of Object.entries(e.settings))for(const[s,r]of this.bindings.entries())r.config.cc?.toString()===i.replace("cc","")&&(s.min!==void 0&&n.min!==void 0&&(s.min=String(n.min)),s.max!==void 0&&n.max!==void 0&&(s.max=String(n.max)));for(const[i,n]of this.bindings.entries()){const{config:s}=n;if(s.cc!==void 0){const r=s.channel||this.options.inputChannel,E=e.channels[r];if(E?.ccs){const o=E.ccs[s.cc];if(o!==void 0){const h=s.min!==void 0?s.min:parseFloat(i.getAttribute?.("min"))||0,N=s.max!==void 0?s.max:parseFloat(i.getAttribute?.("max"))||127,u=s.invert||!1;let a;u?a=N-o/127*(N-h):a=h+o/127*(N-h),s.onInput&&typeof s.onInput=="function"?s.onInput(a):(i.value=a,i.dispatchEvent(new Event("input",{bubbles:!0})))}}}}}_savePatch(e,i=null){const n=i||this._getPatch(e),s=`midiwire_patch_${e}`;try{return localStorage.setItem(s,JSON.stringify(n)),this.emit(A.PATCH_SAVED,{name:e,patch:n}),s}catch(r){throw console.error("Failed to save patch:",r),r}}_loadPatch(e){const i=`midiwire_patch_${e}`;try{const n=localStorage.getItem(i);if(!n)return null;const s=JSON.parse(n);return this.emit(A.PATCH_LOADED,{name:e,patch:s}),s}catch(n){return console.error("Failed to load patch:",n),null}}_deletePatch(e){const i=`midiwire_patch_${e}`;try{return localStorage.removeItem(i),this.emit(A.PATCH_DELETED,{name:e}),!0}catch(n){return console.error("Failed to delete patch:",n),!1}}_listPatches(){const e=[];try{for(let i=0;i<localStorage.length;i++){const n=localStorage.key(i);if(n?.startsWith("midiwire_patch_")){const s=n.replace("midiwire_patch_",""),r=this._loadPatch(s);r&&e.push({name:s,patch:r})}}}catch(i){console.error("Failed to list patches:",i)}return e.sort((i,n)=>i.name.localeCompare(n.name))}}class z{constructor(e={}){this.midi=e.midiController||null,this.onStatusUpdate=e.onStatusUpdate||(()=>{}),this.onConnectionUpdate=e.onConnectionUpdate||(()=>{}),this.channel=e.channel||1,this.currentOutput=null,this.currentInput=null,this.isConnecting=!1}async setupSelectors(e={},i={}){if(!this.midi)throw new Error("MIDI controller not initialized. Pass midiController in constructor options.");const{output:n,input:s,channel:r}=e,E=this._resolveSelector(n),o=this._resolveSelector(s),h=this._resolveSelector(r);if(this._setupDeviceChangeListeners({output:E,input:o},i.onDeviceListChange),E){await this._populateOutputDeviceList(E);const N=i.onConnect?async(a,C)=>i.onConnect({midi:a,device:C,type:"output"}):void 0,u=i.onDisconnect?async a=>i.onDisconnect({midi:a,type:"output"}):void 0;this._connectOutputDeviceSelection(E,N,u)}if(o){await this._populateInputDeviceList(o);const N=i.onConnect?async(a,C)=>i.onConnect({midi:a,device:C,type:"input"}):void 0,u=i.onDisconnect?async a=>i.onDisconnect({midi:a,type:"input"}):void 0;this._connectInputDeviceSelection(o,N,u)}return h&&this._connectChannelSelection(h,"output"),this.midi}updateStatus(e,i=""){this.onStatusUpdate(e,i)}updateConnectionStatus(){this.onConnectionUpdate(this.currentOutput,this.currentInput,this.midi)}_setupDeviceChangeListeners(e={},i){!this.midi||this._listenersInitialized||(this._listenersInitialized=!0,this.midi.on(A.DEV_OUT_CONNECTED,async n=>{this.updateStatus(`Output device connected: ${n?.name||"Unknown"}`,"connected"),e.output&&await this._populateOutputDeviceList(e.output),i&&i()}),this.midi.on(A.DEV_OUT_DISCONNECTED,async n=>{this.updateStatus(`Output device disconnected: ${n?.name||"Unknown"}`,"error"),this.currentOutput&&n?.name===this.currentOutput.name&&(this.currentOutput=null,this.updateConnectionStatus(),e.output&&(e.output.value="")),e.output&&await this._populateOutputDeviceList(e.output),i&&i()}),this.midi.on(A.DEV_IN_CONNECTED,async n=>{this.updateStatus(`Input device connected: ${n?.name||"Unknown"}`,"connected"),e.input&&await this._populateInputDeviceList(e.input),i&&i()}),this.midi.on(A.DEV_IN_DISCONNECTED,async n=>{this.updateStatus(`Input device disconnected: ${n?.name||"Unknown"}`,"error"),e.input&&(e.input.value="",await this._populateInputDeviceList(e.input)),i&&i()}))}_resolveSelector(e){if(typeof e=="string"){const i=document.querySelector(e);return i||console.warn(`MIDIDeviceManager: Selector "${e}" not found`),i}return e||null}_getOutputDevices(){return this.midi?this.midi.device.getOutputs():[]}_getInputDevices(){return this.midi?this.midi.device.getInputs():[]}_connectOutputDeviceSelection(e,i,n){!e||!this.midi||e.addEventListener("change",async s=>{if(this.isConnecting)return;this.isConnecting=!0;const r=s.target.value;if(!r){this.currentOutput&&this.midi&&(await this.midi.device.disconnectOutput(),this.currentOutput=null,this.updateStatus("Output device disconnected",""),this.updateConnectionStatus()),this.isConnecting=!1,n&&await n(this.midi);return}try{if(await this.midi.device.connectOutput(parseInt(r,10)),this.currentOutput=this.midi.device.getCurrentOutput(),this.currentOutput){const o=this.midi.device.getOutputs().findIndex(h=>h.id===this.currentOutput.id);o!==-1&&(e.value=o.toString())}this.updateConnectionStatus(),i&&await i(this.midi,this.currentOutput)}catch(E){this.updateStatus(`Output connection failed: ${E.message}`,"error")}finally{this.isConnecting=!1}})}_connectInputDeviceSelection(e,i,n){!e||!this.midi||e.addEventListener("change",async s=>{const r=s.target.value;if(!r){this.midi&&(await this.midi.device.disconnectInput(),this.updateStatus("Input device disconnected",""),this.updateConnectionStatus()),n&&await n(this.midi);return}if(!this.isConnecting){this.isConnecting=!0;try{await this.midi.device.connectInput(parseInt(r,10));const E=this.midi.device.getCurrentInput();this.updateConnectionStatus(),i&&await i(this.midi,E)}catch(E){this.updateStatus(`Input connection failed: ${E.message}`,"error")}finally{this.isConnecting=!1}}})}_populateDeviceList(e,i,n,s,r){if(i.length>0){if(e.innerHTML='<option value="">Select a device</option>'+i.map((E,o)=>`<option value="${o}">${E.name}</option>`).join(""),n){const E=i.findIndex(o=>o.name===n.name);E!==-1?e.value=E.toString():(e.value="",r&&(this.currentOutput=null,this.updateConnectionStatus()))}else e.value="";e.disabled=!1,r&&!this.currentOutput&&this.updateStatus("Select a device")}else e.innerHTML='<option value="">No devices connected</option>',e.disabled=!0,r&&this.updateStatus("No devices connected","error");s&&s()}async _populateOutputDeviceList(e,i){if(!e||!this.midi)return;const n=this._getOutputDevices();this._populateDeviceList(e,n,this.currentOutput,i,!0)}async _populateInputDeviceList(e,i){if(!e||!this.midi)return;const n=this._getInputDevices(),s=this.midi.device.getCurrentInput();this._populateDeviceList(e,n,s,i,!1)}_connectChannelSelection(e,i){if(!e||!this.midi)return;const n=i==="input"?"inputChannel":"outputChannel";e.addEventListener("change",s=>{this.midi&&(this.midi.options[n]=parseInt(s.target.value,10),this.updateConnectionStatus())})}}const t=class t{constructor(e,i=0){if(e.length!==t.PACKED_SIZE)throw new d(`Invalid voice data length: expected ${t.PACKED_SIZE} bytes, got ${e.length}`,"length",e.length);this.index=i,this.data=new Uint8Array(e),this.name=this._extractName(),this._unpackedCache=null}_extractName(){const e=this.data.subarray(t.PACKED_NAME_START,t.PACKED_NAME_START+t.NAME_LENGTH);return Array.from(e).map(n=>{let s=n&t.MASK_7BIT;return s===t.CHAR_YEN&&(s=t.CHAR_REPLACEMENT_Y),s===t.CHAR_ARROW_RIGHT&&(s=t.CHAR_REPLACEMENT_GT),s===t.CHAR_ARROW_LEFT&&(s=t.CHAR_REPLACEMENT_LT),(s<t.CHAR_MIN_PRINTABLE||s>t.CHAR_MAX_PRINTABLE)&&(s=t.CHAR_SPACE),String.fromCharCode(s)}).join("").trim()}getParameter(e){if(e<0||e>=t.PACKED_SIZE)throw new d(`Parameter offset out of range: ${e} (must be 0-${t.PACKED_SIZE-1})`,"offset",e);return this.data[e]&t.MASK_7BIT}getUnpackedParameter(e){if(e<0||e>=t.UNPACKED_SIZE)throw new d(`Unpacked parameter offset out of range: ${e} (must be 0-${t.UNPACKED_SIZE-1})`,"offset",e);return this._unpackedCache||(this._unpackedCache=this.unpack()),this._unpackedCache[e]&t.MASK_7BIT}setParameter(e,i){if(e<0||e>=t.PACKED_SIZE)throw new d(`Parameter offset out of range: ${e} (must be 0-${t.PACKED_SIZE-1})`,"offset",e);this.data[e]=i&t.MASK_7BIT,this._unpackedCache=null,e>=t.PACKED_NAME_START&&e<t.PACKED_NAME_START+t.NAME_LENGTH&&(this.name=this._extractName())}unpack(){const e=this.data,i=new Uint8Array(t.UNPACKED_SIZE);return this._unpackOperators(e,i),this._unpackPitchEG(e,i),this._unpackGlobalParams(e,i),this._unpackName(e,i),i}_unpackOperators(e,i){for(let n=0;n<t.NUM_OPERATORS;n++){const s=(t.NUM_OPERATORS-1-n)*t.PACKED_OP_SIZE,r=n*t.UNPACKED_OP_SIZE;this._unpackOperator(e,i,s,r)}}_unpackOperator(e,i,n,s){this._unpackOperatorEG(e,i,n,s),this._unpackOperatorScaling(e,i,n,s),this._unpackOperatorPackedParams(e,i,n,s),this._unpackOperatorFrequency(e,i,n,s)}_unpackOperatorEG(e,i,n,s){i[s+t.UNPACKED_OP_EG_RATE_1]=e[n+t.PACKED_OP_EG_RATE_1]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_RATE_2]=e[n+t.PACKED_OP_EG_RATE_2]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_RATE_3]=e[n+t.PACKED_OP_EG_RATE_3]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_RATE_4]=e[n+t.PACKED_OP_EG_RATE_4]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_LEVEL_1]=e[n+t.PACKED_OP_EG_LEVEL_1]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_LEVEL_2]=e[n+t.PACKED_OP_EG_LEVEL_2]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_LEVEL_3]=e[n+t.PACKED_OP_EG_LEVEL_3]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_LEVEL_4]=e[n+t.PACKED_OP_EG_LEVEL_4]&t.MASK_7BIT}_unpackOperatorScaling(e,i,n,s){i[s+t.UNPACKED_OP_BREAK_POINT]=e[n+t.PACKED_OP_BREAK_POINT]&t.MASK_7BIT,i[s+t.UNPACKED_OP_L_SCALE_DEPTH]=e[n+t.PACKED_OP_L_SCALE_DEPTH]&t.MASK_7BIT,i[s+t.UNPACKED_OP_R_SCALE_DEPTH]=e[n+t.PACKED_OP_R_SCALE_DEPTH]&t.MASK_7BIT}_unpackOperatorPackedParams(e,i,n,s){const r=e[n+t.PACKED_OP_CURVES]&t.MASK_7BIT;i[s+t.UNPACKED_OP_L_CURVE]=r&t.MASK_2BIT,i[s+t.UNPACKED_OP_R_CURVE]=r>>2&t.MASK_2BIT;const E=e[n+t.PACKED_OP_RATE_SCALING]&t.MASK_7BIT;i[s+t.UNPACKED_OP_RATE_SCALING]=E&t.MASK_3BIT,i[s+t.UNPACKED_OP_DETUNE]=E>>3&t.MASK_4BIT;const o=e[n+t.PACKED_OP_MOD_SENS]&t.MASK_7BIT;i[s+t.UNPACKED_OP_AMP_MOD_SENS]=o&t.MASK_2BIT,i[s+t.UNPACKED_OP_KEY_VEL_SENS]=o>>2&t.MASK_3BIT,i[s+t.UNPACKED_OP_OUTPUT_LEVEL]=e[n+t.PACKED_OP_OUTPUT_LEVEL]&t.MASK_7BIT}_unpackOperatorFrequency(e,i,n,s){const r=e[n+t.PACKED_OP_MODE_FREQ]&t.MASK_7BIT;i[s+t.UNPACKED_OP_MODE]=r&t.MASK_1BIT,i[s+t.UNPACKED_OP_FREQ_COARSE]=r>>1&t.MASK_5BIT;const E=e[n+t.PACKED_OP_DETUNE_FINE]&t.MASK_7BIT;i[s+t.UNPACKED_OP_OSC_DETUNE]=E&t.MASK_3BIT,i[s+t.UNPACKED_OP_FREQ_FINE]=E>>3&t.MASK_4BIT}_unpackPitchEG(e,i){i[t.UNPACKED_PITCH_EG_RATE_1]=e[t.PACKED_PITCH_EG_RATE_1]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_RATE_2]=e[t.PACKED_PITCH_EG_RATE_2]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_RATE_3]=e[t.PACKED_PITCH_EG_RATE_3]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_RATE_4]=e[t.PACKED_PITCH_EG_RATE_4]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_LEVEL_1]=e[t.PACKED_PITCH_EG_LEVEL_1]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_LEVEL_2]=e[t.PACKED_PITCH_EG_LEVEL_2]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_LEVEL_3]=e[t.PACKED_PITCH_EG_LEVEL_3]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_LEVEL_4]=e[t.PACKED_PITCH_EG_LEVEL_4]&t.MASK_7BIT}_unpackGlobalParams(e,i){i[t.UNPACKED_ALGORITHM]=e[t.OFFSET_ALGORITHM]&t.MASK_5BIT;const n=e[t.OFFSET_FEEDBACK]&t.MASK_7BIT;i[t.UNPACKED_FEEDBACK]=n&t.MASK_3BIT,i[t.UNPACKED_OSC_SYNC]=n>>3&t.MASK_1BIT,i[t.UNPACKED_LFO_SPEED]=e[t.OFFSET_LFO_SPEED]&t.MASK_7BIT,i[t.UNPACKED_LFO_DELAY]=e[t.OFFSET_LFO_DELAY]&t.MASK_7BIT,i[t.UNPACKED_LFO_PM_DEPTH]=e[t.OFFSET_LFO_PM_DEPTH]&t.MASK_7BIT,i[t.UNPACKED_LFO_AM_DEPTH]=e[t.OFFSET_LFO_AM_DEPTH]&t.MASK_7BIT;const s=e[t.OFFSET_LFO_SYNC_WAVE]&t.MASK_7BIT;i[t.UNPACKED_LFO_KEY_SYNC]=s&t.MASK_1BIT,i[t.UNPACKED_LFO_WAVE]=s>>1&t.MASK_3BIT,i[t.UNPACKED_LFO_PM_SENS]=s>>4&t.MASK_3BIT,i[t.UNPACKED_AMP_MOD_SENS]=e[t.OFFSET_AMP_MOD_SENS]&t.MASK_7BIT,i[t.UNPACKED_TRANSPOSE]=e[t.OFFSET_TRANSPOSE]&t.MASK_7BIT,i[t.UNPACKED_EG_BIAS_SENS]=e[t.OFFSET_EG_BIAS_SENS]&t.MASK_7BIT}_unpackName(e,i){for(let n=0;n<t.NAME_LENGTH;n++)i[t.UNPACKED_NAME_START+n]=e[t.PACKED_NAME_START+n]&t.MASK_7BIT}static pack(e){if(e.length!==t.UNPACKED_SIZE)throw new d(`Invalid unpacked data length: expected ${t.UNPACKED_SIZE} bytes, got ${e.length}`,"length",e.length);const i=new Uint8Array(t.PACKED_SIZE);return t._packOperators(e,i),t._packPitchEG(e,i),t._packGlobalParams(e,i),t._packName(e,i),i}static _packOperators(e,i){for(let n=0;n<t.NUM_OPERATORS;n++){const s=n*t.UNPACKED_OP_SIZE,r=(t.NUM_OPERATORS-1-n)*t.PACKED_OP_SIZE;t._packOperator(e,i,s,r)}}static _packOperator(e,i,n,s){t._packOperatorEG(e,i,n,s),t._packOperatorScaling(e,i,n,s),t._packOperatorPackedParams(e,i,n,s),t._packOperatorFrequency(e,i,n,s)}static _packOperatorEG(e,i,n,s){i[s+t.PACKED_OP_EG_RATE_1]=e[n+t.UNPACKED_OP_EG_RATE_1],i[s+t.PACKED_OP_EG_RATE_2]=e[n+t.UNPACKED_OP_EG_RATE_2],i[s+t.PACKED_OP_EG_RATE_3]=e[n+t.UNPACKED_OP_EG_RATE_3],i[s+t.PACKED_OP_EG_RATE_4]=e[n+t.UNPACKED_OP_EG_RATE_4],i[s+t.PACKED_OP_EG_LEVEL_1]=e[n+t.UNPACKED_OP_EG_LEVEL_1],i[s+t.PACKED_OP_EG_LEVEL_2]=e[n+t.UNPACKED_OP_EG_LEVEL_2],i[s+t.PACKED_OP_EG_LEVEL_3]=e[n+t.UNPACKED_OP_EG_LEVEL_3],i[s+t.PACKED_OP_EG_LEVEL_4]=e[n+t.UNPACKED_OP_EG_LEVEL_4]}static _packOperatorScaling(e,i,n,s){i[s+t.PACKED_OP_BREAK_POINT]=e[n+t.UNPACKED_OP_BREAK_POINT],i[s+t.PACKED_OP_L_SCALE_DEPTH]=e[n+t.UNPACKED_OP_L_SCALE_DEPTH],i[s+t.PACKED_OP_R_SCALE_DEPTH]=e[n+t.UNPACKED_OP_R_SCALE_DEPTH]}static _packOperatorPackedParams(e,i,n,s){const r=e[n+t.UNPACKED_OP_L_CURVE]&t.MASK_2BIT,E=e[n+t.UNPACKED_OP_R_CURVE]&t.MASK_2BIT;i[s+t.PACKED_OP_CURVES]=r|E<<2;const o=e[n+t.UNPACKED_OP_RATE_SCALING]&t.MASK_3BIT,h=e[n+t.UNPACKED_OP_DETUNE]&t.MASK_4BIT;i[s+t.PACKED_OP_RATE_SCALING]=o|h<<3;const N=e[n+t.UNPACKED_OP_AMP_MOD_SENS]&t.MASK_2BIT,u=e[n+t.UNPACKED_OP_KEY_VEL_SENS]&t.MASK_3BIT;i[s+t.PACKED_OP_MOD_SENS]=N|u<<2,i[s+t.PACKED_OP_OUTPUT_LEVEL]=e[n+t.UNPACKED_OP_OUTPUT_LEVEL]}static _packOperatorFrequency(e,i,n,s){const r=e[n+t.UNPACKED_OP_MODE]&t.MASK_1BIT,E=e[n+t.UNPACKED_OP_FREQ_COARSE]&t.MASK_5BIT;i[s+t.PACKED_OP_MODE_FREQ]=r|E<<1;const o=e[n+t.UNPACKED_OP_OSC_DETUNE]&t.MASK_3BIT,h=e[n+t.UNPACKED_OP_FREQ_FINE]&t.MASK_4BIT;i[s+t.PACKED_OP_DETUNE_FINE]=o|h<<3}static _packPitchEG(e,i){i[t.PACKED_PITCH_EG_RATE_1]=e[t.UNPACKED_PITCH_EG_RATE_1],i[t.PACKED_PITCH_EG_RATE_2]=e[t.UNPACKED_PITCH_EG_RATE_2],i[t.PACKED_PITCH_EG_RATE_3]=e[t.UNPACKED_PITCH_EG_RATE_3],i[t.PACKED_PITCH_EG_RATE_4]=e[t.UNPACKED_PITCH_EG_RATE_4],i[t.PACKED_PITCH_EG_LEVEL_1]=e[t.UNPACKED_PITCH_EG_LEVEL_1],i[t.PACKED_PITCH_EG_LEVEL_2]=e[t.UNPACKED_PITCH_EG_LEVEL_2],i[t.PACKED_PITCH_EG_LEVEL_3]=e[t.UNPACKED_PITCH_EG_LEVEL_3],i[t.PACKED_PITCH_EG_LEVEL_4]=e[t.UNPACKED_PITCH_EG_LEVEL_4]}static _packGlobalParams(e,i){i[t.OFFSET_ALGORITHM]=e[t.UNPACKED_ALGORITHM];const n=e[t.UNPACKED_FEEDBACK]&t.MASK_3BIT,s=e[t.UNPACKED_OSC_SYNC]&t.MASK_1BIT;i[t.OFFSET_FEEDBACK]=n|s<<3,i[t.OFFSET_LFO_SPEED]=e[t.UNPACKED_LFO_SPEED],i[t.OFFSET_LFO_DELAY]=e[t.UNPACKED_LFO_DELAY],i[t.OFFSET_LFO_PM_DEPTH]=e[t.UNPACKED_LFO_PM_DEPTH],i[t.OFFSET_LFO_AM_DEPTH]=e[t.UNPACKED_LFO_AM_DEPTH];const r=e[t.UNPACKED_LFO_KEY_SYNC]&t.MASK_1BIT,E=e[t.UNPACKED_LFO_WAVE]&t.MASK_3BIT,o=e[t.UNPACKED_LFO_PM_SENS]&t.MASK_3BIT;i[t.OFFSET_LFO_SYNC_WAVE]=r|E<<1|o<<4,i[t.OFFSET_AMP_MOD_SENS]=e[t.UNPACKED_AMP_MOD_SENS],i[t.OFFSET_TRANSPOSE]=e[t.UNPACKED_TRANSPOSE],i[t.OFFSET_EG_BIAS_SENS]=e[t.UNPACKED_EG_BIAS_SENS]}static _packName(e,i){for(let n=0;n<t.NAME_LENGTH;n++)i[t.PACKED_NAME_START+n]=e[t.UNPACKED_NAME_START+n]}static createDefault(e=0){const i=new Uint8Array(t.UNPACKED_SIZE);for(let r=0;r<t.NUM_OPERATORS;r++){const E=r*t.UNPACKED_OP_SIZE;i[E+t.UNPACKED_OP_EG_RATE_1]=t.DEFAULT_EG_RATE,i[E+t.UNPACKED_OP_EG_RATE_2]=t.DEFAULT_EG_RATE,i[E+t.UNPACKED_OP_EG_RATE_3]=t.DEFAULT_EG_RATE,i[E+t.UNPACKED_OP_EG_RATE_4]=t.DEFAULT_EG_RATE,i[E+t.UNPACKED_OP_EG_LEVEL_1]=t.DEFAULT_EG_LEVEL_MAX,i[E+t.UNPACKED_OP_EG_LEVEL_2]=t.DEFAULT_EG_LEVEL_MAX,i[E+t.UNPACKED_OP_EG_LEVEL_3]=t.DEFAULT_EG_LEVEL_MAX,i[E+t.UNPACKED_OP_EG_LEVEL_4]=t.DEFAULT_EG_LEVEL_MIN,i[E+t.UNPACKED_OP_BREAK_POINT]=t.DEFAULT_BREAK_POINT,i[E+t.UNPACKED_OP_L_SCALE_DEPTH]=0,i[E+t.UNPACKED_OP_R_SCALE_DEPTH]=0,i[E+t.UNPACKED_OP_L_CURVE]=0,i[E+t.UNPACKED_OP_R_CURVE]=0,i[E+t.UNPACKED_OP_RATE_SCALING]=0,i[E+t.UNPACKED_OP_DETUNE]=t.DEFAULT_DETUNE,i[E+t.UNPACKED_OP_AMP_MOD_SENS]=0,i[E+t.UNPACKED_OP_KEY_VEL_SENS]=0,i[E+t.UNPACKED_OP_OUTPUT_LEVEL]=t.DEFAULT_OUTPUT_LEVEL,i[E+t.UNPACKED_OP_MODE]=0,i[E+t.UNPACKED_OP_FREQ_COARSE]=t.DEFAULT_FREQ_COARSE,i[E+t.UNPACKED_OP_OSC_DETUNE]=0,i[E+t.UNPACKED_OP_FREQ_FINE]=0}i[t.UNPACKED_PITCH_EG_RATE_1]=t.DEFAULT_EG_RATE,i[t.UNPACKED_PITCH_EG_RATE_2]=t.DEFAULT_EG_RATE,i[t.UNPACKED_PITCH_EG_RATE_3]=t.DEFAULT_EG_RATE,i[t.UNPACKED_PITCH_EG_RATE_4]=t.DEFAULT_EG_RATE,i[t.UNPACKED_PITCH_EG_LEVEL_1]=t.DEFAULT_PITCH_EG_LEVEL,i[t.UNPACKED_PITCH_EG_LEVEL_2]=t.DEFAULT_PITCH_EG_LEVEL,i[t.UNPACKED_PITCH_EG_LEVEL_3]=t.DEFAULT_PITCH_EG_LEVEL,i[t.UNPACKED_PITCH_EG_LEVEL_4]=t.DEFAULT_PITCH_EG_LEVEL,i[t.UNPACKED_ALGORITHM]=t.DEFAULT_ALGORITHM,i[t.UNPACKED_FEEDBACK]=t.DEFAULT_FEEDBACK,i[t.UNPACKED_OSC_SYNC]=t.DEFAULT_OSC_SYNC,i[t.UNPACKED_LFO_SPEED]=t.DEFAULT_LFO_SPEED,i[t.UNPACKED_LFO_DELAY]=0,i[t.UNPACKED_LFO_PM_DEPTH]=0,i[t.UNPACKED_LFO_AM_DEPTH]=0,i[t.UNPACKED_LFO_KEY_SYNC]=t.DEFAULT_LFO_KEY_SYNC,i[t.UNPACKED_LFO_WAVE]=0,i[t.UNPACKED_LFO_PM_SENS]=t.DEFAULT_LFO_PM_SENS,i[t.UNPACKED_AMP_MOD_SENS]=0,i[t.UNPACKED_TRANSPOSE]=t.TRANSPOSE_CENTER,i[t.UNPACKED_EG_BIAS_SENS]=0;const n="Init Voice";for(let r=0;r<t.NAME_LENGTH;r++)i[t.UNPACKED_NAME_START+r]=r<n.length?n.charCodeAt(r):t.CHAR_SPACE;const s=t.pack(i);return new t(s,e)}static fromUnpacked(e,i=0){const n=t.pack(e);return new t(n,i)}static async fromFile(e){return new Promise((i,n)=>{const s=new FileReader;s.onload=r=>{try{const E=new Uint8Array(r.target.result);if(E[0]!==t.VCED_SYSEX_START||E[1]!==t.VCED_YAMAHA_ID||E[2]!==t.VCED_SUB_STATUS||E[3]!==t.VCED_FORMAT_SINGLE||E[4]!==t.VCED_BYTE_COUNT_MSB||E[5]!==t.VCED_BYTE_COUNT_LSB)throw new g("Invalid VCED header","header",0);const o=E.subarray(t.VCED_HEADER_SIZE,t.VCED_HEADER_SIZE+t.VCED_DATA_SIZE),h=E[t.VCED_HEADER_SIZE+t.VCED_DATA_SIZE],N=G._calculateChecksum(o,t.VCED_DATA_SIZE);h!==N&&console.warn(`DX7 VCED checksum mismatch (expected ${N.toString(16)}, got ${h.toString(16)}). This is common with vintage SysEx files.`);const u=new Uint8Array(t.UNPACKED_SIZE);let a=0;for(let S=0;S<t.NUM_OPERATORS;S++){const D=(t.NUM_OPERATORS-1-S)*t.UNPACKED_OP_SIZE;u[D+t.UNPACKED_OP_EG_RATE_1]=o[a++],u[D+t.UNPACKED_OP_EG_RATE_2]=o[a++],u[D+t.UNPACKED_OP_EG_RATE_3]=o[a++],u[D+t.UNPACKED_OP_EG_RATE_4]=o[a++],u[D+t.UNPACKED_OP_EG_LEVEL_1]=o[a++],u[D+t.UNPACKED_OP_EG_LEVEL_2]=o[a++],u[D+t.UNPACKED_OP_EG_LEVEL_3]=o[a++],u[D+t.UNPACKED_OP_EG_LEVEL_4]=o[a++],u[D+t.UNPACKED_OP_BREAK_POINT]=o[a++],u[D+t.UNPACKED_OP_L_SCALE_DEPTH]=o[a++],u[D+t.UNPACKED_OP_R_SCALE_DEPTH]=o[a++],u[D+t.UNPACKED_OP_L_CURVE]=o[a++],u[D+t.UNPACKED_OP_R_CURVE]=o[a++],u[D+t.UNPACKED_OP_RATE_SCALING]=o[a++],u[D+t.UNPACKED_OP_DETUNE]=o[a++];const T=o[a++];u[D+t.UNPACKED_OP_AMP_MOD_SENS]=T&t.MASK_2BIT,u[D+t.UNPACKED_OP_KEY_VEL_SENS]=T>>2&t.MASK_3BIT,u[D+t.UNPACKED_OP_OUTPUT_LEVEL]=o[a++],u[D+t.UNPACKED_OP_MODE]=o[a++],u[D+t.UNPACKED_OP_FREQ_COARSE]=o[a++],u[D+t.UNPACKED_OP_FREQ_FINE]=o[a++],u[D+t.UNPACKED_OP_OSC_DETUNE]=o[a++]}u[t.UNPACKED_PITCH_EG_RATE_1]=o[a++],u[t.UNPACKED_PITCH_EG_RATE_2]=o[a++],u[t.UNPACKED_PITCH_EG_RATE_3]=o[a++],u[t.UNPACKED_PITCH_EG_RATE_4]=o[a++],u[t.UNPACKED_PITCH_EG_LEVEL_1]=o[a++],u[t.UNPACKED_PITCH_EG_LEVEL_2]=o[a++],u[t.UNPACKED_PITCH_EG_LEVEL_3]=o[a++],u[t.UNPACKED_PITCH_EG_LEVEL_4]=o[a++],u[t.UNPACKED_ALGORITHM]=o[a++],u[t.UNPACKED_FEEDBACK]=o[a++],u[t.UNPACKED_OSC_SYNC]=o[a++],u[t.UNPACKED_LFO_SPEED]=o[a++],u[t.UNPACKED_LFO_DELAY]=o[a++],u[t.UNPACKED_LFO_PM_DEPTH]=o[a++],u[t.UNPACKED_LFO_AM_DEPTH]=o[a++],u[t.UNPACKED_LFO_KEY_SYNC]=o[a++],u[t.UNPACKED_LFO_WAVE]=o[a++],u[t.UNPACKED_LFO_PM_SENS]=o[a++],u[t.UNPACKED_TRANSPOSE]=o[a++];for(let S=0;S<t.NAME_LENGTH;S++)u[t.UNPACKED_NAME_START+S]=o[a++];const C=t.pack(u);i(new t(C,0))}catch(E){n(E)}},s.onerror=()=>n(new Error("Failed to read file")),s.readAsArrayBuffer(e)})}static fromSysEx(e,i=0){const n=e instanceof Uint8Array?e:new Uint8Array(e);let s;if(n[0]===t.VCED_SYSEX_START){if(n[0]!==t.VCED_SYSEX_START||n[1]!==t.VCED_YAMAHA_ID||n[2]!==t.VCED_SUB_STATUS||n[3]!==t.VCED_FORMAT_SINGLE||n[4]!==t.VCED_BYTE_COUNT_MSB||n[5]!==t.VCED_BYTE_COUNT_LSB)throw new g("Invalid VCED header","header",0);s=n.subarray(t.VCED_HEADER_SIZE,t.VCED_HEADER_SIZE+t.VCED_DATA_SIZE)}else if(n.length===t.PACKED_SIZE)s=n;else throw new d(`Invalid data length: expected ${t.PACKED_SIZE} or ${t.VCED_SIZE} bytes, got ${n.length}`,"length",n.length);if(s.length!==t.VCED_DATA_SIZE&&s.length!==t.PACKED_SIZE)throw new d(`Invalid voice data length: expected ${t.VCED_DATA_SIZE} or ${t.PACKED_SIZE} bytes, got ${s.length}`,"length",s.length);if(s.length===t.VCED_DATA_SIZE){const r=new Uint8Array(t.UNPACKED_SIZE);let E=0;for(let h=0;h<t.NUM_OPERATORS;h++){const N=(t.NUM_OPERATORS-1-h)*t.UNPACKED_OP_SIZE;r[N+t.UNPACKED_OP_EG_RATE_1]=s[E++],r[N+t.UNPACKED_OP_EG_RATE_2]=s[E++],r[N+t.UNPACKED_OP_EG_RATE_3]=s[E++],r[N+t.UNPACKED_OP_EG_RATE_4]=s[E++],r[N+t.UNPACKED_OP_EG_LEVEL_1]=s[E++],r[N+t.UNPACKED_OP_EG_LEVEL_2]=s[E++],r[N+t.UNPACKED_OP_EG_LEVEL_3]=s[E++],r[N+t.UNPACKED_OP_EG_LEVEL_4]=s[E++],r[N+t.UNPACKED_OP_BREAK_POINT]=s[E++],r[N+t.UNPACKED_OP_L_SCALE_DEPTH]=s[E++],r[N+t.UNPACKED_OP_R_SCALE_DEPTH]=s[E++],r[N+t.UNPACKED_OP_L_CURVE]=s[E++],r[N+t.UNPACKED_OP_R_CURVE]=s[E++],r[N+t.UNPACKED_OP_RATE_SCALING]=s[E++],r[N+t.UNPACKED_OP_DETUNE]=s[E++];const u=s[E++];r[N+t.UNPACKED_OP_AMP_MOD_SENS]=u&t.MASK_2BIT,r[N+t.UNPACKED_OP_KEY_VEL_SENS]=u>>2&t.MASK_3BIT,r[N+t.UNPACKED_OP_OUTPUT_LEVEL]=s[E++],r[N+t.UNPACKED_OP_MODE]=s[E++],r[N+t.UNPACKED_OP_FREQ_COARSE]=s[E++],r[N+t.UNPACKED_OP_FREQ_FINE]=s[E++],r[N+t.UNPACKED_OP_OSC_DETUNE]=s[E++]}r[t.UNPACKED_PITCH_EG_RATE_1]=s[E++],r[t.UNPACKED_PITCH_EG_RATE_2]=s[E++],r[t.UNPACKED_PITCH_EG_RATE_3]=s[E++],r[t.UNPACKED_PITCH_EG_RATE_4]=s[E++],r[t.UNPACKED_PITCH_EG_LEVEL_1]=s[E++],r[t.UNPACKED_PITCH_EG_LEVEL_2]=s[E++],r[t.UNPACKED_PITCH_EG_LEVEL_3]=s[E++],r[t.UNPACKED_PITCH_EG_LEVEL_4]=s[E++],r[t.UNPACKED_ALGORITHM]=s[E++],r[t.UNPACKED_FEEDBACK]=s[E++],r[t.UNPACKED_OSC_SYNC]=s[E++],r[t.UNPACKED_LFO_SPEED]=s[E++],r[t.UNPACKED_LFO_DELAY]=s[E++],r[t.UNPACKED_LFO_PM_DEPTH]=s[E++],r[t.UNPACKED_LFO_AM_DEPTH]=s[E++],r[t.UNPACKED_LFO_KEY_SYNC]=s[E++],r[t.UNPACKED_LFO_WAVE]=s[E++],r[t.UNPACKED_LFO_PM_SENS]=s[E++],r[t.UNPACKED_TRANSPOSE]=s[E++];for(let h=0;h<t.NAME_LENGTH;h++)r[t.UNPACKED_NAME_START+h]=s[E++];const o=t.pack(r);return new t(o,i)}return new t(s,i)}static fromJSON(e,i=0){if(!e||typeof e!="object")throw new d("Invalid JSON: expected object","json",e);const n=new Uint8Array(t.UNPACKED_SIZE),s=(a,C,S,D=0,T=127)=>{if(C==null)throw new d(`Missing required parameter: ${S}`,S,C);const f=Number(C);if(Number.isNaN(f))throw new d(`Invalid parameter value for ${S}: ${C}`,S,C);if(f<D||f>T)throw new d(`Parameter ${S} out of range: ${f} (must be ${D}-${T})`,S,f);n[a]=Math.floor(f)},r=a=>{const C={"-LN":0,"-EX":1,"+EX":2,"+LN":3};return C[a]!==void 0?C[a]:0},E=a=>{const C={TRIANGLE:0,"SAW DOWN":1,"SAW UP":2,SQUARE:3,SINE:4,"SAMPLE & HOLD":5};return C[a]!==void 0?C[a]:0},o=a=>{if(!a||typeof a!="string")return 60;const C=a.trim().match(/^([A-G]#?)(-?\d+)$/);if(!C)return 60;const[,S,D]=C,T=parseInt(D,10),U={C:0,"C#":1,D:2,"D#":3,E:4,F:5,"F#":6,G:7,"G#":8,A:9,"A#":10,B:11}[S.toUpperCase()];return U===void 0?60:(T-t.MIDI_OCTAVE_OFFSET)*12+U};if(!Array.isArray(e.operators))throw new d("Invalid operators array: expected array","operators",e.operators);for(let a=0;a<e.operators.length;a++){const C=e.operators[a];if(!C||typeof C!="object")throw new d(`Invalid operator data at index ${a}`,`operators[${a}]`,C);if(!C.eg||!Array.isArray(C.eg.rates)||C.eg.rates.length!==4)throw new d(`Invalid EG rates for operator ${a}`,`operators[${a}].eg.rates`,C.eg?.rates);if(!C.eg||!Array.isArray(C.eg.levels)||C.eg.levels.length!==4)throw new d(`Invalid EG levels for operator ${a}`,`operators[${a}].eg.levels`,C.eg?.levels)}if(e.operators.length!==t.NUM_OPERATORS)throw new d(`Invalid operators array: expected ${t.NUM_OPERATORS} operators`,"operators",e.operators);for(let a=0;a<t.NUM_OPERATORS;a++){const C=e.operators[a],S=a*t.UNPACKED_OP_SIZE;if(!C.eg||!Array.isArray(C.eg.rates)||C.eg.rates.length!==4)throw new d(`Invalid EG rates for operator ${a}`,`operators[${a}].eg.rates`,C.eg?.rates);if(s(S+t.UNPACKED_OP_EG_RATE_1,C.eg.rates[0],`operators[${a}].eg.rates[0]`,0,99),s(S+t.UNPACKED_OP_EG_RATE_2,C.eg.rates[1],`operators[${a}].eg.rates[1]`,0,99),s(S+t.UNPACKED_OP_EG_RATE_3,C.eg.rates[2],`operators[${a}].eg.rates[2]`,0,99),s(S+t.UNPACKED_OP_EG_RATE_4,C.eg.rates[3],`operators[${a}].eg.rates[3]`,0,99),!C.eg||!Array.isArray(C.eg.levels)||C.eg.levels.length!==4)throw new d(`Invalid EG levels for operator ${a}`,`operators[${a}].eg.levels`,C.eg?.levels);s(S+t.UNPACKED_OP_EG_LEVEL_1,C.eg.levels[0],`operators[${a}].eg.levels[0]`,0,99),s(S+t.UNPACKED_OP_EG_LEVEL_2,C.eg.levels[1],`operators[${a}].eg.levels[1]`,0,99),s(S+t.UNPACKED_OP_EG_LEVEL_3,C.eg.levels[2],`operators[${a}].eg.levels[2]`,0,99),s(S+t.UNPACKED_OP_EG_LEVEL_4,C.eg.levels[3],`operators[${a}].eg.levels[3]`,0,99);const D=o(C.key?.breakPoint)-t.MIDI_BREAK_POINT_OFFSET;s(S+t.UNPACKED_OP_BREAK_POINT,D,`operators[${a}].key.breakPoint`,0,127),s(S+t.UNPACKED_OP_L_SCALE_DEPTH,C.scale?.left?.depth||0,`operators[${a}].scale.left.depth`,0,99),s(S+t.UNPACKED_OP_R_SCALE_DEPTH,C.scale?.right?.depth||0,`operators[${a}].scale.right.depth`,0,99),n[S+t.UNPACKED_OP_L_CURVE]=r(C.scale?.left?.curve||"-LN"),n[S+t.UNPACKED_OP_R_CURVE]=r(C.scale?.right?.curve||"-LN"),s(S+t.UNPACKED_OP_RATE_SCALING,C.key?.scaling||0,`operators[${a}].key.scaling`,0,7);const T=Number(C.osc?.detune)||0;s(S+t.UNPACKED_OP_DETUNE,T+7,`operators[${a}].osc.detune`,0,14),s(S+t.UNPACKED_OP_AMP_MOD_SENS,C.output?.ampModSens||0,`operators[${a}].output.ampModSens`,0,3),s(S+t.UNPACKED_OP_OUTPUT_LEVEL,C.output?.level||0,`operators[${a}].output.level`,0,99);const f=C.osc?.freq?.mode?.toUpperCase()==="FIXED"?1:0,U=Number(C.osc?.freq?.coarse)||0,L=Number(C.osc?.freq?.fine)||0;n[S+t.UNPACKED_OP_MODE]=f,s(S+t.UNPACKED_OP_FREQ_COARSE,U,`operators[${a}].osc.freq.coarse`,0,31),s(S+t.UNPACKED_OP_FREQ_FINE,L,`operators[${a}].osc.freq.fine`,0,15),s(S+t.UNPACKED_OP_KEY_VEL_SENS,C.key?.velocity||0,`operators[${a}].key.velocity`,0,7)}if(!e.pitchEG||!Array.isArray(e.pitchEG.rates)||e.pitchEG.rates.length!==4)throw new d("Invalid pitch EG rates","pitchEG.rates",e.pitchEG?.rates);if(!e.pitchEG||!Array.isArray(e.pitchEG.levels)||e.pitchEG.levels.length!==4)throw new d("Invalid pitch EG levels","pitchEG.levels",e.pitchEG?.levels);if(s(t.UNPACKED_PITCH_EG_RATE_1,e.pitchEG.rates[0],"pitchEG.rates[0]",0,99),s(t.UNPACKED_PITCH_EG_RATE_2,e.pitchEG.rates[1],"pitchEG.rates[1]",0,99),s(t.UNPACKED_PITCH_EG_RATE_3,e.pitchEG.rates[2],"pitchEG.rates[2]",0,99),s(t.UNPACKED_PITCH_EG_RATE_4,e.pitchEG.rates[3],"pitchEG.rates[3]",0,99),s(t.UNPACKED_PITCH_EG_LEVEL_1,e.pitchEG.levels[0],"pitchEG.levels[0]",0,99),s(t.UNPACKED_PITCH_EG_LEVEL_2,e.pitchEG.levels[1],"pitchEG.levels[1]",0,99),s(t.UNPACKED_PITCH_EG_LEVEL_3,e.pitchEG.levels[2],"pitchEG.levels[2]",0,99),s(t.UNPACKED_PITCH_EG_LEVEL_4,e.pitchEG.levels[3],"pitchEG.levels[3]",0,99),!e.lfo||typeof e.lfo!="object")throw new d("Invalid LFO data","lfo",e.lfo);if(s(t.UNPACKED_LFO_SPEED,e.lfo.speed,"lfo.speed",0,99),s(t.UNPACKED_LFO_DELAY,e.lfo.delay,"lfo.delay",0,99),s(t.UNPACKED_LFO_PM_DEPTH,e.lfo.pmDepth,"lfo.pmDepth",0,99),s(t.UNPACKED_LFO_AM_DEPTH,e.lfo.amDepth,"lfo.amDepth",0,99),n[t.UNPACKED_LFO_KEY_SYNC]=e.lfo.keySync?1:0,n[t.UNPACKED_LFO_WAVE]=E(e.lfo.wave),!e.global||typeof e.global!="object")throw new d("Invalid global data","global",e.global);const h=Number(e.global.algorithm)||1;s(t.UNPACKED_ALGORITHM,h-1,"global.algorithm",0,31),s(t.UNPACKED_FEEDBACK,e.global.feedback,"global.feedback",0,7),n[t.UNPACKED_OSC_SYNC]=e.global.oscKeySync?1:0,s(t.UNPACKED_LFO_PM_SENS,e.global.pitchModSens,"global.pitchModSens",0,7);const N=Number(e.global.transpose)||0;s(t.UNPACKED_TRANSPOSE,N+t.TRANSPOSE_CENTER,"global.transpose",0,127),s(t.UNPACKED_AMP_MOD_SENS,e.global.ampModSens||0,"global.ampModSens",0,3),s(t.UNPACKED_EG_BIAS_SENS,e.global.egBiasSens||0,"global.egBiasSens",0,7);const u=e.name||"";for(let a=0;a<t.NAME_LENGTH;a++)n[t.UNPACKED_NAME_START+a]=a<u.length?u.charCodeAt(a):t.CHAR_SPACE;return t.fromUnpacked(n,i)}toSysEx(){const e=this.unpack(),i=new Uint8Array(t.VCED_SIZE);let n=0;i[n++]=t.VCED_SYSEX_START,i[n++]=t.VCED_YAMAHA_ID,i[n++]=t.VCED_SUB_STATUS,i[n++]=t.VCED_FORMAT_SINGLE,i[n++]=t.VCED_BYTE_COUNT_MSB,i[n++]=t.VCED_BYTE_COUNT_LSB;for(let r=t.NUM_OPERATORS-1;r>=0;r--){const E=r*t.UNPACKED_OP_SIZE;i[n++]=e[E+t.UNPACKED_OP_EG_RATE_1],i[n++]=e[E+t.UNPACKED_OP_EG_RATE_2],i[n++]=e[E+t.UNPACKED_OP_EG_RATE_3],i[n++]=e[E+t.UNPACKED_OP_EG_RATE_4],i[n++]=e[E+t.UNPACKED_OP_EG_LEVEL_1],i[n++]=e[E+t.UNPACKED_OP_EG_LEVEL_2],i[n++]=e[E+t.UNPACKED_OP_EG_LEVEL_3],i[n++]=e[E+t.UNPACKED_OP_EG_LEVEL_4],i[n++]=e[E+t.UNPACKED_OP_BREAK_POINT],i[n++]=e[E+t.UNPACKED_OP_L_SCALE_DEPTH],i[n++]=e[E+t.UNPACKED_OP_R_SCALE_DEPTH],i[n++]=e[E+t.UNPACKED_OP_L_CURVE],i[n++]=e[E+t.UNPACKED_OP_R_CURVE],i[n++]=e[E+t.UNPACKED_OP_RATE_SCALING],i[n++]=e[E+t.UNPACKED_OP_DETUNE];const o=e[E+t.UNPACKED_OP_AMP_MOD_SENS]&t.MASK_2BIT,h=e[E+t.UNPACKED_OP_KEY_VEL_SENS]&t.MASK_3BIT;i[n++]=o|h<<2,i[n++]=e[E+t.UNPACKED_OP_OUTPUT_LEVEL],i[n++]=e[E+t.UNPACKED_OP_MODE],i[n++]=e[E+t.UNPACKED_OP_FREQ_COARSE],i[n++]=e[E+t.UNPACKED_OP_OSC_DETUNE],i[n++]=e[E+t.UNPACKED_OP_FREQ_FINE]}i[n++]=e[t.UNPACKED_PITCH_EG_RATE_1],i[n++]=e[t.UNPACKED_PITCH_EG_RATE_2],i[n++]=e[t.UNPACKED_PITCH_EG_RATE_3],i[n++]=e[t.UNPACKED_PITCH_EG_RATE_4],i[n++]=e[t.UNPACKED_PITCH_EG_LEVEL_1],i[n++]=e[t.UNPACKED_PITCH_EG_LEVEL_2],i[n++]=e[t.UNPACKED_PITCH_EG_LEVEL_3],i[n++]=e[t.UNPACKED_PITCH_EG_LEVEL_4],i[n++]=e[t.UNPACKED_ALGORITHM],i[n++]=e[t.UNPACKED_FEEDBACK],i[n++]=e[t.UNPACKED_OSC_SYNC],i[n++]=e[t.UNPACKED_LFO_SPEED],i[n++]=e[t.UNPACKED_LFO_DELAY],i[n++]=e[t.UNPACKED_LFO_PM_DEPTH],i[n++]=e[t.UNPACKED_LFO_AM_DEPTH],i[n++]=e[t.UNPACKED_LFO_KEY_SYNC],i[n++]=e[t.UNPACKED_LFO_WAVE],i[n++]=e[t.UNPACKED_LFO_PM_SENS],i[n++]=e[t.UNPACKED_TRANSPOSE];for(let r=0;r<t.NAME_LENGTH;r++)i[n++]=e[t.UNPACKED_NAME_START+r];const s=i.subarray(t.VCED_HEADER_SIZE,t.VCED_HEADER_SIZE+t.VCED_DATA_SIZE);return i[n++]=G._calculateChecksum(s,t.VCED_DATA_SIZE),i[n++]=t.VCED_SYSEX_END,i}toJSON(){const e=this.unpack(),i=[],n=E=>["-LN","-EX","+EX","+LN"][E]||"UNKNOWN",s=E=>["TRIANGLE","SAW DOWN","SAW UP","SQUARE","SINE","SAMPLE & HOLD"][E]||"UNKNOWN",r=E=>{const o=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],h=Math.floor(E/12)+t.MIDI_OCTAVE_OFFSET;return`${o[E%12]}${h}`};for(let E=0;E<t.NUM_OPERATORS;E++){const o=E*t.UNPACKED_OP_SIZE,h=e[o+t.UNPACKED_OP_MODE]===0?"RATIO":"FIXED";i.push({id:E+1,osc:{detune:e[o+t.UNPACKED_OP_OSC_DETUNE],freq:{coarse:e[o+t.UNPACKED_OP_FREQ_COARSE],fine:e[o+t.UNPACKED_OP_FREQ_FINE],mode:h}},eg:{rates:[e[o+t.UNPACKED_OP_EG_RATE_1],e[o+t.UNPACKED_OP_EG_RATE_2],e[o+t.UNPACKED_OP_EG_RATE_3],e[o+t.UNPACKED_OP_EG_RATE_4]],levels:[e[o+t.UNPACKED_OP_EG_LEVEL_1],e[o+t.UNPACKED_OP_EG_LEVEL_2],e[o+t.UNPACKED_OP_EG_LEVEL_3],e[o+t.UNPACKED_OP_EG_LEVEL_4]]},key:{velocity:e[o+t.UNPACKED_OP_KEY_VEL_SENS],scaling:e[o+t.UNPACKED_OP_RATE_SCALING],breakPoint:r(e[o+t.UNPACKED_OP_BREAK_POINT]+t.MIDI_BREAK_POINT_OFFSET)},output:{level:e[o+t.UNPACKED_OP_OUTPUT_LEVEL],ampModSens:e[o+t.UNPACKED_OP_AMP_MOD_SENS]},scale:{left:{depth:e[o+t.UNPACKED_OP_L_SCALE_DEPTH],curve:n(e[o+t.UNPACKED_OP_L_CURVE])},right:{depth:e[o+t.UNPACKED_OP_R_SCALE_DEPTH],curve:n(e[o+t.UNPACKED_OP_R_CURVE])}}})}return{name:this.name||"(Empty)",operators:i,pitchEG:{rates:[e[t.UNPACKED_PITCH_EG_RATE_1],e[t.UNPACKED_PITCH_EG_RATE_2],e[t.UNPACKED_PITCH_EG_RATE_3],e[t.UNPACKED_PITCH_EG_RATE_4]],levels:[e[t.UNPACKED_PITCH_EG_LEVEL_1],e[t.UNPACKED_PITCH_EG_LEVEL_2],e[t.UNPACKED_PITCH_EG_LEVEL_3],e[t.UNPACKED_PITCH_EG_LEVEL_4]]},lfo:{speed:e[t.UNPACKED_LFO_SPEED],delay:e[t.UNPACKED_LFO_DELAY],pmDepth:e[t.UNPACKED_LFO_PM_DEPTH],amDepth:e[t.UNPACKED_LFO_AM_DEPTH],keySync:e[t.UNPACKED_LFO_KEY_SYNC]===1,wave:s(e[t.UNPACKED_LFO_WAVE])},global:{algorithm:e[t.UNPACKED_ALGORITHM]+1,feedback:e[t.UNPACKED_FEEDBACK],oscKeySync:e[t.UNPACKED_OSC_SYNC]===1,pitchModSens:e[t.UNPACKED_LFO_PM_SENS],transpose:e[t.UNPACKED_TRANSPOSE]-t.TRANSPOSE_CENTER}}}};_(t,"PACKED_SIZE",128),_(t,"PACKED_OP_SIZE",17),_(t,"NUM_OPERATORS",6),_(t,"PACKED_OP_EG_RATE_1",0),_(t,"PACKED_OP_EG_RATE_2",1),_(t,"PACKED_OP_EG_RATE_3",2),_(t,"PACKED_OP_EG_RATE_4",3),_(t,"PACKED_OP_EG_LEVEL_1",4),_(t,"PACKED_OP_EG_LEVEL_2",5),_(t,"PACKED_OP_EG_LEVEL_3",6),_(t,"PACKED_OP_EG_LEVEL_4",7),_(t,"PACKED_OP_BREAK_POINT",8),_(t,"PACKED_OP_L_SCALE_DEPTH",9),_(t,"PACKED_OP_R_SCALE_DEPTH",10),_(t,"PACKED_OP_CURVES",11),_(t,"PACKED_OP_RATE_SCALING",12),_(t,"PACKED_OP_MOD_SENS",13),_(t,"PACKED_OP_OUTPUT_LEVEL",14),_(t,"PACKED_OP_MODE_FREQ",15),_(t,"PACKED_OP_DETUNE_FINE",16),_(t,"PACKED_PITCH_EG_RATE_1",102),_(t,"PACKED_PITCH_EG_RATE_2",103),_(t,"PACKED_PITCH_EG_RATE_3",104),_(t,"PACKED_PITCH_EG_RATE_4",105),_(t,"PACKED_PITCH_EG_LEVEL_1",106),_(t,"PACKED_PITCH_EG_LEVEL_2",107),_(t,"PACKED_PITCH_EG_LEVEL_3",108),_(t,"PACKED_PITCH_EG_LEVEL_4",109),_(t,"OFFSET_ALGORITHM",110),_(t,"OFFSET_FEEDBACK",111),_(t,"OFFSET_LFO_SPEED",112),_(t,"OFFSET_LFO_DELAY",113),_(t,"OFFSET_LFO_PM_DEPTH",114),_(t,"OFFSET_LFO_AM_DEPTH",115),_(t,"OFFSET_LFO_SYNC_WAVE",116),_(t,"OFFSET_TRANSPOSE",117),_(t,"OFFSET_AMP_MOD_SENS",118),_(t,"OFFSET_EG_BIAS_SENS",119),_(t,"PACKED_NAME_START",118),_(t,"NAME_LENGTH",10),_(t,"UNPACKED_SIZE",169),_(t,"UNPACKED_OP_SIZE",23),_(t,"UNPACKED_OP_EG_RATE_1",0),_(t,"UNPACKED_OP_EG_RATE_2",1),_(t,"UNPACKED_OP_EG_RATE_3",2),_(t,"UNPACKED_OP_EG_RATE_4",3),_(t,"UNPACKED_OP_EG_LEVEL_1",4),_(t,"UNPACKED_OP_EG_LEVEL_2",5),_(t,"UNPACKED_OP_EG_LEVEL_3",6),_(t,"UNPACKED_OP_EG_LEVEL_4",7),_(t,"UNPACKED_OP_BREAK_POINT",8),_(t,"UNPACKED_OP_L_SCALE_DEPTH",9),_(t,"UNPACKED_OP_R_SCALE_DEPTH",10),_(t,"UNPACKED_OP_L_CURVE",11),_(t,"UNPACKED_OP_R_CURVE",12),_(t,"UNPACKED_OP_RATE_SCALING",13),_(t,"UNPACKED_OP_DETUNE",14),_(t,"UNPACKED_OP_AMP_MOD_SENS",15),_(t,"UNPACKED_OP_OUTPUT_LEVEL",16),_(t,"UNPACKED_OP_MODE",17),_(t,"UNPACKED_OP_KEY_VEL_SENS",18),_(t,"UNPACKED_OP_FREQ_COARSE",19),_(t,"UNPACKED_OP_OSC_DETUNE",20),_(t,"UNPACKED_OP_FREQ_FINE",21),_(t,"UNPACKED_PITCH_EG_RATE_1",138),_(t,"UNPACKED_PITCH_EG_RATE_2",139),_(t,"UNPACKED_PITCH_EG_RATE_3",140),_(t,"UNPACKED_PITCH_EG_RATE_4",141),_(t,"UNPACKED_PITCH_EG_LEVEL_1",142),_(t,"UNPACKED_PITCH_EG_LEVEL_2",143),_(t,"UNPACKED_PITCH_EG_LEVEL_3",144),_(t,"UNPACKED_PITCH_EG_LEVEL_4",145),_(t,"UNPACKED_ALGORITHM",146),_(t,"UNPACKED_FEEDBACK",147),_(t,"UNPACKED_OSC_SYNC",148),_(t,"UNPACKED_LFO_SPEED",149),_(t,"UNPACKED_LFO_DELAY",150),_(t,"UNPACKED_LFO_PM_DEPTH",151),_(t,"UNPACKED_LFO_AM_DEPTH",152),_(t,"UNPACKED_LFO_KEY_SYNC",153),_(t,"UNPACKED_LFO_WAVE",154),_(t,"UNPACKED_LFO_PM_SENS",155),_(t,"UNPACKED_AMP_MOD_SENS",156),_(t,"UNPACKED_TRANSPOSE",157),_(t,"UNPACKED_EG_BIAS_SENS",158),_(t,"UNPACKED_NAME_START",159),_(t,"VCED_SIZE",163),_(t,"VCED_HEADER_SIZE",6),_(t,"VCED_DATA_SIZE",155),_(t,"VCED_SYSEX_START",240),_(t,"VCED_YAMAHA_ID",67),_(t,"VCED_SUB_STATUS",0),_(t,"VCED_FORMAT_SINGLE",0),_(t,"VCED_BYTE_COUNT_MSB",1),_(t,"VCED_BYTE_COUNT_LSB",27),_(t,"VCED_SYSEX_END",247),_(t,"MASK_7BIT",127),_(t,"MASK_2BIT",3),_(t,"MASK_3BIT",7),_(t,"MASK_4BIT",15),_(t,"MASK_5BIT",31),_(t,"MASK_1BIT",1),_(t,"TRANSPOSE_CENTER",24),_(t,"CHAR_YEN",92),_(t,"CHAR_ARROW_RIGHT",126),_(t,"CHAR_ARROW_LEFT",127),_(t,"CHAR_REPLACEMENT_Y",89),_(t,"CHAR_REPLACEMENT_GT",62),_(t,"CHAR_REPLACEMENT_LT",60),_(t,"CHAR_SPACE",32),_(t,"CHAR_MIN_PRINTABLE",32),_(t,"CHAR_MAX_PRINTABLE",126),_(t,"DEFAULT_EG_RATE",99),_(t,"DEFAULT_EG_LEVEL_MAX",99),_(t,"DEFAULT_EG_LEVEL_MIN",0),_(t,"DEFAULT_BREAK_POINT",0),_(t,"DEFAULT_OUTPUT_LEVEL",99),_(t,"DEFAULT_PITCH_EG_LEVEL",50),_(t,"DEFAULT_LFO_SPEED",35),_(t,"DEFAULT_LFO_PM_SENS",3),_(t,"DEFAULT_DETUNE",7),_(t,"DEFAULT_FREQ_COARSE",1),_(t,"DEFAULT_ALGORITHM",0),_(t,"DEFAULT_FEEDBACK",0),_(t,"DEFAULT_OSC_SYNC",1),_(t,"DEFAULT_LFO_KEY_SYNC",1),_(t,"MIDI_OCTAVE_OFFSET",-2),_(t,"MIDI_BREAK_POINT_OFFSET",21);let m=t;const P=class P{constructor(e,i=""){if(this.voices=new Array(P.NUM_VOICES),this.name=i,e)this._load(e);else for(let n=0;n<P.NUM_VOICES;n++)this.voices[n]=m.createDefault(n)}static _calculateChecksum(e,i){let n=0;for(let s=0;s<i;s++)n+=e[s];return P.CHECKSUM_MODULO-n%P.CHECKSUM_MODULO&P.MASK_7BIT}_load(e){const i=e instanceof Uint8Array?e:new Uint8Array(e);let n,s=0;if(i[0]===P.SYSEX_START){const E=i.subarray(0,P.SYSEX_HEADER_SIZE),o=P.SYSEX_HEADER;for(let h=0;h<P.SYSEX_HEADER_SIZE;h++)if(E[h]!==o[h])throw new g(`Invalid SysEx header at position ${h}: expected ${o[h].toString(16)}, got ${E[h].toString(16)}`,"header",h);n=i.subarray(P.SYSEX_HEADER_SIZE,P.SYSEX_HEADER_SIZE+P.VOICE_DATA_SIZE),s=P.SYSEX_HEADER_SIZE}else if(i.length===P.VOICE_DATA_SIZE)n=i;else throw new d(`Invalid data length: expected ${P.VOICE_DATA_SIZE} or ${P.SYSEX_SIZE} bytes, got ${i.length}`,"length",i.length);if(n.length!==P.VOICE_DATA_SIZE)throw new d(`Invalid voice data length: expected ${P.VOICE_DATA_SIZE} bytes, got ${n.length}`,"length",n.length);const r=P.SYSEX_HEADER_SIZE+P.VOICE_DATA_SIZE;if(s>0&&i.length>=r+1){const E=i[r],o=P._calculateChecksum(n,P.VOICE_DATA_SIZE);E!==o&&console.warn(`DX7 checksum mismatch (expected ${o.toString(16)}, got ${E.toString(16)}). This is common with vintage SysEx files and the data is likely still valid.`)}this.voices=new Array(P.NUM_VOICES);for(let E=0;E<P.NUM_VOICES;E++){const o=E*P.VOICE_SIZE,h=n.subarray(o,o+P.VOICE_SIZE);this.voices[E]=new m(h,E)}}replaceVoice(e,i){if(e<0||e>=P.NUM_VOICES)throw new d(`Invalid voice index: ${e}`,"index",e);const n=new Uint8Array(i.data);this.voices[e]=new m(n,e)}addVoice(e){for(let i=0;i<this.voices.length;i++){const n=this.voices[i];if(n.name===""||n.name==="Init Voice")return this.replaceVoice(i,e),i}return-1}getVoices(){return this.voices}getVoice(e){return e<0||e>=this.voices.length?null:this.voices[e]}getVoiceNames(){return this.voices.map(e=>e.name)}findVoiceByName(e){const i=e.toLowerCase();return this.voices.find(n=>n.name.toLowerCase().includes(i))||null}static async fromFile(e){return new Promise((i,n)=>{const s=new FileReader;s.onload=async r=>{try{const E=e.name||"",o=new Uint8Array(r.target.result);if(o[0]===P.SYSEX_START&&o[3]===m.VCED_FORMAT_SINGLE)n(new g("This is a single voice file. Use DX7Voice.fromFile() instead.","format",3));else{const h=E.replace(/\.[^/.]+$/,""),N=new P(r.target.result,h);i(N)}}catch(E){n(E)}},s.onerror=()=>n(new Error("Failed to read file")),s.readAsArrayBuffer(e)})}static fromSysEx(e,i=""){return new P(e,i)}static fromJSON(e){if(!e||typeof e!="object")throw new d("Invalid JSON: expected object","json",e);const i=new P;if(i.name=e.name||"",!Array.isArray(e.voices))throw new d("Invalid voices array","voices",e.voices);e.voices.length!==P.NUM_VOICES&&console.warn(`Bank JSON has ${e.voices.length} voices, expected ${P.NUM_VOICES}. Missing voices will be filled with defaults.`);const n=Math.min(e.voices.length,P.NUM_VOICES);for(let s=0;s<n;s++){const r=e.voices[s];if(!r||typeof r!="object"){console.warn(`Invalid voice data at index ${s}, using default voice`);continue}try{const{index:E,...o}=r,h=m.fromJSON(o,s);i.replaceVoice(s,h)}catch(E){console.warn(`Failed to load voice at index ${s}: ${E.message}, using default voice`)}}return i}toSysEx(){const e=new Uint8Array(P.SYSEX_SIZE);let i=0;P.SYSEX_HEADER.forEach(s=>{e[i++]=s});for(const s of this.voices)for(let r=0;r<P.VOICE_SIZE;r++)e[i++]=s.data[r];const n=e.subarray(P.SYSEX_HEADER_SIZE,P.SYSEX_HEADER_SIZE+P.VOICE_DATA_SIZE);return e[i++]=P._calculateChecksum(n,P.VOICE_DATA_SIZE),e[i++]=P.SYSEX_END,e}toJSON(){const e=this.voices.map((i,n)=>{const s=i.toJSON();return{index:n+1,...s}});return{version:"1.0",name:this.name||"",voices:e}}};_(P,"SYSEX_START",240),_(P,"SYSEX_END",247),_(P,"SYSEX_YAMAHA_ID",67),_(P,"SYSEX_SUB_STATUS",0),_(P,"SYSEX_FORMAT_32_VOICES",9),_(P,"SYSEX_BYTE_COUNT_MSB",32),_(P,"SYSEX_BYTE_COUNT_LSB",0),_(P,"SYSEX_HEADER",[P.SYSEX_START,P.SYSEX_YAMAHA_ID,P.SYSEX_SUB_STATUS,P.SYSEX_FORMAT_32_VOICES,P.SYSEX_BYTE_COUNT_MSB,P.SYSEX_BYTE_COUNT_LSB]),_(P,"SYSEX_HEADER_SIZE",6),_(P,"VOICE_DATA_SIZE",4096),_(P,"SYSEX_SIZE",4104),_(P,"VOICE_SIZE",128),_(P,"NUM_VOICES",32),_(P,"CHECKSUM_MODULO",128),_(P,"MASK_7BIT",127);let G=P;function nt(c){return c[0]!==240||c[c.length-1]!==247?null:{manufacturerId:c[1],payload:c.slice(2,-1),raw:c}}function st(c,e){return[240,c,...e,247]}function Et(c){return c.length>=2&&c[0]===240&&c[c.length-1]===247}function rt(c){const e=[];for(let i=0;i<c.length;i+=7){const n=c.slice(i,i+7);let s=0;const r=[];for(let E=0;E<n.length;E++){const o=n[E];o&128&&(s|=1<<E),r.push(o&127)}e.push(s,...r)}return e}function ot(c){const e=[];for(let i=0;i<c.length;i+=8){const n=c[i],s=Math.min(7,c.length-i-1);for(let r=0;r<s;r++){let E=c[i+1+r];n&1<<r&&(E|=128),e.push(E)}}return e}function _t(c){return Number.isInteger(c)&&c>=1&&c<=16}function at(c){return Number.isInteger(c)&&c>=0&&c<=127}function ct(c){return Number.isInteger(c)&&c>=0&&c<=31}function Ct(c){return Number.isInteger(c)&&c>=0&&c<=127}function At(c){return Number.isInteger(c)&&c>=0&&c<=127}function Pt(c){return Number.isInteger(c)&&c>=0&&c<=127}function ut(c){return Number.isInteger(c)&&c>=0&&c<=127}function lt(c){return Number.isInteger(c)&&c>=0&&c<=16383}function ht(c,e){return Number.isInteger(c)&&c>=0&&c<=127&&Number.isInteger(e)&&e>=0&&e<=127}async function St(c={}){const{onStatusUpdate:e,onConnectionUpdate:i,inputChannel:n=1,outputChannel:s=1,output:r,sysex:E,onReady:o,onError:h,selector:N,watchDOM:u,...a}=c,S=await q({autoConnect:!1,sysex:E,inputChannel:n,outputChannel:s,selector:N||"[data-midi-cc]",watchDOM:u,onError:h,...a}),D=new z({midiController:S,onStatusUpdate:e||(()=>{}),onConnectionUpdate:i||(()=>{}),channel:s});if(r)try{await S.device.connectOutput(r),D.currentOutput=S.device.getCurrentOutput(),D.updateConnectionStatus()}catch(T){h?h(T):console.error("Failed to connect to MIDI device:",T.message)}return o&&o(S,D),D}async function q(c={}){const e=new Z(c);await e.init();const i=c.selector||"[data-midi-cc]";{const n=new I(e,i);n.bindAll(),c.watchDOM&&n.enableAutoBinding(),e._binder=n}return e}l.CONN=p,l.CONNECTION_EVENTS=p,l.CONTROLLER_EVENTS=A,l.CTRL=A,l.DX7Bank=G,l.DX7Error=H,l.DX7ParseError=g,l.DX7ValidationError=d,l.DX7Voice=m,l.DataAttributeBinder=I,l.EventEmitter=v,l.MIDIAccessError=F,l.MIDIConnection=$,l.MIDIConnectionError=y,l.MIDIController=Z,l.MIDIDeviceError=R,l.MIDIDeviceManager=z,l.MIDIError=K,l.MIDIValidationError=M,l.clamp=O,l.createMIDIController=q,l.createMIDIDeviceManager=St,l.createSysEx=st,l.decode14BitValue=Y,l.decode7Bit=ot,l.denormalize14BitValue=it,l.denormalizeValue=J,l.encode14BitValue=B,l.encode7Bit=rt,l.frequencyToNote=X,l.getCCName=et,l.isSysEx=Et,l.isValid14BitCC=ct,l.isValidCC=at,l.isValidChannel=_t,l.isValidMIDIValue=Ct,l.isValidNote=At,l.isValidPitchBend=lt,l.isValidPitchBendBytes=ht,l.isValidProgramChange=ut,l.isValidVelocity=Pt,l.normalize14BitValue=x,l.normalizeValue=w,l.noteNameToNumber=k,l.noteNumberToName=j,l.noteToFrequency=tt,l.parseSysEx=nt,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(l,I){typeof exports=="object"&&typeof module<"u"?I(exports):typeof define=="function"&&define.amd?define(["exports"],I):(l=typeof globalThis<"u"?globalThis:l||self,I(l.MIDIControls={}))})(this,(function(l){"use strict";var dt=Object.defineProperty;var Tt=(l,I,K)=>I in l?dt(l,I,{enumerable:!0,configurable:!0,writable:!0,value:K}):l[I]=K;var _=(l,I,K)=>Tt(l,typeof I!="symbol"?I+"":I,K);class I{constructor(e,i="[data-midi-cc]"){this.controller=e,this.selector=i,this.observer=null}bindAll(){document.querySelectorAll(this.selector==="[data-midi-cc]"?"[data-midi-cc], [data-midi-msb][data-midi-lsb]":this.selector).forEach(i=>{if(i.hasAttribute("data-midi-bound"))return;const n=this._parseAttributes(i);n&&(this.controller.bind(i,n),i.setAttribute("data-midi-bound","true"))})}enableAutoBinding(){if(this.observer)return;const e=this.selector==="[data-midi-cc]"?"[data-midi-cc], [data-midi-msb][data-midi-lsb]":this.selector;this.observer=new MutationObserver(i=>{i.forEach(n=>{n.addedNodes.forEach(s=>{if(s.nodeType===Node.ELEMENT_NODE){if(s.matches?.(e)){const r=this._parseAttributes(s);r&&!s.hasAttribute("data-midi-bound")&&(this.controller.bind(s,r),s.setAttribute("data-midi-bound","true"))}s.querySelectorAll&&s.querySelectorAll(e).forEach(E=>{if(!E.hasAttribute("data-midi-bound")){const o=this._parseAttributes(E);o&&(this.controller.bind(E,o),E.setAttribute("data-midi-bound","true"))}})}}),n.removedNodes.forEach(s=>{s.nodeType===Node.ELEMENT_NODE&&(s.hasAttribute?.("data-midi-bound")&&this.controller.unbind(s),s.querySelectorAll&&s.querySelectorAll("[data-midi-bound]").forEach(E=>{this.controller.unbind(E)}))})})}),this.observer.observe(document.body,{childList:!0,subtree:!0})}disableAutoBinding(){this.observer&&(this.observer.disconnect(),this.observer=null)}_parseAttributes(e){const i=parseInt(e.dataset.midiMsb,10),n=parseInt(e.dataset.midiLsb,10);if(!Number.isNaN(i)&&!Number.isNaN(n)&&i>=0&&i<=127&&n>=0&&n<=127){const r=parseInt(e.dataset.midiCc,10);return!Number.isNaN(r)&&r>=0&&r<=127&&console.warn(`Element has both 7-bit (data-midi-cc="${r}") and 14-bit (data-midi-msb="${i}" data-midi-lsb="${n}") CC attributes. 14-bit takes precedence.`,e),{msb:i,lsb:n,is14Bit:!0,channel:parseInt(e.dataset.midiChannel,10)||void 0,min:parseFloat(e.getAttribute("min"))||0,max:parseFloat(e.getAttribute("max"))||127,invert:e.dataset.midiInvert==="true",label:e.dataset.midiLabel}}const s=parseInt(e.dataset.midiCc,10);return!Number.isNaN(s)&&s>=0&&s<=127?{cc:s,channel:parseInt(e.dataset.midiChannel,10)||void 0,min:parseFloat(e.getAttribute("min"))||0,max:parseFloat(e.getAttribute("max"))||127,invert:e.dataset.midiInvert==="true",label:e.dataset.midiLabel}:((e.dataset.midiCc!==void 0||e.dataset.midiMsb!==void 0&&e.dataset.midiLsb!==void 0)&&console.warn("Invalid MIDI configuration on element:",e),null)}destroy(){this.disableAutoBinding()}}class K extends Error{constructor(e,i){super(e),this.name="MIDIError",this.code=i,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}}class F extends K{constructor(e,i){super(e,"MIDI_ACCESS_ERROR"),this.name="MIDIAccessError",this.reason=i}}class y extends K{constructor(e){super(e,"MIDI_CONNECTION_ERROR"),this.name="MIDIConnectionError"}}class R extends K{constructor(e,i,n){super(e,"MIDI_DEVICE_ERROR"),this.name="MIDIDeviceError",this.deviceType=i,this.deviceId=n}}class M extends K{constructor(e,i){super(e,"MIDI_VALIDATION_ERROR"),this.name="MIDIValidationError",this.validationType=i}}class H extends Error{constructor(e,i){super(e),this.name="DX7Error",this.code=i,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}}class g extends H{constructor(e,i,n){super(e,"DX7_PARSE_ERROR"),this.name="DX7ParseError",this.parseType=i,this.offset=n}}class d extends H{constructor(e,i,n){super(e,"DX7_VALIDATION_ERROR"),this.name="DX7ValidationError",this.validationType=i,this.value=n}}function O(c,e,i){return Math.max(e,Math.min(i,c))}function w(c,e,i,n=!1){const s=(c-e)/(i-e),E=(n?1-s:s)*127;return O(Math.round(E),0,127)}function J(c,e,i,n=!1){let s=O(c,0,127)/127;return n&&(s=1-s),e+s*(i-e)}function k(c){const e={C:0,"C#":1,DB:1,D:2,"D#":3,EB:3,E:4,F:5,"F#":6,GB:6,G:7,"G#":8,AB:8,A:9,"A#":10,BB:10,B:11},i=c.match(/^([A-G][#b]?)(-?\d+)$/i);if(!i)throw new M(`Invalid note name: ${c}`,"note",c);const[,n,s]=i,r=e[n.toUpperCase()];if(r===void 0)throw new M(`Invalid note: ${n}`,"note",n);const E=(parseInt(s,10)+1)*12+r;return O(E,0,127)}function j(c,e=!1){const s=e?["C","Db","D","Eb","E","F","Gb","G","Ab","A","Bb","B"]:["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],r=Math.floor(c/12)-1;return`${s[c%12]}${r}`}function X(c){const e=69+12*Math.log2(c/440);return O(Math.round(e),0,127)}function tt(c){return 440*2**((c-69)/12)}function et(c){return{0:"Bank Select",1:"Modulation",2:"Breath Controller",4:"Foot Controller",5:"Portamento Time",7:"Volume",8:"Balance",10:"Pan",11:"Expression",64:"Sustain Pedal",65:"Portamento",66:"Sostenuto",67:"Soft Pedal",68:"Legato",71:"Resonance",72:"Release Time",73:"Attack Time",74:"Cutoff",75:"Decay Time",76:"Vibrato Rate",77:"Vibrato Depth",78:"Vibrato Delay",84:"Portamento Control",91:"Reverb",92:"Tremolo",93:"Chorus",94:"Detune",95:"Phaser",120:"All Sound Off",121:"Reset All Controllers",123:"All Notes Off"}[c]||`CC ${c}`}function B(c){const e=O(Math.round(c),0,16383);return{msb:e>>7&127,lsb:e&127}}function Y(c,e){return O(c,0,127)<<7|O(e,0,127)}function x(c,e,i,n=!1){const s=(c-e)/(i-e),E=(n?1-s:s)*16383;return B(E)}function it(c,e,i,n,s=!1){let E=Y(c,e)/16383;return s&&(E=1-E),i+E*(n-i)}class v{constructor(){this.events=new Map}on(e,i){return this.events.has(e)||this.events.set(e,[]),this.events.get(e).push(i),()=>this.off(e,i)}once(e,i){const n=(...s)=>{i(...s),this.off(e,n)};this.on(e,n)}off(e,i){if(!this.events.has(e))return;const n=this.events.get(e),s=n.indexOf(i);s>-1&&n.splice(s,1),n.length===0&&this.events.delete(e)}emit(e,i){if(!this.events.has(e))return;[...this.events.get(e)].forEach(s=>{try{s(i)}catch(r){console.error(`Error in event handler for "${e}":`,r)}})}removeAllListeners(e){e?this.events.delete(e):this.events.clear()}}const p={DEVICE_CHANGE:"device-change",IN_DEV_CONNECTED:"in-dev-connected",IN_DEV_DISCONNECTED:"in-dev-disconnected",OUT_DEV_CONNECTED:"out-dev-connected",OUT_DEV_DISCONNECTED:"out-dev-disconnected"};class $ extends v{constructor(e={}){super(),this.options={sysex:!1,...e},this.midiAccess=null,this.output=null,this.input=null}async requestAccess(){if(!navigator.requestMIDIAccess)throw new F("Web MIDI API is not supported in this browser","unsupported");try{this.midiAccess=await navigator.requestMIDIAccess({sysex:this.options.sysex}),this.midiAccess.onstatechange=e=>{const i=e.port,n=e.port.state;this.emit(p.DEVICE_CHANGE,{port:i,state:n,type:i.type,device:{id:i.id,name:i.name,manufacturer:i.manufacturer||"Unknown"}}),n==="disconnected"?i.type==="input"?(this.emit(p.IN_DEV_DISCONNECTED,{device:i}),this.input&&this.input.id===i.id&&(this.input=null)):i.type==="output"&&(this.emit(p.OUT_DEV_DISCONNECTED,{device:i}),this.output&&this.output.id===i.id&&(this.output=null)):n==="connected"&&(i.type==="input"?this.emit(p.IN_DEV_CONNECTED,{device:i}):i.type==="output"&&this.emit(p.OUT_DEV_CONNECTED,{device:i}))}}catch(e){throw e.name==="SecurityError"?new F("MIDI access denied. SysEx requires user permission.","denied"):new F(`Failed to get MIDI access: ${e.message}`,"failed")}}async connect(e){if(!this.midiAccess)throw new y("MIDI access not initialized. Call requestAccess() first.");const i=Array.from(this.midiAccess.outputs.values());if(i.length===0)throw new R("No MIDI output devices available","output");if(e===void 0){this.output=i[0];return}if(typeof e=="number"){if(e<0||e>=i.length)throw new R(`Output index ${e} out of range (0-${i.length-1})`,"output",e);this.output=i[e];return}if(this.output=i.find(n=>n.name===e||n.id===e),!this.output){const n=i.map(s=>s.name).join(", ");throw new R(`MIDI output "${e}" not found. Available: ${n}`,"output",e)}}async connectInput(e,i){if(!this.midiAccess)throw new y("MIDI access not initialized. Call requestAccess() first.");if(typeof i!="function")throw new M("onMessage callback must be a function","callback");const n=Array.from(this.midiAccess.inputs.values());if(n.length===0)throw new R("No MIDI input devices available","input");if(this.input&&(this.input.onmidimessage=null),e===void 0)this.input=n[0];else if(typeof e=="number"){if(e<0||e>=n.length)throw new R(`Input index ${e} out of range (0-${n.length-1})`,"input",e);this.input=n[e]}else if(this.input=n.find(s=>s.name===e||s.id===e),!this.input){const s=n.map(r=>r.name).join(", ");throw new R(`MIDI input "${e}" not found. Available: ${s}`,"input",e)}this.input.onmidimessage=s=>{i(s)}}disconnectOutput(){this.output=null}disconnectInput(){this.input&&(this.input.onmidimessage=null,this.input=null)}disconnect(){this.disconnectOutput(),this.disconnectInput()}isConnected(){return this.output!==null}getCurrentOutput(){return this.output?{id:this.output.id,name:this.output.name,manufacturer:this.output.manufacturer||"Unknown"}:null}getCurrentInput(){return this.input?{id:this.input.id,name:this.input.name,manufacturer:this.input.manufacturer||"Unknown"}:null}getOutputs(){if(!this.midiAccess)return[];const e=[];return this.midiAccess.outputs.forEach(i=>{i.state==="connected"&&e.push({id:i.id,name:i.name,manufacturer:i.manufacturer||"Unknown"})}),e}getInputs(){if(!this.midiAccess)return[];const e=[];return this.midiAccess.inputs.forEach(i=>{i.state==="connected"&&e.push({id:i.id,name:i.name,manufacturer:i.manufacturer||"Unknown"})}),e}send(e,i=null){if(!this.output){console.warn("No MIDI output connected. Call connect() first.");return}try{const n=new Uint8Array(e);i===null?this.output.send(n):this.output.send(n,i)}catch(n){console.error("Failed to send MIDI message:",n)}}sendSysEx(e,i=!1){if(!this.options.sysex){console.warn("SysEx not enabled. Initialize with sysex: true");return}let n;i?n=[240,...e,247]:n=e,this.send(n)}}const A={READY:"ready",ERROR:"error",DESTROYED:"destroyed",DEV_OUT_CONNECTED:"dev-out-connected",DEV_OUT_DISCONNECTED:"dev-out-disconnected",DEV_IN_CONNECTED:"dev-in-connected",DEV_IN_DISCONNECTED:"dev-in-disconnected",CH_CC_SEND:"ch-cc-send",CH_CC_RECV:"ch-cc-recv",CH_NOTE_ON_SEND:"ch-note-on-send",CH_NOTE_ON_RECV:"ch-note-on-recv",CH_NOTE_OFF_SEND:"ch-note-off-send",CH_NOTE_OFF_RECV:"ch-note-off-recv",CH_PC_SEND:"ch-pc-send",CH_PC_RECV:"ch-pc-recv",CH_PITCH_BEND_SEND:"ch-pitch-bend-send",CH_PITCH_BEND_RECV:"ch-pitch-bend-recv",CH_MONO_PRESS_SEND:"ch-mono-press-send",CH_MONO_PRESS_RECV:"ch-mono-press-recv",CH_POLY_PRESS_SEND:"ch-poly-press-send",CH_POLY_PRESS_RECV:"ch-poly-press-recv",CH_ALL_SOUNDS_OFF_SEND:"ch-all-sounds-off-send",CH_RESET_CONTROLLERS_SEND:"ch-reset-controllers-send",CH_LOCAL_CONTROL_SEND:"ch-local-control-send",CH_ALL_NOTES_OFF_SEND:"ch-all-notes-off-send",CH_OMNI_OFF_SEND:"ch-omni-off-send",CH_OMNI_ON_SEND:"ch-omni-on-send",CH_MONO_ON_SEND:"ch-mono-on-send",CH_POLY_ON_SEND:"ch-poly-on-send",SYS_EX_SEND:"sys-ex-send",SYS_EX_RECV:"sys-ex-recv",SYS_CLOCK_RECV:"sys-clock-recv",SYS_START_RECV:"sys-start-recv",SYS_CONTINUE_RECV:"sys-continue-recv",SYS_STOP_RECV:"sys-stop-recv",SYS_MTC_RECV:"sys-mtc-recv",SYS_SONG_POS_RECV:"sys-song-pos-recv",SYS_SONG_SEL_RECV:"sys-song-sel-recv",SYS_TUNE_REQ_RECV:"sys-tune-req-recv",SYS_ACT_SENSE_RECV:"sys-act-sense-recv",SYS_RESET_RECV:"sys-reset-recv",MIDI_RAW:"midi-raw",PATCH_SAVED:"patch-saved",PATCH_LOADED:"patch-loaded",PATCH_DELETED:"patch-deleted"};class Z extends v{constructor(e={}){super(),this.options={inputChannel:1,outputChannel:1,autoConnect:!0,sysex:!1,...e},this.connection=null,this.bindings=new Map,this.state={controlChange:new Map,programChange:new Map,pitchBend:new Map,monoPressure:new Map,polyPressure:new Map},this.initialized=!1,this._initNamespaces()}async init(){if(this.initialized){console.warn("MIDI Controller already initialized");return}try{this.connection=new $({sysex:this.options.sysex}),await this.connection.requestAccess(),this.connection.on(p.DEVICE_CHANGE,async({state:e,type:i,device:n})=>{try{if(e==="connected")i==="output"?this.emit(A.DEV_OUT_CONNECTED,n):i==="input"&&this.emit(A.DEV_IN_CONNECTED,n);else if(e==="disconnected"){if(i==="output"&&n){const s=this.connection.getCurrentOutput();s&&s.id===n.id?await this._disconnectOutput():this.emit(A.DEV_OUT_DISCONNECTED,n)}if(i==="input"&&n){const s=this.connection.getCurrentInput();s&&s.id===n.id?await this._disconnectInput():this.emit(A.DEV_IN_DISCONNECTED,n)}}}catch(s){console.error("Error in device change handler:",s),this.emit(A.ERROR,s)}}),this.options.autoConnect&&await this.connection.connect(this.options.output),this.options.input!==void 0&&await this._connectInput(this.options.input),this.initialized=!0,this.emit(A.READY,this),this.options.onReady?.(this)}catch(e){throw this.emit(A.ERROR,e),this.options.onError?.(e),e}}_initNamespaces(){this.device={connect:this._connect.bind(this),disconnect:this._disconnect.bind(this),connectInput:this._connectInput.bind(this),disconnectInput:this._disconnectInput.bind(this),connectOutput:this._connectOutput.bind(this),disconnectOutput:this._disconnectOutput.bind(this),getCurrentOutput:this._getCurrentOutput.bind(this),getCurrentInput:this._getCurrentInput.bind(this),getOutputs:this._getOutputs.bind(this),getInputs:this._getInputs.bind(this)},this.channel={sendNoteOn:this._sendNoteOn.bind(this),sendNoteOff:this._sendNoteOff.bind(this),sendCC:this._sendCC.bind(this),getCC:this._getCC.bind(this),sendPC:this._sendPC.bind(this),getPC:this._getPC.bind(this),sendPitchBend:this._sendPitchBend.bind(this),getPitchBend:this._getPitchBend.bind(this),sendMonoPressure:this._sendMonoPressure.bind(this),getMonoPressure:this._getMonoPressure.bind(this),sendPolyPressure:this._sendPolyPressure.bind(this),getPolyPressure:this._getPolyPressure.bind(this),allSoundsOff:this._allSoundsOff.bind(this),resetControllers:this._resetControllers.bind(this),localControl:this._localControl.bind(this),allNotesOff:this._allNotesOff.bind(this),omniOff:this._omniOff.bind(this),omniOn:this._omniOn.bind(this),monoOn:this._monoOn.bind(this),polyOn:this._polyOn.bind(this)},this.system={sendEx:function(e,i=!1){return this._sendSysEx(e,i)}.bind(this),sendClock:this._sendClock.bind(this),start:this._sendStart.bind(this),continue:this._sendContinue.bind(this),stop:this._sendStop.bind(this),sendMTC:this._sendMTC.bind(this),sendSongPosition:this._sendSongPosition.bind(this),sendSongSelect:this._sendSongSelect.bind(this),sendTuneRequest:this._sendTuneRequest.bind(this),sendActiveSensing:this._sendActiveSensing.bind(this),sendSystemReset:this._sendSystemReset.bind(this)},this.patch={get:this._getPatch.bind(this),set:this._setPatch.bind(this),save:this._savePatch.bind(this),load:this._loadPatch.bind(this),delete:this._deletePatch.bind(this),list:this._listPatches.bind(this)}}bind(e,i,n={}){if(!e)return console.warn("Cannot bind: element is null or undefined"),()=>{};const s=this._createBinding(e,i,n);return this.bindings.set(e,s),this.initialized&&this.connection?.isConnected()&&s.handler({target:e}),()=>this.unbind(e)}_createBinding(e,i,n={}){const{min:s=parseFloat(e.getAttribute("min"))||0,max:r=parseFloat(e.getAttribute("max"))||127,channel:E,invert:o=!1,onInput:h=void 0}=i,{debounce:N=0}=n,u={...i,min:s,max:r,invert:o,onInput:h};if(E!==void 0&&(u.channel=E),i.is14Bit){const{msb:T,lsb:f}=i,U=V=>{const W=parseFloat(V.target.value);if(Number.isNaN(W))return;const{msb:Dt,lsb:Ot}=x(W,s,r,o),Q=E||this.options.outputChannel;this._sendCC(T,Dt,Q),this._sendCC(f,Ot,Q)};let L=null;const b=N>0?V=>{L&&clearTimeout(L),L=setTimeout(()=>{U(V),L=null},N)}:U;return e.addEventListener("input",b),e.addEventListener("change",b),{element:e,config:u,handler:U,destroy:()=>{L&&clearTimeout(L),e.removeEventListener("input",b),e.removeEventListener("change",b)}}}const{cc:a}=i,C=T=>{const f=parseFloat(T.target.value);if(Number.isNaN(f))return;const U=w(f,s,r,o),L=E===void 0?this.options.outputChannel:E;this._sendCC(a,U,L)};let S=null;const D=N>0?T=>{S&&clearTimeout(S),S=setTimeout(()=>{C(T),S=null},N)}:C;return e.addEventListener("input",D),e.addEventListener("change",D),{element:e,config:u,handler:C,destroy:()=>{S&&clearTimeout(S),e.removeEventListener("input",D),e.removeEventListener("change",D)}}}unbind(e){const i=this.bindings.get(e);i&&(i.destroy(),this.bindings.delete(e))}async destroy(){for(const e of this.bindings.values())e.destroy();this.bindings.clear(),this.state.controlChange.clear(),this.state.programChange.clear(),this.state.pitchBend.clear(),this.state.monoPressure.clear(),this.state.polyPressure.clear(),await this._disconnect(),this.initialized=!1,this.emit(A.DESTROYED),this.removeAllListeners()}async _connect(e){e?await this.connection.connect(e):this.options.output!==void 0?await this.connection.connect(this.options.output):this.options.autoConnect&&await this.connection.connect()}async _disconnect(){this.connection.disconnect()}async _connectInput(e){await this.connection.connectInput(e,i=>{this._handleMIDIMessage(i)}),this.emit(A.DEV_IN_CONNECTED,this.connection.getCurrentInput())}async _disconnectInput(){const e=this.connection.getCurrentInput();this.connection.disconnectInput(),this.emit(A.DEV_IN_DISCONNECTED,e)}async _connectOutput(e){await this.connection.connect(e),this.emit(A.DEV_OUT_CONNECTED,this.connection.getCurrentOutput())}async _disconnectOutput(){const e=this.connection.getCurrentOutput();this.connection.disconnectOutput(),this.emit(A.DEV_OUT_DISCONNECTED,e)}_getCurrentOutput(){return this.connection?.getCurrentOutput()||null}_getCurrentInput(){return this.connection?.getCurrentInput()||null}_getOutputs(){return this.connection?.getOutputs()||[]}_getInputs(){return this.connection?.getInputs()||[]}send(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send(e)}_sendNoteOn(e,i=64,n=this.options.outputChannel){if(!this.initialized)return;e=O(Math.round(e),0,127),i=O(Math.round(i),0,127),n=O(Math.round(n),1,16);const s=144+(n-1);this.connection.send([s,e,i]),this.emit(A.CH_NOTE_ON_SEND,{note:e,velocity:i,channel:n})}_sendNoteOff(e,i=this.options.outputChannel,n=0){if(!this.initialized)return;e=O(Math.round(e),0,127),n=O(Math.round(n),0,127),i=O(Math.round(i),1,16);const s=144+(i-1);this.connection.send([s,e,n]),this.emit(A.CH_NOTE_OFF_SEND,{note:e,channel:i,velocity:n})}_sendCC(e,i,n=this.options.outputChannel){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}e=O(Math.round(e),0,127),i=O(Math.round(i),0,127),n=O(Math.round(n),1,16);const s=176+(n-1);this.connection.send([s,e,i]);const r=`${n}:${e}`;this.state.controlChange.set(r,i),this.emit(A.CH_CC_SEND,{cc:e,value:i,channel:n})}_sendPC(e,i=this.options.outputChannel){if(!this.initialized)return;e=O(Math.round(e),0,127),i=O(Math.round(i),1,16);const n=192+(i-1);this.connection.send([n,e]),this.state.programChange.set(i.toString(),e),this.emit(A.CH_PC_SEND,{program:e,channel:i})}_getPC(e=this.options.inputChannel){return this.state.programChange.get(e.toString())}_getCC(e,i=this.options.inputChannel){const n=`${i}:${e}`;return this.state.controlChange.get(n)}_sendPitchBend(e,i=this.options.outputChannel){if(!this.initialized)return;e=O(Math.round(e),0,16383),i=O(Math.round(i),1,16);const n=224+(i-1),s=e&127,r=e>>7&127;this.connection.send([n,s,r]),this.state.pitchBend.set(i.toString(),e),this.emit(A.CH_PITCH_BEND_SEND,{value:e,channel:i})}_getPitchBend(e=this.options.inputChannel){return this.state.pitchBend.get(e.toString())}_sendMonoPressure(e,i=this.options.outputChannel){if(!this.initialized)return;e=O(Math.round(e),0,127),i=O(Math.round(i),1,16);const n=208+(i-1);this.connection.send([n,e]),this.state.monoPressure.set(i.toString(),e),this.emit(A.CH_MONO_PRESS_SEND,{pressure:e,channel:i})}_getMonoPressure(e=this.options.inputChannel){return this.state.monoPressure.get(e.toString())}_sendPolyPressure(e,i,n=this.options.outputChannel){if(!this.initialized)return;e=O(Math.round(e),0,127),i=O(Math.round(i),0,127),n=O(Math.round(n),1,16);const s=160+(n-1);this.connection.send([s,e,i]);const r=`${n}:${e}`;this.state.polyPressure.set(r,i),this.emit(A.CH_POLY_PRESS_SEND,{note:e,pressure:i,channel:n})}_getPolyPressure(e,i=this.options.inputChannel){const n=`${i}:${e}`;return this.state.polyPressure.get(n)}_allSoundsOff(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e!==void 0){e=O(Math.round(e),1,16);const i=176+(e-1);this.connection.send([i,120,0]),this.emit(A.CH_ALL_SOUNDS_OFF_SEND,{channel:e})}else{for(let i=1;i<=16;i++){const n=176+(i-1);this.connection.send([n,120,0])}this.emit(A.CH_ALL_SOUNDS_OFF_SEND,{channel:null})}}_resetControllers(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e!==void 0){e=O(Math.round(e),1,16);const i=176+(e-1);this.connection.send([i,121,0]),this.emit(A.CH_RESET_CONTROLLERS_SEND,{channel:e})}else{for(let i=1;i<=16;i++){const n=176+(i-1);this.connection.send([n,121,0])}this.emit(A.CH_RESET_CONTROLLERS_SEND,{channel:null})}}_localControl(e,i){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}const n=e?127:0;if(i!==void 0){i=O(Math.round(i),1,16);const s=176+(i-1);this.connection.send([s,122,n]),this.emit(A.CH_LOCAL_CONTROL_SEND,{enabled:e,channel:i})}else{for(let s=1;s<=16;s++){const r=176+(s-1);this.connection.send([r,122,n])}this.emit(A.CH_LOCAL_CONTROL_SEND,{enabled:e,channel:null})}}_allNotesOff(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e!==void 0){e=O(Math.round(e),1,16);const i=176+(e-1);this.connection.send([i,123,0]),this.emit(A.CH_ALL_NOTES_OFF_SEND,{channel:e})}else{for(let i=1;i<=16;i++){const n=176+(i-1);this.connection.send([n,123,0])}this.emit(A.CH_ALL_NOTES_OFF_SEND,{channel:null})}}_omniOff(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e!==void 0){e=O(Math.round(e),1,16);const i=176+(e-1);this.connection.send([i,124,0]),this.emit(A.CH_OMNI_OFF_SEND,{channel:e})}else{for(let i=1;i<=16;i++){const n=176+(i-1);this.connection.send([n,124,0])}this.emit(A.CH_OMNI_OFF_SEND,{channel:null})}}_omniOn(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e!==void 0){e=O(Math.round(e),1,16);const i=176+(e-1);this.connection.send([i,125,0]),this.emit(A.CH_OMNI_ON_SEND,{channel:e})}else{for(let i=1;i<=16;i++){const n=176+(i-1);this.connection.send([n,125,0])}this.emit(A.CH_OMNI_ON_SEND,{channel:null})}}_monoOn(e=1,i){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e=Math.max(0,Math.min(16,Math.round(e))),i!==void 0){i=O(Math.round(i),1,16);const n=176+(i-1);this.connection.send([n,126,e]),this.emit(A.CH_MONO_ON_SEND,{channels:e,channel:i})}else{for(let n=1;n<=16;n++){const s=176+(n-1);this.connection.send([s,126,e])}this.emit(A.CH_MONO_ON_SEND,{channels:e,channel:null})}}_polyOn(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(e!==void 0){e=O(Math.round(e),1,16);const i=176+(e-1);this.connection.send([i,127,0]),this.emit(A.CH_POLY_ON_SEND,{channel:e})}else{for(let i=1;i<=16;i++){const n=176+(i-1);this.connection.send([n,127,0])}this.emit(A.CH_POLY_ON_SEND,{channel:null})}}_sendSysEx(e,i=!1){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}if(!this.options.sysex){console.warn("SysEx not enabled. Initialize with sysex: true");return}this.connection.sendSysEx(e,i),this.emit(A.SYS_EX_SEND,{data:e,includeWrapper:i})}_sendClock(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([248])}_sendStart(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([250])}_sendContinue(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([251])}_sendStop(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([252])}_sendMTC(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}e=O(Math.round(e),0,127),this.connection.send([241,e])}_sendSongPosition(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}e=O(Math.round(e),0,16383);const i=e&127,n=e>>7&127;this.connection.send([242,i,n])}_sendSongSelect(e){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}e=O(Math.round(e),0,127),this.connection.send([243,e])}_sendTuneRequest(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([246])}_sendActiveSensing(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([254])}_sendSystemReset(){if(!this.initialized){console.warn("MIDI not initialized. Call init() first.");return}this.connection.send([255])}_handleMIDIMessage(e){const[i,n,s]=e.data,r=i&240,E=(i&15)+1;if(i===248){this.emit(A.SYS_CLOCK_RECV,{timestamp:e.midiwire});return}if(i===250){this.emit(A.SYS_START_RECV,{timestamp:e.midiwire});return}if(i===251){this.emit(A.SYS_CONTINUE_RECV,{timestamp:e.midiwire});return}if(i===252){this.emit(A.SYS_STOP_RECV,{timestamp:e.midiwire});return}if(i===254){this.emit(A.SYS_ACT_SENSE_RECV,{timestamp:e.midiwire});return}if(i===255){this.emit(A.SYS_RESET_RECV,{timestamp:e.midiwire});return}if(i===240){this.emit(A.SYS_EX_RECV,{data:Array.from(e.data),timestamp:e.midiwire});return}if(i===241){this.emit(A.SYS_MTC_RECV,{data:n,timestamp:e.midiwire});return}if(i===242){const o=n+(s<<7);this.emit(A.SYS_SONG_POS_RECV,{position:o,timestamp:e.midiwire});return}if(i===243){this.emit(A.SYS_SONG_SEL_RECV,{song:n,timestamp:e.midiwire});return}if(i===246){this.emit(A.SYS_TUNE_REQ_RECV,{timestamp:e.midiwire});return}if(i===247){this.emit(A.MIDI_RAW,{status:i,data:[n,s],channel:E,timestamp:e.midiwire});return}if(r===176){const o=`${E}:${n}`;this.state.controlChange.set(o,s),this.emit(A.CH_CC_RECV,{cc:n,value:s,channel:E});return}if(r===192){this.state.programChange.set(E.toString(),n),this.emit(A.CH_PC_RECV,{program:n,channel:E});return}if(r===224){const o=n+(s<<7);this.state.pitchBend.set(E.toString(),o),this.emit(A.CH_PITCH_BEND_RECV,{value:o,channel:E});return}if(r===208){this.state.monoPressure.set(E.toString(),n),this.emit(A.CH_MONO_PRESS_RECV,{pressure:n,channel:E});return}if(r===160){const o=`${E}:${n}`;this.state.polyPressure.set(o,s),this.emit(A.CH_POLY_PRESS_RECV,{note:n,pressure:s,channel:E});return}if(r===144&&s>0){this.emit(A.CH_NOTE_ON_RECV,{note:n,velocity:s,channel:E});return}if(r===128||r===144&&s===0){this.emit(A.CH_NOTE_OFF_RECV,{note:n,channel:E});return}this.emit(A.MIDI_RAW,{status:i,data:[n,s],channel:E,timestamp:e.midiwire})}_getPatch(e="Unnamed Patch"){const i={name:e,device:this._getCurrentOutput()?.name||null,timestamp:new Date().toISOString(),version:"1.0",channels:{},settings:{}};for(const[n,s]of this.state.controlChange.entries()){const[r,E]=n.split(":").map(Number);i.channels[r]||(i.channels[r]={ccs:{},notes:{}}),i.channels[r].ccs[E]=s}for(const[n,s]of this.state.programChange.entries()){const r=parseInt(n,10);i.channels[r]||(i.channels[r]={ccs:{},notes:{}}),i.channels[r].program=s}for(const[n,s]of this.state.pitchBend.entries()){const r=parseInt(n,10);i.channels[r]||(i.channels[r]={ccs:{},notes:{}}),i.channels[r].pitchBend=s}for(const[n,s]of this.state.monoPressure.entries()){const r=parseInt(n,10);i.channels[r]||(i.channels[r]={ccs:{},notes:{}}),i.channels[r].monoPressure=s}for(const[n,s]of this.state.polyPressure.entries()){const[r,E]=n.split(":").map(Number),o=parseInt(r,10);i.channels[o]||(i.channels[o]={ccs:{},notes:{}}),i.channels[o].polyPressure||(i.channels[o].polyPressure={}),i.channels[o].polyPressure[E]=s}for(const[n,s]of this.bindings.entries()){const{config:r}=s;if(r.cc){const E=`cc${r.cc}`;i.settings[E]={min:r.min,max:r.max,invert:r.invert||!1,is14Bit:r.is14Bit||!1,label:n.getAttribute?.("data-midi-label")||null,elementId:n.id||null}}}return i}async _setPatch(e){if(!e||!e.channels)throw new M("Invalid patch format","patch");const i=e.version||"1.0";i==="1.0"?await this._applyPatchV1(e):(console.warn(`Unknown patch version: ${i}. Attempting to apply as v1.0`),await this._applyPatchV1(e)),this.emit(A.PATCH_LOADED,{patch:e})}async _applyPatchV1(e){for(const[i,n]of Object.entries(e.channels)){const s=parseInt(i,10);if(n.ccs)for(const[r,E]of Object.entries(n.ccs)){const o=parseInt(r,10);this._sendCC(o,E,s)}if(n.program!==void 0&&this._sendPC(n.program,s),n.pitchBend!==void 0&&this._sendPitchBend(n.pitchBend,s),n.monoPressure!==void 0&&this._sendMonoPressure(n.monoPressure,s),n.polyPressure)for(const[r,E]of Object.entries(n.polyPressure)){const o=parseInt(r,10);this._sendPolyPressure(o,E,s)}if(n.notes)for(const[r,E]of Object.entries(n.notes)){const o=parseInt(r,10);E>0?this._sendNoteOn(o,E,s):this._sendNoteOff(o,s)}}if(e.settings)for(const[i,n]of Object.entries(e.settings))for(const[s,r]of this.bindings.entries())r.config.cc?.toString()===i.replace("cc","")&&(s.min!==void 0&&n.min!==void 0&&(s.min=String(n.min)),s.max!==void 0&&n.max!==void 0&&(s.max=String(n.max)));for(const[i,n]of this.bindings.entries()){const{config:s}=n;if(s.cc!==void 0){const r=s.channel||this.options.inputChannel,E=e.channels[r];if(E?.ccs){const o=E.ccs[s.cc];if(o!==void 0){const h=s.min!==void 0?s.min:parseFloat(i.getAttribute?.("min"))||0,N=s.max!==void 0?s.max:parseFloat(i.getAttribute?.("max"))||127,u=s.invert||!1;let a;u?a=N-o/127*(N-h):a=h+o/127*(N-h),s.onInput&&typeof s.onInput=="function"?s.onInput(a):(i.value=a,i.dispatchEvent(new Event("input",{bubbles:!0})))}}}}}_savePatch(e,i=null){const n=i||this._getPatch(e),s=`midiwire_patch_${e}`;try{return localStorage.setItem(s,JSON.stringify(n)),this.emit(A.PATCH_SAVED,{name:e,patch:n}),s}catch(r){throw console.error("Failed to save patch:",r),r}}_loadPatch(e){const i=`midiwire_patch_${e}`;try{const n=localStorage.getItem(i);if(!n)return null;const s=JSON.parse(n);return this.emit(A.PATCH_LOADED,{name:e,patch:s}),s}catch(n){return console.error("Failed to load patch:",n),null}}_deletePatch(e){const i=`midiwire_patch_${e}`;try{return localStorage.removeItem(i),this.emit(A.PATCH_DELETED,{name:e}),!0}catch(n){return console.error("Failed to delete patch:",n),!1}}_listPatches(){const e=[];try{for(let i=0;i<localStorage.length;i++){const n=localStorage.key(i);if(n?.startsWith("midiwire_patch_")){const s=n.replace("midiwire_patch_",""),r=this._loadPatch(s);r&&e.push({name:s,patch:r})}}}catch(i){console.error("Failed to list patches:",i)}return e.sort((i,n)=>i.name.localeCompare(n.name))}}class z{constructor(e={}){this.midi=e.midiController||null,this.onStatusUpdate=e.onStatusUpdate||(()=>{}),this.onConnectionUpdate=e.onConnectionUpdate||(()=>{}),this.channel=e.channel||1,this.currentOutput=null,this.currentInput=null,this.isConnecting=!1}async setupSelectors(e={},i={}){if(!this.midi)throw new Error("MIDI controller not initialized. Pass midiController in constructor options.");const{output:n,input:s,channel:r}=e,E=this._resolveSelector(n),o=this._resolveSelector(s),h=this._resolveSelector(r);if(this._setupDeviceChangeListeners({output:E,input:o},i.onDeviceListChange),E){await this._populateOutputDeviceList(E);const N=i.onConnect?async(a,C)=>i.onConnect({midi:a,device:C,type:"output"}):void 0,u=i.onDisconnect?async a=>i.onDisconnect({midi:a,type:"output"}):void 0;this._connectOutputDeviceSelection(E,N,u)}if(o){await this._populateInputDeviceList(o);const N=i.onConnect?async(a,C)=>i.onConnect({midi:a,device:C,type:"input"}):void 0,u=i.onDisconnect?async a=>i.onDisconnect({midi:a,type:"input"}):void 0;this._connectInputDeviceSelection(o,N,u)}return h&&this._connectChannelSelection(h,"output"),this.midi}updateStatus(e,i=""){this.onStatusUpdate(e,i)}updateConnectionStatus(){this.onConnectionUpdate(this.currentOutput,this.currentInput,this.midi)}_setupDeviceChangeListeners(e={},i){!this.midi||this._listenersInitialized||(this._listenersInitialized=!0,this.midi.on(A.DEV_OUT_CONNECTED,async n=>{this.updateStatus(`Output device connected: ${n?.name||"Unknown"}`,"connected"),e.output&&await this._populateOutputDeviceList(e.output),i&&i()}),this.midi.on(A.DEV_OUT_DISCONNECTED,async n=>{this.updateStatus(`Output device disconnected: ${n?.name||"Unknown"}`,"error"),this.currentOutput&&n?.name===this.currentOutput.name&&(this.currentOutput=null,this.updateConnectionStatus(),e.output&&(e.output.value="")),e.output&&await this._populateOutputDeviceList(e.output),i&&i()}),this.midi.on(A.DEV_IN_CONNECTED,async n=>{this.updateStatus(`Input device connected: ${n?.name||"Unknown"}`,"connected"),e.input&&await this._populateInputDeviceList(e.input),i&&i()}),this.midi.on(A.DEV_IN_DISCONNECTED,async n=>{this.updateStatus(`Input device disconnected: ${n?.name||"Unknown"}`,"error"),e.input&&(e.input.value="",await this._populateInputDeviceList(e.input)),i&&i()}))}_resolveSelector(e){if(typeof e=="string"){const i=document.querySelector(e);return i||console.warn(`MIDIDeviceManager: Selector "${e}" not found`),i}return e||null}_getOutputDevices(){return this.midi?this.midi.device.getOutputs():[]}_getInputDevices(){return this.midi?this.midi.device.getInputs():[]}_connectOutputDeviceSelection(e,i,n){!e||!this.midi||e.addEventListener("change",async s=>{if(this.isConnecting)return;this.isConnecting=!0;const r=s.target.value;if(!r){this.currentOutput&&this.midi&&(await this.midi.device.disconnectOutput(),this.currentOutput=null,this.updateStatus("Output device disconnected",""),this.updateConnectionStatus()),this.isConnecting=!1,n&&await n(this.midi);return}try{if(await this.midi.device.connectOutput(parseInt(r,10)),this.currentOutput=this.midi.device.getCurrentOutput(),this.currentOutput){const o=this.midi.device.getOutputs().findIndex(h=>h.id===this.currentOutput.id);o!==-1&&(e.value=o.toString())}this.updateConnectionStatus(),i&&await i(this.midi,this.currentOutput)}catch(E){this.updateStatus(`Output connection failed: ${E.message}`,"error")}finally{this.isConnecting=!1}})}_connectInputDeviceSelection(e,i,n){!e||!this.midi||e.addEventListener("change",async s=>{const r=s.target.value;if(!r){this.midi&&(await this.midi.device.disconnectInput(),this.updateStatus("Input device disconnected",""),this.updateConnectionStatus()),n&&await n(this.midi);return}if(!this.isConnecting){this.isConnecting=!0;try{await this.midi.device.connectInput(parseInt(r,10));const E=this.midi.device.getCurrentInput();this.updateConnectionStatus(),i&&await i(this.midi,E)}catch(E){this.updateStatus(`Input connection failed: ${E.message}`,"error")}finally{this.isConnecting=!1}}})}_populateDeviceList(e,i,n,s,r){if(i.length>0){if(e.innerHTML='<option value="">Select a device</option>'+i.map((E,o)=>`<option value="${o}">${E.name}</option>`).join(""),n){const E=i.findIndex(o=>o.name===n.name);E!==-1?e.value=E.toString():(e.value="",r&&(this.currentOutput=null,this.updateConnectionStatus()))}else e.value="";e.disabled=!1,r&&!this.currentOutput&&this.updateStatus("Select a device")}else e.innerHTML='<option value="">No devices connected</option>',e.disabled=!0,r&&this.updateStatus("No devices connected","error");s&&s()}async _populateOutputDeviceList(e,i){if(!e||!this.midi)return;const n=this._getOutputDevices();this._populateDeviceList(e,n,this.currentOutput,i,!0)}async _populateInputDeviceList(e,i){if(!e||!this.midi)return;const n=this._getInputDevices(),s=this.midi.device.getCurrentInput();this._populateDeviceList(e,n,s,i,!1)}_connectChannelSelection(e,i){if(!e||!this.midi)return;const n=i==="input"?"inputChannel":"outputChannel";e.addEventListener("change",s=>{this.midi&&(this.midi.options[n]=parseInt(s.target.value,10),this.updateConnectionStatus())})}}const t=class t{constructor(e,i=0){if(e.length!==t.PACKED_SIZE)throw new d(`Invalid voice data length: expected ${t.PACKED_SIZE} bytes, got ${e.length}`,"length",e.length);this.index=i,this.data=new Uint8Array(e),this.name=this._extractName(),this._unpackedCache=null}_extractName(){const e=this.data.subarray(t.PACKED_NAME_START,t.PACKED_NAME_START+t.NAME_LENGTH);return Array.from(e).map(n=>{let s=n&t.MASK_7BIT;return s===t.CHAR_YEN&&(s=t.CHAR_REPLACEMENT_Y),s===t.CHAR_ARROW_RIGHT&&(s=t.CHAR_REPLACEMENT_GT),s===t.CHAR_ARROW_LEFT&&(s=t.CHAR_REPLACEMENT_LT),(s<t.CHAR_MIN_PRINTABLE||s>t.CHAR_MAX_PRINTABLE)&&(s=t.CHAR_SPACE),String.fromCharCode(s)}).join("").trim()}getParameter(e){if(e<0||e>=t.PACKED_SIZE)throw new d(`Parameter offset out of range: ${e} (must be 0-${t.PACKED_SIZE-1})`,"offset",e);return this.data[e]&t.MASK_7BIT}getUnpackedParameter(e){if(e<0||e>=t.UNPACKED_SIZE)throw new d(`Unpacked parameter offset out of range: ${e} (must be 0-${t.UNPACKED_SIZE-1})`,"offset",e);return this._unpackedCache||(this._unpackedCache=this.unpack()),this._unpackedCache[e]&t.MASK_7BIT}setParameter(e,i){if(e<0||e>=t.PACKED_SIZE)throw new d(`Parameter offset out of range: ${e} (must be 0-${t.PACKED_SIZE-1})`,"offset",e);this.data[e]=i&t.MASK_7BIT,this._unpackedCache=null,e>=t.PACKED_NAME_START&&e<t.PACKED_NAME_START+t.NAME_LENGTH&&(this.name=this._extractName())}unpack(){const e=this.data,i=new Uint8Array(t.UNPACKED_SIZE);return this._unpackOperators(e,i),this._unpackPitchEG(e,i),this._unpackGlobalParams(e,i),this._unpackName(e,i),i}_unpackOperators(e,i){for(let n=0;n<t.NUM_OPERATORS;n++){const s=(t.NUM_OPERATORS-1-n)*t.PACKED_OP_SIZE,r=n*t.UNPACKED_OP_SIZE;this._unpackOperator(e,i,s,r)}}_unpackOperator(e,i,n,s){this._unpackOperatorEG(e,i,n,s),this._unpackOperatorScaling(e,i,n,s),this._unpackOperatorPackedParams(e,i,n,s),this._unpackOperatorFrequency(e,i,n,s)}_unpackOperatorEG(e,i,n,s){i[s+t.UNPACKED_OP_EG_RATE_1]=e[n+t.PACKED_OP_EG_RATE_1]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_RATE_2]=e[n+t.PACKED_OP_EG_RATE_2]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_RATE_3]=e[n+t.PACKED_OP_EG_RATE_3]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_RATE_4]=e[n+t.PACKED_OP_EG_RATE_4]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_LEVEL_1]=e[n+t.PACKED_OP_EG_LEVEL_1]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_LEVEL_2]=e[n+t.PACKED_OP_EG_LEVEL_2]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_LEVEL_3]=e[n+t.PACKED_OP_EG_LEVEL_3]&t.MASK_7BIT,i[s+t.UNPACKED_OP_EG_LEVEL_4]=e[n+t.PACKED_OP_EG_LEVEL_4]&t.MASK_7BIT}_unpackOperatorScaling(e,i,n,s){i[s+t.UNPACKED_OP_BREAK_POINT]=e[n+t.PACKED_OP_BREAK_POINT]&t.MASK_7BIT,i[s+t.UNPACKED_OP_L_SCALE_DEPTH]=e[n+t.PACKED_OP_L_SCALE_DEPTH]&t.MASK_7BIT,i[s+t.UNPACKED_OP_R_SCALE_DEPTH]=e[n+t.PACKED_OP_R_SCALE_DEPTH]&t.MASK_7BIT}_unpackOperatorPackedParams(e,i,n,s){const r=e[n+t.PACKED_OP_CURVES]&t.MASK_7BIT;i[s+t.UNPACKED_OP_L_CURVE]=r&t.MASK_2BIT,i[s+t.UNPACKED_OP_R_CURVE]=r>>2&t.MASK_2BIT;const E=e[n+t.PACKED_OP_RATE_SCALING]&t.MASK_7BIT;i[s+t.UNPACKED_OP_RATE_SCALING]=E&t.MASK_3BIT,i[s+t.UNPACKED_OP_DETUNE]=E>>3&t.MASK_4BIT;const o=e[n+t.PACKED_OP_MOD_SENS]&t.MASK_7BIT;i[s+t.UNPACKED_OP_AMP_MOD_SENS]=o&t.MASK_2BIT,i[s+t.UNPACKED_OP_KEY_VEL_SENS]=o>>2&t.MASK_3BIT,i[s+t.UNPACKED_OP_OUTPUT_LEVEL]=e[n+t.PACKED_OP_OUTPUT_LEVEL]&t.MASK_7BIT}_unpackOperatorFrequency(e,i,n,s){const r=e[n+t.PACKED_OP_MODE_FREQ]&t.MASK_7BIT;i[s+t.UNPACKED_OP_MODE]=r&t.MASK_1BIT,i[s+t.UNPACKED_OP_FREQ_COARSE]=r>>1&t.MASK_5BIT;const E=e[n+t.PACKED_OP_DETUNE_FINE]&t.MASK_7BIT;i[s+t.UNPACKED_OP_OSC_DETUNE]=E&t.MASK_3BIT,i[s+t.UNPACKED_OP_FREQ_FINE]=E>>3&t.MASK_4BIT}_unpackPitchEG(e,i){i[t.UNPACKED_PITCH_EG_RATE_1]=e[t.PACKED_PITCH_EG_RATE_1]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_RATE_2]=e[t.PACKED_PITCH_EG_RATE_2]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_RATE_3]=e[t.PACKED_PITCH_EG_RATE_3]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_RATE_4]=e[t.PACKED_PITCH_EG_RATE_4]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_LEVEL_1]=e[t.PACKED_PITCH_EG_LEVEL_1]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_LEVEL_2]=e[t.PACKED_PITCH_EG_LEVEL_2]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_LEVEL_3]=e[t.PACKED_PITCH_EG_LEVEL_3]&t.MASK_7BIT,i[t.UNPACKED_PITCH_EG_LEVEL_4]=e[t.PACKED_PITCH_EG_LEVEL_4]&t.MASK_7BIT}_unpackGlobalParams(e,i){i[t.UNPACKED_ALGORITHM]=e[t.OFFSET_ALGORITHM]&t.MASK_5BIT;const n=e[t.OFFSET_FEEDBACK]&t.MASK_7BIT;i[t.UNPACKED_FEEDBACK]=n&t.MASK_3BIT,i[t.UNPACKED_OSC_SYNC]=n>>3&t.MASK_1BIT,i[t.UNPACKED_LFO_SPEED]=e[t.OFFSET_LFO_SPEED]&t.MASK_7BIT,i[t.UNPACKED_LFO_DELAY]=e[t.OFFSET_LFO_DELAY]&t.MASK_7BIT,i[t.UNPACKED_LFO_PM_DEPTH]=e[t.OFFSET_LFO_PM_DEPTH]&t.MASK_7BIT,i[t.UNPACKED_LFO_AM_DEPTH]=e[t.OFFSET_LFO_AM_DEPTH]&t.MASK_7BIT;const s=e[t.OFFSET_LFO_SYNC_WAVE]&t.MASK_7BIT;i[t.UNPACKED_LFO_KEY_SYNC]=s&t.MASK_1BIT,i[t.UNPACKED_LFO_WAVE]=s>>1&t.MASK_3BIT,i[t.UNPACKED_LFO_PM_SENS]=s>>4&t.MASK_3BIT,i[t.UNPACKED_AMP_MOD_SENS]=e[t.OFFSET_AMP_MOD_SENS]&t.MASK_7BIT,i[t.UNPACKED_TRANSPOSE]=e[t.OFFSET_TRANSPOSE]&t.MASK_7BIT,i[t.UNPACKED_EG_BIAS_SENS]=e[t.OFFSET_EG_BIAS_SENS]&t.MASK_7BIT}_unpackName(e,i){for(let n=0;n<t.NAME_LENGTH;n++)i[t.UNPACKED_NAME_START+n]=e[t.PACKED_NAME_START+n]&t.MASK_7BIT}static pack(e){if(e.length!==t.UNPACKED_SIZE)throw new d(`Invalid unpacked data length: expected ${t.UNPACKED_SIZE} bytes, got ${e.length}`,"length",e.length);const i=new Uint8Array(t.PACKED_SIZE);return t._packOperators(e,i),t._packPitchEG(e,i),t._packGlobalParams(e,i),t._packName(e,i),i}static _packOperators(e,i){for(let n=0;n<t.NUM_OPERATORS;n++){const s=n*t.UNPACKED_OP_SIZE,r=(t.NUM_OPERATORS-1-n)*t.PACKED_OP_SIZE;t._packOperator(e,i,s,r)}}static _packOperator(e,i,n,s){t._packOperatorEG(e,i,n,s),t._packOperatorScaling(e,i,n,s),t._packOperatorPackedParams(e,i,n,s),t._packOperatorFrequency(e,i,n,s)}static _packOperatorEG(e,i,n,s){i[s+t.PACKED_OP_EG_RATE_1]=e[n+t.UNPACKED_OP_EG_RATE_1],i[s+t.PACKED_OP_EG_RATE_2]=e[n+t.UNPACKED_OP_EG_RATE_2],i[s+t.PACKED_OP_EG_RATE_3]=e[n+t.UNPACKED_OP_EG_RATE_3],i[s+t.PACKED_OP_EG_RATE_4]=e[n+t.UNPACKED_OP_EG_RATE_4],i[s+t.PACKED_OP_EG_LEVEL_1]=e[n+t.UNPACKED_OP_EG_LEVEL_1],i[s+t.PACKED_OP_EG_LEVEL_2]=e[n+t.UNPACKED_OP_EG_LEVEL_2],i[s+t.PACKED_OP_EG_LEVEL_3]=e[n+t.UNPACKED_OP_EG_LEVEL_3],i[s+t.PACKED_OP_EG_LEVEL_4]=e[n+t.UNPACKED_OP_EG_LEVEL_4]}static _packOperatorScaling(e,i,n,s){i[s+t.PACKED_OP_BREAK_POINT]=e[n+t.UNPACKED_OP_BREAK_POINT],i[s+t.PACKED_OP_L_SCALE_DEPTH]=e[n+t.UNPACKED_OP_L_SCALE_DEPTH],i[s+t.PACKED_OP_R_SCALE_DEPTH]=e[n+t.UNPACKED_OP_R_SCALE_DEPTH]}static _packOperatorPackedParams(e,i,n,s){const r=e[n+t.UNPACKED_OP_L_CURVE]&t.MASK_2BIT,E=e[n+t.UNPACKED_OP_R_CURVE]&t.MASK_2BIT;i[s+t.PACKED_OP_CURVES]=r|E<<2;const o=e[n+t.UNPACKED_OP_RATE_SCALING]&t.MASK_3BIT,h=e[n+t.UNPACKED_OP_DETUNE]&t.MASK_4BIT;i[s+t.PACKED_OP_RATE_SCALING]=o|h<<3;const N=e[n+t.UNPACKED_OP_AMP_MOD_SENS]&t.MASK_2BIT,u=e[n+t.UNPACKED_OP_KEY_VEL_SENS]&t.MASK_3BIT;i[s+t.PACKED_OP_MOD_SENS]=N|u<<2,i[s+t.PACKED_OP_OUTPUT_LEVEL]=e[n+t.UNPACKED_OP_OUTPUT_LEVEL]}static _packOperatorFrequency(e,i,n,s){const r=e[n+t.UNPACKED_OP_MODE]&t.MASK_1BIT,E=e[n+t.UNPACKED_OP_FREQ_COARSE]&t.MASK_5BIT;i[s+t.PACKED_OP_MODE_FREQ]=r|E<<1;const o=e[n+t.UNPACKED_OP_OSC_DETUNE]&t.MASK_3BIT,h=e[n+t.UNPACKED_OP_FREQ_FINE]&t.MASK_4BIT;i[s+t.PACKED_OP_DETUNE_FINE]=o|h<<3}static _packPitchEG(e,i){i[t.PACKED_PITCH_EG_RATE_1]=e[t.UNPACKED_PITCH_EG_RATE_1],i[t.PACKED_PITCH_EG_RATE_2]=e[t.UNPACKED_PITCH_EG_RATE_2],i[t.PACKED_PITCH_EG_RATE_3]=e[t.UNPACKED_PITCH_EG_RATE_3],i[t.PACKED_PITCH_EG_RATE_4]=e[t.UNPACKED_PITCH_EG_RATE_4],i[t.PACKED_PITCH_EG_LEVEL_1]=e[t.UNPACKED_PITCH_EG_LEVEL_1],i[t.PACKED_PITCH_EG_LEVEL_2]=e[t.UNPACKED_PITCH_EG_LEVEL_2],i[t.PACKED_PITCH_EG_LEVEL_3]=e[t.UNPACKED_PITCH_EG_LEVEL_3],i[t.PACKED_PITCH_EG_LEVEL_4]=e[t.UNPACKED_PITCH_EG_LEVEL_4]}static _packGlobalParams(e,i){i[t.OFFSET_ALGORITHM]=e[t.UNPACKED_ALGORITHM];const n=e[t.UNPACKED_FEEDBACK]&t.MASK_3BIT,s=e[t.UNPACKED_OSC_SYNC]&t.MASK_1BIT;i[t.OFFSET_FEEDBACK]=n|s<<3,i[t.OFFSET_LFO_SPEED]=e[t.UNPACKED_LFO_SPEED],i[t.OFFSET_LFO_DELAY]=e[t.UNPACKED_LFO_DELAY],i[t.OFFSET_LFO_PM_DEPTH]=e[t.UNPACKED_LFO_PM_DEPTH],i[t.OFFSET_LFO_AM_DEPTH]=e[t.UNPACKED_LFO_AM_DEPTH];const r=e[t.UNPACKED_LFO_KEY_SYNC]&t.MASK_1BIT,E=e[t.UNPACKED_LFO_WAVE]&t.MASK_3BIT,o=e[t.UNPACKED_LFO_PM_SENS]&t.MASK_3BIT;i[t.OFFSET_LFO_SYNC_WAVE]=r|E<<1|o<<4,i[t.OFFSET_AMP_MOD_SENS]=e[t.UNPACKED_AMP_MOD_SENS],i[t.OFFSET_TRANSPOSE]=e[t.UNPACKED_TRANSPOSE],i[t.OFFSET_EG_BIAS_SENS]=e[t.UNPACKED_EG_BIAS_SENS]}static _packName(e,i){for(let n=0;n<t.NAME_LENGTH;n++)i[t.PACKED_NAME_START+n]=e[t.UNPACKED_NAME_START+n]}static createDefault(e=0){const i=new Uint8Array(t.UNPACKED_SIZE);for(let r=0;r<t.NUM_OPERATORS;r++){const E=r*t.UNPACKED_OP_SIZE;i[E+t.UNPACKED_OP_EG_RATE_1]=t.DEFAULT_EG_RATE,i[E+t.UNPACKED_OP_EG_RATE_2]=t.DEFAULT_EG_RATE,i[E+t.UNPACKED_OP_EG_RATE_3]=t.DEFAULT_EG_RATE,i[E+t.UNPACKED_OP_EG_RATE_4]=t.DEFAULT_EG_RATE,i[E+t.UNPACKED_OP_EG_LEVEL_1]=t.DEFAULT_EG_LEVEL_MAX,i[E+t.UNPACKED_OP_EG_LEVEL_2]=t.DEFAULT_EG_LEVEL_MAX,i[E+t.UNPACKED_OP_EG_LEVEL_3]=t.DEFAULT_EG_LEVEL_MAX,i[E+t.UNPACKED_OP_EG_LEVEL_4]=t.DEFAULT_EG_LEVEL_MIN,i[E+t.UNPACKED_OP_BREAK_POINT]=t.DEFAULT_BREAK_POINT,i[E+t.UNPACKED_OP_L_SCALE_DEPTH]=0,i[E+t.UNPACKED_OP_R_SCALE_DEPTH]=0,i[E+t.UNPACKED_OP_L_CURVE]=0,i[E+t.UNPACKED_OP_R_CURVE]=0,i[E+t.UNPACKED_OP_RATE_SCALING]=0,i[E+t.UNPACKED_OP_DETUNE]=t.DEFAULT_DETUNE,i[E+t.UNPACKED_OP_AMP_MOD_SENS]=0,i[E+t.UNPACKED_OP_KEY_VEL_SENS]=0,i[E+t.UNPACKED_OP_OUTPUT_LEVEL]=t.DEFAULT_OUTPUT_LEVEL,i[E+t.UNPACKED_OP_MODE]=0,i[E+t.UNPACKED_OP_FREQ_COARSE]=t.DEFAULT_FREQ_COARSE,i[E+t.UNPACKED_OP_OSC_DETUNE]=0,i[E+t.UNPACKED_OP_FREQ_FINE]=0}i[t.UNPACKED_PITCH_EG_RATE_1]=t.DEFAULT_EG_RATE,i[t.UNPACKED_PITCH_EG_RATE_2]=t.DEFAULT_EG_RATE,i[t.UNPACKED_PITCH_EG_RATE_3]=t.DEFAULT_EG_RATE,i[t.UNPACKED_PITCH_EG_RATE_4]=t.DEFAULT_EG_RATE,i[t.UNPACKED_PITCH_EG_LEVEL_1]=t.DEFAULT_PITCH_EG_LEVEL,i[t.UNPACKED_PITCH_EG_LEVEL_2]=t.DEFAULT_PITCH_EG_LEVEL,i[t.UNPACKED_PITCH_EG_LEVEL_3]=t.DEFAULT_PITCH_EG_LEVEL,i[t.UNPACKED_PITCH_EG_LEVEL_4]=t.DEFAULT_PITCH_EG_LEVEL,i[t.UNPACKED_ALGORITHM]=t.DEFAULT_ALGORITHM,i[t.UNPACKED_FEEDBACK]=t.DEFAULT_FEEDBACK,i[t.UNPACKED_OSC_SYNC]=t.DEFAULT_OSC_SYNC,i[t.UNPACKED_LFO_SPEED]=t.DEFAULT_LFO_SPEED,i[t.UNPACKED_LFO_DELAY]=0,i[t.UNPACKED_LFO_PM_DEPTH]=0,i[t.UNPACKED_LFO_AM_DEPTH]=0,i[t.UNPACKED_LFO_KEY_SYNC]=t.DEFAULT_LFO_KEY_SYNC,i[t.UNPACKED_LFO_WAVE]=0,i[t.UNPACKED_LFO_PM_SENS]=t.DEFAULT_LFO_PM_SENS,i[t.UNPACKED_AMP_MOD_SENS]=0,i[t.UNPACKED_TRANSPOSE]=t.TRANSPOSE_CENTER,i[t.UNPACKED_EG_BIAS_SENS]=0;const n="Init Voice";for(let r=0;r<t.NAME_LENGTH;r++)i[t.UNPACKED_NAME_START+r]=r<n.length?n.charCodeAt(r):t.CHAR_SPACE;const s=t.pack(i);return new t(s,e)}static fromUnpacked(e,i=0){const n=t.pack(e);return new t(n,i)}static async fromFile(e){return new Promise((i,n)=>{const s=new FileReader;s.onload=r=>{try{const E=new Uint8Array(r.target.result);if(E[0]!==t.VCED_SYSEX_START||E[1]!==t.VCED_YAMAHA_ID||E[2]!==t.VCED_SUB_STATUS||E[3]!==t.VCED_FORMAT_SINGLE||E[4]!==t.VCED_BYTE_COUNT_MSB||E[5]!==t.VCED_BYTE_COUNT_LSB)throw new g("Invalid VCED header","header",0);const o=E.subarray(t.VCED_HEADER_SIZE,t.VCED_HEADER_SIZE+t.VCED_DATA_SIZE),h=E[t.VCED_HEADER_SIZE+t.VCED_DATA_SIZE],N=G._calculateChecksum(o,t.VCED_DATA_SIZE);h!==N&&console.warn(`DX7 VCED checksum mismatch (expected ${N.toString(16)}, got ${h.toString(16)}). This is common with vintage SysEx files.`);const u=new Uint8Array(t.UNPACKED_SIZE);let a=0;for(let S=0;S<t.NUM_OPERATORS;S++){const D=(t.NUM_OPERATORS-1-S)*t.UNPACKED_OP_SIZE;u[D+t.UNPACKED_OP_EG_RATE_1]=o[a++],u[D+t.UNPACKED_OP_EG_RATE_2]=o[a++],u[D+t.UNPACKED_OP_EG_RATE_3]=o[a++],u[D+t.UNPACKED_OP_EG_RATE_4]=o[a++],u[D+t.UNPACKED_OP_EG_LEVEL_1]=o[a++],u[D+t.UNPACKED_OP_EG_LEVEL_2]=o[a++],u[D+t.UNPACKED_OP_EG_LEVEL_3]=o[a++],u[D+t.UNPACKED_OP_EG_LEVEL_4]=o[a++],u[D+t.UNPACKED_OP_BREAK_POINT]=o[a++],u[D+t.UNPACKED_OP_L_SCALE_DEPTH]=o[a++],u[D+t.UNPACKED_OP_R_SCALE_DEPTH]=o[a++],u[D+t.UNPACKED_OP_L_CURVE]=o[a++],u[D+t.UNPACKED_OP_R_CURVE]=o[a++],u[D+t.UNPACKED_OP_RATE_SCALING]=o[a++],u[D+t.UNPACKED_OP_DETUNE]=o[a++];const T=o[a++];u[D+t.UNPACKED_OP_AMP_MOD_SENS]=T&t.MASK_2BIT,u[D+t.UNPACKED_OP_KEY_VEL_SENS]=T>>2&t.MASK_3BIT,u[D+t.UNPACKED_OP_OUTPUT_LEVEL]=o[a++],u[D+t.UNPACKED_OP_MODE]=o[a++],u[D+t.UNPACKED_OP_FREQ_COARSE]=o[a++],u[D+t.UNPACKED_OP_FREQ_FINE]=o[a++],u[D+t.UNPACKED_OP_OSC_DETUNE]=o[a++]}u[t.UNPACKED_PITCH_EG_RATE_1]=o[a++],u[t.UNPACKED_PITCH_EG_RATE_2]=o[a++],u[t.UNPACKED_PITCH_EG_RATE_3]=o[a++],u[t.UNPACKED_PITCH_EG_RATE_4]=o[a++],u[t.UNPACKED_PITCH_EG_LEVEL_1]=o[a++],u[t.UNPACKED_PITCH_EG_LEVEL_2]=o[a++],u[t.UNPACKED_PITCH_EG_LEVEL_3]=o[a++],u[t.UNPACKED_PITCH_EG_LEVEL_4]=o[a++],u[t.UNPACKED_ALGORITHM]=o[a++],u[t.UNPACKED_FEEDBACK]=o[a++],u[t.UNPACKED_OSC_SYNC]=o[a++],u[t.UNPACKED_LFO_SPEED]=o[a++],u[t.UNPACKED_LFO_DELAY]=o[a++],u[t.UNPACKED_LFO_PM_DEPTH]=o[a++],u[t.UNPACKED_LFO_AM_DEPTH]=o[a++],u[t.UNPACKED_LFO_KEY_SYNC]=o[a++],u[t.UNPACKED_LFO_WAVE]=o[a++],u[t.UNPACKED_LFO_PM_SENS]=o[a++],u[t.UNPACKED_TRANSPOSE]=o[a++];for(let S=0;S<t.NAME_LENGTH;S++)u[t.UNPACKED_NAME_START+S]=o[a++];const C=t.pack(u);i(new t(C,0))}catch(E){n(E)}},s.onerror=()=>n(new Error("Failed to read file")),s.readAsArrayBuffer(e)})}static fromSysEx(e,i=0){const n=e instanceof Uint8Array?e:new Uint8Array(e);let s;if(n[0]===t.VCED_SYSEX_START){if(n[0]!==t.VCED_SYSEX_START||n[1]!==t.VCED_YAMAHA_ID||n[2]!==t.VCED_SUB_STATUS||n[3]!==t.VCED_FORMAT_SINGLE||n[4]!==t.VCED_BYTE_COUNT_MSB||n[5]!==t.VCED_BYTE_COUNT_LSB)throw new g("Invalid VCED header","header",0);s=n.subarray(t.VCED_HEADER_SIZE,t.VCED_HEADER_SIZE+t.VCED_DATA_SIZE)}else if(n.length===t.PACKED_SIZE)s=n;else throw new d(`Invalid data length: expected ${t.PACKED_SIZE} or ${t.VCED_SIZE} bytes, got ${n.length}`,"length",n.length);if(s.length!==t.VCED_DATA_SIZE&&s.length!==t.PACKED_SIZE)throw new d(`Invalid voice data length: expected ${t.VCED_DATA_SIZE} or ${t.PACKED_SIZE} bytes, got ${s.length}`,"length",s.length);if(s.length===t.VCED_DATA_SIZE){const r=new Uint8Array(t.UNPACKED_SIZE);let E=0;for(let h=0;h<t.NUM_OPERATORS;h++){const N=(t.NUM_OPERATORS-1-h)*t.UNPACKED_OP_SIZE;r[N+t.UNPACKED_OP_EG_RATE_1]=s[E++],r[N+t.UNPACKED_OP_EG_RATE_2]=s[E++],r[N+t.UNPACKED_OP_EG_RATE_3]=s[E++],r[N+t.UNPACKED_OP_EG_RATE_4]=s[E++],r[N+t.UNPACKED_OP_EG_LEVEL_1]=s[E++],r[N+t.UNPACKED_OP_EG_LEVEL_2]=s[E++],r[N+t.UNPACKED_OP_EG_LEVEL_3]=s[E++],r[N+t.UNPACKED_OP_EG_LEVEL_4]=s[E++],r[N+t.UNPACKED_OP_BREAK_POINT]=s[E++],r[N+t.UNPACKED_OP_L_SCALE_DEPTH]=s[E++],r[N+t.UNPACKED_OP_R_SCALE_DEPTH]=s[E++],r[N+t.UNPACKED_OP_L_CURVE]=s[E++],r[N+t.UNPACKED_OP_R_CURVE]=s[E++],r[N+t.UNPACKED_OP_RATE_SCALING]=s[E++],r[N+t.UNPACKED_OP_DETUNE]=s[E++];const u=s[E++];r[N+t.UNPACKED_OP_AMP_MOD_SENS]=u&t.MASK_2BIT,r[N+t.UNPACKED_OP_KEY_VEL_SENS]=u>>2&t.MASK_3BIT,r[N+t.UNPACKED_OP_OUTPUT_LEVEL]=s[E++],r[N+t.UNPACKED_OP_MODE]=s[E++],r[N+t.UNPACKED_OP_FREQ_COARSE]=s[E++],r[N+t.UNPACKED_OP_FREQ_FINE]=s[E++],r[N+t.UNPACKED_OP_OSC_DETUNE]=s[E++]}r[t.UNPACKED_PITCH_EG_RATE_1]=s[E++],r[t.UNPACKED_PITCH_EG_RATE_2]=s[E++],r[t.UNPACKED_PITCH_EG_RATE_3]=s[E++],r[t.UNPACKED_PITCH_EG_RATE_4]=s[E++],r[t.UNPACKED_PITCH_EG_LEVEL_1]=s[E++],r[t.UNPACKED_PITCH_EG_LEVEL_2]=s[E++],r[t.UNPACKED_PITCH_EG_LEVEL_3]=s[E++],r[t.UNPACKED_PITCH_EG_LEVEL_4]=s[E++],r[t.UNPACKED_ALGORITHM]=s[E++],r[t.UNPACKED_FEEDBACK]=s[E++],r[t.UNPACKED_OSC_SYNC]=s[E++],r[t.UNPACKED_LFO_SPEED]=s[E++],r[t.UNPACKED_LFO_DELAY]=s[E++],r[t.UNPACKED_LFO_PM_DEPTH]=s[E++],r[t.UNPACKED_LFO_AM_DEPTH]=s[E++],r[t.UNPACKED_LFO_KEY_SYNC]=s[E++],r[t.UNPACKED_LFO_WAVE]=s[E++],r[t.UNPACKED_LFO_PM_SENS]=s[E++],r[t.UNPACKED_TRANSPOSE]=s[E++];for(let h=0;h<t.NAME_LENGTH;h++)r[t.UNPACKED_NAME_START+h]=s[E++];const o=t.pack(r);return new t(o,i)}return new t(s,i)}static fromJSON(e,i=0){if(!e||typeof e!="object")throw new d("Invalid JSON: expected object","json",e);const n=new Uint8Array(t.UNPACKED_SIZE),s=(a,C,S,D=0,T=127)=>{if(C==null)throw new d(`Missing required parameter: ${S}`,S,C);const f=Number(C);if(Number.isNaN(f))throw new d(`Invalid parameter value for ${S}: ${C}`,S,C);if(f<D||f>T)throw new d(`Parameter ${S} out of range: ${f} (must be ${D}-${T})`,S,f);n[a]=Math.floor(f)},r=a=>{const C={"-LN":0,"-EX":1,"+EX":2,"+LN":3};return C[a]!==void 0?C[a]:0},E=a=>{const C={TRIANGLE:0,"SAW DOWN":1,"SAW UP":2,SQUARE:3,SINE:4,"SAMPLE & HOLD":5};return C[a]!==void 0?C[a]:0},o=a=>{if(!a||typeof a!="string")return 60;const C=a.trim().match(/^([A-G]#?)(-?\d+)$/);if(!C)return 60;const[,S,D]=C,T=parseInt(D,10),U={C:0,"C#":1,D:2,"D#":3,E:4,F:5,"F#":6,G:7,"G#":8,A:9,"A#":10,B:11}[S.toUpperCase()];return U===void 0?60:(T-t.MIDI_OCTAVE_OFFSET)*12+U};if(!Array.isArray(e.operators))throw new d("Invalid operators array: expected array","operators",e.operators);for(let a=0;a<e.operators.length;a++){const C=e.operators[a];if(!C||typeof C!="object")throw new d(`Invalid operator data at index ${a}`,`operators[${a}]`,C);if(!C.eg||!Array.isArray(C.eg.rates)||C.eg.rates.length!==4)throw new d(`Invalid EG rates for operator ${a}`,`operators[${a}].eg.rates`,C.eg?.rates);if(!C.eg||!Array.isArray(C.eg.levels)||C.eg.levels.length!==4)throw new d(`Invalid EG levels for operator ${a}`,`operators[${a}].eg.levels`,C.eg?.levels)}if(e.operators.length!==t.NUM_OPERATORS)throw new d(`Invalid operators array: expected ${t.NUM_OPERATORS} operators`,"operators",e.operators);for(let a=0;a<t.NUM_OPERATORS;a++){const C=e.operators[a],S=a*t.UNPACKED_OP_SIZE;if(!C.eg||!Array.isArray(C.eg.rates)||C.eg.rates.length!==4)throw new d(`Invalid EG rates for operator ${a}`,`operators[${a}].eg.rates`,C.eg?.rates);if(s(S+t.UNPACKED_OP_EG_RATE_1,C.eg.rates[0],`operators[${a}].eg.rates[0]`,0,99),s(S+t.UNPACKED_OP_EG_RATE_2,C.eg.rates[1],`operators[${a}].eg.rates[1]`,0,99),s(S+t.UNPACKED_OP_EG_RATE_3,C.eg.rates[2],`operators[${a}].eg.rates[2]`,0,99),s(S+t.UNPACKED_OP_EG_RATE_4,C.eg.rates[3],`operators[${a}].eg.rates[3]`,0,99),!C.eg||!Array.isArray(C.eg.levels)||C.eg.levels.length!==4)throw new d(`Invalid EG levels for operator ${a}`,`operators[${a}].eg.levels`,C.eg?.levels);s(S+t.UNPACKED_OP_EG_LEVEL_1,C.eg.levels[0],`operators[${a}].eg.levels[0]`,0,99),s(S+t.UNPACKED_OP_EG_LEVEL_2,C.eg.levels[1],`operators[${a}].eg.levels[1]`,0,99),s(S+t.UNPACKED_OP_EG_LEVEL_3,C.eg.levels[2],`operators[${a}].eg.levels[2]`,0,99),s(S+t.UNPACKED_OP_EG_LEVEL_4,C.eg.levels[3],`operators[${a}].eg.levels[3]`,0,99);const D=o(C.key?.breakPoint)-t.MIDI_BREAK_POINT_OFFSET;s(S+t.UNPACKED_OP_BREAK_POINT,D,`operators[${a}].key.breakPoint`,0,127),s(S+t.UNPACKED_OP_L_SCALE_DEPTH,C.scale?.left?.depth||0,`operators[${a}].scale.left.depth`,0,99),s(S+t.UNPACKED_OP_R_SCALE_DEPTH,C.scale?.right?.depth||0,`operators[${a}].scale.right.depth`,0,99),n[S+t.UNPACKED_OP_L_CURVE]=r(C.scale?.left?.curve||"-LN"),n[S+t.UNPACKED_OP_R_CURVE]=r(C.scale?.right?.curve||"-LN"),s(S+t.UNPACKED_OP_RATE_SCALING,C.key?.scaling||0,`operators[${a}].key.scaling`,0,7);const T=Number(C.osc?.detune)||0;s(S+t.UNPACKED_OP_DETUNE,T+7,`operators[${a}].osc.detune`,0,14),s(S+t.UNPACKED_OP_AMP_MOD_SENS,C.output?.ampModSens||0,`operators[${a}].output.ampModSens`,0,3),s(S+t.UNPACKED_OP_OUTPUT_LEVEL,C.output?.level||0,`operators[${a}].output.level`,0,99);const f=C.osc?.freq?.mode?.toUpperCase()==="FIXED"?1:0,U=Number(C.osc?.freq?.coarse)||0,L=Number(C.osc?.freq?.fine)||0;n[S+t.UNPACKED_OP_MODE]=f,s(S+t.UNPACKED_OP_FREQ_COARSE,U,`operators[${a}].osc.freq.coarse`,0,31),s(S+t.UNPACKED_OP_FREQ_FINE,L,`operators[${a}].osc.freq.fine`,0,15),s(S+t.UNPACKED_OP_KEY_VEL_SENS,C.key?.velocity||0,`operators[${a}].key.velocity`,0,7)}if(!e.pitchEG||!Array.isArray(e.pitchEG.rates)||e.pitchEG.rates.length!==4)throw new d("Invalid pitch EG rates","pitchEG.rates",e.pitchEG?.rates);if(!e.pitchEG||!Array.isArray(e.pitchEG.levels)||e.pitchEG.levels.length!==4)throw new d("Invalid pitch EG levels","pitchEG.levels",e.pitchEG?.levels);if(s(t.UNPACKED_PITCH_EG_RATE_1,e.pitchEG.rates[0],"pitchEG.rates[0]",0,99),s(t.UNPACKED_PITCH_EG_RATE_2,e.pitchEG.rates[1],"pitchEG.rates[1]",0,99),s(t.UNPACKED_PITCH_EG_RATE_3,e.pitchEG.rates[2],"pitchEG.rates[2]",0,99),s(t.UNPACKED_PITCH_EG_RATE_4,e.pitchEG.rates[3],"pitchEG.rates[3]",0,99),s(t.UNPACKED_PITCH_EG_LEVEL_1,e.pitchEG.levels[0],"pitchEG.levels[0]",0,99),s(t.UNPACKED_PITCH_EG_LEVEL_2,e.pitchEG.levels[1],"pitchEG.levels[1]",0,99),s(t.UNPACKED_PITCH_EG_LEVEL_3,e.pitchEG.levels[2],"pitchEG.levels[2]",0,99),s(t.UNPACKED_PITCH_EG_LEVEL_4,e.pitchEG.levels[3],"pitchEG.levels[3]",0,99),!e.lfo||typeof e.lfo!="object")throw new d("Invalid LFO data","lfo",e.lfo);if(s(t.UNPACKED_LFO_SPEED,e.lfo.speed,"lfo.speed",0,99),s(t.UNPACKED_LFO_DELAY,e.lfo.delay,"lfo.delay",0,99),s(t.UNPACKED_LFO_PM_DEPTH,e.lfo.pmDepth,"lfo.pmDepth",0,99),s(t.UNPACKED_LFO_AM_DEPTH,e.lfo.amDepth,"lfo.amDepth",0,99),n[t.UNPACKED_LFO_KEY_SYNC]=e.lfo.keySync?1:0,n[t.UNPACKED_LFO_WAVE]=E(e.lfo.wave),!e.global||typeof e.global!="object")throw new d("Invalid global data","global",e.global);const h=Number(e.global.algorithm)||1;s(t.UNPACKED_ALGORITHM,h-1,"global.algorithm",0,31),s(t.UNPACKED_FEEDBACK,e.global.feedback,"global.feedback",0,7),n[t.UNPACKED_OSC_SYNC]=e.global.oscKeySync?1:0,s(t.UNPACKED_LFO_PM_SENS,e.global.pitchModSens,"global.pitchModSens",0,7);const N=Number(e.global.transpose)||0;s(t.UNPACKED_TRANSPOSE,N+t.TRANSPOSE_CENTER,"global.transpose",0,127),s(t.UNPACKED_AMP_MOD_SENS,e.global.ampModSens||0,"global.ampModSens",0,3),s(t.UNPACKED_EG_BIAS_SENS,e.global.egBiasSens||0,"global.egBiasSens",0,7);const u=e.name||"";for(let a=0;a<t.NAME_LENGTH;a++)n[t.UNPACKED_NAME_START+a]=a<u.length?u.charCodeAt(a):t.CHAR_SPACE;return t.fromUnpacked(n,i)}toSysEx(){const e=this.unpack(),i=new Uint8Array(t.VCED_SIZE);let n=0;i[n++]=t.VCED_SYSEX_START,i[n++]=t.VCED_YAMAHA_ID,i[n++]=t.VCED_SUB_STATUS,i[n++]=t.VCED_FORMAT_SINGLE,i[n++]=t.VCED_BYTE_COUNT_MSB,i[n++]=t.VCED_BYTE_COUNT_LSB;for(let r=t.NUM_OPERATORS-1;r>=0;r--){const E=r*t.UNPACKED_OP_SIZE;i[n++]=e[E+t.UNPACKED_OP_EG_RATE_1],i[n++]=e[E+t.UNPACKED_OP_EG_RATE_2],i[n++]=e[E+t.UNPACKED_OP_EG_RATE_3],i[n++]=e[E+t.UNPACKED_OP_EG_RATE_4],i[n++]=e[E+t.UNPACKED_OP_EG_LEVEL_1],i[n++]=e[E+t.UNPACKED_OP_EG_LEVEL_2],i[n++]=e[E+t.UNPACKED_OP_EG_LEVEL_3],i[n++]=e[E+t.UNPACKED_OP_EG_LEVEL_4],i[n++]=e[E+t.UNPACKED_OP_BREAK_POINT],i[n++]=e[E+t.UNPACKED_OP_L_SCALE_DEPTH],i[n++]=e[E+t.UNPACKED_OP_R_SCALE_DEPTH],i[n++]=e[E+t.UNPACKED_OP_L_CURVE],i[n++]=e[E+t.UNPACKED_OP_R_CURVE],i[n++]=e[E+t.UNPACKED_OP_RATE_SCALING],i[n++]=e[E+t.UNPACKED_OP_DETUNE];const o=e[E+t.UNPACKED_OP_AMP_MOD_SENS]&t.MASK_2BIT,h=e[E+t.UNPACKED_OP_KEY_VEL_SENS]&t.MASK_3BIT;i[n++]=o|h<<2,i[n++]=e[E+t.UNPACKED_OP_OUTPUT_LEVEL],i[n++]=e[E+t.UNPACKED_OP_MODE],i[n++]=e[E+t.UNPACKED_OP_FREQ_COARSE],i[n++]=e[E+t.UNPACKED_OP_OSC_DETUNE],i[n++]=e[E+t.UNPACKED_OP_FREQ_FINE]}i[n++]=e[t.UNPACKED_PITCH_EG_RATE_1],i[n++]=e[t.UNPACKED_PITCH_EG_RATE_2],i[n++]=e[t.UNPACKED_PITCH_EG_RATE_3],i[n++]=e[t.UNPACKED_PITCH_EG_RATE_4],i[n++]=e[t.UNPACKED_PITCH_EG_LEVEL_1],i[n++]=e[t.UNPACKED_PITCH_EG_LEVEL_2],i[n++]=e[t.UNPACKED_PITCH_EG_LEVEL_3],i[n++]=e[t.UNPACKED_PITCH_EG_LEVEL_4],i[n++]=e[t.UNPACKED_ALGORITHM],i[n++]=e[t.UNPACKED_FEEDBACK],i[n++]=e[t.UNPACKED_OSC_SYNC],i[n++]=e[t.UNPACKED_LFO_SPEED],i[n++]=e[t.UNPACKED_LFO_DELAY],i[n++]=e[t.UNPACKED_LFO_PM_DEPTH],i[n++]=e[t.UNPACKED_LFO_AM_DEPTH],i[n++]=e[t.UNPACKED_LFO_KEY_SYNC],i[n++]=e[t.UNPACKED_LFO_WAVE],i[n++]=e[t.UNPACKED_LFO_PM_SENS],i[n++]=e[t.UNPACKED_TRANSPOSE];for(let r=0;r<t.NAME_LENGTH;r++)i[n++]=e[t.UNPACKED_NAME_START+r];const s=i.subarray(t.VCED_HEADER_SIZE,t.VCED_HEADER_SIZE+t.VCED_DATA_SIZE);return i[n++]=G._calculateChecksum(s,t.VCED_DATA_SIZE),i[n++]=t.VCED_SYSEX_END,i}toJSON(){const e=this.unpack(),i=[],n=E=>["-LN","-EX","+EX","+LN"][E]||"UNKNOWN",s=E=>["TRIANGLE","SAW DOWN","SAW UP","SQUARE","SINE","SAMPLE & HOLD"][E]||"UNKNOWN",r=E=>{const o=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],h=Math.floor(E/12)+t.MIDI_OCTAVE_OFFSET;return`${o[E%12]}${h}`};for(let E=0;E<t.NUM_OPERATORS;E++){const o=E*t.UNPACKED_OP_SIZE,h=e[o+t.UNPACKED_OP_MODE]===0?"RATIO":"FIXED";i.push({id:E+1,osc:{detune:e[o+t.UNPACKED_OP_OSC_DETUNE],freq:{coarse:e[o+t.UNPACKED_OP_FREQ_COARSE],fine:e[o+t.UNPACKED_OP_FREQ_FINE],mode:h}},eg:{rates:[e[o+t.UNPACKED_OP_EG_RATE_1],e[o+t.UNPACKED_OP_EG_RATE_2],e[o+t.UNPACKED_OP_EG_RATE_3],e[o+t.UNPACKED_OP_EG_RATE_4]],levels:[e[o+t.UNPACKED_OP_EG_LEVEL_1],e[o+t.UNPACKED_OP_EG_LEVEL_2],e[o+t.UNPACKED_OP_EG_LEVEL_3],e[o+t.UNPACKED_OP_EG_LEVEL_4]]},key:{velocity:e[o+t.UNPACKED_OP_KEY_VEL_SENS],scaling:e[o+t.UNPACKED_OP_RATE_SCALING],breakPoint:r(e[o+t.UNPACKED_OP_BREAK_POINT]+t.MIDI_BREAK_POINT_OFFSET)},output:{level:e[o+t.UNPACKED_OP_OUTPUT_LEVEL],ampModSens:e[o+t.UNPACKED_OP_AMP_MOD_SENS]},scale:{left:{depth:e[o+t.UNPACKED_OP_L_SCALE_DEPTH],curve:n(e[o+t.UNPACKED_OP_L_CURVE])},right:{depth:e[o+t.UNPACKED_OP_R_SCALE_DEPTH],curve:n(e[o+t.UNPACKED_OP_R_CURVE])}}})}return{name:this.name||"(Empty)",operators:i,pitchEG:{rates:[e[t.UNPACKED_PITCH_EG_RATE_1],e[t.UNPACKED_PITCH_EG_RATE_2],e[t.UNPACKED_PITCH_EG_RATE_3],e[t.UNPACKED_PITCH_EG_RATE_4]],levels:[e[t.UNPACKED_PITCH_EG_LEVEL_1],e[t.UNPACKED_PITCH_EG_LEVEL_2],e[t.UNPACKED_PITCH_EG_LEVEL_3],e[t.UNPACKED_PITCH_EG_LEVEL_4]]},lfo:{speed:e[t.UNPACKED_LFO_SPEED],delay:e[t.UNPACKED_LFO_DELAY],pmDepth:e[t.UNPACKED_LFO_PM_DEPTH],amDepth:e[t.UNPACKED_LFO_AM_DEPTH],keySync:e[t.UNPACKED_LFO_KEY_SYNC]===1,wave:s(e[t.UNPACKED_LFO_WAVE])},global:{algorithm:e[t.UNPACKED_ALGORITHM]+1,feedback:e[t.UNPACKED_FEEDBACK],oscKeySync:e[t.UNPACKED_OSC_SYNC]===1,pitchModSens:e[t.UNPACKED_LFO_PM_SENS],transpose:e[t.UNPACKED_TRANSPOSE]-t.TRANSPOSE_CENTER}}}};_(t,"PACKED_SIZE",128),_(t,"PACKED_OP_SIZE",17),_(t,"NUM_OPERATORS",6),_(t,"PACKED_OP_EG_RATE_1",0),_(t,"PACKED_OP_EG_RATE_2",1),_(t,"PACKED_OP_EG_RATE_3",2),_(t,"PACKED_OP_EG_RATE_4",3),_(t,"PACKED_OP_EG_LEVEL_1",4),_(t,"PACKED_OP_EG_LEVEL_2",5),_(t,"PACKED_OP_EG_LEVEL_3",6),_(t,"PACKED_OP_EG_LEVEL_4",7),_(t,"PACKED_OP_BREAK_POINT",8),_(t,"PACKED_OP_L_SCALE_DEPTH",9),_(t,"PACKED_OP_R_SCALE_DEPTH",10),_(t,"PACKED_OP_CURVES",11),_(t,"PACKED_OP_RATE_SCALING",12),_(t,"PACKED_OP_MOD_SENS",13),_(t,"PACKED_OP_OUTPUT_LEVEL",14),_(t,"PACKED_OP_MODE_FREQ",15),_(t,"PACKED_OP_DETUNE_FINE",16),_(t,"PACKED_PITCH_EG_RATE_1",102),_(t,"PACKED_PITCH_EG_RATE_2",103),_(t,"PACKED_PITCH_EG_RATE_3",104),_(t,"PACKED_PITCH_EG_RATE_4",105),_(t,"PACKED_PITCH_EG_LEVEL_1",106),_(t,"PACKED_PITCH_EG_LEVEL_2",107),_(t,"PACKED_PITCH_EG_LEVEL_3",108),_(t,"PACKED_PITCH_EG_LEVEL_4",109),_(t,"OFFSET_ALGORITHM",110),_(t,"OFFSET_FEEDBACK",111),_(t,"OFFSET_LFO_SPEED",112),_(t,"OFFSET_LFO_DELAY",113),_(t,"OFFSET_LFO_PM_DEPTH",114),_(t,"OFFSET_LFO_AM_DEPTH",115),_(t,"OFFSET_LFO_SYNC_WAVE",116),_(t,"OFFSET_TRANSPOSE",117),_(t,"OFFSET_AMP_MOD_SENS",118),_(t,"OFFSET_EG_BIAS_SENS",119),_(t,"PACKED_NAME_START",118),_(t,"NAME_LENGTH",10),_(t,"UNPACKED_SIZE",169),_(t,"UNPACKED_OP_SIZE",23),_(t,"UNPACKED_OP_EG_RATE_1",0),_(t,"UNPACKED_OP_EG_RATE_2",1),_(t,"UNPACKED_OP_EG_RATE_3",2),_(t,"UNPACKED_OP_EG_RATE_4",3),_(t,"UNPACKED_OP_EG_LEVEL_1",4),_(t,"UNPACKED_OP_EG_LEVEL_2",5),_(t,"UNPACKED_OP_EG_LEVEL_3",6),_(t,"UNPACKED_OP_EG_LEVEL_4",7),_(t,"UNPACKED_OP_BREAK_POINT",8),_(t,"UNPACKED_OP_L_SCALE_DEPTH",9),_(t,"UNPACKED_OP_R_SCALE_DEPTH",10),_(t,"UNPACKED_OP_L_CURVE",11),_(t,"UNPACKED_OP_R_CURVE",12),_(t,"UNPACKED_OP_RATE_SCALING",13),_(t,"UNPACKED_OP_DETUNE",14),_(t,"UNPACKED_OP_AMP_MOD_SENS",15),_(t,"UNPACKED_OP_OUTPUT_LEVEL",16),_(t,"UNPACKED_OP_MODE",17),_(t,"UNPACKED_OP_KEY_VEL_SENS",18),_(t,"UNPACKED_OP_FREQ_COARSE",19),_(t,"UNPACKED_OP_OSC_DETUNE",20),_(t,"UNPACKED_OP_FREQ_FINE",21),_(t,"UNPACKED_PITCH_EG_RATE_1",138),_(t,"UNPACKED_PITCH_EG_RATE_2",139),_(t,"UNPACKED_PITCH_EG_RATE_3",140),_(t,"UNPACKED_PITCH_EG_RATE_4",141),_(t,"UNPACKED_PITCH_EG_LEVEL_1",142),_(t,"UNPACKED_PITCH_EG_LEVEL_2",143),_(t,"UNPACKED_PITCH_EG_LEVEL_3",144),_(t,"UNPACKED_PITCH_EG_LEVEL_4",145),_(t,"UNPACKED_ALGORITHM",146),_(t,"UNPACKED_FEEDBACK",147),_(t,"UNPACKED_OSC_SYNC",148),_(t,"UNPACKED_LFO_SPEED",149),_(t,"UNPACKED_LFO_DELAY",150),_(t,"UNPACKED_LFO_PM_DEPTH",151),_(t,"UNPACKED_LFO_AM_DEPTH",152),_(t,"UNPACKED_LFO_KEY_SYNC",153),_(t,"UNPACKED_LFO_WAVE",154),_(t,"UNPACKED_LFO_PM_SENS",155),_(t,"UNPACKED_AMP_MOD_SENS",156),_(t,"UNPACKED_TRANSPOSE",157),_(t,"UNPACKED_EG_BIAS_SENS",158),_(t,"UNPACKED_NAME_START",159),_(t,"VCED_SIZE",163),_(t,"VCED_HEADER_SIZE",6),_(t,"VCED_DATA_SIZE",155),_(t,"VCED_SYSEX_START",240),_(t,"VCED_YAMAHA_ID",67),_(t,"VCED_SUB_STATUS",0),_(t,"VCED_FORMAT_SINGLE",0),_(t,"VCED_BYTE_COUNT_MSB",1),_(t,"VCED_BYTE_COUNT_LSB",27),_(t,"VCED_SYSEX_END",247),_(t,"MASK_7BIT",127),_(t,"MASK_2BIT",3),_(t,"MASK_3BIT",7),_(t,"MASK_4BIT",15),_(t,"MASK_5BIT",31),_(t,"MASK_1BIT",1),_(t,"TRANSPOSE_CENTER",24),_(t,"CHAR_YEN",92),_(t,"CHAR_ARROW_RIGHT",126),_(t,"CHAR_ARROW_LEFT",127),_(t,"CHAR_REPLACEMENT_Y",89),_(t,"CHAR_REPLACEMENT_GT",62),_(t,"CHAR_REPLACEMENT_LT",60),_(t,"CHAR_SPACE",32),_(t,"CHAR_MIN_PRINTABLE",32),_(t,"CHAR_MAX_PRINTABLE",126),_(t,"DEFAULT_EG_RATE",99),_(t,"DEFAULT_EG_LEVEL_MAX",99),_(t,"DEFAULT_EG_LEVEL_MIN",0),_(t,"DEFAULT_BREAK_POINT",0),_(t,"DEFAULT_OUTPUT_LEVEL",99),_(t,"DEFAULT_PITCH_EG_LEVEL",50),_(t,"DEFAULT_LFO_SPEED",35),_(t,"DEFAULT_LFO_PM_SENS",3),_(t,"DEFAULT_DETUNE",7),_(t,"DEFAULT_FREQ_COARSE",1),_(t,"DEFAULT_ALGORITHM",0),_(t,"DEFAULT_FEEDBACK",0),_(t,"DEFAULT_OSC_SYNC",1),_(t,"DEFAULT_LFO_KEY_SYNC",1),_(t,"MIDI_OCTAVE_OFFSET",-2),_(t,"MIDI_BREAK_POINT_OFFSET",21);let m=t;const P=class P{constructor(e,i=""){if(this.voices=new Array(P.NUM_VOICES),this.name=i,e)this._load(e);else for(let n=0;n<P.NUM_VOICES;n++)this.voices[n]=m.createDefault(n)}static _calculateChecksum(e,i){let n=0;for(let s=0;s<i;s++)n+=e[s];return P.CHECKSUM_MODULO-n%P.CHECKSUM_MODULO&P.MASK_7BIT}_load(e){const i=e instanceof Uint8Array?e:new Uint8Array(e);let n,s=0;if(i[0]===P.SYSEX_START){const E=i.subarray(0,P.SYSEX_HEADER_SIZE),o=P.SYSEX_HEADER;for(let h=0;h<P.SYSEX_HEADER_SIZE;h++)if(E[h]!==o[h])throw new g(`Invalid SysEx header at position ${h}: expected ${o[h].toString(16)}, got ${E[h].toString(16)}`,"header",h);n=i.subarray(P.SYSEX_HEADER_SIZE,P.SYSEX_HEADER_SIZE+P.VOICE_DATA_SIZE),s=P.SYSEX_HEADER_SIZE}else if(i.length===P.VOICE_DATA_SIZE)n=i;else throw new d(`Invalid data length: expected ${P.VOICE_DATA_SIZE} or ${P.SYSEX_SIZE} bytes, got ${i.length}`,"length",i.length);if(n.length!==P.VOICE_DATA_SIZE)throw new d(`Invalid voice data length: expected ${P.VOICE_DATA_SIZE} bytes, got ${n.length}`,"length",n.length);const r=P.SYSEX_HEADER_SIZE+P.VOICE_DATA_SIZE;if(s>0&&i.length>=r+1){const E=i[r],o=P._calculateChecksum(n,P.VOICE_DATA_SIZE);E!==o&&console.warn(`DX7 checksum mismatch (expected ${o.toString(16)}, got ${E.toString(16)}). This is common with vintage SysEx files and the data is likely still valid.`)}this.voices=new Array(P.NUM_VOICES);for(let E=0;E<P.NUM_VOICES;E++){const o=E*P.VOICE_SIZE,h=n.subarray(o,o+P.VOICE_SIZE);this.voices[E]=new m(h,E)}}replaceVoice(e,i){if(e<0||e>=P.NUM_VOICES)throw new d(`Invalid voice index: ${e}`,"index",e);const n=new Uint8Array(i.data);this.voices[e]=new m(n,e)}addVoice(e){for(let i=0;i<this.voices.length;i++){const n=this.voices[i];if(n.name===""||n.name==="Init Voice")return this.replaceVoice(i,e),i}return-1}getVoices(){return this.voices}getVoice(e){return e<0||e>=this.voices.length?null:this.voices[e]}getVoiceNames(){return this.voices.map(e=>e.name)}findVoiceByName(e){const i=e.toLowerCase();return this.voices.find(n=>n.name.toLowerCase().includes(i))||null}static async fromFile(e){return new Promise((i,n)=>{const s=new FileReader;s.onload=async r=>{try{const E=e.name||"",o=new Uint8Array(r.target.result);if(o[0]===P.SYSEX_START&&o[3]===m.VCED_FORMAT_SINGLE)n(new g("This is a single voice file. Use DX7Voice.fromFile() instead.","format",3));else{const h=E.replace(/\.[^/.]+$/,""),N=new P(r.target.result,h);i(N)}}catch(E){n(E)}},s.onerror=()=>n(new Error("Failed to read file")),s.readAsArrayBuffer(e)})}static fromSysEx(e,i=""){return new P(e,i)}static fromJSON(e){if(!e||typeof e!="object")throw new d("Invalid JSON: expected object","json",e);const i=new P;if(i.name=e.name||"",!Array.isArray(e.voices))throw new d("Invalid voices array","voices",e.voices);e.voices.length!==P.NUM_VOICES&&console.warn(`Bank JSON has ${e.voices.length} voices, expected ${P.NUM_VOICES}. Missing voices will be filled with defaults.`);const n=Math.min(e.voices.length,P.NUM_VOICES);for(let s=0;s<n;s++){const r=e.voices[s];if(!r||typeof r!="object"){console.warn(`Invalid voice data at index ${s}, using default voice`);continue}try{const{index:E,...o}=r,h=m.fromJSON(o,s);i.replaceVoice(s,h)}catch(E){console.warn(`Failed to load voice at index ${s}: ${E.message}, using default voice`)}}return i}toSysEx(){const e=new Uint8Array(P.SYSEX_SIZE);let i=0;P.SYSEX_HEADER.forEach(s=>{e[i++]=s});for(const s of this.voices)for(let r=0;r<P.VOICE_SIZE;r++)e[i++]=s.data[r];const n=e.subarray(P.SYSEX_HEADER_SIZE,P.SYSEX_HEADER_SIZE+P.VOICE_DATA_SIZE);return e[i++]=P._calculateChecksum(n,P.VOICE_DATA_SIZE),e[i++]=P.SYSEX_END,e}toJSON(){const e=this.voices.map((i,n)=>{const s=i.toJSON();return{index:n+1,...s}});return{version:"1.0",name:this.name||"",voices:e}}};_(P,"SYSEX_START",240),_(P,"SYSEX_END",247),_(P,"SYSEX_YAMAHA_ID",67),_(P,"SYSEX_SUB_STATUS",0),_(P,"SYSEX_FORMAT_32_VOICES",9),_(P,"SYSEX_BYTE_COUNT_MSB",32),_(P,"SYSEX_BYTE_COUNT_LSB",0),_(P,"SYSEX_HEADER",[P.SYSEX_START,P.SYSEX_YAMAHA_ID,P.SYSEX_SUB_STATUS,P.SYSEX_FORMAT_32_VOICES,P.SYSEX_BYTE_COUNT_MSB,P.SYSEX_BYTE_COUNT_LSB]),_(P,"SYSEX_HEADER_SIZE",6),_(P,"VOICE_DATA_SIZE",4096),_(P,"SYSEX_SIZE",4104),_(P,"VOICE_SIZE",128),_(P,"NUM_VOICES",32),_(P,"CHECKSUM_MODULO",128),_(P,"MASK_7BIT",127);let G=P;function nt(c){return c[0]!==240||c[c.length-1]!==247?null:{manufacturerId:c[1],payload:c.slice(2,-1),raw:c}}function st(c,e){return[240,c,...e,247]}function Et(c){return c.length>=2&&c[0]===240&&c[c.length-1]===247}function rt(c){const e=[];for(let i=0;i<c.length;i+=7){const n=c.slice(i,i+7);let s=0;const r=[];for(let E=0;E<n.length;E++){const o=n[E];o&128&&(s|=1<<E),r.push(o&127)}e.push(s,...r)}return e}function ot(c){const e=[];for(let i=0;i<c.length;i+=8){const n=c[i],s=Math.min(7,c.length-i-1);for(let r=0;r<s;r++){let E=c[i+1+r];n&1<<r&&(E|=128),e.push(E)}}return e}function _t(c){return Number.isInteger(c)&&c>=1&&c<=16}function at(c){return Number.isInteger(c)&&c>=0&&c<=127}function ct(c){return Number.isInteger(c)&&c>=0&&c<=31}function Ct(c){return Number.isInteger(c)&&c>=0&&c<=127}function At(c){return Number.isInteger(c)&&c>=0&&c<=127}function Pt(c){return Number.isInteger(c)&&c>=0&&c<=127}function ut(c){return Number.isInteger(c)&&c>=0&&c<=127}function lt(c){return Number.isInteger(c)&&c>=0&&c<=16383}function ht(c,e){return Number.isInteger(c)&&c>=0&&c<=127&&Number.isInteger(e)&&e>=0&&e<=127}async function St(c={}){const{onStatusUpdate:e,onConnectionUpdate:i,inputChannel:n=1,outputChannel:s=1,output:r,sysex:E,onReady:o,onError:h,selector:N,watchDOM:u,...a}=c,S=await q({autoConnect:!1,sysex:E,inputChannel:n,outputChannel:s,selector:N||"[data-midi-cc]",watchDOM:u,onError:h,...a}),D=new z({midiController:S,onStatusUpdate:e||(()=>{}),onConnectionUpdate:i||(()=>{}),channel:s});if(r)try{await S.device.connectOutput(r),D.currentOutput=S.device.getCurrentOutput(),D.updateConnectionStatus()}catch(T){h?h(T):console.error("Failed to connect to MIDI device:",T.message)}return o&&o(S,D),D}async function q(c={}){const e=new Z(c);await e.init();const i=c.selector||"[data-midi-cc]";{const n=new I(e,i);n.bindAll(),c.watchDOM&&n.enableAutoBinding(),e._binder=n}return e}function Nt(){return typeof navigator<"u"&&typeof navigator.requestMIDIAccess=="function"}l.CONN=p,l.CONNECTION_EVENTS=p,l.CONTROLLER_EVENTS=A,l.CTRL=A,l.DX7Bank=G,l.DX7Error=H,l.DX7ParseError=g,l.DX7ValidationError=d,l.DX7Voice=m,l.DataAttributeBinder=I,l.EventEmitter=v,l.MIDIAccessError=F,l.MIDIConnection=$,l.MIDIConnectionError=y,l.MIDIController=Z,l.MIDIDeviceError=R,l.MIDIDeviceManager=z,l.MIDIError=K,l.MIDIValidationError=M,l.clamp=O,l.createMIDIController=q,l.createMIDIDeviceManager=St,l.createSysEx=st,l.decode14BitValue=Y,l.decode7Bit=ot,l.denormalize14BitValue=it,l.denormalizeValue=J,l.encode14BitValue=B,l.encode7Bit=rt,l.frequencyToNote=X,l.getCCName=et,l.isMIDISupported=Nt,l.isSysEx=Et,l.isValid14BitCC=ct,l.isValidCC=at,l.isValidChannel=_t,l.isValidMIDIValue=Ct,l.isValidNote=At,l.isValidPitchBend=lt,l.isValidPitchBendBytes=ht,l.isValidProgramChange=ut,l.isValidVelocity=Pt,l.normalize14BitValue=x,l.normalizeValue=w,l.noteNameToNumber=k,l.noteNumberToName=j,l.noteToFrequency=tt,l.parseSysEx=nt,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "midiwire",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Declarative JavaScript library for browser-based MIDI control",
5
5
  "type": "module",
6
6
  "main": "./dist/midiwire.umd.js",
package/src/index.js CHANGED
@@ -372,6 +372,33 @@ export async function createMIDIController(options = {}) {
372
372
  return controller
373
373
  }
374
374
 
375
+ /**
376
+ * Check if the browser supports the Web MIDI API.
377
+ * Returns true if `navigator.requestMIDIAccess` is available.
378
+ *
379
+ * @returns {boolean} True if Web MIDI is supported, false otherwise
380
+ *
381
+ * @example
382
+ * // Check before initializing
383
+ * if (isMIDISupported()) {
384
+ * const midi = await createMIDIController()
385
+ * } else {
386
+ * alert("Please use Chrome, Edge, or Opera for Web MIDI support")
387
+ * }
388
+ *
389
+ * @example
390
+ * // Conditional UI rendering
391
+ * const midiSection = document.getElementById("midi-controls")
392
+ * if (isMIDISupported()) {
393
+ * midiSection.style.display = "block"
394
+ * } else {
395
+ * midiSection.innerHTML = "<p>MIDI not supported in this browser</p>"
396
+ * }
397
+ */
398
+ export function isMIDISupported() {
399
+ return typeof navigator !== "undefined" && typeof navigator.requestMIDIAccess === "function"
400
+ }
401
+
375
402
  export { DataAttributeBinder } from "./bindings/DataAttributeBinder.js"
376
403
  export { EventEmitter } from "./core/EventEmitter.js"
377
404
  export {
@@ -0,0 +1,214 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
2
+ import { createMIDIController, createMIDIDeviceManager, isMIDISupported } from "./index.js"
3
+
4
+ describe("createMIDIController", () => {
5
+ let mockMIDIAccess
6
+ let mockOutput
7
+ let mockInput
8
+ let originalNavigator
9
+
10
+ beforeEach(() => {
11
+ originalNavigator = global.navigator
12
+
13
+ mockOutput = {
14
+ id: "test-output-1",
15
+ name: "Test Output Device",
16
+ manufacturer: "Test Manufacturer",
17
+ state: "connected",
18
+ send: vi.fn(),
19
+ }
20
+
21
+ mockInput = {
22
+ id: "test-input-1",
23
+ name: "Test Input Device",
24
+ manufacturer: "Test Manufacturer",
25
+ state: "connected",
26
+ onmidimessage: null,
27
+ }
28
+
29
+ mockMIDIAccess = {
30
+ outputs: new Map([["output-1", mockOutput]]),
31
+ inputs: new Map([["input-1", mockInput]]),
32
+ onstatechange: null,
33
+ }
34
+
35
+ global.navigator = {
36
+ requestMIDIAccess: vi.fn().mockResolvedValue(mockMIDIAccess),
37
+ }
38
+
39
+ // Mock document methods for DataAttributeBinder
40
+ global.document = {
41
+ querySelectorAll: vi.fn().mockReturnValue([]),
42
+ }
43
+ })
44
+
45
+ afterEach(() => {
46
+ global.navigator = originalNavigator
47
+ vi.clearAllMocks()
48
+ })
49
+
50
+ it("should create and initialize a MIDIController", async () => {
51
+ const controller = await createMIDIController()
52
+
53
+ expect(controller).toBeDefined()
54
+ expect(controller.initialized).toBe(true)
55
+ expect(controller.options.outputChannel).toBe(1)
56
+ })
57
+
58
+ it("should merge custom options", async () => {
59
+ const onReady = vi.fn()
60
+ const controller = await createMIDIController({
61
+ outputChannel: 5,
62
+ sysex: true,
63
+ onReady,
64
+ })
65
+
66
+ expect(controller.options.outputChannel).toBe(5)
67
+ expect(controller.options.sysex).toBe(true)
68
+ expect(onReady).toHaveBeenCalledWith(controller)
69
+ })
70
+
71
+ it("should connect to specified output device", async () => {
72
+ const controller = await createMIDIController({
73
+ output: "Test Output Device",
74
+ autoConnect: false,
75
+ })
76
+
77
+ await controller.device.connect("Test Output Device")
78
+ expect(controller.device.getCurrentOutput()?.name).toBe("Test Output Device")
79
+ })
80
+
81
+ it("should call onError when initialization fails", async () => {
82
+ global.navigator.requestMIDIAccess = vi.fn().mockRejectedValue(new Error("Access denied"))
83
+ const onError = vi.fn()
84
+
85
+ await expect(createMIDIController({ onError })).rejects.toThrow()
86
+
87
+ expect(onError).toHaveBeenCalled()
88
+ })
89
+ })
90
+
91
+ describe("createMIDIDeviceManager", () => {
92
+ let mockMIDIAccess
93
+ let mockOutput
94
+ let mockInput
95
+ let originalNavigator
96
+
97
+ beforeEach(() => {
98
+ originalNavigator = global.navigator
99
+
100
+ mockOutput = {
101
+ id: "test-output-1",
102
+ name: "Test Output Device",
103
+ manufacturer: "Test Manufacturer",
104
+ state: "connected",
105
+ send: vi.fn(),
106
+ }
107
+
108
+ mockInput = {
109
+ id: "test-input-1",
110
+ name: "Test Input Device",
111
+ manufacturer: "Test Manufacturer",
112
+ state: "connected",
113
+ onmidimessage: null,
114
+ }
115
+
116
+ mockMIDIAccess = {
117
+ outputs: new Map([["output-1", mockOutput]]),
118
+ inputs: new Map([["input-1", mockInput]]),
119
+ onstatechange: null,
120
+ }
121
+
122
+ global.navigator = {
123
+ requestMIDIAccess: vi.fn().mockResolvedValue(mockMIDIAccess),
124
+ }
125
+
126
+ global.document = {
127
+ querySelectorAll: vi.fn().mockReturnValue([]),
128
+ }
129
+ })
130
+
131
+ afterEach(() => {
132
+ global.navigator = originalNavigator
133
+ vi.clearAllMocks()
134
+ })
135
+
136
+ it("should create and initialize a MIDIDeviceManager", async () => {
137
+ const deviceManager = await createMIDIDeviceManager()
138
+
139
+ expect(deviceManager).toBeDefined()
140
+ expect(deviceManager.midi).toBeDefined()
141
+ expect(deviceManager.midi.initialized).toBe(true)
142
+ })
143
+
144
+ it("should auto-connect to specified output device", async () => {
145
+ const onConnectionUpdate = vi.fn()
146
+ const deviceManager = await createMIDIDeviceManager({
147
+ output: "Test Output Device",
148
+ onConnectionUpdate,
149
+ })
150
+
151
+ expect(deviceManager.currentOutput).toBeDefined()
152
+ expect(deviceManager.currentOutput.name).toBe("Test Output Device")
153
+ })
154
+
155
+ it("should call onReady with midi and deviceManager", async () => {
156
+ const onReady = vi.fn()
157
+ const deviceManager = await createMIDIDeviceManager({ onReady })
158
+
159
+ expect(onReady).toHaveBeenCalledWith(deviceManager.midi, deviceManager)
160
+ })
161
+
162
+ it("should use separate input and output channels", async () => {
163
+ const deviceManager = await createMIDIDeviceManager({
164
+ inputChannel: 3,
165
+ outputChannel: 7,
166
+ })
167
+
168
+ expect(deviceManager.midi.options.inputChannel).toBe(3)
169
+ expect(deviceManager.midi.options.outputChannel).toBe(7)
170
+ })
171
+ })
172
+
173
+ describe("isMIDISupported", () => {
174
+ let originalNavigator
175
+
176
+ beforeEach(() => {
177
+ // Save original navigator
178
+ originalNavigator = global.navigator
179
+ })
180
+
181
+ afterEach(() => {
182
+ // Restore original navigator
183
+ global.navigator = originalNavigator
184
+ })
185
+
186
+ it("should return true when navigator.requestMIDIAccess is defined", () => {
187
+ global.navigator = {
188
+ requestMIDIAccess: () => {},
189
+ }
190
+
191
+ expect(isMIDISupported()).toBe(true)
192
+ })
193
+
194
+ it("should return false when navigator is undefined", () => {
195
+ // eslint-disable-next-line no-global-assign
196
+ global.navigator = undefined
197
+
198
+ expect(isMIDISupported()).toBe(false)
199
+ })
200
+
201
+ it("should return false when navigator.requestMIDIAccess is undefined", () => {
202
+ global.navigator = {}
203
+
204
+ expect(isMIDISupported()).toBe(false)
205
+ })
206
+
207
+ it("should return false when navigator.requestMIDIAccess is not a function", () => {
208
+ global.navigator = {
209
+ requestMIDIAccess: "not a function",
210
+ }
211
+
212
+ expect(isMIDISupported()).toBe(false)
213
+ })
214
+ })