midiwire 0.2.0 → 0.3.1

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.
@@ -1,10 +1,10 @@
1
- class B {
1
+ class w {
2
2
  /**
3
3
  * @param {import("../core/MIDIController.js").MIDIController} controller
4
4
  * @param {string} selector - CSS selector for elements to bind
5
5
  */
6
- constructor(t, n = "[data-midi-cc]") {
7
- this.controller = t, this.selector = n, this.observer = null;
6
+ constructor(E, s = "[data-midi-cc]") {
7
+ this.controller = E, this.selector = s, this.observer = null;
8
8
  }
9
9
  /**
10
10
  * Bind all matching elements in the document
@@ -12,10 +12,10 @@ class B {
12
12
  bindAll() {
13
13
  document.querySelectorAll(
14
14
  this.selector === "[data-midi-cc]" ? "[data-midi-cc], [data-midi-msb][data-midi-lsb]" : this.selector
15
- ).forEach((n) => {
16
- if (n.hasAttribute("data-midi-bound")) return;
17
- const s = this._parseAttributes(n);
18
- s && (this.controller.bind(n, s), n.setAttribute("data-midi-bound", "true"));
15
+ ).forEach((s) => {
16
+ if (s.hasAttribute("data-midi-bound")) return;
17
+ const n = this._parseAttributes(s);
18
+ n && (this.controller.bind(s, n), s.setAttribute("data-midi-bound", "true"));
19
19
  });
20
20
  }
21
21
  /**
@@ -23,25 +23,25 @@ class B {
23
23
  */
24
24
  enableAutoBinding() {
25
25
  if (this.observer) return;
26
- const t = this.selector === "[data-midi-cc]" ? "[data-midi-cc], [data-midi-msb][data-midi-lsb]" : this.selector;
27
- this.observer = new MutationObserver((n) => {
28
- n.forEach((s) => {
29
- s.addedNodes.forEach((_) => {
26
+ const E = this.selector === "[data-midi-cc]" ? "[data-midi-cc], [data-midi-msb][data-midi-lsb]" : this.selector;
27
+ this.observer = new MutationObserver((s) => {
28
+ s.forEach((n) => {
29
+ n.addedNodes.forEach((_) => {
30
30
  if (_.nodeType === Node.ELEMENT_NODE) {
31
- if (_.matches?.(t)) {
32
- const e = this._parseAttributes(_);
33
- e && !_.hasAttribute("data-midi-bound") && (this.controller.bind(_, e), _.setAttribute("data-midi-bound", "true"));
31
+ if (_.matches?.(E)) {
32
+ const r = this._parseAttributes(_);
33
+ r && !_.hasAttribute("data-midi-bound") && (this.controller.bind(_, r), _.setAttribute("data-midi-bound", "true"));
34
34
  }
35
- _.querySelectorAll && _.querySelectorAll(t).forEach((r) => {
36
- if (!r.hasAttribute("data-midi-bound")) {
37
- const A = this._parseAttributes(r);
38
- A && (this.controller.bind(r, A), r.setAttribute("data-midi-bound", "true"));
35
+ _.querySelectorAll && _.querySelectorAll(E).forEach((e) => {
36
+ if (!e.hasAttribute("data-midi-bound")) {
37
+ const a = this._parseAttributes(e);
38
+ a && (this.controller.bind(e, a), e.setAttribute("data-midi-bound", "true"));
39
39
  }
40
40
  });
41
41
  }
42
- }), s.removedNodes.forEach((_) => {
43
- _.nodeType === Node.ELEMENT_NODE && (_.hasAttribute?.("data-midi-bound") && this.controller.unbind(_), _.querySelectorAll && _.querySelectorAll("[data-midi-bound]").forEach((r) => {
44
- this.controller.unbind(r);
42
+ }), n.removedNodes.forEach((_) => {
43
+ _.nodeType === Node.ELEMENT_NODE && (_.hasAttribute?.("data-midi-bound") && this.controller.unbind(_), _.querySelectorAll && _.querySelectorAll("[data-midi-bound]").forEach((e) => {
44
+ this.controller.unbind(e);
45
45
  }));
46
46
  });
47
47
  });
@@ -62,33 +62,33 @@ class B {
62
62
  * @returns {Object|null}
63
63
  * @private
64
64
  */
65
- _parseAttributes(t) {
66
- const n = parseInt(t.dataset.midiMsb, 10), s = parseInt(t.dataset.midiLsb, 10);
67
- if (!Number.isNaN(n) && !Number.isNaN(s) && n >= 0 && n <= 127 && s >= 0 && s <= 127) {
68
- const e = parseInt(t.dataset.midiCc, 10);
69
- return !Number.isNaN(e) && e >= 0 && e <= 127 && console.warn(
70
- `Element has both 7-bit (data-midi-cc="${e}") and 14-bit (data-midi-msb="${n}" data-midi-lsb="${s}") CC attributes. 14-bit takes precedence.`,
71
- t
65
+ _parseAttributes(E) {
66
+ const s = parseInt(E.dataset.midiMsb, 10), n = parseInt(E.dataset.midiLsb, 10);
67
+ if (!Number.isNaN(s) && !Number.isNaN(n) && s >= 0 && s <= 127 && n >= 0 && n <= 127) {
68
+ const r = parseInt(E.dataset.midiCc, 10);
69
+ return !Number.isNaN(r) && r >= 0 && r <= 127 && console.warn(
70
+ `Element has both 7-bit (data-midi-cc="${r}") and 14-bit (data-midi-msb="${s}" data-midi-lsb="${n}") CC attributes. 14-bit takes precedence.`,
71
+ E
72
72
  ), {
73
- msb: n,
74
- lsb: s,
73
+ msb: s,
74
+ lsb: n,
75
75
  is14Bit: !0,
76
- channel: parseInt(t.dataset.midiChannel, 10) || void 0,
77
- min: parseFloat(t.getAttribute("min")) || 0,
78
- max: parseFloat(t.getAttribute("max")) || 127,
79
- invert: t.dataset.midiInvert === "true",
80
- label: t.dataset.midiLabel
76
+ channel: parseInt(E.dataset.midiChannel, 10) || void 0,
77
+ min: parseFloat(E.getAttribute("min")) || 0,
78
+ max: parseFloat(E.getAttribute("max")) || 127,
79
+ invert: E.dataset.midiInvert === "true",
80
+ label: E.dataset.midiLabel
81
81
  };
82
82
  }
83
- const _ = parseInt(t.dataset.midiCc, 10);
83
+ const _ = parseInt(E.dataset.midiCc, 10);
84
84
  return !Number.isNaN(_) && _ >= 0 && _ <= 127 ? {
85
85
  cc: _,
86
- channel: parseInt(t.dataset.midiChannel, 10) || void 0,
87
- min: parseFloat(t.getAttribute("min")) || 0,
88
- max: parseFloat(t.getAttribute("max")) || 127,
89
- invert: t.dataset.midiInvert === "true",
90
- label: t.dataset.midiLabel
91
- } : ((t.dataset.midiCc !== void 0 || t.dataset.midiMsb !== void 0 && t.dataset.midiLsb !== void 0) && console.warn("Invalid MIDI configuration on element:", t), null);
86
+ channel: parseInt(E.dataset.midiChannel, 10) || void 0,
87
+ min: parseFloat(E.getAttribute("min")) || 0,
88
+ max: parseFloat(E.getAttribute("max")) || 127,
89
+ invert: E.dataset.midiInvert === "true",
90
+ label: E.dataset.midiLabel
91
+ } : ((E.dataset.midiCc !== void 0 || E.dataset.midiMsb !== void 0 && E.dataset.midiLsb !== void 0) && console.warn("Invalid MIDI configuration on element:", E), null);
92
92
  }
93
93
  /**
94
94
  * Clean up
@@ -97,59 +97,59 @@ class B {
97
97
  this.disableAutoBinding();
98
98
  }
99
99
  }
100
- class m extends Error {
101
- constructor(t, n) {
102
- super(t), this.name = "MIDIError", this.code = n, Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);
100
+ class p extends Error {
101
+ constructor(E, s) {
102
+ super(E), this.name = "MIDIError", this.code = s, Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);
103
103
  }
104
104
  }
105
- class F extends m {
106
- constructor(t, n) {
107
- super(t, "MIDI_ACCESS_ERROR"), this.name = "MIDIAccessError", this.reason = n;
105
+ class G extends p {
106
+ constructor(E, s) {
107
+ super(E, "MIDI_ACCESS_ERROR"), this.name = "MIDIAccessError", this.reason = s;
108
108
  }
109
109
  }
110
- class g extends m {
111
- constructor(t) {
112
- super(t, "MIDI_CONNECTION_ERROR"), this.name = "MIDIConnectionError";
110
+ class D extends p {
111
+ constructor(E) {
112
+ super(E, "MIDI_CONNECTION_ERROR"), this.name = "MIDIConnectionError";
113
113
  }
114
114
  }
115
- class L extends m {
116
- constructor(t, n, s) {
117
- super(t, "MIDI_DEVICE_ERROR"), this.name = "MIDIDeviceError", this.deviceType = n, this.deviceId = s;
115
+ class c extends p {
116
+ constructor(E, s, n) {
117
+ super(E, "MIDI_DEVICE_ERROR"), this.name = "MIDIDeviceError", this.deviceType = s, this.deviceId = n;
118
118
  }
119
119
  }
120
- class R extends m {
121
- constructor(t, n) {
122
- super(t, "MIDI_VALIDATION_ERROR"), this.name = "MIDIValidationError", this.validationType = n;
120
+ class R extends p {
121
+ constructor(E, s) {
122
+ super(E, "MIDI_VALIDATION_ERROR"), this.name = "MIDIValidationError", this.validationType = s;
123
123
  }
124
124
  }
125
125
  class H extends Error {
126
- constructor(t, n) {
127
- super(t), this.name = "DX7Error", this.code = n, Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);
126
+ constructor(E, s) {
127
+ super(E), this.name = "DX7Error", this.code = s, Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);
128
128
  }
129
129
  }
130
- class D extends H {
131
- constructor(t, n, s) {
132
- super(t, "DX7_PARSE_ERROR"), this.name = "DX7ParseError", this.parseType = n, this.offset = s;
130
+ class m extends H {
131
+ constructor(E, s, n) {
132
+ super(E, "DX7_PARSE_ERROR"), this.name = "DX7ParseError", this.parseType = s, this.offset = n;
133
133
  }
134
134
  }
135
- class I extends H {
136
- constructor(t, n, s) {
137
- super(t, "DX7_VALIDATION_ERROR"), this.name = "DX7ValidationError", this.validationType = n, this.value = s;
135
+ class o extends H {
136
+ constructor(E, s, n) {
137
+ super(E, "DX7_VALIDATION_ERROR"), this.name = "DX7ValidationError", this.validationType = s, this.value = n;
138
138
  }
139
139
  }
140
- function o(i, t, n) {
141
- return Math.max(t, Math.min(n, i));
140
+ function h(A, E, s) {
141
+ return Math.max(E, Math.min(s, A));
142
142
  }
143
- function w(i, t, n, s = !1) {
144
- const _ = (i - t) / (n - t), r = (s ? 1 - _ : _) * 127;
145
- return o(Math.round(r), 0, 127);
143
+ function B(A, E, s, n = !1) {
144
+ const _ = (A - E) / (s - E), e = (n ? 1 - _ : _) * 127;
145
+ return h(Math.round(e), 0, 127);
146
146
  }
147
- function Q(i, t, n, s = !1) {
148
- let _ = o(i, 0, 127) / 127;
149
- return s && (_ = 1 - _), t + _ * (n - t);
147
+ function Q(A, E, s, n = !1) {
148
+ let _ = h(A, 0, 127) / 127;
149
+ return n && (_ = 1 - _), E + _ * (s - E);
150
150
  }
151
- function j(i) {
152
- const t = {
151
+ function J(A) {
152
+ const E = {
153
153
  C: 0,
154
154
  "C#": 1,
155
155
  DB: 1,
@@ -167,27 +167,27 @@ function j(i) {
167
167
  "A#": 10,
168
168
  BB: 10,
169
169
  B: 11
170
- }, n = i.match(/^([A-G][#b]?)(-?\d+)$/i);
171
- if (!n)
172
- throw new R(`Invalid note name: ${i}`, "note", i);
173
- const [, s, _] = n, e = t[s.toUpperCase()];
174
- if (e === void 0)
175
- throw new R(`Invalid note: ${s}`, "note", s);
176
- const r = (parseInt(_, 10) + 1) * 12 + e;
177
- return o(r, 0, 127);
170
+ }, s = A.match(/^([A-G][#b]?)(-?\d+)$/i);
171
+ if (!s)
172
+ throw new R(`Invalid note name: ${A}`, "note", A);
173
+ const [, n, _] = s, r = E[n.toUpperCase()];
174
+ if (r === void 0)
175
+ throw new R(`Invalid note: ${n}`, "note", n);
176
+ const e = (parseInt(_, 10) + 1) * 12 + r;
177
+ return h(e, 0, 127);
178
178
  }
179
- function J(i, t = !1) {
180
- const _ = t ? ["C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B"] : ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"], e = Math.floor(i / 12) - 1;
181
- return `${_[i % 12]}${e}`;
179
+ function j(A, E = !1) {
180
+ const _ = 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(A / 12) - 1;
181
+ return `${_[A % 12]}${r}`;
182
182
  }
183
- function k(i) {
184
- const t = 69 + 12 * Math.log2(i / 440);
185
- return o(Math.round(t), 0, 127);
183
+ function k(A) {
184
+ const E = 69 + 12 * Math.log2(A / 440);
185
+ return h(Math.round(E), 0, 127);
186
186
  }
187
- function V(i) {
188
- return 440 * 2 ** ((i - 69) / 12);
187
+ function V(A) {
188
+ return 440 * 2 ** ((A - 69) / 12);
189
189
  }
190
- function X(i) {
190
+ function X(A) {
191
191
  return {
192
192
  0: "Bank Select",
193
193
  1: "Modulation",
@@ -220,27 +220,27 @@ function X(i) {
220
220
  120: "All Sound Off",
221
221
  121: "Reset All Controllers",
222
222
  123: "All Notes Off"
223
- }[i] || `CC ${i}`;
223
+ }[A] || `CC ${A}`;
224
224
  }
225
- function x(i) {
226
- const t = o(Math.round(i), 0, 16383);
225
+ function x(A) {
226
+ const E = h(Math.round(A), 0, 16383);
227
227
  return {
228
- msb: t >> 7 & 127,
229
- lsb: t & 127
228
+ msb: E >> 7 & 127,
229
+ lsb: E & 127
230
230
  };
231
231
  }
232
- function Y(i, t) {
233
- return o(i, 0, 127) << 7 | o(t, 0, 127);
232
+ function Y(A, E) {
233
+ return h(A, 0, 127) << 7 | h(E, 0, 127);
234
234
  }
235
- function Z(i, t, n, s = !1) {
236
- const _ = (i - t) / (n - t), r = (s ? 1 - _ : _) * 16383;
237
- return x(r);
235
+ function $(A, E, s, n = !1) {
236
+ const _ = (A - E) / (s - E), e = (n ? 1 - _ : _) * 16383;
237
+ return x(e);
238
238
  }
239
- function tt(i, t, n, s, _ = !1) {
240
- let r = Y(i, t) / 16383;
241
- return _ && (r = 1 - r), n + r * (s - n);
239
+ function tt(A, E, s, n, _ = !1) {
240
+ let e = Y(A, E) / 16383;
241
+ return _ && (e = 1 - e), s + e * (n - s);
242
242
  }
243
- class b {
243
+ class v {
244
244
  constructor() {
245
245
  this.events = /* @__PURE__ */ new Map();
246
246
  }
@@ -250,42 +250,42 @@ class b {
250
250
  * @param {Function} handler - Event handler function
251
251
  * @returns {Function} Unsubscribe function
252
252
  */
253
- on(t, n) {
254
- return this.events.has(t) || this.events.set(t, []), this.events.get(t).push(n), () => this.off(t, n);
253
+ on(E, s) {
254
+ return this.events.has(E) || this.events.set(E, []), this.events.get(E).push(s), () => this.off(E, s);
255
255
  }
256
256
  /**
257
257
  * Register a one-time event listener
258
258
  * @param {string} event - Event name
259
259
  * @param {Function} handler - Event handler function
260
260
  */
261
- once(t, n) {
262
- const s = (..._) => {
263
- n(..._), this.off(t, s);
261
+ once(E, s) {
262
+ const n = (..._) => {
263
+ s(..._), this.off(E, n);
264
264
  };
265
- this.on(t, s);
265
+ this.on(E, n);
266
266
  }
267
267
  /**
268
268
  * Remove an event listener
269
269
  * @param {string} event - Event name
270
270
  * @param {Function} handler - Event handler function
271
271
  */
272
- off(t, n) {
273
- if (!this.events.has(t)) return;
274
- const s = this.events.get(t), _ = s.indexOf(n);
275
- _ > -1 && s.splice(_, 1), s.length === 0 && this.events.delete(t);
272
+ off(E, s) {
273
+ if (!this.events.has(E)) return;
274
+ const n = this.events.get(E), _ = n.indexOf(s);
275
+ _ > -1 && n.splice(_, 1), n.length === 0 && this.events.delete(E);
276
276
  }
277
277
  /**
278
278
  * Emit an event
279
279
  * @param {string} event - Event name
280
280
  * @param {*} data - Event data
281
281
  */
282
- emit(t, n) {
283
- if (!this.events.has(t)) return;
284
- [...this.events.get(t)].forEach((_) => {
282
+ emit(E, s) {
283
+ if (!this.events.has(E)) return;
284
+ [...this.events.get(E)].forEach((_) => {
285
285
  try {
286
- _(n);
287
- } catch (e) {
288
- console.error(`Error in event handler for "${t}":`, e);
286
+ _(s);
287
+ } catch (r) {
288
+ console.error(`Error in event handler for "${E}":`, r);
289
289
  }
290
290
  });
291
291
  }
@@ -293,26 +293,26 @@ class b {
293
293
  * Remove all event listeners
294
294
  * @param {string} [event] - Optional event name to clear specific event
295
295
  */
296
- removeAllListeners(t) {
297
- t ? this.events.delete(t) : this.events.clear();
296
+ removeAllListeners(E) {
297
+ E ? this.events.delete(E) : this.events.clear();
298
298
  }
299
299
  }
300
- const U = {
300
+ const f = {
301
301
  DEVICE_CHANGE: "device-change",
302
302
  INPUT_DEVICE_CONNECTED: "input-device-connected",
303
303
  INPUT_DEVICE_DISCONNECTED: "input-device-disconnected",
304
304
  OUTPUT_DEVICE_CONNECTED: "output-device-connected",
305
305
  OUTPUT_DEVICE_DISCONNECTED: "output-device-disconnected"
306
306
  };
307
- class $ extends b {
307
+ class Z extends v {
308
308
  /**
309
309
  * @param {Object} options
310
310
  * @param {boolean} [options.sysex=false] - Request SysEx access
311
311
  */
312
- constructor(t = {}) {
312
+ constructor(E = {}) {
313
313
  super(), this.options = {
314
314
  sysex: !1,
315
- ...t
315
+ ...E
316
316
  }, this.midiAccess = null, this.output = null, this.input = null;
317
317
  }
318
318
  /**
@@ -322,25 +322,25 @@ class $ extends b {
322
322
  */
323
323
  async requestAccess() {
324
324
  if (!navigator.requestMIDIAccess)
325
- throw new F("Web MIDI API is not supported in this browser", "unsupported");
325
+ throw new G("Web MIDI API is not supported in this browser", "unsupported");
326
326
  try {
327
327
  this.midiAccess = await navigator.requestMIDIAccess({
328
328
  sysex: this.options.sysex
329
- }), this.midiAccess.onstatechange = (t) => {
330
- const n = t.port, s = t.port.state;
331
- this.emit(U.DEVICE_CHANGE, {
332
- port: n,
333
- state: s,
334
- type: n.type,
329
+ }), this.midiAccess.onstatechange = (E) => {
330
+ const s = E.port, n = E.port.state;
331
+ this.emit(f.DEVICE_CHANGE, {
332
+ port: s,
333
+ state: n,
334
+ type: s.type,
335
335
  device: {
336
- id: n.id,
337
- name: n.name,
338
- manufacturer: n.manufacturer || "Unknown"
336
+ id: s.id,
337
+ name: s.name,
338
+ manufacturer: s.manufacturer || "Unknown"
339
339
  }
340
- }), s === "disconnected" ? n.type === "input" ? (this.emit(U.INPUT_DEVICE_DISCONNECTED, { device: n }), this.input && this.input.id === n.id && (this.input = null)) : n.type === "output" && (this.emit(U.OUTPUT_DEVICE_DISCONNECTED, { device: n }), this.output && this.output.id === n.id && (this.output = null)) : s === "connected" && (n.type === "input" ? this.emit(U.INPUT_DEVICE_CONNECTED, { device: n }) : n.type === "output" && this.emit(U.OUTPUT_DEVICE_CONNECTED, { device: n }));
340
+ }), n === "disconnected" ? s.type === "input" ? (this.emit(f.INPUT_DEVICE_DISCONNECTED, { device: s }), this.input && this.input.id === s.id && (this.input = null)) : s.type === "output" && (this.emit(f.OUTPUT_DEVICE_DISCONNECTED, { device: s }), this.output && this.output.id === s.id && (this.output = null)) : n === "connected" && (s.type === "input" ? this.emit(f.INPUT_DEVICE_CONNECTED, { device: s }) : s.type === "output" && this.emit(f.OUTPUT_DEVICE_CONNECTED, { device: s }));
341
341
  };
342
- } catch (t) {
343
- throw t.name === "SecurityError" ? new F("MIDI access denied. SysEx requires user permission.", "denied") : new F(`Failed to get MIDI access: ${t.message}`, "failed");
342
+ } catch (E) {
343
+ throw E.name === "SecurityError" ? new G("MIDI access denied. SysEx requires user permission.", "denied") : new G(`Failed to get MIDI access: ${E.message}`, "failed");
344
344
  }
345
345
  }
346
346
  /**
@@ -349,14 +349,14 @@ class $ extends b {
349
349
  */
350
350
  getOutputs() {
351
351
  if (!this.midiAccess) return [];
352
- const t = [];
353
- return this.midiAccess.outputs.forEach((n) => {
354
- n.state === "connected" && t.push({
355
- id: n.id,
356
- name: n.name,
357
- manufacturer: n.manufacturer || "Unknown"
352
+ const E = [];
353
+ return this.midiAccess.outputs.forEach((s) => {
354
+ s.state === "connected" && E.push({
355
+ id: s.id,
356
+ name: s.name,
357
+ manufacturer: s.manufacturer || "Unknown"
358
358
  });
359
- }), t;
359
+ }), E;
360
360
  }
361
361
  /**
362
362
  * Get all available MIDI inputs
@@ -364,14 +364,14 @@ class $ extends b {
364
364
  */
365
365
  getInputs() {
366
366
  if (!this.midiAccess) return [];
367
- const t = [];
368
- return this.midiAccess.inputs.forEach((n) => {
369
- n.state === "connected" && t.push({
370
- id: n.id,
371
- name: n.name,
372
- manufacturer: n.manufacturer || "Unknown"
367
+ const E = [];
368
+ return this.midiAccess.inputs.forEach((s) => {
369
+ s.state === "connected" && E.push({
370
+ id: s.id,
371
+ name: s.name,
372
+ manufacturer: s.manufacturer || "Unknown"
373
373
  });
374
- }), t;
374
+ }), E;
375
375
  }
376
376
  /**
377
377
  * Connect to a MIDI output device
@@ -380,25 +380,25 @@ class $ extends b {
380
380
  * @throws {MIDIConnectionError} If MIDI access not initialized
381
381
  * @throws {MIDIDeviceError} If device not found or index out of range
382
382
  */
383
- async connect(t) {
383
+ async connect(E) {
384
384
  if (!this.midiAccess)
385
- throw new g("MIDI access not initialized. Call requestAccess() first.");
386
- const n = Array.from(this.midiAccess.outputs.values());
387
- if (n.length === 0)
388
- throw new L("No MIDI output devices available", "output");
389
- if (t === void 0) {
390
- this.output = n[0];
385
+ throw new D("MIDI access not initialized. Call requestAccess() first.");
386
+ const s = Array.from(this.midiAccess.outputs.values());
387
+ if (s.length === 0)
388
+ throw new c("No MIDI output devices available", "output");
389
+ if (E === void 0) {
390
+ this.output = s[0];
391
391
  return;
392
392
  }
393
- if (typeof t == "number") {
394
- if (t < 0 || t >= n.length)
395
- throw new L(`Output index ${t} out of range (0-${n.length - 1})`, "output", t);
396
- this.output = n[t];
393
+ if (typeof E == "number") {
394
+ if (E < 0 || E >= s.length)
395
+ throw new c(`Output index ${E} out of range (0-${s.length - 1})`, "output", E);
396
+ this.output = s[E];
397
397
  return;
398
398
  }
399
- if (this.output = n.find((s) => s.name === t || s.id === t), !this.output) {
400
- const s = n.map((_) => _.name).join(", ");
401
- throw new L(`MIDI output "${t}" not found. Available: ${s}`, "output", t);
399
+ if (this.output = s.find((n) => n.name === E || n.id === E), !this.output) {
400
+ const n = s.map((_) => _.name).join(", ");
401
+ throw new c(`MIDI output "${E}" not found. Available: ${n}`, "output", E);
402
402
  }
403
403
  }
404
404
  /**
@@ -410,26 +410,26 @@ class $ extends b {
410
410
  * @throws {MIDIValidationError} If onMessage is not a function
411
411
  * @throws {MIDIDeviceError} If device not found or index out of range
412
412
  */
413
- async connectInput(t, n) {
413
+ async connectInput(E, s) {
414
414
  if (!this.midiAccess)
415
- throw new g("MIDI access not initialized. Call requestAccess() first.");
416
- if (typeof n != "function")
415
+ throw new D("MIDI access not initialized. Call requestAccess() first.");
416
+ if (typeof s != "function")
417
417
  throw new R("onMessage callback must be a function", "callback");
418
- const s = Array.from(this.midiAccess.inputs.values());
419
- if (s.length === 0)
420
- throw new L("No MIDI input devices available", "input");
421
- if (this.input && (this.input.onmidimessage = null), t === void 0)
422
- this.input = s[0];
423
- else if (typeof t == "number") {
424
- if (t < 0 || t >= s.length)
425
- throw new L(`Input index ${t} out of range (0-${s.length - 1})`, "input", t);
426
- this.input = s[t];
427
- } else if (this.input = s.find((_) => _.name === t || _.id === t), !this.input) {
428
- const _ = s.map((e) => e.name).join(", ");
429
- throw new L(`MIDI input "${t}" not found. Available: ${_}`, "input", t);
418
+ const n = Array.from(this.midiAccess.inputs.values());
419
+ if (n.length === 0)
420
+ throw new c("No MIDI input devices available", "input");
421
+ if (this.input && (this.input.onmidimessage = null), E === void 0)
422
+ this.input = n[0];
423
+ else if (typeof E == "number") {
424
+ if (E < 0 || E >= n.length)
425
+ throw new c(`Input index ${E} out of range (0-${n.length - 1})`, "input", E);
426
+ this.input = n[E];
427
+ } else if (this.input = n.find((_) => _.name === E || _.id === E), !this.input) {
428
+ const _ = n.map((r) => r.name).join(", ");
429
+ throw new c(`MIDI input "${E}" not found. Available: ${_}`, "input", E);
430
430
  }
431
431
  this.input.onmidimessage = (_) => {
432
- n(_);
432
+ s(_);
433
433
  };
434
434
  }
435
435
  /**
@@ -437,16 +437,16 @@ class $ extends b {
437
437
  * @param {Uint8Array|Array<number>} message - MIDI message bytes
438
438
  * @param {number} [timestamp=performance.now()] - Optional timestamp
439
439
  */
440
- send(t, n = null) {
440
+ send(E, s = null) {
441
441
  if (!this.output) {
442
442
  console.warn("No MIDI output connected. Call connect() first.");
443
443
  return;
444
444
  }
445
445
  try {
446
- const s = new Uint8Array(t);
447
- n === null ? this.output.send(s) : this.output.send(s, n);
448
- } catch (s) {
449
- console.error("Failed to send MIDI message:", s);
446
+ const n = new Uint8Array(E);
447
+ s === null ? this.output.send(n) : this.output.send(n, s);
448
+ } catch (n) {
449
+ console.error("Failed to send MIDI message:", n);
450
450
  }
451
451
  }
452
452
  /**
@@ -454,13 +454,13 @@ class $ extends b {
454
454
  * @param {Array<number>} data - SysEx data bytes (without F0/F7 wrapper)
455
455
  * @param {boolean} [includeWrapper=false] - If true, data already includes F0/F7
456
456
  */
457
- sendSysEx(t, n = !1) {
457
+ sendSysEx(E, s = !1) {
458
458
  if (!this.options.sysex) {
459
459
  console.warn("SysEx not enabled. Initialize with sysex: true");
460
460
  return;
461
461
  }
462
- let s;
463
- n ? s = [240, ...t, 247] : s = t, this.send(s);
462
+ let n;
463
+ s ? n = [240, ...E, 247] : n = E, this.send(n);
464
464
  }
465
465
  /**
466
466
  * Disconnect from current output and input
@@ -498,7 +498,7 @@ class $ extends b {
498
498
  } : null;
499
499
  }
500
500
  }
501
- const O = {
501
+ const u = {
502
502
  READY: "ready",
503
503
  ERROR: "error",
504
504
  CC_SEND: "cc-send",
@@ -517,7 +517,7 @@ const O = {
517
517
  PATCH_LOADED: "patch-loaded",
518
518
  PATCH_DELETED: "patch-deleted"
519
519
  };
520
- class z extends b {
520
+ class z extends v {
521
521
  /**
522
522
  * @param {Object} options
523
523
  * @param {number} [options.channel=1] - Default MIDI channel (1-16)
@@ -528,12 +528,12 @@ class z extends b {
528
528
  * @param {Function} [options.onReady] - Callback when MIDI is ready
529
529
  * @param {Function} [options.onError] - Error handler
530
530
  */
531
- constructor(t = {}) {
531
+ constructor(E = {}) {
532
532
  super(), this.options = {
533
533
  channel: 1,
534
534
  autoConnect: !0,
535
535
  sysex: !1,
536
- ...t
536
+ ...E
537
537
  }, this.connection = null, this.bindings = /* @__PURE__ */ new Map(), this.state = /* @__PURE__ */ new Map(), this.initialized = !1;
538
538
  }
539
539
  /**
@@ -546,11 +546,11 @@ class z extends b {
546
546
  return;
547
547
  }
548
548
  try {
549
- this.connection = new $({
549
+ this.connection = new Z({
550
550
  sysex: this.options.sysex
551
- }), await this.connection.requestAccess(), 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(O.READY, this), this.options.onReady?.(this);
552
- } catch (t) {
553
- throw this.emit(O.ERROR, t), this.options.onError?.(t), t;
551
+ }), await this.connection.requestAccess(), 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(u.READY, this), this.options.onReady?.(this);
552
+ } catch (E) {
553
+ throw this.emit(u.ERROR, E), this.options.onError?.(E), E;
554
554
  }
555
555
  }
556
556
  /**
@@ -558,10 +558,10 @@ class z extends b {
558
558
  * @param {string|number} device - Device name, ID, or index
559
559
  * @returns {Promise<void>}
560
560
  */
561
- async connectInput(t) {
562
- await this.connection.connectInput(t, (n) => {
563
- this._handleMIDIMessage(n);
564
- }), this.emit(O.INPUT_CONNECTED, this.connection.getCurrentInput());
561
+ async connectInput(E) {
562
+ await this.connection.connectInput(E, (s) => {
563
+ this._handleMIDIMessage(s);
564
+ }), this.emit(u.INPUT_CONNECTED, this.connection.getCurrentInput());
565
565
  }
566
566
  /**
567
567
  * Send a control change message
@@ -569,16 +569,16 @@ class z extends b {
569
569
  * @param {number} value - CC value (0-127)
570
570
  * @param {number} [channel] - MIDI channel (defaults to controller channel)
571
571
  */
572
- sendCC(t, n, s = this.options.channel) {
572
+ sendCC(E, s, n = this.options.channel) {
573
573
  if (!this.initialized) {
574
574
  console.warn("MIDI not initialized. Call initialize() first.");
575
575
  return;
576
576
  }
577
- t = o(Math.round(t), 0, 127), n = o(Math.round(n), 0, 127), s = o(Math.round(s), 1, 16);
578
- const _ = 176 + (s - 1);
579
- this.connection.send([_, t, n]);
580
- const e = `${s}:${t}`;
581
- this.state.set(e, n), this.emit(O.CC_SEND, { cc: t, value: n, channel: s });
577
+ E = h(Math.round(E), 0, 127), s = h(Math.round(s), 0, 127), n = h(Math.round(n), 1, 16);
578
+ const _ = 176 + (n - 1);
579
+ this.connection.send([_, E, s]);
580
+ const r = `${n}:${E}`;
581
+ this.state.set(r, s), this.emit(u.CC_SEND, { cc: E, value: s, channel: n });
582
582
  }
583
583
  /**
584
584
  * Send a SysEx message
@@ -589,7 +589,7 @@ class z extends b {
589
589
  * // Send with wrapper included
590
590
  * midi.sendSysEx([0xF0, 0x42, 0x30, 0x00, 0x01, 0x2F, 0x12, 0xF7], true)
591
591
  */
592
- sendSysEx(t, n = !1) {
592
+ sendSysEx(E, s = !1) {
593
593
  if (!this.initialized) {
594
594
  console.warn("MIDI not initialized. Call initialize() first.");
595
595
  return;
@@ -598,7 +598,7 @@ class z extends b {
598
598
  console.warn("SysEx not enabled. Initialize with sysex: true");
599
599
  return;
600
600
  }
601
- this.connection.sendSysEx(t, n), this.emit(O.SYSEX_SEND, { data: t, includeWrapper: n });
601
+ this.connection.sendSysEx(E, s), this.emit(u.SYSEX_SEND, { data: E, includeWrapper: s });
602
602
  }
603
603
  /**
604
604
  * Send a note on message
@@ -606,11 +606,11 @@ class z extends b {
606
606
  * @param {number} [velocity=64] - Note velocity (0-127)
607
607
  * @param {number} [channel] - MIDI channel
608
608
  */
609
- sendNoteOn(t, n = 64, s = this.options.channel) {
609
+ sendNoteOn(E, s = 64, n = this.options.channel) {
610
610
  if (!this.initialized) return;
611
- t = o(Math.round(t), 0, 127), n = o(Math.round(n), 0, 127), s = o(Math.round(s), 1, 16);
612
- const _ = 144 + (s - 1);
613
- this.connection.send([_, t, n]), this.emit(O.NOTE_ON_SEND, { note: t, velocity: n, channel: s });
611
+ E = h(Math.round(E), 0, 127), s = h(Math.round(s), 0, 127), n = h(Math.round(n), 1, 16);
612
+ const _ = 144 + (n - 1);
613
+ this.connection.send([_, E, s]), this.emit(u.NOTE_ON_SEND, { note: E, velocity: s, channel: n });
614
614
  }
615
615
  /**
616
616
  * Send a note off message
@@ -618,11 +618,11 @@ class z extends b {
618
618
  * @param {number} [channel] - MIDI channel
619
619
  * @param {number} [velocity=0] - Release velocity (0-127)
620
620
  */
621
- sendNoteOff(t, n = this.options.channel, s = 0) {
621
+ sendNoteOff(E, s = this.options.channel, n = 0) {
622
622
  if (!this.initialized) return;
623
- t = o(Math.round(t), 0, 127), s = o(Math.round(s), 0, 127), n = o(Math.round(n), 1, 16);
624
- const _ = 144 + (n - 1);
625
- this.connection.send([_, t, s]), this.emit(O.NOTE_OFF_SEND, { note: t, channel: n, velocity: s });
623
+ E = h(Math.round(E), 0, 127), n = h(Math.round(n), 0, 127), s = h(Math.round(s), 1, 16);
624
+ const _ = 144 + (s - 1);
625
+ this.connection.send([_, E, n]), this.emit(u.NOTE_OFF_SEND, { note: E, channel: s, velocity: n });
626
626
  }
627
627
  /**
628
628
  * Bind a control programmatically
@@ -638,20 +638,20 @@ class z extends b {
638
638
  * @param {number} [options.debounce=0] - Debounce delay in ms for high-frequency updates
639
639
  * @returns {Function} Unbind function
640
640
  */
641
- bind(t, n, s = {}) {
642
- if (!t)
641
+ bind(E, s, n = {}) {
642
+ if (!E)
643
643
  return console.warn("Cannot bind: element is null or undefined"), () => {
644
644
  };
645
- const _ = this._createBinding(t, n, s);
646
- return this.bindings.set(t, _), this.initialized && this.connection?.isConnected() && _.handler({ target: t }), () => this.unbind(t);
645
+ const _ = this._createBinding(E, s, n);
646
+ return this.bindings.set(E, _), this.initialized && this.connection?.isConnected() && _.handler({ target: E }), () => this.unbind(E);
647
647
  }
648
648
  /**
649
649
  * Unbind a control
650
650
  * @param {HTMLElement} element
651
651
  */
652
- unbind(t) {
653
- const n = this.bindings.get(t);
654
- n && (n.destroy(), this.bindings.delete(t));
652
+ unbind(E) {
653
+ const s = this.bindings.get(E);
654
+ s && (s.destroy(), this.bindings.delete(E));
655
655
  }
656
656
  /**
657
657
  * Get current value of a CC
@@ -659,9 +659,9 @@ class z extends b {
659
659
  * @param {number} [channel] - MIDI channel
660
660
  * @returns {number|undefined}
661
661
  */
662
- getCC(t, n = this.options.channel) {
663
- const s = `${n}:${t}`;
664
- return this.state.get(s);
662
+ getCC(E, s = this.options.channel) {
663
+ const n = `${s}:${E}`;
664
+ return this.state.get(n);
665
665
  }
666
666
  /**
667
667
  * Get all available MIDI outputs
@@ -682,8 +682,8 @@ class z extends b {
682
682
  * @param {string|number} output - Device name, ID, or index
683
683
  * @returns {Promise<void>}
684
684
  */
685
- async setOutput(t) {
686
- await this.connection.connect(t), this.emit(O.OUTPUT_CHANGED, this.connection.getCurrentOutput());
685
+ async setOutput(E) {
686
+ await this.connection.connect(E), this.emit(u.OUTPUT_CHANGED, this.connection.getCurrentOutput());
687
687
  }
688
688
  /**
689
689
  * Get current output device
@@ -703,112 +703,112 @@ class z extends b {
703
703
  * Clean up resources
704
704
  */
705
705
  destroy() {
706
- for (const t of this.bindings.values())
707
- t.destroy();
708
- this.bindings.clear(), this.state.clear(), this.connection?.disconnect(), this.initialized = !1, this.emit(O.DESTROYED), this.removeAllListeners();
706
+ for (const E of this.bindings.values())
707
+ E.destroy();
708
+ this.bindings.clear(), this.state.clear(), this.connection?.disconnect(), this.initialized = !1, this.emit(u.DESTROYED), this.removeAllListeners();
709
709
  }
710
710
  /**
711
711
  * Handle incoming MIDI messages
712
712
  * @private
713
713
  */
714
- _handleMIDIMessage(t) {
715
- const [n, s, _] = t.data, e = n & 240, r = (n & 15) + 1;
716
- if (n === 240) {
717
- this.emit(O.SYSEX_RECV, {
718
- data: Array.from(t.data),
719
- timestamp: t.midiwire
714
+ _handleMIDIMessage(E) {
715
+ const [s, n, _] = E.data, r = s & 240, e = (s & 15) + 1;
716
+ if (s === 240) {
717
+ this.emit(u.SYSEX_RECV, {
718
+ data: Array.from(E.data),
719
+ timestamp: E.midiwire
720
720
  });
721
721
  return;
722
722
  }
723
- if (e === 176) {
724
- const A = `${r}:${s}`;
725
- this.state.set(A, _), this.emit(O.CC_RECV, {
726
- cc: s,
723
+ if (r === 176) {
724
+ const a = `${e}:${n}`;
725
+ this.state.set(a, _), this.emit(u.CC_RECV, {
726
+ cc: n,
727
727
  value: _,
728
- channel: r
728
+ channel: e
729
729
  });
730
730
  return;
731
731
  }
732
- if (e === 144 && _ > 0) {
733
- this.emit(O.NOTE_ON_RECV, {
734
- note: s,
732
+ if (r === 144 && _ > 0) {
733
+ this.emit(u.NOTE_ON_RECV, {
734
+ note: n,
735
735
  velocity: _,
736
- channel: r
736
+ channel: e
737
737
  });
738
738
  return;
739
739
  }
740
- if (e === 128 || e === 144 && _ === 0) {
741
- this.emit(O.NOTE_OFF_RECV, {
742
- note: s,
743
- channel: r
740
+ if (r === 128 || r === 144 && _ === 0) {
741
+ this.emit(u.NOTE_OFF_RECV, {
742
+ note: n,
743
+ channel: e
744
744
  });
745
745
  return;
746
746
  }
747
- this.emit(O.MIDI_MSG, {
748
- status: n,
749
- data: [s, _],
750
- channel: r,
751
- timestamp: t.midiwire
747
+ this.emit(u.MIDI_MSG, {
748
+ status: s,
749
+ data: [n, _],
750
+ channel: e,
751
+ timestamp: E.midiwire
752
752
  });
753
753
  }
754
754
  /**
755
755
  * Create a binding between an element and MIDI CC
756
756
  * @private
757
757
  */
758
- _createBinding(t, n, s = {}) {
758
+ _createBinding(E, s, n = {}) {
759
759
  const {
760
- min: _ = parseFloat(t.getAttribute("min")) || 0,
761
- max: e = parseFloat(t.getAttribute("max")) || 127,
762
- channel: r,
763
- invert: A = !1,
760
+ min: _ = parseFloat(E.getAttribute("min")) || 0,
761
+ max: r = parseFloat(E.getAttribute("max")) || 127,
762
+ channel: e,
763
+ invert: a = !1,
764
764
  onInput: T = void 0
765
- } = n, { debounce: S = 0 } = s, a = {
766
- ...n,
765
+ } = s, { debounce: S = 0 } = n, C = {
766
+ ...s,
767
767
  min: _,
768
- max: e,
769
- invert: A,
768
+ max: r,
769
+ invert: a,
770
770
  onInput: T
771
771
  };
772
- if (r !== void 0 && (a.channel = r), n.is14Bit) {
773
- const { msb: h, lsb: f } = n, c = (M) => {
774
- const G = parseFloat(M.target.value);
775
- if (Number.isNaN(G)) return;
776
- const { msb: y, lsb: v } = Z(G, _, e, A), p = r || this.options.channel;
777
- this.sendCC(h, y, p), this.sendCC(f, v, p);
772
+ if (e !== void 0 && (C.channel = e), s.is14Bit) {
773
+ const { msb: K, lsb: U } = s, I = (M) => {
774
+ const g = parseFloat(M.target.value);
775
+ if (Number.isNaN(g)) return;
776
+ const { msb: b, lsb: y } = $(g, _, r, a), F = e || this.options.channel;
777
+ this.sendCC(K, b, F), this.sendCC(U, y, F);
778
778
  };
779
- let K = null;
779
+ let L = null;
780
780
  const d = S > 0 ? (M) => {
781
- K && clearTimeout(K), K = setTimeout(() => {
782
- c(M), K = null;
781
+ L && clearTimeout(L), L = setTimeout(() => {
782
+ I(M), L = null;
783
783
  }, S);
784
- } : c;
785
- return t.addEventListener("input", d), t.addEventListener("change", d), {
786
- element: t,
787
- config: a,
788
- handler: c,
784
+ } : I;
785
+ return E.addEventListener("input", d), E.addEventListener("change", d), {
786
+ element: E,
787
+ config: C,
788
+ handler: I,
789
789
  destroy: () => {
790
- K && clearTimeout(K), t.removeEventListener("input", d), t.removeEventListener("change", d);
790
+ L && clearTimeout(L), E.removeEventListener("input", d), E.removeEventListener("change", d);
791
791
  }
792
792
  };
793
793
  }
794
- const { cc: P } = n, l = (h) => {
795
- const f = parseFloat(h.target.value);
796
- if (Number.isNaN(f)) return;
797
- const c = w(f, _, e, A), K = r === void 0 ? this.options.channel : r;
798
- this.sendCC(P, c, K);
794
+ const { cc: P } = s, i = (K) => {
795
+ const U = parseFloat(K.target.value);
796
+ if (Number.isNaN(U)) return;
797
+ const I = B(U, _, r, a), L = e === void 0 ? this.options.channel : e;
798
+ this.sendCC(P, I, L);
799
799
  };
800
- let u = null;
801
- const N = S > 0 ? (h) => {
802
- u && clearTimeout(u), u = setTimeout(() => {
803
- l(h), u = null;
800
+ let l = null;
801
+ const O = S > 0 ? (K) => {
802
+ l && clearTimeout(l), l = setTimeout(() => {
803
+ i(K), l = null;
804
804
  }, S);
805
- } : l;
806
- return t.addEventListener("input", N), t.addEventListener("change", N), {
807
- element: t,
808
- config: a,
809
- handler: l,
805
+ } : i;
806
+ return E.addEventListener("input", O), E.addEventListener("change", O), {
807
+ element: E,
808
+ config: C,
809
+ handler: i,
810
810
  destroy: () => {
811
- u && clearTimeout(u), t.removeEventListener("input", N), t.removeEventListener("change", N);
811
+ l && clearTimeout(l), E.removeEventListener("input", O), E.removeEventListener("change", O);
812
812
  }
813
813
  };
814
814
  }
@@ -817,79 +817,79 @@ class z extends b {
817
817
  * @param {string} [name] - Optional patch name
818
818
  * @returns {Object} Patch object
819
819
  */
820
- getPatch(t = "Unnamed Patch") {
821
- const n = {
822
- name: t,
820
+ getPatch(E = "Unnamed Patch") {
821
+ const s = {
822
+ name: E,
823
823
  device: this.getCurrentOutput()?.name || null,
824
824
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
825
825
  version: "1.0",
826
826
  channels: {},
827
827
  settings: {}
828
828
  };
829
- for (const [s, _] of this.state.entries()) {
830
- const [e, r] = s.split(":").map(Number);
831
- n.channels[e] || (n.channels[e] = { ccs: {}, notes: {} }), n.channels[e].ccs[r] = _;
829
+ for (const [n, _] of this.state.entries()) {
830
+ const [r, e] = n.split(":").map(Number);
831
+ s.channels[r] || (s.channels[r] = { ccs: {}, notes: {} }), s.channels[r].ccs[e] = _;
832
832
  }
833
- for (const [s, _] of this.bindings.entries()) {
834
- const { config: e } = _;
835
- if (e.cc) {
836
- const r = `cc${e.cc}`;
837
- n.settings[r] = {
838
- min: e.min,
839
- max: e.max,
840
- invert: e.invert || !1,
841
- is14Bit: e.is14Bit || !1,
842
- label: s.getAttribute?.("data-midi-label") || null,
843
- elementId: s.id || null
833
+ for (const [n, _] of this.bindings.entries()) {
834
+ const { config: r } = _;
835
+ if (r.cc) {
836
+ const e = `cc${r.cc}`;
837
+ s.settings[e] = {
838
+ min: r.min,
839
+ max: r.max,
840
+ invert: r.invert || !1,
841
+ is14Bit: r.is14Bit || !1,
842
+ label: n.getAttribute?.("data-midi-label") || null,
843
+ elementId: n.id || null
844
844
  };
845
845
  }
846
846
  }
847
- return n;
847
+ return s;
848
848
  }
849
849
  /**
850
850
  * Apply a patch to the controller
851
851
  * @param {PatchData} patch - Patch object
852
852
  * @returns {Promise<void>}
853
853
  */
854
- async setPatch(t) {
855
- if (!t || !t.channels)
854
+ async setPatch(E) {
855
+ if (!E || !E.channels)
856
856
  throw new R("Invalid patch format", "patch");
857
- const n = t.version || "1.0";
858
- n === "1.0" ? await this._applyPatchV1(t) : (console.warn(`Unknown patch version: ${n}. Attempting to apply as v1.0`), await this._applyPatchV1(t)), this.emit(O.PATCH_LOADED, { patch: t });
857
+ const s = E.version || "1.0";
858
+ s === "1.0" ? await this._applyPatchV1(E) : (console.warn(`Unknown patch version: ${s}. Attempting to apply as v1.0`), await this._applyPatchV1(E)), this.emit(u.PATCH_LOADED, { patch: E });
859
859
  }
860
860
  /**
861
861
  * Apply v1.0 patch format
862
862
  * @private
863
863
  * @param {PatchData} patch
864
864
  */
865
- async _applyPatchV1(t) {
866
- for (const [n, s] of Object.entries(t.channels)) {
867
- const _ = parseInt(n, 10);
868
- if (s.ccs)
869
- for (const [e, r] of Object.entries(s.ccs)) {
870
- const A = parseInt(e, 10);
871
- this.sendCC(A, r, _);
865
+ async _applyPatchV1(E) {
866
+ for (const [s, n] of Object.entries(E.channels)) {
867
+ const _ = parseInt(s, 10);
868
+ if (n.ccs)
869
+ for (const [r, e] of Object.entries(n.ccs)) {
870
+ const a = parseInt(r, 10);
871
+ this.sendCC(a, e, _);
872
872
  }
873
- if (s.notes)
874
- for (const [e, r] of Object.entries(s.notes)) {
875
- const A = parseInt(e, 10);
876
- r > 0 ? this.sendNoteOn(A, r, _) : this.sendNoteOff(A, _);
873
+ if (n.notes)
874
+ for (const [r, e] of Object.entries(n.notes)) {
875
+ const a = parseInt(r, 10);
876
+ e > 0 ? this.sendNoteOn(a, e, _) : this.sendNoteOff(a, _);
877
877
  }
878
878
  }
879
- if (t.settings)
880
- for (const [n, s] of Object.entries(t.settings))
881
- for (const [_, e] of this.bindings.entries())
882
- e.config.cc?.toString() === n.replace("cc", "") && (_.min !== void 0 && s.min !== void 0 && (_.min = String(s.min)), _.max !== void 0 && s.max !== void 0 && (_.max = String(s.max)));
883
- for (const [n, s] of this.bindings.entries()) {
884
- const { config: _ } = s;
879
+ if (E.settings)
880
+ for (const [s, n] of Object.entries(E.settings))
881
+ for (const [_, r] of this.bindings.entries())
882
+ r.config.cc?.toString() === s.replace("cc", "") && (_.min !== void 0 && n.min !== void 0 && (_.min = String(n.min)), _.max !== void 0 && n.max !== void 0 && (_.max = String(n.max)));
883
+ for (const [s, n] of this.bindings.entries()) {
884
+ const { config: _ } = n;
885
885
  if (_.cc !== void 0) {
886
- const e = _.channel || this.options.channel, r = t.channels[e];
887
- if (r?.ccs) {
888
- const A = r.ccs[_.cc];
889
- if (A !== void 0) {
890
- const T = _.min !== void 0 ? _.min : parseFloat(n.getAttribute?.("min")) || 0, S = _.max !== void 0 ? _.max : parseFloat(n.getAttribute?.("max")) || 127, a = _.invert || !1;
886
+ const r = _.channel || this.options.channel, e = E.channels[r];
887
+ if (e?.ccs) {
888
+ const a = e.ccs[_.cc];
889
+ if (a !== void 0) {
890
+ const T = _.min !== void 0 ? _.min : parseFloat(s.getAttribute?.("min")) || 0, S = _.max !== void 0 ? _.max : parseFloat(s.getAttribute?.("max")) || 127, C = _.invert || !1;
891
891
  let P;
892
- a ? P = S - A / 127 * (S - T) : P = T + A / 127 * (S - T), _.onInput && typeof _.onInput == "function" ? _.onInput(P) : (n.value = P, n.dispatchEvent(new Event("input", { bubbles: !0 })));
892
+ C ? P = S - a / 127 * (S - T) : P = T + a / 127 * (S - T), _.onInput && typeof _.onInput == "function" ? _.onInput(P) : (s.value = P, s.dispatchEvent(new Event("input", { bubbles: !0 })));
893
893
  }
894
894
  }
895
895
  }
@@ -901,12 +901,12 @@ class z extends b {
901
901
  * @param {Object} [patch] - Optional patch object (will use getPatch() if not provided)
902
902
  * @returns {string} Storage key used
903
903
  */
904
- savePatch(t, n = null) {
905
- const s = n || this.getPatch(t), _ = `midiwire_patch_${t}`;
904
+ savePatch(E, s = null) {
905
+ const n = s || this.getPatch(E), _ = `midiwire_patch_${E}`;
906
906
  try {
907
- return localStorage.setItem(_, JSON.stringify(s)), this.emit(O.PATCH_SAVED, { name: t, patch: s }), _;
908
- } catch (e) {
909
- throw console.error("Failed to save patch:", e), e;
907
+ return localStorage.setItem(_, JSON.stringify(n)), this.emit(u.PATCH_SAVED, { name: E, patch: n }), _;
908
+ } catch (r) {
909
+ throw console.error("Failed to save patch:", r), r;
910
910
  }
911
911
  }
912
912
  /**
@@ -914,16 +914,16 @@ class z extends b {
914
914
  * @param {string} name - Patch name
915
915
  * @returns {Object|null} Patch object or null if not found
916
916
  */
917
- loadPatch(t) {
918
- const n = `midiwire_patch_${t}`;
917
+ loadPatch(E) {
918
+ const s = `midiwire_patch_${E}`;
919
919
  try {
920
- const s = localStorage.getItem(n);
921
- if (!s)
920
+ const n = localStorage.getItem(s);
921
+ if (!n)
922
922
  return null;
923
- const _ = JSON.parse(s);
924
- return this.emit(O.PATCH_LOADED, { name: t, patch: _ }), _;
925
- } catch (s) {
926
- return console.error("Failed to load patch:", s), null;
923
+ const _ = JSON.parse(n);
924
+ return this.emit(u.PATCH_LOADED, { name: E, patch: _ }), _;
925
+ } catch (n) {
926
+ return console.error("Failed to load patch:", n), null;
927
927
  }
928
928
  }
929
929
  /**
@@ -931,12 +931,12 @@ class z extends b {
931
931
  * @param {string} name - Patch name
932
932
  * @returns {boolean} Success
933
933
  */
934
- deletePatch(t) {
935
- const n = `midiwire_patch_${t}`;
934
+ deletePatch(E) {
935
+ const s = `midiwire_patch_${E}`;
936
936
  try {
937
- return localStorage.removeItem(n), this.emit(O.PATCH_DELETED, { name: t }), !0;
938
- } catch (s) {
939
- return console.error("Failed to delete patch:", s), !1;
937
+ return localStorage.removeItem(s), this.emit(u.PATCH_DELETED, { name: E }), !0;
938
+ } catch (n) {
939
+ return console.error("Failed to delete patch:", n), !1;
940
940
  }
941
941
  }
942
942
  /**
@@ -944,19 +944,19 @@ class z extends b {
944
944
  * @returns {Array<Object>} Array of { name, patch }
945
945
  */
946
946
  listPatches() {
947
- const t = [];
947
+ const E = [];
948
948
  try {
949
- for (let n = 0; n < localStorage.length; n++) {
950
- const s = localStorage.key(n);
951
- if (s?.startsWith("midiwire_patch_")) {
952
- const _ = s.replace("midiwire_patch_", ""), e = this.loadPatch(_);
953
- e && t.push({ name: _, patch: e });
949
+ for (let s = 0; s < localStorage.length; s++) {
950
+ const n = localStorage.key(s);
951
+ if (n?.startsWith("midiwire_patch_")) {
952
+ const _ = n.replace("midiwire_patch_", ""), r = this.loadPatch(_);
953
+ r && E.push({ name: _, patch: r });
954
954
  }
955
955
  }
956
- } catch (n) {
957
- console.error("Failed to list patches:", n);
956
+ } catch (s) {
957
+ console.error("Failed to list patches:", s);
958
958
  }
959
- return t.sort((n, s) => n.name.localeCompare(s.name));
959
+ return E.sort((s, n) => s.name.localeCompare(n.name));
960
960
  }
961
961
  }
962
962
  class q {
@@ -967,27 +967,27 @@ class q {
967
967
  * @param {Function} options.onConnectionUpdate - Callback when connection status changes
968
968
  * @param {number} [options.channel=1] - Default MIDI channel
969
969
  */
970
- constructor(t = {}) {
971
- this.midi = t.midiController || null, this.onStatusUpdate = t.onStatusUpdate || (() => {
972
- }), this.onConnectionUpdate = t.onConnectionUpdate || (() => {
973
- }), this.channel = t.channel || 1, this.currentDevice = null, this.isConnecting = !1;
970
+ constructor(E = {}) {
971
+ this.midi = E.midiController || null, this.onStatusUpdate = E.onStatusUpdate || (() => {
972
+ }), this.onConnectionUpdate = E.onConnectionUpdate || (() => {
973
+ }), this.channel = E.channel || 1, this.currentDevice = null, this.isConnecting = !1;
974
974
  }
975
975
  /**
976
976
  * Initialize the device manager with a MIDIController
977
977
  * @param {MIDIController} midi
978
978
  */
979
- setMIDI(t) {
980
- this.midi = t;
979
+ setMIDI(E) {
980
+ this.midi = E;
981
981
  }
982
982
  /**
983
983
  * Set up device change event listeners
984
984
  * @param {Function} [onDeviceListChange] - Optional callback when device list should be refreshed
985
985
  */
986
- setupDeviceListeners(t) {
987
- this.midi?.connection && (this.midi.connection.on(U.OUTPUT_DEVICE_CONNECTED, ({ device: n }) => {
988
- this.updateStatus(`Device connected: ${n.name}`, "connected"), t && t();
989
- }), this.midi.connection.on(U.OUTPUT_DEVICE_DISCONNECTED, ({ device: n }) => {
990
- this.updateStatus(`Device disconnected: ${n.name}`, "error"), this.currentDevice && n.name === this.currentDevice.name && (this.currentDevice = null, this.updateConnectionStatus()), t && t();
986
+ setupDeviceListeners(E) {
987
+ this.midi?.connection && (this.midi.connection.on(f.OUTPUT_DEVICE_CONNECTED, ({ device: s }) => {
988
+ this.updateStatus(`Device connected: ${s.name}`, "connected"), E && E();
989
+ }), this.midi.connection.on(f.OUTPUT_DEVICE_DISCONNECTED, ({ device: s }) => {
990
+ this.updateStatus(`Device disconnected: ${s.name}`, "error"), this.currentDevice && s.name === this.currentDevice.name && (this.currentDevice = null, this.updateConnectionStatus()), E && E();
991
991
  }));
992
992
  }
993
993
  /**
@@ -995,8 +995,8 @@ class q {
995
995
  * @param {string} message
996
996
  * @param {string} state
997
997
  */
998
- updateStatus(t, n = "") {
999
- this.onStatusUpdate(t, n);
998
+ updateStatus(E, s = "") {
999
+ this.onStatusUpdate(E, s);
1000
1000
  }
1001
1001
  /**
1002
1002
  * Update connection status
@@ -1016,17 +1016,17 @@ class q {
1016
1016
  * @param {string} deviceName
1017
1017
  * @returns {boolean}
1018
1018
  */
1019
- isDeviceConnected(t) {
1020
- return this.midi?.connection ? this.midi.connection.getOutputs().some((s) => s.name === t) : !1;
1019
+ isDeviceConnected(E) {
1020
+ return this.midi?.connection ? this.midi.connection.getOutputs().some((n) => n.name === E) : !1;
1021
1021
  }
1022
1022
  /**
1023
1023
  * Connect device selection events to the device manager
1024
1024
  * @param {HTMLSelectElement} deviceSelectElement
1025
1025
  * @param {Function} onConnect - Callback when device is connected (midi, device)
1026
1026
  */
1027
- connectDeviceSelection(t, n) {
1028
- !t || !this.midi || t.addEventListener("change", async (s) => {
1029
- const _ = s.target.value;
1027
+ connectDeviceSelection(E, s) {
1028
+ !E || !this.midi || E.addEventListener("change", async (n) => {
1029
+ const _ = n.target.value;
1030
1030
  if (!_) {
1031
1031
  this.currentDevice && this.midi && (this.midi.connection.disconnect(), this.currentDevice = null, this.updateStatus("Disconnected"), this.updateConnectionStatus());
1032
1032
  return;
@@ -1034,9 +1034,9 @@ class q {
1034
1034
  if (!this.isConnecting) {
1035
1035
  this.isConnecting = !0;
1036
1036
  try {
1037
- await this.midi.setOutput(parseInt(_, 10)), this.currentDevice = this.midi.getCurrentOutput(), this.updateConnectionStatus(), n && await n(this.midi, this.currentDevice);
1038
- } catch (e) {
1039
- this.updateStatus(`Connection failed: ${e.message}`, "error");
1037
+ await this.midi.setOutput(parseInt(_, 10)), this.currentDevice = this.midi.getCurrentOutput(), this.updateConnectionStatus(), s && await s(this.midi, this.currentDevice);
1038
+ } catch (r) {
1039
+ this.updateStatus(`Connection failed: ${r.message}`, "error");
1040
1040
  } finally {
1041
1041
  this.isConnecting = !1;
1042
1042
  }
@@ -1047,9 +1047,9 @@ class q {
1047
1047
  * Connect channel selection events
1048
1048
  * @param {HTMLSelectElement} channelSelectElement
1049
1049
  */
1050
- connectChannelSelection(t) {
1051
- !t || !this.midi || t.addEventListener("change", (n) => {
1052
- this.midi && (this.midi.options.channel = parseInt(n.target.value, 10), this.updateConnectionStatus());
1050
+ connectChannelSelection(E) {
1051
+ !E || !this.midi || E.addEventListener("change", (s) => {
1052
+ this.midi && (this.midi.options.channel = parseInt(s.target.value, 10), this.updateConnectionStatus());
1053
1053
  });
1054
1054
  }
1055
1055
  /**
@@ -1057,22 +1057,22 @@ class q {
1057
1057
  * @param {HTMLSelectElement} selectElement
1058
1058
  * @param {Function} [onChange] - Optional callback when selection should change
1059
1059
  */
1060
- populateDeviceList(t, n) {
1061
- if (!t) return;
1062
- const s = this.getOutputDevices();
1063
- if (s.length > 0) {
1064
- if (t.innerHTML = '<option value="">Select a device</option>' + s.map((_, e) => `<option value="${e}">${_.name}</option>`).join(""), this.currentDevice) {
1065
- const _ = s.findIndex((e) => e.name === this.currentDevice.name);
1066
- _ !== -1 ? t.value = _.toString() : (t.value = "", this.currentDevice = null, this.updateConnectionStatus());
1060
+ populateDeviceList(E, s) {
1061
+ if (!E) return;
1062
+ const n = this.getOutputDevices();
1063
+ if (n.length > 0) {
1064
+ if (E.innerHTML = '<option value="">Select a device</option>' + n.map((_, r) => `<option value="${r}">${_.name}</option>`).join(""), this.currentDevice) {
1065
+ const _ = n.findIndex((r) => r.name === this.currentDevice.name);
1066
+ _ !== -1 ? E.value = _.toString() : (E.value = "", this.currentDevice = null, this.updateConnectionStatus());
1067
1067
  } else
1068
- t.value = "";
1068
+ E.value = "";
1069
1069
  this.currentDevice || this.updateStatus("Select a MIDI device");
1070
1070
  } else
1071
- t.innerHTML = '<option value="">No MIDI devices found</option>', this.updateStatus("No MIDI devices available", "error");
1072
- n && n();
1071
+ E.innerHTML = '<option value="">No MIDI devices found</option>', this.updateStatus("No MIDI devices available", "error");
1072
+ s && s();
1073
1073
  }
1074
1074
  }
1075
- class E {
1075
+ class t {
1076
1076
  // Packed format (128 bytes)
1077
1077
  // See: DX7 Service Manual, Voice Memory Format
1078
1078
  static PACKED_SIZE = 128;
@@ -1261,24 +1261,24 @@ class E {
1261
1261
  * @param {number} index - Voice index (0-31)
1262
1262
  * @throws {DX7ValidationError} If data length is not exactly 128 bytes
1263
1263
  */
1264
- constructor(t, n = 0) {
1265
- if (t.length !== E.PACKED_SIZE)
1266
- throw new I(
1267
- `Invalid voice data length: expected ${E.PACKED_SIZE} bytes, got ${t.length}`,
1264
+ constructor(E, s = 0) {
1265
+ if (E.length !== t.PACKED_SIZE)
1266
+ throw new o(
1267
+ `Invalid voice data length: expected ${t.PACKED_SIZE} bytes, got ${E.length}`,
1268
1268
  "length",
1269
- t.length
1269
+ E.length
1270
1270
  );
1271
- this.index = n, this.data = new Uint8Array(t), this.name = this._extractName(), this._unpackedCache = null;
1271
+ this.index = s, this.data = new Uint8Array(E), this.name = this._extractName(), this._unpackedCache = null;
1272
1272
  }
1273
1273
  /**
1274
1274
  * Extract the voice name from the data (10 characters at offset 118)
1275
1275
  * @private
1276
1276
  */
1277
1277
  _extractName() {
1278
- const t = this.data.subarray(E.PACKED_NAME_START, E.PACKED_NAME_START + E.NAME_LENGTH);
1279
- return Array.from(t).map((s) => {
1280
- let _ = s & E.MASK_7BIT;
1281
- return _ === E.CHAR_YEN && (_ = E.CHAR_REPLACEMENT_Y), _ === E.CHAR_ARROW_RIGHT && (_ = E.CHAR_REPLACEMENT_GT), _ === E.CHAR_ARROW_LEFT && (_ = E.CHAR_REPLACEMENT_LT), (_ < E.CHAR_MIN_PRINTABLE || _ > E.CHAR_MAX_PRINTABLE) && (_ = E.CHAR_SPACE), String.fromCharCode(_);
1278
+ const E = this.data.subarray(t.PACKED_NAME_START, t.PACKED_NAME_START + t.NAME_LENGTH);
1279
+ return Array.from(E).map((n) => {
1280
+ let _ = n & t.MASK_7BIT;
1281
+ return _ === t.CHAR_YEN && (_ = t.CHAR_REPLACEMENT_Y), _ === t.CHAR_ARROW_RIGHT && (_ = t.CHAR_REPLACEMENT_GT), _ === t.CHAR_ARROW_LEFT && (_ = t.CHAR_REPLACEMENT_LT), (_ < t.CHAR_MIN_PRINTABLE || _ > t.CHAR_MAX_PRINTABLE) && (_ = t.CHAR_SPACE), String.fromCharCode(_);
1282
1282
  }).join("").trim();
1283
1283
  }
1284
1284
  /**
@@ -1287,14 +1287,14 @@ class E {
1287
1287
  * @returns {number} Parameter value (0-127)
1288
1288
  * @throws {DX7ValidationError} If offset is out of range
1289
1289
  */
1290
- getParameter(t) {
1291
- if (t < 0 || t >= E.PACKED_SIZE)
1292
- throw new I(
1293
- `Parameter offset out of range: ${t} (must be 0-${E.PACKED_SIZE - 1})`,
1290
+ getParameter(E) {
1291
+ if (E < 0 || E >= t.PACKED_SIZE)
1292
+ throw new o(
1293
+ `Parameter offset out of range: ${E} (must be 0-${t.PACKED_SIZE - 1})`,
1294
1294
  "offset",
1295
- t
1295
+ E
1296
1296
  );
1297
- return this.data[t] & E.MASK_7BIT;
1297
+ return this.data[E] & t.MASK_7BIT;
1298
1298
  }
1299
1299
  /**
1300
1300
  * Get a parameter value from the unpacked 169-byte format
@@ -1302,28 +1302,28 @@ class E {
1302
1302
  * @returns {number} Parameter value (0-127)
1303
1303
  * @throws {DX7ValidationError} If offset is out of range
1304
1304
  */
1305
- getUnpackedParameter(t) {
1306
- if (t < 0 || t >= E.UNPACKED_SIZE)
1307
- throw new I(
1308
- `Unpacked parameter offset out of range: ${t} (must be 0-${E.UNPACKED_SIZE - 1})`,
1305
+ getUnpackedParameter(E) {
1306
+ if (E < 0 || E >= t.UNPACKED_SIZE)
1307
+ throw new o(
1308
+ `Unpacked parameter offset out of range: ${E} (must be 0-${t.UNPACKED_SIZE - 1})`,
1309
1309
  "offset",
1310
- t
1310
+ E
1311
1311
  );
1312
- return this._unpackedCache || (this._unpackedCache = this.unpack()), this._unpackedCache[t] & E.MASK_7BIT;
1312
+ return this._unpackedCache || (this._unpackedCache = this.unpack()), this._unpackedCache[E] & t.MASK_7BIT;
1313
1313
  }
1314
1314
  /**
1315
1315
  * Set a raw parameter value in the packed data
1316
1316
  * @param {number} offset - Byte offset in the voice data
1317
1317
  * @param {number} value - Parameter value (0-127)
1318
1318
  */
1319
- setParameter(t, n) {
1320
- if (t < 0 || t >= E.PACKED_SIZE)
1321
- throw new I(
1322
- `Parameter offset out of range: ${t} (must be 0-${E.PACKED_SIZE - 1})`,
1319
+ setParameter(E, s) {
1320
+ if (E < 0 || E >= t.PACKED_SIZE)
1321
+ throw new o(
1322
+ `Parameter offset out of range: ${E} (must be 0-${t.PACKED_SIZE - 1})`,
1323
1323
  "offset",
1324
- t
1324
+ E
1325
1325
  );
1326
- this.data[t] = n & E.MASK_7BIT, this._unpackedCache = null, t >= E.PACKED_NAME_START && t < E.PACKED_NAME_START + E.NAME_LENGTH && (this.name = this._extractName());
1326
+ this.data[E] = s & t.MASK_7BIT, this._unpackedCache = null, E >= t.PACKED_NAME_START && E < t.PACKED_NAME_START + t.NAME_LENGTH && (this.name = this._extractName());
1327
1327
  }
1328
1328
  /**
1329
1329
  * Unpack the voice data to 169-byte unpacked format
@@ -1331,199 +1331,199 @@ class E {
1331
1331
  * @returns {Uint8Array} 169 bytes of unpacked voice data (138 operator + 8 pitch EG + 13 global + 10 name = 169 bytes)
1332
1332
  */
1333
1333
  unpack() {
1334
- const t = this.data, n = new Uint8Array(E.UNPACKED_SIZE);
1335
- return this._unpackOperators(t, n), this._unpackPitchEG(t, n), this._unpackGlobalParams(t, n), this._unpackName(t, n), n;
1334
+ const E = this.data, s = new Uint8Array(t.UNPACKED_SIZE);
1335
+ return this._unpackOperators(E, s), this._unpackPitchEG(E, s), this._unpackGlobalParams(E, s), this._unpackName(E, s), s;
1336
1336
  }
1337
1337
  /**
1338
1338
  * Unpack all 6 operators from packed to unpacked format
1339
1339
  * @private
1340
1340
  */
1341
- _unpackOperators(t, n) {
1342
- for (let s = 0; s < E.NUM_OPERATORS; s++) {
1343
- const _ = (E.NUM_OPERATORS - 1 - s) * E.PACKED_OP_SIZE, e = s * E.UNPACKED_OP_SIZE;
1344
- this._unpackOperator(t, n, _, e);
1341
+ _unpackOperators(E, s) {
1342
+ for (let n = 0; n < t.NUM_OPERATORS; n++) {
1343
+ const _ = (t.NUM_OPERATORS - 1 - n) * t.PACKED_OP_SIZE, r = n * t.UNPACKED_OP_SIZE;
1344
+ this._unpackOperator(E, s, _, r);
1345
1345
  }
1346
1346
  }
1347
1347
  /**
1348
1348
  * Unpack a single operator's parameters
1349
1349
  * @private
1350
1350
  */
1351
- _unpackOperator(t, n, s, _) {
1352
- this._unpackOperatorEG(t, n, s, _), this._unpackOperatorScaling(t, n, s, _), this._unpackOperatorPackedParams(t, n, s, _), this._unpackOperatorFrequency(t, n, s, _);
1351
+ _unpackOperator(E, s, n, _) {
1352
+ this._unpackOperatorEG(E, s, n, _), this._unpackOperatorScaling(E, s, n, _), this._unpackOperatorPackedParams(E, s, n, _), this._unpackOperatorFrequency(E, s, n, _);
1353
1353
  }
1354
1354
  /**
1355
1355
  * Unpack operator EG rates and levels
1356
1356
  * @private
1357
1357
  */
1358
- _unpackOperatorEG(t, n, s, _) {
1359
- n[_ + E.UNPACKED_OP_EG_RATE_1] = t[s + E.PACKED_OP_EG_RATE_1] & E.MASK_7BIT, n[_ + E.UNPACKED_OP_EG_RATE_2] = t[s + E.PACKED_OP_EG_RATE_2] & E.MASK_7BIT, n[_ + E.UNPACKED_OP_EG_RATE_3] = t[s + E.PACKED_OP_EG_RATE_3] & E.MASK_7BIT, n[_ + E.UNPACKED_OP_EG_RATE_4] = t[s + E.PACKED_OP_EG_RATE_4] & E.MASK_7BIT, n[_ + E.UNPACKED_OP_EG_LEVEL_1] = t[s + E.PACKED_OP_EG_LEVEL_1] & E.MASK_7BIT, n[_ + E.UNPACKED_OP_EG_LEVEL_2] = t[s + E.PACKED_OP_EG_LEVEL_2] & E.MASK_7BIT, n[_ + E.UNPACKED_OP_EG_LEVEL_3] = t[s + E.PACKED_OP_EG_LEVEL_3] & E.MASK_7BIT, n[_ + E.UNPACKED_OP_EG_LEVEL_4] = t[s + E.PACKED_OP_EG_LEVEL_4] & E.MASK_7BIT;
1358
+ _unpackOperatorEG(E, s, n, _) {
1359
+ s[_ + t.UNPACKED_OP_EG_RATE_1] = E[n + t.PACKED_OP_EG_RATE_1] & t.MASK_7BIT, s[_ + t.UNPACKED_OP_EG_RATE_2] = E[n + t.PACKED_OP_EG_RATE_2] & t.MASK_7BIT, s[_ + t.UNPACKED_OP_EG_RATE_3] = E[n + t.PACKED_OP_EG_RATE_3] & t.MASK_7BIT, s[_ + t.UNPACKED_OP_EG_RATE_4] = E[n + t.PACKED_OP_EG_RATE_4] & t.MASK_7BIT, s[_ + t.UNPACKED_OP_EG_LEVEL_1] = E[n + t.PACKED_OP_EG_LEVEL_1] & t.MASK_7BIT, s[_ + t.UNPACKED_OP_EG_LEVEL_2] = E[n + t.PACKED_OP_EG_LEVEL_2] & t.MASK_7BIT, s[_ + t.UNPACKED_OP_EG_LEVEL_3] = E[n + t.PACKED_OP_EG_LEVEL_3] & t.MASK_7BIT, s[_ + t.UNPACKED_OP_EG_LEVEL_4] = E[n + t.PACKED_OP_EG_LEVEL_4] & t.MASK_7BIT;
1360
1360
  }
1361
1361
  /**
1362
1362
  * Unpack operator keyboard scaling parameters
1363
1363
  * @private
1364
1364
  */
1365
- _unpackOperatorScaling(t, n, s, _) {
1366
- n[_ + E.UNPACKED_OP_BREAK_POINT] = t[s + E.PACKED_OP_BREAK_POINT] & E.MASK_7BIT, n[_ + E.UNPACKED_OP_L_SCALE_DEPTH] = t[s + E.PACKED_OP_L_SCALE_DEPTH] & E.MASK_7BIT, n[_ + E.UNPACKED_OP_R_SCALE_DEPTH] = t[s + E.PACKED_OP_R_SCALE_DEPTH] & E.MASK_7BIT;
1365
+ _unpackOperatorScaling(E, s, n, _) {
1366
+ s[_ + t.UNPACKED_OP_BREAK_POINT] = E[n + t.PACKED_OP_BREAK_POINT] & t.MASK_7BIT, s[_ + t.UNPACKED_OP_L_SCALE_DEPTH] = E[n + t.PACKED_OP_L_SCALE_DEPTH] & t.MASK_7BIT, s[_ + t.UNPACKED_OP_R_SCALE_DEPTH] = E[n + t.PACKED_OP_R_SCALE_DEPTH] & t.MASK_7BIT;
1367
1367
  }
1368
1368
  /**
1369
1369
  * Unpack operator bit-packed parameters (curves, rate scaling, mod sens)
1370
1370
  * @private
1371
1371
  */
1372
- _unpackOperatorPackedParams(t, n, s, _) {
1373
- const e = t[s + E.PACKED_OP_CURVES] & E.MASK_7BIT;
1374
- n[_ + E.UNPACKED_OP_L_CURVE] = e & E.MASK_2BIT, n[_ + E.UNPACKED_OP_R_CURVE] = e >> 2 & E.MASK_2BIT;
1375
- const r = t[s + E.PACKED_OP_RATE_SCALING] & E.MASK_7BIT;
1376
- n[_ + E.UNPACKED_OP_RATE_SCALING] = r & E.MASK_3BIT, n[_ + E.UNPACKED_OP_DETUNE] = r >> 3 & E.MASK_4BIT;
1377
- const A = t[s + E.PACKED_OP_MOD_SENS] & E.MASK_7BIT;
1378
- n[_ + E.UNPACKED_OP_AMP_MOD_SENS] = A & E.MASK_2BIT, n[_ + E.UNPACKED_OP_KEY_VEL_SENS] = A >> 2 & E.MASK_3BIT, n[_ + E.UNPACKED_OP_OUTPUT_LEVEL] = t[s + E.PACKED_OP_OUTPUT_LEVEL] & E.MASK_7BIT;
1372
+ _unpackOperatorPackedParams(E, s, n, _) {
1373
+ const r = E[n + t.PACKED_OP_CURVES] & t.MASK_7BIT;
1374
+ s[_ + t.UNPACKED_OP_L_CURVE] = r & t.MASK_2BIT, s[_ + t.UNPACKED_OP_R_CURVE] = r >> 2 & t.MASK_2BIT;
1375
+ const e = E[n + t.PACKED_OP_RATE_SCALING] & t.MASK_7BIT;
1376
+ s[_ + t.UNPACKED_OP_RATE_SCALING] = e & t.MASK_3BIT, s[_ + t.UNPACKED_OP_DETUNE] = e >> 3 & t.MASK_4BIT;
1377
+ const a = E[n + t.PACKED_OP_MOD_SENS] & t.MASK_7BIT;
1378
+ s[_ + t.UNPACKED_OP_AMP_MOD_SENS] = a & t.MASK_2BIT, s[_ + t.UNPACKED_OP_KEY_VEL_SENS] = a >> 2 & t.MASK_3BIT, s[_ + t.UNPACKED_OP_OUTPUT_LEVEL] = E[n + t.PACKED_OP_OUTPUT_LEVEL] & t.MASK_7BIT;
1379
1379
  }
1380
1380
  /**
1381
1381
  * Unpack operator frequency parameters
1382
1382
  * @private
1383
1383
  */
1384
- _unpackOperatorFrequency(t, n, s, _) {
1385
- const e = t[s + E.PACKED_OP_MODE_FREQ] & E.MASK_7BIT;
1386
- n[_ + E.UNPACKED_OP_MODE] = e & E.MASK_1BIT, n[_ + E.UNPACKED_OP_FREQ_COARSE] = e >> 1 & E.MASK_5BIT;
1387
- const r = t[s + E.PACKED_OP_DETUNE_FINE] & E.MASK_7BIT;
1388
- n[_ + E.UNPACKED_OP_OSC_DETUNE] = r & E.MASK_3BIT, n[_ + E.UNPACKED_OP_FREQ_FINE] = r >> 3 & E.MASK_4BIT;
1384
+ _unpackOperatorFrequency(E, s, n, _) {
1385
+ const r = E[n + t.PACKED_OP_MODE_FREQ] & t.MASK_7BIT;
1386
+ s[_ + t.UNPACKED_OP_MODE] = r & t.MASK_1BIT, s[_ + t.UNPACKED_OP_FREQ_COARSE] = r >> 1 & t.MASK_5BIT;
1387
+ const e = E[n + t.PACKED_OP_DETUNE_FINE] & t.MASK_7BIT;
1388
+ s[_ + t.UNPACKED_OP_OSC_DETUNE] = e & t.MASK_3BIT, s[_ + t.UNPACKED_OP_FREQ_FINE] = e >> 3 & t.MASK_4BIT;
1389
1389
  }
1390
1390
  /**
1391
1391
  * Unpack pitch envelope generator parameters
1392
1392
  * @private
1393
1393
  */
1394
- _unpackPitchEG(t, n) {
1395
- n[E.UNPACKED_PITCH_EG_RATE_1] = t[E.PACKED_PITCH_EG_RATE_1] & E.MASK_7BIT, n[E.UNPACKED_PITCH_EG_RATE_2] = t[E.PACKED_PITCH_EG_RATE_2] & E.MASK_7BIT, n[E.UNPACKED_PITCH_EG_RATE_3] = t[E.PACKED_PITCH_EG_RATE_3] & E.MASK_7BIT, n[E.UNPACKED_PITCH_EG_RATE_4] = t[E.PACKED_PITCH_EG_RATE_4] & E.MASK_7BIT, n[E.UNPACKED_PITCH_EG_LEVEL_1] = t[E.PACKED_PITCH_EG_LEVEL_1] & E.MASK_7BIT, n[E.UNPACKED_PITCH_EG_LEVEL_2] = t[E.PACKED_PITCH_EG_LEVEL_2] & E.MASK_7BIT, n[E.UNPACKED_PITCH_EG_LEVEL_3] = t[E.PACKED_PITCH_EG_LEVEL_3] & E.MASK_7BIT, n[E.UNPACKED_PITCH_EG_LEVEL_4] = t[E.PACKED_PITCH_EG_LEVEL_4] & E.MASK_7BIT;
1394
+ _unpackPitchEG(E, s) {
1395
+ s[t.UNPACKED_PITCH_EG_RATE_1] = E[t.PACKED_PITCH_EG_RATE_1] & t.MASK_7BIT, s[t.UNPACKED_PITCH_EG_RATE_2] = E[t.PACKED_PITCH_EG_RATE_2] & t.MASK_7BIT, s[t.UNPACKED_PITCH_EG_RATE_3] = E[t.PACKED_PITCH_EG_RATE_3] & t.MASK_7BIT, s[t.UNPACKED_PITCH_EG_RATE_4] = E[t.PACKED_PITCH_EG_RATE_4] & t.MASK_7BIT, s[t.UNPACKED_PITCH_EG_LEVEL_1] = E[t.PACKED_PITCH_EG_LEVEL_1] & t.MASK_7BIT, s[t.UNPACKED_PITCH_EG_LEVEL_2] = E[t.PACKED_PITCH_EG_LEVEL_2] & t.MASK_7BIT, s[t.UNPACKED_PITCH_EG_LEVEL_3] = E[t.PACKED_PITCH_EG_LEVEL_3] & t.MASK_7BIT, s[t.UNPACKED_PITCH_EG_LEVEL_4] = E[t.PACKED_PITCH_EG_LEVEL_4] & t.MASK_7BIT;
1396
1396
  }
1397
1397
  /**
1398
1398
  * Unpack global voice parameters (algorithm, feedback, LFO, etc.)
1399
1399
  * @private
1400
1400
  */
1401
- _unpackGlobalParams(t, n) {
1402
- n[E.UNPACKED_ALGORITHM] = t[E.OFFSET_ALGORITHM] & E.MASK_5BIT;
1403
- const s = t[E.OFFSET_FEEDBACK] & E.MASK_7BIT;
1404
- n[E.UNPACKED_FEEDBACK] = s & E.MASK_3BIT, n[E.UNPACKED_OSC_SYNC] = s >> 3 & E.MASK_1BIT, n[E.UNPACKED_LFO_SPEED] = t[E.OFFSET_LFO_SPEED] & E.MASK_7BIT, n[E.UNPACKED_LFO_DELAY] = t[E.OFFSET_LFO_DELAY] & E.MASK_7BIT, n[E.UNPACKED_LFO_PM_DEPTH] = t[E.OFFSET_LFO_PM_DEPTH] & E.MASK_7BIT, n[E.UNPACKED_LFO_AM_DEPTH] = t[E.OFFSET_LFO_AM_DEPTH] & E.MASK_7BIT;
1405
- const _ = t[E.OFFSET_LFO_SYNC_WAVE] & E.MASK_7BIT;
1406
- n[E.UNPACKED_LFO_KEY_SYNC] = _ & E.MASK_1BIT, n[E.UNPACKED_LFO_WAVE] = _ >> 1 & E.MASK_3BIT, n[E.UNPACKED_LFO_PM_SENS] = _ >> 4 & E.MASK_3BIT, n[E.UNPACKED_AMP_MOD_SENS] = t[E.OFFSET_AMP_MOD_SENS] & E.MASK_7BIT, n[E.UNPACKED_TRANSPOSE] = t[E.OFFSET_TRANSPOSE] & E.MASK_7BIT, n[E.UNPACKED_EG_BIAS_SENS] = t[E.OFFSET_EG_BIAS_SENS] & E.MASK_7BIT;
1401
+ _unpackGlobalParams(E, s) {
1402
+ s[t.UNPACKED_ALGORITHM] = E[t.OFFSET_ALGORITHM] & t.MASK_5BIT;
1403
+ const n = E[t.OFFSET_FEEDBACK] & t.MASK_7BIT;
1404
+ s[t.UNPACKED_FEEDBACK] = n & t.MASK_3BIT, s[t.UNPACKED_OSC_SYNC] = n >> 3 & t.MASK_1BIT, s[t.UNPACKED_LFO_SPEED] = E[t.OFFSET_LFO_SPEED] & t.MASK_7BIT, s[t.UNPACKED_LFO_DELAY] = E[t.OFFSET_LFO_DELAY] & t.MASK_7BIT, s[t.UNPACKED_LFO_PM_DEPTH] = E[t.OFFSET_LFO_PM_DEPTH] & t.MASK_7BIT, s[t.UNPACKED_LFO_AM_DEPTH] = E[t.OFFSET_LFO_AM_DEPTH] & t.MASK_7BIT;
1405
+ const _ = E[t.OFFSET_LFO_SYNC_WAVE] & t.MASK_7BIT;
1406
+ s[t.UNPACKED_LFO_KEY_SYNC] = _ & t.MASK_1BIT, s[t.UNPACKED_LFO_WAVE] = _ >> 1 & t.MASK_3BIT, s[t.UNPACKED_LFO_PM_SENS] = _ >> 4 & t.MASK_3BIT, s[t.UNPACKED_AMP_MOD_SENS] = E[t.OFFSET_AMP_MOD_SENS] & t.MASK_7BIT, s[t.UNPACKED_TRANSPOSE] = E[t.OFFSET_TRANSPOSE] & t.MASK_7BIT, s[t.UNPACKED_EG_BIAS_SENS] = E[t.OFFSET_EG_BIAS_SENS] & t.MASK_7BIT;
1407
1407
  }
1408
1408
  /**
1409
1409
  * Copy voice name from packed to unpacked format
1410
1410
  * @private
1411
1411
  */
1412
- _unpackName(t, n) {
1413
- for (let s = 0; s < E.NAME_LENGTH; s++)
1414
- n[E.UNPACKED_NAME_START + s] = t[E.PACKED_NAME_START + s] & E.MASK_7BIT;
1412
+ _unpackName(E, s) {
1413
+ for (let n = 0; n < t.NAME_LENGTH; n++)
1414
+ s[t.UNPACKED_NAME_START + n] = E[t.PACKED_NAME_START + n] & t.MASK_7BIT;
1415
1415
  }
1416
1416
  /**
1417
1417
  * Pack 169-byte unpacked data to 128-byte format
1418
1418
  * @param {Array<number>|Uint8Array} unpacked - 169 bytes of unpacked data (159 parameters + 10 name bytes)
1419
1419
  * @returns {Uint8Array} 128 bytes of packed data
1420
1420
  */
1421
- static pack(t) {
1422
- if (t.length !== E.UNPACKED_SIZE)
1423
- throw new I(
1424
- `Invalid unpacked data length: expected ${E.UNPACKED_SIZE} bytes, got ${t.length}`,
1421
+ static pack(E) {
1422
+ if (E.length !== t.UNPACKED_SIZE)
1423
+ throw new o(
1424
+ `Invalid unpacked data length: expected ${t.UNPACKED_SIZE} bytes, got ${E.length}`,
1425
1425
  "length",
1426
- t.length
1426
+ E.length
1427
1427
  );
1428
- const n = new Uint8Array(E.PACKED_SIZE);
1429
- return E._packOperators(t, n), E._packPitchEG(t, n), E._packGlobalParams(t, n), E._packName(t, n), n;
1428
+ const s = new Uint8Array(t.PACKED_SIZE);
1429
+ return t._packOperators(E, s), t._packPitchEG(E, s), t._packGlobalParams(E, s), t._packName(E, s), s;
1430
1430
  }
1431
1431
  /**
1432
1432
  * Pack all 6 operators from unpacked to packed format
1433
1433
  * @private
1434
1434
  */
1435
- static _packOperators(t, n) {
1436
- for (let s = 0; s < E.NUM_OPERATORS; s++) {
1437
- const _ = s * E.UNPACKED_OP_SIZE, e = (E.NUM_OPERATORS - 1 - s) * E.PACKED_OP_SIZE;
1438
- E._packOperator(t, n, _, e);
1435
+ static _packOperators(E, s) {
1436
+ for (let n = 0; n < t.NUM_OPERATORS; n++) {
1437
+ const _ = n * t.UNPACKED_OP_SIZE, r = (t.NUM_OPERATORS - 1 - n) * t.PACKED_OP_SIZE;
1438
+ t._packOperator(E, s, _, r);
1439
1439
  }
1440
1440
  }
1441
1441
  /**
1442
1442
  * Pack a single operator's parameters
1443
1443
  * @private
1444
1444
  */
1445
- static _packOperator(t, n, s, _) {
1446
- E._packOperatorEG(t, n, s, _), E._packOperatorScaling(t, n, s, _), E._packOperatorPackedParams(t, n, s, _), E._packOperatorFrequency(t, n, s, _);
1445
+ static _packOperator(E, s, n, _) {
1446
+ t._packOperatorEG(E, s, n, _), t._packOperatorScaling(E, s, n, _), t._packOperatorPackedParams(E, s, n, _), t._packOperatorFrequency(E, s, n, _);
1447
1447
  }
1448
1448
  /**
1449
1449
  * Pack operator EG rates and levels
1450
1450
  * @private
1451
1451
  */
1452
- static _packOperatorEG(t, n, s, _) {
1453
- n[_ + E.PACKED_OP_EG_RATE_1] = t[s + E.UNPACKED_OP_EG_RATE_1], n[_ + E.PACKED_OP_EG_RATE_2] = t[s + E.UNPACKED_OP_EG_RATE_2], n[_ + E.PACKED_OP_EG_RATE_3] = t[s + E.UNPACKED_OP_EG_RATE_3], n[_ + E.PACKED_OP_EG_RATE_4] = t[s + E.UNPACKED_OP_EG_RATE_4], n[_ + E.PACKED_OP_EG_LEVEL_1] = t[s + E.UNPACKED_OP_EG_LEVEL_1], n[_ + E.PACKED_OP_EG_LEVEL_2] = t[s + E.UNPACKED_OP_EG_LEVEL_2], n[_ + E.PACKED_OP_EG_LEVEL_3] = t[s + E.UNPACKED_OP_EG_LEVEL_3], n[_ + E.PACKED_OP_EG_LEVEL_4] = t[s + E.UNPACKED_OP_EG_LEVEL_4];
1452
+ static _packOperatorEG(E, s, n, _) {
1453
+ s[_ + t.PACKED_OP_EG_RATE_1] = E[n + t.UNPACKED_OP_EG_RATE_1], s[_ + t.PACKED_OP_EG_RATE_2] = E[n + t.UNPACKED_OP_EG_RATE_2], s[_ + t.PACKED_OP_EG_RATE_3] = E[n + t.UNPACKED_OP_EG_RATE_3], s[_ + t.PACKED_OP_EG_RATE_4] = E[n + t.UNPACKED_OP_EG_RATE_4], s[_ + t.PACKED_OP_EG_LEVEL_1] = E[n + t.UNPACKED_OP_EG_LEVEL_1], s[_ + t.PACKED_OP_EG_LEVEL_2] = E[n + t.UNPACKED_OP_EG_LEVEL_2], s[_ + t.PACKED_OP_EG_LEVEL_3] = E[n + t.UNPACKED_OP_EG_LEVEL_3], s[_ + t.PACKED_OP_EG_LEVEL_4] = E[n + t.UNPACKED_OP_EG_LEVEL_4];
1454
1454
  }
1455
1455
  /**
1456
1456
  * Pack operator keyboard scaling parameters
1457
1457
  * @private
1458
1458
  */
1459
- static _packOperatorScaling(t, n, s, _) {
1460
- n[_ + E.PACKED_OP_BREAK_POINT] = t[s + E.UNPACKED_OP_BREAK_POINT], n[_ + E.PACKED_OP_L_SCALE_DEPTH] = t[s + E.UNPACKED_OP_L_SCALE_DEPTH], n[_ + E.PACKED_OP_R_SCALE_DEPTH] = t[s + E.UNPACKED_OP_R_SCALE_DEPTH];
1459
+ static _packOperatorScaling(E, s, n, _) {
1460
+ s[_ + t.PACKED_OP_BREAK_POINT] = E[n + t.UNPACKED_OP_BREAK_POINT], s[_ + t.PACKED_OP_L_SCALE_DEPTH] = E[n + t.UNPACKED_OP_L_SCALE_DEPTH], s[_ + t.PACKED_OP_R_SCALE_DEPTH] = E[n + t.UNPACKED_OP_R_SCALE_DEPTH];
1461
1461
  }
1462
1462
  /**
1463
1463
  * Pack operator bit-packed parameters
1464
1464
  * @private
1465
1465
  */
1466
- static _packOperatorPackedParams(t, n, s, _) {
1467
- const e = t[s + E.UNPACKED_OP_L_CURVE] & E.MASK_2BIT, r = t[s + E.UNPACKED_OP_R_CURVE] & E.MASK_2BIT;
1468
- n[_ + E.PACKED_OP_CURVES] = e | r << 2;
1469
- const A = t[s + E.UNPACKED_OP_RATE_SCALING] & E.MASK_3BIT, T = t[s + E.UNPACKED_OP_DETUNE] & E.MASK_4BIT;
1470
- n[_ + E.PACKED_OP_RATE_SCALING] = A | T << 3;
1471
- const S = t[s + E.UNPACKED_OP_AMP_MOD_SENS] & E.MASK_2BIT, a = t[s + E.UNPACKED_OP_KEY_VEL_SENS] & E.MASK_3BIT;
1472
- n[_ + E.PACKED_OP_MOD_SENS] = S | a << 2, n[_ + E.PACKED_OP_OUTPUT_LEVEL] = t[s + E.UNPACKED_OP_OUTPUT_LEVEL];
1466
+ static _packOperatorPackedParams(E, s, n, _) {
1467
+ const r = E[n + t.UNPACKED_OP_L_CURVE] & t.MASK_2BIT, e = E[n + t.UNPACKED_OP_R_CURVE] & t.MASK_2BIT;
1468
+ s[_ + t.PACKED_OP_CURVES] = r | e << 2;
1469
+ const a = E[n + t.UNPACKED_OP_RATE_SCALING] & t.MASK_3BIT, T = E[n + t.UNPACKED_OP_DETUNE] & t.MASK_4BIT;
1470
+ s[_ + t.PACKED_OP_RATE_SCALING] = a | T << 3;
1471
+ const S = E[n + t.UNPACKED_OP_AMP_MOD_SENS] & t.MASK_2BIT, C = E[n + t.UNPACKED_OP_KEY_VEL_SENS] & t.MASK_3BIT;
1472
+ s[_ + t.PACKED_OP_MOD_SENS] = S | C << 2, s[_ + t.PACKED_OP_OUTPUT_LEVEL] = E[n + t.UNPACKED_OP_OUTPUT_LEVEL];
1473
1473
  }
1474
1474
  /**
1475
1475
  * Pack operator frequency parameters
1476
1476
  * @private
1477
1477
  */
1478
- static _packOperatorFrequency(t, n, s, _) {
1479
- const e = t[s + E.UNPACKED_OP_MODE] & E.MASK_1BIT, r = t[s + E.UNPACKED_OP_FREQ_COARSE] & E.MASK_5BIT;
1480
- n[_ + E.PACKED_OP_MODE_FREQ] = e | r << 1;
1481
- const A = t[s + E.UNPACKED_OP_OSC_DETUNE] & E.MASK_3BIT, T = t[s + E.UNPACKED_OP_FREQ_FINE] & E.MASK_4BIT;
1482
- n[_ + E.PACKED_OP_DETUNE_FINE] = A | T << 3;
1478
+ static _packOperatorFrequency(E, s, n, _) {
1479
+ const r = E[n + t.UNPACKED_OP_MODE] & t.MASK_1BIT, e = E[n + t.UNPACKED_OP_FREQ_COARSE] & t.MASK_5BIT;
1480
+ s[_ + t.PACKED_OP_MODE_FREQ] = r | e << 1;
1481
+ const a = E[n + t.UNPACKED_OP_OSC_DETUNE] & t.MASK_3BIT, T = E[n + t.UNPACKED_OP_FREQ_FINE] & t.MASK_4BIT;
1482
+ s[_ + t.PACKED_OP_DETUNE_FINE] = a | T << 3;
1483
1483
  }
1484
1484
  /**
1485
1485
  * Pack pitch envelope generator parameters
1486
1486
  * @private
1487
1487
  */
1488
- static _packPitchEG(t, n) {
1489
- n[E.PACKED_PITCH_EG_RATE_1] = t[E.UNPACKED_PITCH_EG_RATE_1], n[E.PACKED_PITCH_EG_RATE_2] = t[E.UNPACKED_PITCH_EG_RATE_2], n[E.PACKED_PITCH_EG_RATE_3] = t[E.UNPACKED_PITCH_EG_RATE_3], n[E.PACKED_PITCH_EG_RATE_4] = t[E.UNPACKED_PITCH_EG_RATE_4], n[E.PACKED_PITCH_EG_LEVEL_1] = t[E.UNPACKED_PITCH_EG_LEVEL_1], n[E.PACKED_PITCH_EG_LEVEL_2] = t[E.UNPACKED_PITCH_EG_LEVEL_2], n[E.PACKED_PITCH_EG_LEVEL_3] = t[E.UNPACKED_PITCH_EG_LEVEL_3], n[E.PACKED_PITCH_EG_LEVEL_4] = t[E.UNPACKED_PITCH_EG_LEVEL_4];
1488
+ static _packPitchEG(E, s) {
1489
+ s[t.PACKED_PITCH_EG_RATE_1] = E[t.UNPACKED_PITCH_EG_RATE_1], s[t.PACKED_PITCH_EG_RATE_2] = E[t.UNPACKED_PITCH_EG_RATE_2], s[t.PACKED_PITCH_EG_RATE_3] = E[t.UNPACKED_PITCH_EG_RATE_3], s[t.PACKED_PITCH_EG_RATE_4] = E[t.UNPACKED_PITCH_EG_RATE_4], s[t.PACKED_PITCH_EG_LEVEL_1] = E[t.UNPACKED_PITCH_EG_LEVEL_1], s[t.PACKED_PITCH_EG_LEVEL_2] = E[t.UNPACKED_PITCH_EG_LEVEL_2], s[t.PACKED_PITCH_EG_LEVEL_3] = E[t.UNPACKED_PITCH_EG_LEVEL_3], s[t.PACKED_PITCH_EG_LEVEL_4] = E[t.UNPACKED_PITCH_EG_LEVEL_4];
1490
1490
  }
1491
1491
  /**
1492
1492
  * Pack global voice parameters (algorithm, feedback, LFO, etc.)
1493
1493
  * @private
1494
1494
  */
1495
- static _packGlobalParams(t, n) {
1496
- n[E.OFFSET_ALGORITHM] = t[E.UNPACKED_ALGORITHM];
1497
- const s = t[E.UNPACKED_FEEDBACK] & E.MASK_3BIT, _ = t[E.UNPACKED_OSC_SYNC] & E.MASK_1BIT;
1498
- n[E.OFFSET_FEEDBACK] = s | _ << 3, n[E.OFFSET_LFO_SPEED] = t[E.UNPACKED_LFO_SPEED], n[E.OFFSET_LFO_DELAY] = t[E.UNPACKED_LFO_DELAY], n[E.OFFSET_LFO_PM_DEPTH] = t[E.UNPACKED_LFO_PM_DEPTH], n[E.OFFSET_LFO_AM_DEPTH] = t[E.UNPACKED_LFO_AM_DEPTH];
1499
- const e = t[E.UNPACKED_LFO_KEY_SYNC] & E.MASK_1BIT, r = t[E.UNPACKED_LFO_WAVE] & E.MASK_3BIT, A = t[E.UNPACKED_LFO_PM_SENS] & E.MASK_3BIT;
1500
- n[E.OFFSET_LFO_SYNC_WAVE] = e | r << 1 | A << 4, n[E.OFFSET_AMP_MOD_SENS] = t[E.UNPACKED_AMP_MOD_SENS], n[E.OFFSET_TRANSPOSE] = t[E.UNPACKED_TRANSPOSE], n[E.OFFSET_EG_BIAS_SENS] = t[E.UNPACKED_EG_BIAS_SENS];
1495
+ static _packGlobalParams(E, s) {
1496
+ s[t.OFFSET_ALGORITHM] = E[t.UNPACKED_ALGORITHM];
1497
+ const n = E[t.UNPACKED_FEEDBACK] & t.MASK_3BIT, _ = E[t.UNPACKED_OSC_SYNC] & t.MASK_1BIT;
1498
+ s[t.OFFSET_FEEDBACK] = n | _ << 3, s[t.OFFSET_LFO_SPEED] = E[t.UNPACKED_LFO_SPEED], s[t.OFFSET_LFO_DELAY] = E[t.UNPACKED_LFO_DELAY], s[t.OFFSET_LFO_PM_DEPTH] = E[t.UNPACKED_LFO_PM_DEPTH], s[t.OFFSET_LFO_AM_DEPTH] = E[t.UNPACKED_LFO_AM_DEPTH];
1499
+ const r = E[t.UNPACKED_LFO_KEY_SYNC] & t.MASK_1BIT, e = E[t.UNPACKED_LFO_WAVE] & t.MASK_3BIT, a = E[t.UNPACKED_LFO_PM_SENS] & t.MASK_3BIT;
1500
+ s[t.OFFSET_LFO_SYNC_WAVE] = r | e << 1 | a << 4, s[t.OFFSET_AMP_MOD_SENS] = E[t.UNPACKED_AMP_MOD_SENS], s[t.OFFSET_TRANSPOSE] = E[t.UNPACKED_TRANSPOSE], s[t.OFFSET_EG_BIAS_SENS] = E[t.UNPACKED_EG_BIAS_SENS];
1501
1501
  }
1502
1502
  /**
1503
1503
  * Copy voice name from unpacked to packed format
1504
1504
  * @private
1505
1505
  */
1506
- static _packName(t, n) {
1507
- for (let s = 0; s < E.NAME_LENGTH; s++)
1508
- n[E.PACKED_NAME_START + s] = t[E.UNPACKED_NAME_START + s];
1506
+ static _packName(E, s) {
1507
+ for (let n = 0; n < t.NAME_LENGTH; n++)
1508
+ s[t.PACKED_NAME_START + n] = E[t.UNPACKED_NAME_START + n];
1509
1509
  }
1510
1510
  /**
1511
1511
  * Create a default/empty voice
1512
1512
  * @param {number} index - Voice index
1513
1513
  * @returns {DX7Voice}
1514
1514
  */
1515
- static createDefault(t = 0) {
1516
- const n = new Uint8Array(E.UNPACKED_SIZE);
1517
- for (let e = 0; e < E.NUM_OPERATORS; e++) {
1518
- const r = e * E.UNPACKED_OP_SIZE;
1519
- n[r + E.UNPACKED_OP_EG_RATE_1] = E.DEFAULT_EG_RATE, n[r + E.UNPACKED_OP_EG_RATE_2] = E.DEFAULT_EG_RATE, n[r + E.UNPACKED_OP_EG_RATE_3] = E.DEFAULT_EG_RATE, n[r + E.UNPACKED_OP_EG_RATE_4] = E.DEFAULT_EG_RATE, n[r + E.UNPACKED_OP_EG_LEVEL_1] = E.DEFAULT_EG_LEVEL_MAX, n[r + E.UNPACKED_OP_EG_LEVEL_2] = E.DEFAULT_EG_LEVEL_MAX, n[r + E.UNPACKED_OP_EG_LEVEL_3] = E.DEFAULT_EG_LEVEL_MAX, n[r + E.UNPACKED_OP_EG_LEVEL_4] = E.DEFAULT_EG_LEVEL_MIN, n[r + E.UNPACKED_OP_BREAK_POINT] = E.DEFAULT_BREAK_POINT, n[r + E.UNPACKED_OP_L_SCALE_DEPTH] = 0, n[r + E.UNPACKED_OP_R_SCALE_DEPTH] = 0, n[r + E.UNPACKED_OP_L_CURVE] = 0, n[r + E.UNPACKED_OP_R_CURVE] = 0, n[r + E.UNPACKED_OP_RATE_SCALING] = 0, n[r + E.UNPACKED_OP_AMP_MOD_SENS] = 0, n[r + E.UNPACKED_OP_KEY_VEL_SENS] = 0, n[r + E.UNPACKED_OP_OUTPUT_LEVEL] = E.DEFAULT_OUTPUT_LEVEL, n[r + E.UNPACKED_OP_MODE] = 0, n[r + E.UNPACKED_OP_FREQ_COARSE] = 0, n[r + E.UNPACKED_OP_OSC_DETUNE] = 0, n[r + E.UNPACKED_OP_FREQ_FINE] = 0;
1515
+ static createDefault(E = 0) {
1516
+ const s = new Uint8Array(t.UNPACKED_SIZE);
1517
+ for (let r = 0; r < t.NUM_OPERATORS; r++) {
1518
+ const e = r * t.UNPACKED_OP_SIZE;
1519
+ s[e + t.UNPACKED_OP_EG_RATE_1] = t.DEFAULT_EG_RATE, s[e + t.UNPACKED_OP_EG_RATE_2] = t.DEFAULT_EG_RATE, s[e + t.UNPACKED_OP_EG_RATE_3] = t.DEFAULT_EG_RATE, s[e + t.UNPACKED_OP_EG_RATE_4] = t.DEFAULT_EG_RATE, s[e + t.UNPACKED_OP_EG_LEVEL_1] = t.DEFAULT_EG_LEVEL_MAX, s[e + t.UNPACKED_OP_EG_LEVEL_2] = t.DEFAULT_EG_LEVEL_MAX, s[e + t.UNPACKED_OP_EG_LEVEL_3] = t.DEFAULT_EG_LEVEL_MAX, s[e + t.UNPACKED_OP_EG_LEVEL_4] = t.DEFAULT_EG_LEVEL_MIN, s[e + t.UNPACKED_OP_BREAK_POINT] = t.DEFAULT_BREAK_POINT, s[e + t.UNPACKED_OP_L_SCALE_DEPTH] = 0, s[e + t.UNPACKED_OP_R_SCALE_DEPTH] = 0, s[e + t.UNPACKED_OP_L_CURVE] = 0, s[e + t.UNPACKED_OP_R_CURVE] = 0, s[e + t.UNPACKED_OP_RATE_SCALING] = 0, s[e + t.UNPACKED_OP_DETUNE] = 7, s[e + t.UNPACKED_OP_AMP_MOD_SENS] = 0, s[e + t.UNPACKED_OP_KEY_VEL_SENS] = 0, s[e + t.UNPACKED_OP_OUTPUT_LEVEL] = t.DEFAULT_OUTPUT_LEVEL, s[e + t.UNPACKED_OP_MODE] = 0, s[e + t.UNPACKED_OP_FREQ_COARSE] = 0, s[e + t.UNPACKED_OP_OSC_DETUNE] = 0, s[e + t.UNPACKED_OP_FREQ_FINE] = 0;
1520
1520
  }
1521
- n[E.UNPACKED_PITCH_EG_RATE_1] = E.DEFAULT_EG_RATE, n[E.UNPACKED_PITCH_EG_RATE_2] = E.DEFAULT_EG_RATE, n[E.UNPACKED_PITCH_EG_RATE_3] = E.DEFAULT_EG_RATE, n[E.UNPACKED_PITCH_EG_RATE_4] = E.DEFAULT_EG_RATE, n[E.UNPACKED_PITCH_EG_LEVEL_1] = E.DEFAULT_PITCH_EG_LEVEL, n[E.UNPACKED_PITCH_EG_LEVEL_2] = E.DEFAULT_PITCH_EG_LEVEL, n[E.UNPACKED_PITCH_EG_LEVEL_3] = E.DEFAULT_PITCH_EG_LEVEL, n[E.UNPACKED_PITCH_EG_LEVEL_4] = E.DEFAULT_PITCH_EG_LEVEL, n[E.UNPACKED_ALGORITHM] = E.DEFAULT_ALGORITHM, n[E.UNPACKED_FEEDBACK] = E.DEFAULT_FEEDBACK, n[E.UNPACKED_OSC_SYNC] = 0, n[E.UNPACKED_LFO_SPEED] = E.DEFAULT_LFO_SPEED, n[E.UNPACKED_LFO_DELAY] = 0, n[E.UNPACKED_LFO_PM_DEPTH] = 0, n[E.UNPACKED_LFO_AM_DEPTH] = 0, n[E.UNPACKED_LFO_KEY_SYNC] = 0, n[E.UNPACKED_LFO_WAVE] = 0, n[E.UNPACKED_LFO_PM_SENS] = E.DEFAULT_LFO_PM_SENS, n[E.UNPACKED_AMP_MOD_SENS] = 0, n[E.UNPACKED_TRANSPOSE] = E.TRANSPOSE_CENTER, n[E.UNPACKED_EG_BIAS_SENS] = 0;
1522
- const s = "Init Voice";
1523
- for (let e = 0; e < E.NAME_LENGTH; e++)
1524
- n[E.UNPACKED_NAME_START + e] = e < s.length ? s.charCodeAt(e) : E.CHAR_SPACE;
1525
- const _ = E.pack(n);
1526
- return new E(_, t);
1521
+ s[t.UNPACKED_PITCH_EG_RATE_1] = t.DEFAULT_EG_RATE, s[t.UNPACKED_PITCH_EG_RATE_2] = t.DEFAULT_EG_RATE, s[t.UNPACKED_PITCH_EG_RATE_3] = t.DEFAULT_EG_RATE, s[t.UNPACKED_PITCH_EG_RATE_4] = t.DEFAULT_EG_RATE, s[t.UNPACKED_PITCH_EG_LEVEL_1] = t.DEFAULT_PITCH_EG_LEVEL, s[t.UNPACKED_PITCH_EG_LEVEL_2] = t.DEFAULT_PITCH_EG_LEVEL, s[t.UNPACKED_PITCH_EG_LEVEL_3] = t.DEFAULT_PITCH_EG_LEVEL, s[t.UNPACKED_PITCH_EG_LEVEL_4] = t.DEFAULT_PITCH_EG_LEVEL, s[t.UNPACKED_ALGORITHM] = t.DEFAULT_ALGORITHM, s[t.UNPACKED_FEEDBACK] = t.DEFAULT_FEEDBACK, s[t.UNPACKED_OSC_SYNC] = 0, s[t.UNPACKED_LFO_SPEED] = t.DEFAULT_LFO_SPEED, s[t.UNPACKED_LFO_DELAY] = 0, s[t.UNPACKED_LFO_PM_DEPTH] = 0, s[t.UNPACKED_LFO_AM_DEPTH] = 0, s[t.UNPACKED_LFO_KEY_SYNC] = 0, s[t.UNPACKED_LFO_WAVE] = 0, s[t.UNPACKED_LFO_PM_SENS] = t.DEFAULT_LFO_PM_SENS, s[t.UNPACKED_AMP_MOD_SENS] = 0, s[t.UNPACKED_TRANSPOSE] = t.TRANSPOSE_CENTER, s[t.UNPACKED_EG_BIAS_SENS] = 0;
1522
+ const n = "Init Voice";
1523
+ for (let r = 0; r < t.NAME_LENGTH; r++)
1524
+ s[t.UNPACKED_NAME_START + r] = r < n.length ? n.charCodeAt(r) : t.CHAR_SPACE;
1525
+ const _ = t.pack(s);
1526
+ return new t(_, E);
1527
1527
  }
1528
1528
  /**
1529
1529
  * Create a voice from unpacked 169-byte data
@@ -1531,9 +1531,9 @@ class E {
1531
1531
  * @param {number} index - Voice index
1532
1532
  * @returns {DX7Voice}
1533
1533
  */
1534
- static fromUnpacked(t, n = 0) {
1535
- const s = E.pack(t);
1536
- return new E(s, n);
1534
+ static fromUnpacked(E, s = 0) {
1535
+ const n = t.pack(E);
1536
+ return new t(n, s);
1537
1537
  }
1538
1538
  /**
1539
1539
  * Load a DX7 voice from a single voice SYX file
@@ -1542,40 +1542,229 @@ class E {
1542
1542
  * @throws {DX7ParseError} If file has invalid VCED header
1543
1543
  * @throws {Error} If file cannot be read (FileReader error)
1544
1544
  */
1545
- static async fromFile(t) {
1546
- return new Promise((n, s) => {
1545
+ static async fromFile(E) {
1546
+ return new Promise((s, n) => {
1547
1547
  const _ = new FileReader();
1548
- _.onload = (e) => {
1548
+ _.onload = (r) => {
1549
1549
  try {
1550
- const r = new Uint8Array(e.target.result);
1551
- if (r[0] !== E.VCED_SYSEX_START || r[1] !== E.VCED_YAMAHA_ID || r[2] !== E.VCED_SUB_STATUS || r[3] !== E.VCED_FORMAT_SINGLE || r[4] !== E.VCED_BYTE_COUNT_MSB || r[5] !== E.VCED_BYTE_COUNT_LSB)
1552
- throw new D("Invalid VCED header", "header", 0);
1553
- const A = r.subarray(
1554
- E.VCED_HEADER_SIZE,
1555
- E.VCED_HEADER_SIZE + E.VCED_DATA_SIZE
1556
- ), T = r[E.VCED_HEADER_SIZE + E.VCED_DATA_SIZE], S = C._calculateChecksum(A, E.VCED_DATA_SIZE);
1550
+ const e = new Uint8Array(r.target.result);
1551
+ 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)
1552
+ throw new m("Invalid VCED header", "header", 0);
1553
+ const a = e.subarray(
1554
+ t.VCED_HEADER_SIZE,
1555
+ t.VCED_HEADER_SIZE + t.VCED_DATA_SIZE
1556
+ ), T = e[t.VCED_HEADER_SIZE + t.VCED_DATA_SIZE], S = N._calculateChecksum(a, t.VCED_DATA_SIZE);
1557
1557
  T !== S && console.warn(
1558
1558
  `DX7 VCED checksum mismatch (expected ${S.toString(16)}, got ${T.toString(16)}). This is common with vintage SysEx files.`
1559
1559
  );
1560
- const a = new Uint8Array(E.UNPACKED_SIZE);
1560
+ const C = new Uint8Array(t.UNPACKED_SIZE);
1561
1561
  let P = 0;
1562
- for (let u = 0; u < E.NUM_OPERATORS; u++) {
1563
- const N = (E.NUM_OPERATORS - 1 - u) * E.UNPACKED_OP_SIZE;
1564
- a[N + E.UNPACKED_OP_EG_RATE_1] = A[P++], a[N + E.UNPACKED_OP_EG_RATE_2] = A[P++], a[N + E.UNPACKED_OP_EG_RATE_3] = A[P++], a[N + E.UNPACKED_OP_EG_RATE_4] = A[P++], a[N + E.UNPACKED_OP_EG_LEVEL_1] = A[P++], a[N + E.UNPACKED_OP_EG_LEVEL_2] = A[P++], a[N + E.UNPACKED_OP_EG_LEVEL_3] = A[P++], a[N + E.UNPACKED_OP_EG_LEVEL_4] = A[P++], a[N + E.UNPACKED_OP_BREAK_POINT] = A[P++], a[N + E.UNPACKED_OP_L_SCALE_DEPTH] = A[P++], a[N + E.UNPACKED_OP_R_SCALE_DEPTH] = A[P++], a[N + E.UNPACKED_OP_L_CURVE] = A[P++], a[N + E.UNPACKED_OP_R_CURVE] = A[P++], a[N + E.UNPACKED_OP_RATE_SCALING] = A[P++], a[N + E.UNPACKED_OP_DETUNE] = A[P++];
1565
- const h = A[P++];
1566
- a[N + E.UNPACKED_OP_AMP_MOD_SENS] = h & E.MASK_2BIT, a[N + E.UNPACKED_OP_KEY_VEL_SENS] = h >> 2 & E.MASK_3BIT, a[N + E.UNPACKED_OP_OUTPUT_LEVEL] = A[P++], a[N + E.UNPACKED_OP_MODE] = A[P++], a[N + E.UNPACKED_OP_FREQ_COARSE] = A[P++], a[N + E.UNPACKED_OP_FREQ_FINE] = A[P++], a[N + E.UNPACKED_OP_OSC_DETUNE] = A[P++];
1562
+ for (let l = 0; l < t.NUM_OPERATORS; l++) {
1563
+ const O = (t.NUM_OPERATORS - 1 - l) * t.UNPACKED_OP_SIZE;
1564
+ C[O + t.UNPACKED_OP_EG_RATE_1] = a[P++], C[O + t.UNPACKED_OP_EG_RATE_2] = a[P++], C[O + t.UNPACKED_OP_EG_RATE_3] = a[P++], C[O + t.UNPACKED_OP_EG_RATE_4] = a[P++], C[O + t.UNPACKED_OP_EG_LEVEL_1] = a[P++], C[O + t.UNPACKED_OP_EG_LEVEL_2] = a[P++], C[O + t.UNPACKED_OP_EG_LEVEL_3] = a[P++], C[O + t.UNPACKED_OP_EG_LEVEL_4] = a[P++], C[O + t.UNPACKED_OP_BREAK_POINT] = a[P++], C[O + t.UNPACKED_OP_L_SCALE_DEPTH] = a[P++], C[O + t.UNPACKED_OP_R_SCALE_DEPTH] = a[P++], C[O + t.UNPACKED_OP_L_CURVE] = a[P++], C[O + t.UNPACKED_OP_R_CURVE] = a[P++], C[O + t.UNPACKED_OP_RATE_SCALING] = a[P++], C[O + t.UNPACKED_OP_DETUNE] = a[P++];
1565
+ const K = a[P++];
1566
+ C[O + t.UNPACKED_OP_AMP_MOD_SENS] = K & t.MASK_2BIT, C[O + t.UNPACKED_OP_KEY_VEL_SENS] = K >> 2 & t.MASK_3BIT, C[O + t.UNPACKED_OP_OUTPUT_LEVEL] = a[P++], C[O + t.UNPACKED_OP_MODE] = a[P++], C[O + t.UNPACKED_OP_FREQ_COARSE] = a[P++], C[O + t.UNPACKED_OP_FREQ_FINE] = a[P++], C[O + t.UNPACKED_OP_OSC_DETUNE] = a[P++];
1567
1567
  }
1568
- a[E.UNPACKED_PITCH_EG_RATE_1] = A[P++], a[E.UNPACKED_PITCH_EG_RATE_2] = A[P++], a[E.UNPACKED_PITCH_EG_RATE_3] = A[P++], a[E.UNPACKED_PITCH_EG_RATE_4] = A[P++], a[E.UNPACKED_PITCH_EG_LEVEL_1] = A[P++], a[E.UNPACKED_PITCH_EG_LEVEL_2] = A[P++], a[E.UNPACKED_PITCH_EG_LEVEL_3] = A[P++], a[E.UNPACKED_PITCH_EG_LEVEL_4] = A[P++], a[E.UNPACKED_ALGORITHM] = A[P++], a[E.UNPACKED_FEEDBACK] = A[P++], a[E.UNPACKED_OSC_SYNC] = A[P++], a[E.UNPACKED_LFO_SPEED] = A[P++], a[E.UNPACKED_LFO_DELAY] = A[P++], a[E.UNPACKED_LFO_PM_DEPTH] = A[P++], a[E.UNPACKED_LFO_AM_DEPTH] = A[P++], a[E.UNPACKED_LFO_KEY_SYNC] = A[P++], a[E.UNPACKED_LFO_WAVE] = A[P++], a[E.UNPACKED_LFO_PM_SENS] = A[P++], a[E.UNPACKED_TRANSPOSE] = A[P++];
1569
- for (let u = 0; u < E.NAME_LENGTH; u++)
1570
- a[E.UNPACKED_NAME_START + u] = A[P++];
1571
- const l = E.pack(a);
1572
- n(new E(l, 0));
1573
- } catch (r) {
1574
- s(r);
1568
+ C[t.UNPACKED_PITCH_EG_RATE_1] = a[P++], C[t.UNPACKED_PITCH_EG_RATE_2] = a[P++], C[t.UNPACKED_PITCH_EG_RATE_3] = a[P++], C[t.UNPACKED_PITCH_EG_RATE_4] = a[P++], C[t.UNPACKED_PITCH_EG_LEVEL_1] = a[P++], C[t.UNPACKED_PITCH_EG_LEVEL_2] = a[P++], C[t.UNPACKED_PITCH_EG_LEVEL_3] = a[P++], C[t.UNPACKED_PITCH_EG_LEVEL_4] = a[P++], C[t.UNPACKED_ALGORITHM] = a[P++], C[t.UNPACKED_FEEDBACK] = a[P++], C[t.UNPACKED_OSC_SYNC] = a[P++], C[t.UNPACKED_LFO_SPEED] = a[P++], C[t.UNPACKED_LFO_DELAY] = a[P++], C[t.UNPACKED_LFO_PM_DEPTH] = a[P++], C[t.UNPACKED_LFO_AM_DEPTH] = a[P++], C[t.UNPACKED_LFO_KEY_SYNC] = a[P++], C[t.UNPACKED_LFO_WAVE] = a[P++], C[t.UNPACKED_LFO_PM_SENS] = a[P++], C[t.UNPACKED_TRANSPOSE] = a[P++];
1569
+ for (let l = 0; l < t.NAME_LENGTH; l++)
1570
+ C[t.UNPACKED_NAME_START + l] = a[P++];
1571
+ const i = t.pack(C);
1572
+ s(new t(i, 0));
1573
+ } catch (e) {
1574
+ n(e);
1575
1575
  }
1576
- }, _.onerror = () => s(new Error("Failed to read file")), _.readAsArrayBuffer(t);
1576
+ }, _.onerror = () => n(new Error("Failed to read file")), _.readAsArrayBuffer(E);
1577
1577
  });
1578
1578
  }
1579
+ /**
1580
+ * Create a DX7Voice from SysEx data
1581
+ * @param {Array<number>|ArrayBuffer|Uint8Array} data - Voice data (128 bytes of packed voice data) or VCED SysEx data (163 bytes with header/footer)
1582
+ * @param {number} index - Voice index (optional, defaults to 0)
1583
+ * @returns {DX7Voice}
1584
+ * @throws {DX7ParseError} If VCED header is invalid
1585
+ * @throws {DX7ValidationError} If data length is invalid
1586
+ */
1587
+ static fromSysEx(E, s = 0) {
1588
+ const n = E instanceof Uint8Array ? E : new Uint8Array(E);
1589
+ let _;
1590
+ if (n[0] === t.VCED_SYSEX_START) {
1591
+ 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)
1592
+ throw new m("Invalid VCED header", "header", 0);
1593
+ _ = n.subarray(t.VCED_HEADER_SIZE, t.VCED_HEADER_SIZE + t.VCED_DATA_SIZE);
1594
+ } else if (n.length === t.PACKED_SIZE)
1595
+ _ = n;
1596
+ else
1597
+ throw new o(
1598
+ `Invalid data length: expected ${t.PACKED_SIZE} or ${t.VCED_SIZE} bytes, got ${n.length}`,
1599
+ "length",
1600
+ n.length
1601
+ );
1602
+ if (_.length !== t.VCED_DATA_SIZE && _.length !== t.PACKED_SIZE)
1603
+ throw new o(
1604
+ `Invalid voice data length: expected ${t.VCED_DATA_SIZE} or ${t.PACKED_SIZE} bytes, got ${_.length}`,
1605
+ "length",
1606
+ _.length
1607
+ );
1608
+ if (_.length === t.VCED_DATA_SIZE) {
1609
+ const r = new Uint8Array(t.UNPACKED_SIZE);
1610
+ let e = 0;
1611
+ for (let T = 0; T < t.NUM_OPERATORS; T++) {
1612
+ const S = (t.NUM_OPERATORS - 1 - T) * t.UNPACKED_OP_SIZE;
1613
+ r[S + t.UNPACKED_OP_EG_RATE_1] = _[e++], r[S + t.UNPACKED_OP_EG_RATE_2] = _[e++], r[S + t.UNPACKED_OP_EG_RATE_3] = _[e++], r[S + t.UNPACKED_OP_EG_RATE_4] = _[e++], r[S + t.UNPACKED_OP_EG_LEVEL_1] = _[e++], r[S + t.UNPACKED_OP_EG_LEVEL_2] = _[e++], r[S + t.UNPACKED_OP_EG_LEVEL_3] = _[e++], r[S + t.UNPACKED_OP_EG_LEVEL_4] = _[e++], r[S + t.UNPACKED_OP_BREAK_POINT] = _[e++], r[S + t.UNPACKED_OP_L_SCALE_DEPTH] = _[e++], r[S + t.UNPACKED_OP_R_SCALE_DEPTH] = _[e++], r[S + t.UNPACKED_OP_L_CURVE] = _[e++], r[S + t.UNPACKED_OP_R_CURVE] = _[e++], r[S + t.UNPACKED_OP_RATE_SCALING] = _[e++], r[S + t.UNPACKED_OP_DETUNE] = _[e++];
1614
+ const C = _[e++];
1615
+ r[S + t.UNPACKED_OP_AMP_MOD_SENS] = C & t.MASK_2BIT, r[S + t.UNPACKED_OP_KEY_VEL_SENS] = C >> 2 & t.MASK_3BIT, r[S + t.UNPACKED_OP_OUTPUT_LEVEL] = _[e++], r[S + t.UNPACKED_OP_MODE] = _[e++], r[S + t.UNPACKED_OP_FREQ_COARSE] = _[e++], r[S + t.UNPACKED_OP_FREQ_FINE] = _[e++], r[S + t.UNPACKED_OP_OSC_DETUNE] = _[e++];
1616
+ }
1617
+ r[t.UNPACKED_PITCH_EG_RATE_1] = _[e++], r[t.UNPACKED_PITCH_EG_RATE_2] = _[e++], r[t.UNPACKED_PITCH_EG_RATE_3] = _[e++], r[t.UNPACKED_PITCH_EG_RATE_4] = _[e++], r[t.UNPACKED_PITCH_EG_LEVEL_1] = _[e++], r[t.UNPACKED_PITCH_EG_LEVEL_2] = _[e++], r[t.UNPACKED_PITCH_EG_LEVEL_3] = _[e++], r[t.UNPACKED_PITCH_EG_LEVEL_4] = _[e++], r[t.UNPACKED_ALGORITHM] = _[e++], r[t.UNPACKED_FEEDBACK] = _[e++], r[t.UNPACKED_OSC_SYNC] = _[e++], r[t.UNPACKED_LFO_SPEED] = _[e++], r[t.UNPACKED_LFO_DELAY] = _[e++], r[t.UNPACKED_LFO_PM_DEPTH] = _[e++], r[t.UNPACKED_LFO_AM_DEPTH] = _[e++], r[t.UNPACKED_LFO_KEY_SYNC] = _[e++], r[t.UNPACKED_LFO_WAVE] = _[e++], r[t.UNPACKED_LFO_PM_SENS] = _[e++], r[t.UNPACKED_TRANSPOSE] = _[e++];
1618
+ for (let T = 0; T < t.NAME_LENGTH; T++)
1619
+ r[t.UNPACKED_NAME_START + T] = _[e++];
1620
+ const a = t.pack(r);
1621
+ return new t(a, s);
1622
+ }
1623
+ return new t(_, s);
1624
+ }
1625
+ /**
1626
+ * Create a DX7Voice from a JSON object
1627
+ * @param {DX7VoiceJSON} json - JSON representation of a DX7 voice
1628
+ * @param {number} index - Voice index (optional, defaults to 0)
1629
+ * @returns {DX7Voice}
1630
+ * @throws {DX7ValidationError} If JSON structure is invalid
1631
+ */
1632
+ static fromJSON(E, s = 0) {
1633
+ if (!E || typeof E != "object")
1634
+ throw new o("Invalid JSON: expected object", "json", E);
1635
+ const n = new Uint8Array(t.UNPACKED_SIZE), _ = (P, i, l, O = 0, K = 127) => {
1636
+ if (i == null)
1637
+ throw new o(`Missing required parameter: ${l}`, l, i);
1638
+ const U = Number(i);
1639
+ if (Number.isNaN(U))
1640
+ throw new o(`Invalid parameter value for ${l}: ${i}`, l, i);
1641
+ if (U < O || U > K)
1642
+ throw new o(
1643
+ `Parameter ${l} out of range: ${U} (must be ${O}-${K})`,
1644
+ l,
1645
+ U
1646
+ );
1647
+ n[P] = Math.floor(U);
1648
+ }, r = (P) => {
1649
+ const i = { "-LN": 0, "-EX": 1, "+EX": 2, "+LN": 3 };
1650
+ return i[P] !== void 0 ? i[P] : 0;
1651
+ }, e = (P) => {
1652
+ const i = {
1653
+ TRIANGLE: 0,
1654
+ "SAW DOWN": 1,
1655
+ "SAW UP": 2,
1656
+ SQUARE: 3,
1657
+ SINE: 4,
1658
+ "SAMPLE & HOLD": 5
1659
+ };
1660
+ return i[P] !== void 0 ? i[P] : 0;
1661
+ }, a = (P) => {
1662
+ if (!P || typeof P != "string") return 60;
1663
+ const i = P.trim().match(/^([A-G]#?)(-?\d+)$/);
1664
+ if (!i) return 60;
1665
+ const [, l, O] = i, K = parseInt(O, 10), I = { C: 0, "C#": 1, D: 2, "D#": 3, E: 4, F: 5, "F#": 6, G: 7, "G#": 8, A: 9, "A#": 10, B: 11 }[l.toUpperCase()];
1666
+ return I === void 0 ? 60 : (K - t.MIDI_OCTAVE_OFFSET) * 12 + I;
1667
+ };
1668
+ if (!Array.isArray(E.operators))
1669
+ throw new o("Invalid operators array: expected array", "operators", E.operators);
1670
+ for (let P = 0; P < E.operators.length; P++) {
1671
+ const i = E.operators[P];
1672
+ if (!i || typeof i != "object")
1673
+ throw new o(`Invalid operator data at index ${P}`, `operators[${P}]`, i);
1674
+ if (!i.eg || !Array.isArray(i.eg.rates) || i.eg.rates.length !== 4)
1675
+ throw new o(
1676
+ `Invalid EG rates for operator ${P}`,
1677
+ `operators[${P}].eg.rates`,
1678
+ i.eg?.rates
1679
+ );
1680
+ if (!i.eg || !Array.isArray(i.eg.levels) || i.eg.levels.length !== 4)
1681
+ throw new o(
1682
+ `Invalid EG levels for operator ${P}`,
1683
+ `operators[${P}].eg.levels`,
1684
+ i.eg?.levels
1685
+ );
1686
+ }
1687
+ if (E.operators.length !== t.NUM_OPERATORS)
1688
+ throw new o(
1689
+ `Invalid operators array: expected ${t.NUM_OPERATORS} operators`,
1690
+ "operators",
1691
+ E.operators
1692
+ );
1693
+ for (let P = 0; P < t.NUM_OPERATORS; P++) {
1694
+ const i = E.operators[P], l = P * t.UNPACKED_OP_SIZE;
1695
+ if (!i.eg || !Array.isArray(i.eg.rates) || i.eg.rates.length !== 4)
1696
+ throw new o(
1697
+ `Invalid EG rates for operator ${P}`,
1698
+ `operators[${P}].eg.rates`,
1699
+ i.eg?.rates
1700
+ );
1701
+ if (_(l + t.UNPACKED_OP_EG_RATE_1, i.eg.rates[0], `operators[${P}].eg.rates[0]`, 0, 99), _(l + t.UNPACKED_OP_EG_RATE_2, i.eg.rates[1], `operators[${P}].eg.rates[1]`, 0, 99), _(l + t.UNPACKED_OP_EG_RATE_3, i.eg.rates[2], `operators[${P}].eg.rates[2]`, 0, 99), _(l + t.UNPACKED_OP_EG_RATE_4, i.eg.rates[3], `operators[${P}].eg.rates[3]`, 0, 99), !i.eg || !Array.isArray(i.eg.levels) || i.eg.levels.length !== 4)
1702
+ throw new o(
1703
+ `Invalid EG levels for operator ${P}`,
1704
+ `operators[${P}].eg.levels`,
1705
+ i.eg?.levels
1706
+ );
1707
+ _(l + t.UNPACKED_OP_EG_LEVEL_1, i.eg.levels[0], `operators[${P}].eg.levels[0]`, 0, 99), _(l + t.UNPACKED_OP_EG_LEVEL_2, i.eg.levels[1], `operators[${P}].eg.levels[1]`, 0, 99), _(l + t.UNPACKED_OP_EG_LEVEL_3, i.eg.levels[2], `operators[${P}].eg.levels[2]`, 0, 99), _(l + t.UNPACKED_OP_EG_LEVEL_4, i.eg.levels[3], `operators[${P}].eg.levels[3]`, 0, 99);
1708
+ const O = a(i.key?.breakPoint) - t.MIDI_BREAK_POINT_OFFSET;
1709
+ _(l + t.UNPACKED_OP_BREAK_POINT, O, `operators[${P}].key.breakPoint`, 0, 127), _(
1710
+ l + t.UNPACKED_OP_L_SCALE_DEPTH,
1711
+ i.scale?.left?.depth || 0,
1712
+ `operators[${P}].scale.left.depth`,
1713
+ 0,
1714
+ 99
1715
+ ), _(
1716
+ l + t.UNPACKED_OP_R_SCALE_DEPTH,
1717
+ i.scale?.right?.depth || 0,
1718
+ `operators[${P}].scale.right.depth`,
1719
+ 0,
1720
+ 99
1721
+ ), n[l + t.UNPACKED_OP_L_CURVE] = r(i.scale?.left?.curve || "-LN"), n[l + t.UNPACKED_OP_R_CURVE] = r(i.scale?.right?.curve || "-LN"), _(
1722
+ l + t.UNPACKED_OP_RATE_SCALING,
1723
+ i.key?.scaling || 0,
1724
+ `operators[${P}].key.scaling`,
1725
+ 0,
1726
+ 7
1727
+ );
1728
+ const K = Number(i.osc?.detune) || 0;
1729
+ _(l + t.UNPACKED_OP_DETUNE, K + 7, `operators[${P}].osc.detune`, 0, 14), _(
1730
+ l + t.UNPACKED_OP_AMP_MOD_SENS,
1731
+ i.output?.ampModSens || 0,
1732
+ `operators[${P}].output.ampModSens`,
1733
+ 0,
1734
+ 3
1735
+ ), _(
1736
+ l + t.UNPACKED_OP_OUTPUT_LEVEL,
1737
+ i.output?.level || 0,
1738
+ `operators[${P}].output.level`,
1739
+ 0,
1740
+ 99
1741
+ );
1742
+ const U = i.osc?.freq?.mode?.toUpperCase() === "FIXED" ? 1 : 0, I = Number(i.osc?.freq?.coarse) || 0, L = Number(i.osc?.freq?.fine) || 0;
1743
+ n[l + t.UNPACKED_OP_MODE] = U, _(l + t.UNPACKED_OP_FREQ_COARSE, I, `operators[${P}].osc.freq.coarse`, 0, 31), _(l + t.UNPACKED_OP_FREQ_FINE, L, `operators[${P}].osc.freq.fine`, 0, 15), _(
1744
+ l + t.UNPACKED_OP_KEY_VEL_SENS,
1745
+ i.key?.velocity || 0,
1746
+ `operators[${P}].key.velocity`,
1747
+ 0,
1748
+ 7
1749
+ );
1750
+ }
1751
+ if (!E.pitchEG || !Array.isArray(E.pitchEG.rates) || E.pitchEG.rates.length !== 4)
1752
+ throw new o("Invalid pitch EG rates", "pitchEG.rates", E.pitchEG?.rates);
1753
+ if (!E.pitchEG || !Array.isArray(E.pitchEG.levels) || E.pitchEG.levels.length !== 4)
1754
+ throw new o("Invalid pitch EG levels", "pitchEG.levels", E.pitchEG?.levels);
1755
+ if (_(t.UNPACKED_PITCH_EG_RATE_1, E.pitchEG.rates[0], "pitchEG.rates[0]", 0, 99), _(t.UNPACKED_PITCH_EG_RATE_2, E.pitchEG.rates[1], "pitchEG.rates[1]", 0, 99), _(t.UNPACKED_PITCH_EG_RATE_3, E.pitchEG.rates[2], "pitchEG.rates[2]", 0, 99), _(t.UNPACKED_PITCH_EG_RATE_4, E.pitchEG.rates[3], "pitchEG.rates[3]", 0, 99), _(t.UNPACKED_PITCH_EG_LEVEL_1, E.pitchEG.levels[0], "pitchEG.levels[0]", 0, 99), _(t.UNPACKED_PITCH_EG_LEVEL_2, E.pitchEG.levels[1], "pitchEG.levels[1]", 0, 99), _(t.UNPACKED_PITCH_EG_LEVEL_3, E.pitchEG.levels[2], "pitchEG.levels[2]", 0, 99), _(t.UNPACKED_PITCH_EG_LEVEL_4, E.pitchEG.levels[3], "pitchEG.levels[3]", 0, 99), !E.lfo || typeof E.lfo != "object")
1756
+ throw new o("Invalid LFO data", "lfo", E.lfo);
1757
+ if (_(t.UNPACKED_LFO_SPEED, E.lfo.speed, "lfo.speed", 0, 99), _(t.UNPACKED_LFO_DELAY, E.lfo.delay, "lfo.delay", 0, 99), _(t.UNPACKED_LFO_PM_DEPTH, E.lfo.pmDepth, "lfo.pmDepth", 0, 99), _(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")
1758
+ throw new o("Invalid global data", "global", E.global);
1759
+ const T = Number(E.global.algorithm) || 1;
1760
+ _(t.UNPACKED_ALGORITHM, T - 1, "global.algorithm", 0, 31), _(t.UNPACKED_FEEDBACK, E.global.feedback, "global.feedback", 0, 7), n[t.UNPACKED_OSC_SYNC] = E.global.oscKeySync ? 1 : 0, _(t.UNPACKED_LFO_PM_SENS, E.global.pitchModSens, "global.pitchModSens", 0, 7);
1761
+ const S = Number(E.global.transpose) || 0;
1762
+ _(t.UNPACKED_TRANSPOSE, S + t.TRANSPOSE_CENTER, "global.transpose", 0, 127), _(t.UNPACKED_AMP_MOD_SENS, E.global.ampModSens || 0, "global.ampModSens", 0, 3), _(t.UNPACKED_EG_BIAS_SENS, E.global.egBiasSens || 0, "global.egBiasSens", 0, 7);
1763
+ const C = E.name || "";
1764
+ for (let P = 0; P < t.NAME_LENGTH; P++)
1765
+ n[t.UNPACKED_NAME_START + P] = P < C.length ? C.charCodeAt(P) : t.CHAR_SPACE;
1766
+ return t.fromUnpacked(n, s);
1767
+ }
1579
1768
  /**
1580
1769
  * Export voice to DX7 single voice SysEx format (VCED format)
1581
1770
  * This is useful for synths that only support single voice dumps (e.g., KORG Volca FM)
@@ -1583,118 +1772,118 @@ class E {
1583
1772
  * @returns {Uint8Array} Single voice SysEx data (163 bytes)
1584
1773
  */
1585
1774
  toSysEx() {
1586
- const t = this.unpack(), n = new Uint8Array(E.VCED_SIZE);
1587
- let s = 0;
1588
- n[s++] = E.VCED_SYSEX_START, n[s++] = E.VCED_YAMAHA_ID, n[s++] = E.VCED_SUB_STATUS, n[s++] = E.VCED_FORMAT_SINGLE, n[s++] = E.VCED_BYTE_COUNT_MSB, n[s++] = E.VCED_BYTE_COUNT_LSB;
1589
- for (let e = E.NUM_OPERATORS - 1; e >= 0; e--) {
1590
- const r = e * E.UNPACKED_OP_SIZE;
1591
- n[s++] = t[r + E.UNPACKED_OP_EG_RATE_1], n[s++] = t[r + E.UNPACKED_OP_EG_RATE_2], n[s++] = t[r + E.UNPACKED_OP_EG_RATE_3], n[s++] = t[r + E.UNPACKED_OP_EG_RATE_4], n[s++] = t[r + E.UNPACKED_OP_EG_LEVEL_1], n[s++] = t[r + E.UNPACKED_OP_EG_LEVEL_2], n[s++] = t[r + E.UNPACKED_OP_EG_LEVEL_3], n[s++] = t[r + E.UNPACKED_OP_EG_LEVEL_4], n[s++] = t[r + E.UNPACKED_OP_BREAK_POINT], n[s++] = t[r + E.UNPACKED_OP_L_SCALE_DEPTH], n[s++] = t[r + E.UNPACKED_OP_R_SCALE_DEPTH], n[s++] = t[r + E.UNPACKED_OP_L_CURVE], n[s++] = t[r + E.UNPACKED_OP_R_CURVE], n[s++] = t[r + E.UNPACKED_OP_RATE_SCALING], n[s++] = t[r + E.UNPACKED_OP_DETUNE];
1592
- const A = t[r + E.UNPACKED_OP_AMP_MOD_SENS] & E.MASK_2BIT, T = t[r + E.UNPACKED_OP_KEY_VEL_SENS] & E.MASK_3BIT;
1593
- n[s++] = A | T << 2, n[s++] = t[r + E.UNPACKED_OP_OUTPUT_LEVEL], n[s++] = t[r + E.UNPACKED_OP_MODE], n[s++] = t[r + E.UNPACKED_OP_FREQ_COARSE], n[s++] = t[r + E.UNPACKED_OP_OSC_DETUNE], n[s++] = t[r + E.UNPACKED_OP_FREQ_FINE];
1775
+ const E = this.unpack(), s = new Uint8Array(t.VCED_SIZE);
1776
+ let n = 0;
1777
+ s[n++] = t.VCED_SYSEX_START, s[n++] = t.VCED_YAMAHA_ID, s[n++] = t.VCED_SUB_STATUS, s[n++] = t.VCED_FORMAT_SINGLE, s[n++] = t.VCED_BYTE_COUNT_MSB, s[n++] = t.VCED_BYTE_COUNT_LSB;
1778
+ for (let r = t.NUM_OPERATORS - 1; r >= 0; r--) {
1779
+ const e = r * t.UNPACKED_OP_SIZE;
1780
+ s[n++] = E[e + t.UNPACKED_OP_EG_RATE_1], s[n++] = E[e + t.UNPACKED_OP_EG_RATE_2], s[n++] = E[e + t.UNPACKED_OP_EG_RATE_3], s[n++] = E[e + t.UNPACKED_OP_EG_RATE_4], s[n++] = E[e + t.UNPACKED_OP_EG_LEVEL_1], s[n++] = E[e + t.UNPACKED_OP_EG_LEVEL_2], s[n++] = E[e + t.UNPACKED_OP_EG_LEVEL_3], s[n++] = E[e + t.UNPACKED_OP_EG_LEVEL_4], s[n++] = E[e + t.UNPACKED_OP_BREAK_POINT], s[n++] = E[e + t.UNPACKED_OP_L_SCALE_DEPTH], s[n++] = E[e + t.UNPACKED_OP_R_SCALE_DEPTH], s[n++] = E[e + t.UNPACKED_OP_L_CURVE], s[n++] = E[e + t.UNPACKED_OP_R_CURVE], s[n++] = E[e + t.UNPACKED_OP_RATE_SCALING], s[n++] = E[e + t.UNPACKED_OP_DETUNE];
1781
+ const a = E[e + t.UNPACKED_OP_AMP_MOD_SENS] & t.MASK_2BIT, T = E[e + t.UNPACKED_OP_KEY_VEL_SENS] & t.MASK_3BIT;
1782
+ s[n++] = a | T << 2, s[n++] = E[e + t.UNPACKED_OP_OUTPUT_LEVEL], s[n++] = E[e + t.UNPACKED_OP_MODE], s[n++] = E[e + t.UNPACKED_OP_FREQ_COARSE], s[n++] = E[e + t.UNPACKED_OP_OSC_DETUNE], s[n++] = E[e + t.UNPACKED_OP_FREQ_FINE];
1594
1783
  }
1595
- n[s++] = t[E.UNPACKED_PITCH_EG_RATE_1], n[s++] = t[E.UNPACKED_PITCH_EG_RATE_2], n[s++] = t[E.UNPACKED_PITCH_EG_RATE_3], n[s++] = t[E.UNPACKED_PITCH_EG_RATE_4], n[s++] = t[E.UNPACKED_PITCH_EG_LEVEL_1], n[s++] = t[E.UNPACKED_PITCH_EG_LEVEL_2], n[s++] = t[E.UNPACKED_PITCH_EG_LEVEL_3], n[s++] = t[E.UNPACKED_PITCH_EG_LEVEL_4], n[s++] = t[E.UNPACKED_ALGORITHM], n[s++] = t[E.UNPACKED_FEEDBACK], n[s++] = t[E.UNPACKED_OSC_SYNC], n[s++] = t[E.UNPACKED_LFO_SPEED], n[s++] = t[E.UNPACKED_LFO_DELAY], n[s++] = t[E.UNPACKED_LFO_PM_DEPTH], n[s++] = t[E.UNPACKED_LFO_AM_DEPTH], n[s++] = t[E.UNPACKED_LFO_KEY_SYNC], n[s++] = t[E.UNPACKED_LFO_WAVE], n[s++] = t[E.UNPACKED_LFO_PM_SENS], n[s++] = t[E.UNPACKED_TRANSPOSE];
1596
- for (let e = 0; e < E.NAME_LENGTH; e++)
1597
- n[s++] = t[E.UNPACKED_NAME_START + e];
1598
- const _ = n.subarray(
1599
- E.VCED_HEADER_SIZE,
1600
- E.VCED_HEADER_SIZE + E.VCED_DATA_SIZE
1784
+ s[n++] = E[t.UNPACKED_PITCH_EG_RATE_1], s[n++] = E[t.UNPACKED_PITCH_EG_RATE_2], s[n++] = E[t.UNPACKED_PITCH_EG_RATE_3], s[n++] = E[t.UNPACKED_PITCH_EG_RATE_4], s[n++] = E[t.UNPACKED_PITCH_EG_LEVEL_1], s[n++] = E[t.UNPACKED_PITCH_EG_LEVEL_2], s[n++] = E[t.UNPACKED_PITCH_EG_LEVEL_3], s[n++] = E[t.UNPACKED_PITCH_EG_LEVEL_4], s[n++] = E[t.UNPACKED_ALGORITHM], s[n++] = E[t.UNPACKED_FEEDBACK], s[n++] = E[t.UNPACKED_OSC_SYNC], s[n++] = E[t.UNPACKED_LFO_SPEED], s[n++] = E[t.UNPACKED_LFO_DELAY], s[n++] = E[t.UNPACKED_LFO_PM_DEPTH], s[n++] = E[t.UNPACKED_LFO_AM_DEPTH], s[n++] = E[t.UNPACKED_LFO_KEY_SYNC], s[n++] = E[t.UNPACKED_LFO_WAVE], s[n++] = E[t.UNPACKED_LFO_PM_SENS], s[n++] = E[t.UNPACKED_TRANSPOSE];
1785
+ for (let r = 0; r < t.NAME_LENGTH; r++)
1786
+ s[n++] = E[t.UNPACKED_NAME_START + r];
1787
+ const _ = s.subarray(
1788
+ t.VCED_HEADER_SIZE,
1789
+ t.VCED_HEADER_SIZE + t.VCED_DATA_SIZE
1601
1790
  );
1602
- return n[s++] = C._calculateChecksum(_, E.VCED_DATA_SIZE), n[s++] = E.VCED_SYSEX_END, n;
1791
+ return s[n++] = N._calculateChecksum(_, t.VCED_DATA_SIZE), s[n++] = t.VCED_SYSEX_END, s;
1603
1792
  }
1604
1793
  /**
1605
1794
  * Convert voice to JSON format
1606
1795
  * @returns {object} Voice data in JSON format
1607
1796
  */
1608
1797
  toJSON() {
1609
- const t = this.unpack(), n = [], s = (r) => ["-LN", "-EX", "+EX", "+LN"][r] || "UNKNOWN", _ = (r) => ["TRIANGLE", "SAW DOWN", "SAW UP", "SQUARE", "SINE", "SAMPLE & HOLD"][r] || "UNKNOWN", e = (r) => {
1610
- const A = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"], T = Math.floor(r / 12) + E.MIDI_OCTAVE_OFFSET;
1611
- return `${A[r % 12]}${T}`;
1798
+ const E = this.unpack(), s = [], n = (e) => ["-LN", "-EX", "+EX", "+LN"][e] || "UNKNOWN", _ = (e) => ["TRIANGLE", "SAW DOWN", "SAW UP", "SQUARE", "SINE", "SAMPLE & HOLD"][e] || "UNKNOWN", r = (e) => {
1799
+ const a = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"], T = Math.floor(e / 12) + t.MIDI_OCTAVE_OFFSET;
1800
+ return `${a[e % 12]}${T}`;
1612
1801
  };
1613
- for (let r = 0; r < E.NUM_OPERATORS; r++) {
1614
- const A = r * E.UNPACKED_OP_SIZE, T = t[A + E.UNPACKED_OP_MODE] === 0 ? "RATIO" : "FIXED";
1615
- n.push({
1616
- id: r + 1,
1802
+ for (let e = 0; e < t.NUM_OPERATORS; e++) {
1803
+ const a = e * t.UNPACKED_OP_SIZE, T = E[a + t.UNPACKED_OP_MODE] === 0 ? "RATIO" : "FIXED";
1804
+ s.push({
1805
+ id: e + 1,
1617
1806
  osc: {
1618
- detune: t[A + E.UNPACKED_OP_OSC_DETUNE],
1807
+ detune: E[a + t.UNPACKED_OP_OSC_DETUNE],
1619
1808
  freq: {
1620
- coarse: t[A + E.UNPACKED_OP_FREQ_COARSE],
1621
- fine: t[A + E.UNPACKED_OP_FREQ_FINE],
1809
+ coarse: E[a + t.UNPACKED_OP_FREQ_COARSE],
1810
+ fine: E[a + t.UNPACKED_OP_FREQ_FINE],
1622
1811
  mode: T
1623
1812
  }
1624
1813
  },
1625
1814
  eg: {
1626
1815
  rates: [
1627
- t[A + E.UNPACKED_OP_EG_RATE_1],
1628
- t[A + E.UNPACKED_OP_EG_RATE_2],
1629
- t[A + E.UNPACKED_OP_EG_RATE_3],
1630
- t[A + E.UNPACKED_OP_EG_RATE_4]
1816
+ E[a + t.UNPACKED_OP_EG_RATE_1],
1817
+ E[a + t.UNPACKED_OP_EG_RATE_2],
1818
+ E[a + t.UNPACKED_OP_EG_RATE_3],
1819
+ E[a + t.UNPACKED_OP_EG_RATE_4]
1631
1820
  ],
1632
1821
  levels: [
1633
- t[A + E.UNPACKED_OP_EG_LEVEL_1],
1634
- t[A + E.UNPACKED_OP_EG_LEVEL_2],
1635
- t[A + E.UNPACKED_OP_EG_LEVEL_3],
1636
- t[A + E.UNPACKED_OP_EG_LEVEL_4]
1822
+ E[a + t.UNPACKED_OP_EG_LEVEL_1],
1823
+ E[a + t.UNPACKED_OP_EG_LEVEL_2],
1824
+ E[a + t.UNPACKED_OP_EG_LEVEL_3],
1825
+ E[a + t.UNPACKED_OP_EG_LEVEL_4]
1637
1826
  ]
1638
1827
  },
1639
1828
  key: {
1640
- velocity: t[A + E.UNPACKED_OP_KEY_VEL_SENS],
1641
- scaling: t[A + E.UNPACKED_OP_RATE_SCALING],
1642
- breakPoint: e(
1643
- t[A + E.UNPACKED_OP_BREAK_POINT] + E.MIDI_BREAK_POINT_OFFSET
1829
+ velocity: E[a + t.UNPACKED_OP_KEY_VEL_SENS],
1830
+ scaling: E[a + t.UNPACKED_OP_RATE_SCALING],
1831
+ breakPoint: r(
1832
+ E[a + t.UNPACKED_OP_BREAK_POINT] + t.MIDI_BREAK_POINT_OFFSET
1644
1833
  )
1645
1834
  },
1646
1835
  output: {
1647
- level: t[A + E.UNPACKED_OP_OUTPUT_LEVEL],
1648
- ampModSens: t[A + E.UNPACKED_OP_AMP_MOD_SENS]
1836
+ level: E[a + t.UNPACKED_OP_OUTPUT_LEVEL],
1837
+ ampModSens: E[a + t.UNPACKED_OP_AMP_MOD_SENS]
1649
1838
  },
1650
1839
  scale: {
1651
1840
  left: {
1652
- depth: t[A + E.UNPACKED_OP_L_SCALE_DEPTH],
1653
- curve: s(t[A + E.UNPACKED_OP_L_CURVE])
1841
+ depth: E[a + t.UNPACKED_OP_L_SCALE_DEPTH],
1842
+ curve: n(E[a + t.UNPACKED_OP_L_CURVE])
1654
1843
  },
1655
1844
  right: {
1656
- depth: t[A + E.UNPACKED_OP_R_SCALE_DEPTH],
1657
- curve: s(t[A + E.UNPACKED_OP_R_CURVE])
1845
+ depth: E[a + t.UNPACKED_OP_R_SCALE_DEPTH],
1846
+ curve: n(E[a + t.UNPACKED_OP_R_CURVE])
1658
1847
  }
1659
1848
  }
1660
1849
  });
1661
1850
  }
1662
1851
  return {
1663
1852
  name: this.name || "(Empty)",
1664
- operators: n,
1853
+ operators: s,
1665
1854
  pitchEG: {
1666
1855
  rates: [
1667
- t[E.UNPACKED_PITCH_EG_RATE_1],
1668
- t[E.UNPACKED_PITCH_EG_RATE_2],
1669
- t[E.UNPACKED_PITCH_EG_RATE_3],
1670
- t[E.UNPACKED_PITCH_EG_RATE_4]
1856
+ E[t.UNPACKED_PITCH_EG_RATE_1],
1857
+ E[t.UNPACKED_PITCH_EG_RATE_2],
1858
+ E[t.UNPACKED_PITCH_EG_RATE_3],
1859
+ E[t.UNPACKED_PITCH_EG_RATE_4]
1671
1860
  ],
1672
1861
  levels: [
1673
- t[E.UNPACKED_PITCH_EG_LEVEL_1],
1674
- t[E.UNPACKED_PITCH_EG_LEVEL_2],
1675
- t[E.UNPACKED_PITCH_EG_LEVEL_3],
1676
- t[E.UNPACKED_PITCH_EG_LEVEL_4]
1862
+ E[t.UNPACKED_PITCH_EG_LEVEL_1],
1863
+ E[t.UNPACKED_PITCH_EG_LEVEL_2],
1864
+ E[t.UNPACKED_PITCH_EG_LEVEL_3],
1865
+ E[t.UNPACKED_PITCH_EG_LEVEL_4]
1677
1866
  ]
1678
1867
  },
1679
1868
  lfo: {
1680
- speed: t[E.UNPACKED_LFO_SPEED],
1681
- delay: t[E.UNPACKED_LFO_DELAY],
1682
- pmDepth: t[E.UNPACKED_LFO_PM_DEPTH],
1683
- amDepth: t[E.UNPACKED_LFO_AM_DEPTH],
1684
- keySync: t[E.UNPACKED_LFO_KEY_SYNC] === 1,
1685
- wave: _(t[E.UNPACKED_LFO_WAVE])
1869
+ speed: E[t.UNPACKED_LFO_SPEED],
1870
+ delay: E[t.UNPACKED_LFO_DELAY],
1871
+ pmDepth: E[t.UNPACKED_LFO_PM_DEPTH],
1872
+ amDepth: E[t.UNPACKED_LFO_AM_DEPTH],
1873
+ keySync: E[t.UNPACKED_LFO_KEY_SYNC] === 1,
1874
+ wave: _(E[t.UNPACKED_LFO_WAVE])
1686
1875
  },
1687
1876
  global: {
1688
- algorithm: t[E.UNPACKED_ALGORITHM] + 1,
1689
- feedback: t[E.UNPACKED_FEEDBACK],
1690
- oscKeySync: t[E.UNPACKED_OSC_SYNC] === 1,
1691
- pitchModSens: t[E.UNPACKED_LFO_PM_SENS],
1692
- transpose: t[E.UNPACKED_TRANSPOSE] - E.TRANSPOSE_CENTER
1877
+ algorithm: E[t.UNPACKED_ALGORITHM] + 1,
1878
+ feedback: E[t.UNPACKED_FEEDBACK],
1879
+ oscKeySync: E[t.UNPACKED_OSC_SYNC] === 1,
1880
+ pitchModSens: E[t.UNPACKED_LFO_PM_SENS],
1881
+ transpose: E[t.UNPACKED_TRANSPOSE] - t.TRANSPOSE_CENTER
1693
1882
  }
1694
1883
  };
1695
1884
  }
1696
1885
  }
1697
- class C {
1886
+ class N {
1698
1887
  // SysEx header
1699
1888
  static SYSEX_START = 240;
1700
1889
  static SYSEX_END = 247;
@@ -1704,12 +1893,12 @@ class C {
1704
1893
  static SYSEX_BYTE_COUNT_MSB = 32;
1705
1894
  static SYSEX_BYTE_COUNT_LSB = 0;
1706
1895
  static SYSEX_HEADER = [
1707
- C.SYSEX_START,
1708
- C.SYSEX_YAMAHA_ID,
1709
- C.SYSEX_SUB_STATUS,
1710
- C.SYSEX_FORMAT_32_VOICES,
1711
- C.SYSEX_BYTE_COUNT_MSB,
1712
- C.SYSEX_BYTE_COUNT_LSB
1896
+ N.SYSEX_START,
1897
+ N.SYSEX_YAMAHA_ID,
1898
+ N.SYSEX_SUB_STATUS,
1899
+ N.SYSEX_FORMAT_32_VOICES,
1900
+ N.SYSEX_BYTE_COUNT_MSB,
1901
+ N.SYSEX_BYTE_COUNT_LSB
1713
1902
  ];
1714
1903
  static SYSEX_HEADER_SIZE = 6;
1715
1904
  // Bank structure
@@ -1728,12 +1917,12 @@ class C {
1728
1917
  * @param {Array<number>|ArrayBuffer|Uint8Array} data - Bank SYX data (optional)
1729
1918
  * @param {string} name - Optional bank name (e.g., filename)
1730
1919
  */
1731
- constructor(t, n = "") {
1732
- if (this.voices = new Array(C.NUM_VOICES), this.name = n, t)
1733
- this._load(t);
1920
+ constructor(E, s = "") {
1921
+ if (this.voices = new Array(N.NUM_VOICES), this.name = s, E)
1922
+ this._load(E);
1734
1923
  else
1735
- for (let s = 0; s < C.NUM_VOICES; s++)
1736
- this.voices[s] = E.createDefault(s);
1924
+ for (let n = 0; n < N.NUM_VOICES; n++)
1925
+ this.voices[n] = t.createDefault(n);
1737
1926
  }
1738
1927
  /**
1739
1928
  * Calculate DX7 SysEx checksum
@@ -1742,55 +1931,55 @@ class C {
1742
1931
  * @param {number} size - Number of bytes
1743
1932
  * @returns {number} Checksum byte
1744
1933
  */
1745
- static _calculateChecksum(t, n) {
1746
- let s = 0;
1747
- for (let _ = 0; _ < n; _++)
1748
- s += t[_];
1749
- return C.CHECKSUM_MODULO - s % C.CHECKSUM_MODULO & C.MASK_7BIT;
1934
+ static _calculateChecksum(E, s) {
1935
+ let n = 0;
1936
+ for (let _ = 0; _ < s; _++)
1937
+ n += E[_];
1938
+ return N.CHECKSUM_MODULO - n % N.CHECKSUM_MODULO & N.MASK_7BIT;
1750
1939
  }
1751
1940
  /**
1752
1941
  * Load and validate bank data
1753
1942
  * @private
1754
1943
  * @param {Array<number>|ArrayBuffer|Uint8Array} data
1755
1944
  */
1756
- _load(t) {
1757
- const n = t instanceof Uint8Array ? t : new Uint8Array(t);
1758
- let s, _ = 0;
1759
- if (n[0] === C.SYSEX_START) {
1760
- const r = n.subarray(0, C.SYSEX_HEADER_SIZE), A = C.SYSEX_HEADER;
1761
- for (let T = 0; T < C.SYSEX_HEADER_SIZE; T++)
1762
- if (r[T] !== A[T])
1763
- throw new D(
1764
- `Invalid SysEx header at position ${T}: expected ${A[T].toString(16)}, got ${r[T].toString(16)}`,
1945
+ _load(E) {
1946
+ const s = E instanceof Uint8Array ? E : new Uint8Array(E);
1947
+ let n, _ = 0;
1948
+ if (s[0] === N.SYSEX_START) {
1949
+ const e = s.subarray(0, N.SYSEX_HEADER_SIZE), a = N.SYSEX_HEADER;
1950
+ for (let T = 0; T < N.SYSEX_HEADER_SIZE; T++)
1951
+ if (e[T] !== a[T])
1952
+ throw new m(
1953
+ `Invalid SysEx header at position ${T}: expected ${a[T].toString(16)}, got ${e[T].toString(16)}`,
1765
1954
  "header",
1766
1955
  T
1767
1956
  );
1768
- s = n.subarray(C.SYSEX_HEADER_SIZE, C.SYSEX_HEADER_SIZE + C.VOICE_DATA_SIZE), _ = C.SYSEX_HEADER_SIZE;
1769
- } else if (n.length === C.VOICE_DATA_SIZE)
1770
- s = n;
1957
+ n = s.subarray(N.SYSEX_HEADER_SIZE, N.SYSEX_HEADER_SIZE + N.VOICE_DATA_SIZE), _ = N.SYSEX_HEADER_SIZE;
1958
+ } else if (s.length === N.VOICE_DATA_SIZE)
1959
+ n = s;
1771
1960
  else
1772
- throw new I(
1773
- `Invalid data length: expected ${C.VOICE_DATA_SIZE} or ${C.SYSEX_SIZE} bytes, got ${n.length}`,
1961
+ throw new o(
1962
+ `Invalid data length: expected ${N.VOICE_DATA_SIZE} or ${N.SYSEX_SIZE} bytes, got ${s.length}`,
1774
1963
  "length",
1775
- n.length
1964
+ s.length
1776
1965
  );
1777
- if (s.length !== C.VOICE_DATA_SIZE)
1778
- throw new I(
1779
- `Invalid voice data length: expected ${C.VOICE_DATA_SIZE} bytes, got ${s.length}`,
1966
+ if (n.length !== N.VOICE_DATA_SIZE)
1967
+ throw new o(
1968
+ `Invalid voice data length: expected ${N.VOICE_DATA_SIZE} bytes, got ${n.length}`,
1780
1969
  "length",
1781
- s.length
1970
+ n.length
1782
1971
  );
1783
- const e = C.SYSEX_HEADER_SIZE + C.VOICE_DATA_SIZE;
1784
- if (_ > 0 && n.length >= e + 1) {
1785
- const r = n[e], A = C._calculateChecksum(s, C.VOICE_DATA_SIZE);
1786
- r !== A && console.warn(
1787
- `DX7 checksum mismatch (expected ${A.toString(16)}, got ${r.toString(16)}). This is common with vintage SysEx files and the data is likely still valid.`
1972
+ const r = N.SYSEX_HEADER_SIZE + N.VOICE_DATA_SIZE;
1973
+ if (_ > 0 && s.length >= r + 1) {
1974
+ const e = s[r], a = N._calculateChecksum(n, N.VOICE_DATA_SIZE);
1975
+ e !== a && console.warn(
1976
+ `DX7 checksum mismatch (expected ${a.toString(16)}, got ${e.toString(16)}). This is common with vintage SysEx files and the data is likely still valid.`
1788
1977
  );
1789
1978
  }
1790
- this.voices = new Array(C.NUM_VOICES);
1791
- for (let r = 0; r < C.NUM_VOICES; r++) {
1792
- const A = r * C.VOICE_SIZE, T = s.subarray(A, A + C.VOICE_SIZE);
1793
- this.voices[r] = new E(T, r);
1979
+ this.voices = new Array(N.NUM_VOICES);
1980
+ for (let e = 0; e < N.NUM_VOICES; e++) {
1981
+ const a = e * N.VOICE_SIZE, T = n.subarray(a, a + N.VOICE_SIZE);
1982
+ this.voices[e] = new t(T, e);
1794
1983
  }
1795
1984
  }
1796
1985
  /**
@@ -1799,22 +1988,22 @@ class C {
1799
1988
  * @param {DX7Voice} voice - Voice to insert
1800
1989
  * @throws {DX7ValidationError} If index is out of range
1801
1990
  */
1802
- replaceVoice(t, n) {
1803
- if (t < 0 || t >= C.NUM_VOICES)
1804
- throw new I(`Invalid voice index: ${t}`, "index", t);
1805
- const s = new Uint8Array(n.data);
1806
- this.voices[t] = new E(s, t);
1991
+ replaceVoice(E, s) {
1992
+ if (E < 0 || E >= N.NUM_VOICES)
1993
+ throw new o(`Invalid voice index: ${E}`, "index", E);
1994
+ const n = new Uint8Array(s.data);
1995
+ this.voices[E] = new t(n, E);
1807
1996
  }
1808
1997
  /**
1809
1998
  * Add a voice to the first empty slot
1810
1999
  * @param {DX7Voice} voice - Voice to add
1811
2000
  * @returns {number} Index where voice was added, or -1 if bank is full
1812
2001
  */
1813
- addVoice(t) {
1814
- for (let n = 0; n < this.voices.length; n++) {
1815
- const s = this.voices[n];
1816
- if (s.name === "" || s.name === "Init Voice")
1817
- return this.replaceVoice(n, t), n;
2002
+ addVoice(E) {
2003
+ for (let s = 0; s < this.voices.length; s++) {
2004
+ const n = this.voices[s];
2005
+ if (n.name === "" || n.name === "Init Voice")
2006
+ return this.replaceVoice(s, E), s;
1818
2007
  }
1819
2008
  return -1;
1820
2009
  }
@@ -1830,24 +2019,24 @@ class C {
1830
2019
  * @param {number} index - Voice index (0-31)
1831
2020
  * @returns {DX7Voice|null}
1832
2021
  */
1833
- getVoice(t) {
1834
- return t < 0 || t >= this.voices.length ? null : this.voices[t];
2022
+ getVoice(E) {
2023
+ return E < 0 || E >= this.voices.length ? null : this.voices[E];
1835
2024
  }
1836
2025
  /**
1837
2026
  * Get all voice names
1838
2027
  * @returns {string[]}
1839
2028
  */
1840
2029
  getVoiceNames() {
1841
- return this.voices.map((t) => t.name);
2030
+ return this.voices.map((E) => E.name);
1842
2031
  }
1843
2032
  /**
1844
2033
  * Find a voice by name (case-insensitive, partial match)
1845
2034
  * @param {string} name - Voice name to search for
1846
2035
  * @returns {DX7Voice|null}
1847
2036
  */
1848
- findVoiceByName(t) {
1849
- const n = t.toLowerCase();
1850
- return this.voices.find((s) => s.name.toLowerCase().includes(n)) || null;
2037
+ findVoiceByName(E) {
2038
+ const s = E.toLowerCase();
2039
+ return this.voices.find((n) => n.name.toLowerCase().includes(s)) || null;
1851
2040
  }
1852
2041
  /**
1853
2042
  * Load a DX7 bank from a file
@@ -1857,216 +2046,258 @@ class C {
1857
2046
  * @throws {DX7ValidationError} If data is not valid DX7 SYX format
1858
2047
  * @throws {Error} If file cannot be read (FileReader error)
1859
2048
  */
1860
- static async fromFile(t) {
1861
- return new Promise((n, s) => {
2049
+ static async fromFile(E) {
2050
+ return new Promise((s, n) => {
1862
2051
  const _ = new FileReader();
1863
- _.onload = async (e) => {
2052
+ _.onload = async (r) => {
1864
2053
  try {
1865
- const r = t.name || "", A = new Uint8Array(e.target.result);
1866
- if (A[0] === C.SYSEX_START && A[3] === E.VCED_FORMAT_SINGLE)
1867
- s(new D("This is a single voice file. Use DX7Voice.fromFile() instead.", "format", 3));
2054
+ const e = E.name || "", a = new Uint8Array(r.target.result);
2055
+ if (a[0] === N.SYSEX_START && a[3] === t.VCED_FORMAT_SINGLE)
2056
+ n(new m("This is a single voice file. Use DX7Voice.fromFile() instead.", "format", 3));
1868
2057
  else {
1869
- const T = r.replace(/\.[^/.]+$/, ""), S = new C(e.target.result, T);
1870
- n(S);
2058
+ const T = e.replace(/\.[^/.]+$/, ""), S = new N(r.target.result, T);
2059
+ s(S);
1871
2060
  }
1872
- } catch (r) {
1873
- s(r);
2061
+ } catch (e) {
2062
+ n(e);
1874
2063
  }
1875
- }, _.onerror = () => s(new Error("Failed to read file")), _.readAsArrayBuffer(t);
2064
+ }, _.onerror = () => n(new Error("Failed to read file")), _.readAsArrayBuffer(E);
1876
2065
  });
1877
2066
  }
2067
+ /**
2068
+ * Create a DX7Bank from SysEx data
2069
+ * @param {Array<number>|ArrayBuffer|Uint8Array} data - SysEx data (4104 bytes with header/footer) or raw voice data (4096 bytes)
2070
+ * @param {string} name - Optional bank name
2071
+ * @returns {DX7Bank}
2072
+ * @throws {DX7ParseError} If SysEx header is invalid
2073
+ * @throws {DX7ValidationError} If data length is invalid
2074
+ */
2075
+ static fromSysEx(E, s = "") {
2076
+ return new N(E, s);
2077
+ }
2078
+ /**
2079
+ * Create a DX7Bank from a JSON object
2080
+ * @param {DX7BankJSON} json - JSON representation of a DX7 bank
2081
+ * @returns {DX7Bank}
2082
+ * @throws {DX7ValidationError} If JSON structure is invalid
2083
+ */
2084
+ static fromJSON(E) {
2085
+ if (!E || typeof E != "object")
2086
+ throw new o("Invalid JSON: expected object", "json", E);
2087
+ const s = new N();
2088
+ if (s.name = E.name || "", !Array.isArray(E.voices))
2089
+ throw new o("Invalid voices array", "voices", E.voices);
2090
+ E.voices.length !== N.NUM_VOICES && console.warn(
2091
+ `Bank JSON has ${E.voices.length} voices, expected ${N.NUM_VOICES}. Missing voices will be filled with defaults.`
2092
+ );
2093
+ const n = Math.min(E.voices.length, N.NUM_VOICES);
2094
+ for (let _ = 0; _ < n; _++) {
2095
+ const r = E.voices[_];
2096
+ if (!r || typeof r != "object") {
2097
+ console.warn(`Invalid voice data at index ${_}, using default voice`);
2098
+ continue;
2099
+ }
2100
+ try {
2101
+ const { index: e, ...a } = r, T = t.fromJSON(a, _);
2102
+ s.replaceVoice(_, T);
2103
+ } catch (e) {
2104
+ console.warn(`Failed to load voice at index ${_}: ${e.message}, using default voice`);
2105
+ }
2106
+ }
2107
+ return s;
2108
+ }
1878
2109
  /**
1879
2110
  * Export bank to SysEx format
1880
2111
  * @returns {Uint8Array} Full SysEx data (4104 bytes)
1881
2112
  */
1882
2113
  toSysEx() {
1883
- const t = new Uint8Array(C.SYSEX_SIZE);
1884
- let n = 0;
1885
- C.SYSEX_HEADER.forEach((_) => {
1886
- t[n++] = _;
2114
+ const E = new Uint8Array(N.SYSEX_SIZE);
2115
+ let s = 0;
2116
+ N.SYSEX_HEADER.forEach((_) => {
2117
+ E[s++] = _;
1887
2118
  });
1888
2119
  for (const _ of this.voices)
1889
- for (let e = 0; e < C.VOICE_SIZE; e++)
1890
- t[n++] = _.data[e];
1891
- const s = t.subarray(C.SYSEX_HEADER_SIZE, C.SYSEX_HEADER_SIZE + C.VOICE_DATA_SIZE);
1892
- return t[n++] = C._calculateChecksum(s, C.VOICE_DATA_SIZE), t[n++] = C.SYSEX_END, t;
2120
+ for (let r = 0; r < N.VOICE_SIZE; r++)
2121
+ E[s++] = _.data[r];
2122
+ const n = E.subarray(N.SYSEX_HEADER_SIZE, N.SYSEX_HEADER_SIZE + N.VOICE_DATA_SIZE);
2123
+ return E[s++] = N._calculateChecksum(n, N.VOICE_DATA_SIZE), E[s++] = N.SYSEX_END, E;
1893
2124
  }
1894
2125
  /**
1895
2126
  * Convert bank to JSON format
1896
2127
  * @returns {object} Bank data in JSON format
1897
2128
  */
1898
2129
  toJSON() {
1899
- const t = this.voices.map((n, s) => {
1900
- const _ = n.toJSON();
2130
+ const E = this.voices.map((s, n) => {
2131
+ const _ = s.toJSON();
1901
2132
  return {
1902
- index: s + 1,
2133
+ index: n + 1,
1903
2134
  ..._
1904
2135
  };
1905
2136
  });
1906
2137
  return {
1907
2138
  version: "1.0",
1908
2139
  name: this.name || "",
1909
- voices: t
2140
+ voices: E
1910
2141
  };
1911
2142
  }
1912
2143
  }
1913
- function Et(i) {
1914
- return i[0] !== 240 || i[i.length - 1] !== 247 ? null : {
1915
- manufacturerId: i[1],
1916
- payload: i.slice(2, -1),
1917
- raw: i
2144
+ function Et(A) {
2145
+ return A[0] !== 240 || A[A.length - 1] !== 247 ? null : {
2146
+ manufacturerId: A[1],
2147
+ payload: A.slice(2, -1),
2148
+ raw: A
1918
2149
  };
1919
2150
  }
1920
- function nt(i, t) {
1921
- return [240, i, ...t, 247];
2151
+ function st(A, E) {
2152
+ return [240, A, ...E, 247];
1922
2153
  }
1923
- function st(i) {
1924
- return i.length >= 2 && i[0] === 240 && i[i.length - 1] === 247;
2154
+ function nt(A) {
2155
+ return A.length >= 2 && A[0] === 240 && A[A.length - 1] === 247;
1925
2156
  }
1926
- function _t(i) {
1927
- const t = [];
1928
- for (let n = 0; n < i.length; n += 7) {
1929
- const s = i.slice(n, n + 7);
2157
+ function _t(A) {
2158
+ const E = [];
2159
+ for (let s = 0; s < A.length; s += 7) {
2160
+ const n = A.slice(s, s + 7);
1930
2161
  let _ = 0;
1931
- const e = [];
1932
- for (let r = 0; r < s.length; r++) {
1933
- const A = s[r];
1934
- A & 128 && (_ |= 1 << r), e.push(A & 127);
2162
+ const r = [];
2163
+ for (let e = 0; e < n.length; e++) {
2164
+ const a = n[e];
2165
+ a & 128 && (_ |= 1 << e), r.push(a & 127);
1935
2166
  }
1936
- t.push(_, ...e);
2167
+ E.push(_, ...r);
1937
2168
  }
1938
- return t;
2169
+ return E;
1939
2170
  }
1940
- function rt(i) {
1941
- const t = [];
1942
- for (let n = 0; n < i.length; n += 8) {
1943
- const s = i[n], _ = Math.min(7, i.length - n - 1);
1944
- for (let e = 0; e < _; e++) {
1945
- let r = i[n + 1 + e];
1946
- s & 1 << e && (r |= 128), t.push(r);
2171
+ function et(A) {
2172
+ const E = [];
2173
+ for (let s = 0; s < A.length; s += 8) {
2174
+ const n = A[s], _ = Math.min(7, A.length - s - 1);
2175
+ for (let r = 0; r < _; r++) {
2176
+ let e = A[s + 1 + r];
2177
+ n & 1 << r && (e |= 128), E.push(e);
1947
2178
  }
1948
2179
  }
1949
- return t;
2180
+ return E;
1950
2181
  }
1951
- function et(i) {
1952
- return Number.isInteger(i) && i >= 1 && i <= 16;
2182
+ function rt(A) {
2183
+ return Number.isInteger(A) && A >= 1 && A <= 16;
1953
2184
  }
1954
- function At(i) {
1955
- return Number.isInteger(i) && i >= 0 && i <= 127;
2185
+ function at(A) {
2186
+ return Number.isInteger(A) && A >= 0 && A <= 127;
1956
2187
  }
1957
- function it(i) {
1958
- return Number.isInteger(i) && i >= 0 && i <= 31;
2188
+ function At(A) {
2189
+ return Number.isInteger(A) && A >= 0 && A <= 31;
1959
2190
  }
1960
- function at(i) {
1961
- return Number.isInteger(i) && i >= 0 && i <= 127;
2191
+ function Pt(A) {
2192
+ return Number.isInteger(A) && A >= 0 && A <= 127;
1962
2193
  }
1963
- function Pt(i) {
1964
- return Number.isInteger(i) && i >= 0 && i <= 127;
2194
+ function it(A) {
2195
+ return Number.isInteger(A) && A >= 0 && A <= 127;
1965
2196
  }
1966
- function Ct(i) {
1967
- return Number.isInteger(i) && i >= 0 && i <= 127;
2197
+ function Ct(A) {
2198
+ return Number.isInteger(A) && A >= 0 && A <= 127;
1968
2199
  }
1969
- function Tt(i) {
1970
- return Number.isInteger(i) && i >= 0 && i <= 127;
2200
+ function Nt(A) {
2201
+ return Number.isInteger(A) && A >= 0 && A <= 127;
1971
2202
  }
1972
- function Nt(i) {
1973
- return Number.isInteger(i) && i >= 0 && i <= 16383;
2203
+ function lt(A) {
2204
+ return Number.isInteger(A) && A >= 0 && A <= 16383;
1974
2205
  }
1975
- function ut(i, t) {
1976
- return Number.isInteger(i) && i >= 0 && i <= 127 && Number.isInteger(t) && t >= 0 && t <= 127;
2206
+ function Tt(A, E) {
2207
+ return Number.isInteger(A) && A >= 0 && A <= 127 && Number.isInteger(E) && E >= 0 && E <= 127;
1977
2208
  }
1978
- async function W(i = {}) {
1979
- const t = new z(i);
1980
- await t.initialize();
1981
- const n = i.selector || "[data-midi-cc]";
2209
+ async function W(A = {}) {
2210
+ const E = new z(A);
2211
+ await E.initialize();
2212
+ const s = A.selector || "[data-midi-cc]";
1982
2213
  {
1983
- const s = new B(t, n);
1984
- s.bindAll(), i.watchDOM && s.enableAutoBinding(), t._binder = s;
2214
+ const n = new w(E, s);
2215
+ n.bindAll(), A.watchDOM && n.enableAutoBinding(), E._binder = n;
1985
2216
  }
1986
- return t;
2217
+ return E;
1987
2218
  }
1988
- async function St(i = {}) {
2219
+ async function St(A = {}) {
1989
2220
  const {
1990
- onStatusUpdate: t,
1991
- onConnectionUpdate: n,
1992
- channel: s,
2221
+ onStatusUpdate: E,
2222
+ onConnectionUpdate: s,
2223
+ channel: n,
1993
2224
  output: _,
1994
- sysex: e,
1995
- onReady: r,
1996
- onError: A,
2225
+ sysex: r,
2226
+ onReady: e,
2227
+ onError: a,
1997
2228
  selector: T,
1998
2229
  watchDOM: S,
1999
- ...a
2000
- } = i, l = await W({
2230
+ ...C
2231
+ } = A, i = await W({
2001
2232
  autoConnect: !1,
2002
- sysex: e,
2003
- channel: s || 1,
2233
+ sysex: r,
2234
+ channel: n || 1,
2004
2235
  selector: T || "[data-midi-cc]",
2005
2236
  watchDOM: S,
2006
- onError: A,
2007
- ...a
2008
- }), u = new q({
2009
- midiController: l,
2010
- onStatusUpdate: t || (() => {
2237
+ onError: a,
2238
+ ...C
2239
+ }), l = new q({
2240
+ midiController: i,
2241
+ onStatusUpdate: E || (() => {
2011
2242
  }),
2012
- onConnectionUpdate: n || (() => {
2243
+ onConnectionUpdate: s || (() => {
2013
2244
  }),
2014
- channel: s || 1
2245
+ channel: n || 1
2015
2246
  });
2016
2247
  if (_)
2017
2248
  try {
2018
- await l.setOutput(_), u.currentDevice = l.getCurrentOutput(), u.updateConnectionStatus();
2019
- } catch (N) {
2020
- A ? A(N) : console.error("Failed to connect to MIDI device:", N.message);
2249
+ await i.setOutput(_), l.currentDevice = i.getCurrentOutput(), l.updateConnectionStatus();
2250
+ } catch (O) {
2251
+ a ? a(O) : console.error("Failed to connect to MIDI device:", O.message);
2021
2252
  }
2022
- return r && r(l, u), u;
2253
+ return e && e(i, l), l;
2023
2254
  }
2024
2255
  export {
2025
- U as CONN,
2026
- U as CONNECTION_EVENTS,
2027
- O as CONTROLLER_EVENTS,
2028
- O as CTRL,
2029
- C as DX7Bank,
2256
+ f as CONN,
2257
+ f as CONNECTION_EVENTS,
2258
+ u as CONTROLLER_EVENTS,
2259
+ u as CTRL,
2260
+ N as DX7Bank,
2030
2261
  H as DX7Error,
2031
- D as DX7ParseError,
2032
- I as DX7ValidationError,
2033
- E as DX7Voice,
2034
- B as DataAttributeBinder,
2035
- b as EventEmitter,
2036
- F as MIDIAccessError,
2037
- $ as MIDIConnection,
2038
- g as MIDIConnectionError,
2262
+ m as DX7ParseError,
2263
+ o as DX7ValidationError,
2264
+ t as DX7Voice,
2265
+ w as DataAttributeBinder,
2266
+ v as EventEmitter,
2267
+ G as MIDIAccessError,
2268
+ Z as MIDIConnection,
2269
+ D as MIDIConnectionError,
2039
2270
  z as MIDIController,
2040
- L as MIDIDeviceError,
2271
+ c as MIDIDeviceError,
2041
2272
  q as MIDIDeviceManager,
2042
- m as MIDIError,
2273
+ p as MIDIError,
2043
2274
  R as MIDIValidationError,
2044
- o as clamp,
2275
+ h as clamp,
2045
2276
  W as createMIDIController,
2046
2277
  St as createMIDIDeviceManager,
2047
- nt as createSysEx,
2278
+ st as createSysEx,
2048
2279
  Y as decode14BitValue,
2049
- rt as decode7Bit,
2280
+ et as decode7Bit,
2050
2281
  tt as denormalize14BitValue,
2051
2282
  Q as denormalizeValue,
2052
2283
  x as encode14BitValue,
2053
2284
  _t as encode7Bit,
2054
2285
  k as frequencyToNote,
2055
2286
  X as getCCName,
2056
- st as isSysEx,
2057
- it as isValid14BitCC,
2058
- At as isValidCC,
2059
- et as isValidChannel,
2060
- at as isValidMIDIValue,
2061
- Pt as isValidNote,
2062
- Nt as isValidPitchBend,
2063
- ut as isValidPitchBendBytes,
2064
- Tt as isValidProgramChange,
2287
+ nt as isSysEx,
2288
+ At as isValid14BitCC,
2289
+ at as isValidCC,
2290
+ rt as isValidChannel,
2291
+ Pt as isValidMIDIValue,
2292
+ it as isValidNote,
2293
+ lt as isValidPitchBend,
2294
+ Tt as isValidPitchBendBytes,
2295
+ Nt as isValidProgramChange,
2065
2296
  Ct as isValidVelocity,
2066
- Z as normalize14BitValue,
2067
- w as normalizeValue,
2068
- j as noteNameToNumber,
2069
- J as noteNumberToName,
2297
+ $ as normalize14BitValue,
2298
+ B as normalizeValue,
2299
+ J as noteNameToNumber,
2300
+ j as noteNumberToName,
2070
2301
  V as noteToFrequency,
2071
2302
  Et as parseSysEx
2072
2303
  };