libadlmidi-js 1.2.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -5
- package/dist/core.d.ts +191 -4
- package/dist/fm_banks/manifest.json +1 -1
- package/dist/libadlmidi.d.ts +146 -66
- package/dist/libadlmidi.dosbox.browser.js +1 -1
- package/dist/libadlmidi.dosbox.browser.wasm +0 -0
- package/dist/libadlmidi.dosbox.core.js +1 -1
- package/dist/libadlmidi.dosbox.core.wasm +0 -0
- package/dist/libadlmidi.dosbox.js +0 -0
- package/dist/libadlmidi.dosbox.processor.js +247 -74
- package/dist/libadlmidi.dosbox.slim.browser.js +1 -1
- package/dist/libadlmidi.dosbox.slim.browser.wasm +0 -0
- package/dist/libadlmidi.dosbox.slim.core.js +1 -1
- package/dist/libadlmidi.dosbox.slim.core.wasm +0 -0
- package/dist/libadlmidi.dosbox.slim.js +0 -0
- package/dist/libadlmidi.dosbox.slim.processor.js +247 -74
- package/dist/libadlmidi.full.browser.js +1 -1
- package/dist/libadlmidi.full.browser.wasm +0 -0
- package/dist/libadlmidi.full.core.js +1 -1
- package/dist/libadlmidi.full.core.wasm +0 -0
- package/dist/libadlmidi.full.js +0 -0
- package/dist/libadlmidi.full.processor.js +247 -74
- package/dist/libadlmidi.full.slim.browser.js +1 -1
- package/dist/libadlmidi.full.slim.browser.wasm +0 -0
- package/dist/libadlmidi.full.slim.core.js +1 -1
- package/dist/libadlmidi.full.slim.core.wasm +0 -0
- package/dist/libadlmidi.full.slim.js +0 -0
- package/dist/libadlmidi.full.slim.processor.js +247 -74
- package/dist/libadlmidi.js +473 -24
- package/dist/libadlmidi.js.map +3 -3
- package/dist/libadlmidi.light.browser.js +1 -1
- package/dist/libadlmidi.light.browser.wasm +0 -0
- package/dist/libadlmidi.light.core.js +1 -1
- package/dist/libadlmidi.light.core.wasm +0 -0
- package/dist/libadlmidi.light.js +0 -0
- package/dist/libadlmidi.light.processor.js +247 -74
- package/dist/libadlmidi.light.slim.browser.js +1 -1
- package/dist/libadlmidi.light.slim.browser.wasm +0 -0
- package/dist/libadlmidi.light.slim.core.js +1 -1
- package/dist/libadlmidi.light.slim.core.wasm +0 -0
- package/dist/libadlmidi.light.slim.js +0 -0
- package/dist/libadlmidi.light.slim.processor.js +247 -74
- package/dist/libadlmidi.nuked.browser.js +1 -1
- package/dist/libadlmidi.nuked.browser.wasm +0 -0
- package/dist/libadlmidi.nuked.core.js +1 -1
- package/dist/libadlmidi.nuked.core.wasm +0 -0
- package/dist/libadlmidi.nuked.js +0 -0
- package/dist/libadlmidi.nuked.processor.js +247 -74
- package/dist/libadlmidi.nuked.slim.browser.js +1 -1
- package/dist/libadlmidi.nuked.slim.browser.wasm +0 -0
- package/dist/libadlmidi.nuked.slim.core.js +1 -1
- package/dist/libadlmidi.nuked.slim.core.wasm +0 -0
- package/dist/libadlmidi.nuked.slim.js +0 -0
- package/dist/libadlmidi.nuked.slim.processor.js +247 -74
- package/dist/profiles/dosbox.d.ts +7 -2
- package/dist/profiles/dosbox.slim.d.ts +7 -2
- package/dist/profiles/full.d.ts +7 -2
- package/dist/profiles/full.slim.d.ts +7 -2
- package/dist/profiles/light.d.ts +7 -2
- package/dist/profiles/light.slim.d.ts +7 -2
- package/dist/profiles/nuked.d.ts +7 -2
- package/dist/profiles/nuked.slim.d.ts +7 -2
- package/dist/utils/constants.d.ts +61 -0
- package/package.json +30 -9
- package/src/core.js +361 -4
- package/src/libadlmidi.js +379 -58
- package/src/processor.js +210 -12
- package/src/profiles/dosbox.js +20 -10
- package/src/profiles/dosbox.slim.js +20 -10
- package/src/profiles/full.js +21 -11
- package/src/profiles/full.slim.js +21 -11
- package/src/profiles/light.js +21 -11
- package/src/profiles/light.slim.js +21 -11
- package/src/profiles/nuked.js +21 -11
- package/src/profiles/nuked.slim.js +21 -11
- package/src/utils/constants.js +53 -0
package/dist/libadlmidi.js
CHANGED
|
@@ -6,12 +6,22 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
|
|
|
6
6
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
7
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
8
8
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
9
|
+
var __privateWrapper = (obj, member, setter, getter) => ({
|
|
10
|
+
set _(value) {
|
|
11
|
+
__privateSet(obj, member, value, setter);
|
|
12
|
+
},
|
|
13
|
+
get _() {
|
|
14
|
+
return __privateGet(obj, member, getter);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
9
17
|
|
|
10
|
-
// src/
|
|
18
|
+
// src/utils/constants.js
|
|
11
19
|
var Emulator = Object.freeze({
|
|
12
20
|
/** Nuked OPL3 v1.8 - Most accurate, higher CPU usage */
|
|
13
21
|
NUKED: 0,
|
|
14
|
-
/** Nuked
|
|
22
|
+
/** Optimized Nuked 1.8 fork by tgies with identical output */
|
|
23
|
+
NUKED_FAST: 1,
|
|
24
|
+
/** @deprecated Use NUKED_FAST */
|
|
15
25
|
NUKED_174: 1,
|
|
16
26
|
/** DosBox OPL3 - Good accuracy, lower CPU usage */
|
|
17
27
|
DOSBOX: 2,
|
|
@@ -20,7 +30,7 @@ var Emulator = Object.freeze({
|
|
|
20
30
|
/** Java OPL3 - Port of emu8950 */
|
|
21
31
|
JAVA: 4,
|
|
22
32
|
/** ESFMu - ESFM chip emulator */
|
|
23
|
-
|
|
33
|
+
ESFMu: 5,
|
|
24
34
|
/** MAME OPL2 */
|
|
25
35
|
MAME_OPL2: 6,
|
|
26
36
|
/** YMFM OPL2 */
|
|
@@ -34,7 +44,17 @@ var Emulator = Object.freeze({
|
|
|
34
44
|
/** Nuked OPL2 Lite - Lightweight OPL2 emulation for AdLib-era music */
|
|
35
45
|
NUKED_OPL2_LITE: 11
|
|
36
46
|
});
|
|
37
|
-
var
|
|
47
|
+
var TrackOption = Object.freeze({
|
|
48
|
+
/** Enable the track (default state) */
|
|
49
|
+
ON: 1,
|
|
50
|
+
/** Mute/disable the track */
|
|
51
|
+
OFF: 2,
|
|
52
|
+
/** Solo the track (mute all others) */
|
|
53
|
+
SOLO: 3
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// src/libadlmidi.js
|
|
57
|
+
var _ready, _messageHandlers, _nextRequestId, _AdlMidi_instances, handleMessage_fn, onceMessage_fn, onceCorrelatedMessage_fn, send_fn;
|
|
38
58
|
var AdlMidi = class {
|
|
39
59
|
/**
|
|
40
60
|
* Create a new AdlMidi instance
|
|
@@ -46,6 +66,8 @@ var AdlMidi = class {
|
|
|
46
66
|
__privateAdd(this, _ready, false);
|
|
47
67
|
/** @type {Map<string, Set<Function>>} */
|
|
48
68
|
__privateAdd(this, _messageHandlers, /* @__PURE__ */ new Map());
|
|
69
|
+
/** @type {number} */
|
|
70
|
+
__privateAdd(this, _nextRequestId, 0);
|
|
49
71
|
this.ctx = context || null;
|
|
50
72
|
this.node = null;
|
|
51
73
|
}
|
|
@@ -68,9 +90,11 @@ var AdlMidi = class {
|
|
|
68
90
|
* @param {string} processorUrl - URL to the bundled processor JavaScript file
|
|
69
91
|
* @param {string | null} [wasmUrl=null] - Optional URL to the .wasm file for split builds.
|
|
70
92
|
* If not provided, assumes bundled version with embedded WASM.
|
|
93
|
+
* @param {object} [defaultSettings={}] - Initial synth settings applied before ready.
|
|
94
|
+
* Profile wrappers use this to set a default emulator.
|
|
71
95
|
* @returns {Promise<void>}
|
|
72
96
|
*/
|
|
73
|
-
async init(processorUrl, wasmUrl = null) {
|
|
97
|
+
async init(processorUrl, wasmUrl = null, defaultSettings = {}) {
|
|
74
98
|
if (!this.ctx) {
|
|
75
99
|
this.ctx = new AudioContext({ sampleRate: 44100 });
|
|
76
100
|
}
|
|
@@ -87,8 +111,9 @@ var AdlMidi = class {
|
|
|
87
111
|
this.node = new AudioWorkletNode(this.ctx, "adl-midi-processor", {
|
|
88
112
|
processorOptions: {
|
|
89
113
|
sampleRate: this.ctx.sampleRate,
|
|
90
|
-
wasmBinary
|
|
114
|
+
wasmBinary,
|
|
91
115
|
// null for bundled, ArrayBuffer for split
|
|
116
|
+
settings: defaultSettings
|
|
92
117
|
}
|
|
93
118
|
});
|
|
94
119
|
this.node.connect(this.ctx.destination);
|
|
@@ -228,7 +253,7 @@ var AdlMidi = class {
|
|
|
228
253
|
* @param {ArrayBuffer} arrayBuffer - Bank file data
|
|
229
254
|
* @returns {Promise<void>}
|
|
230
255
|
*/
|
|
231
|
-
async
|
|
256
|
+
async loadBankData(arrayBuffer) {
|
|
232
257
|
return new Promise((resolve, reject) => {
|
|
233
258
|
__privateMethod(this, _AdlMidi_instances, onceMessage_fn).call(
|
|
234
259
|
this,
|
|
@@ -242,7 +267,7 @@ var AdlMidi = class {
|
|
|
242
267
|
}
|
|
243
268
|
}
|
|
244
269
|
);
|
|
245
|
-
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "
|
|
270
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "loadBankData", data: arrayBuffer });
|
|
246
271
|
});
|
|
247
272
|
}
|
|
248
273
|
/**
|
|
@@ -345,6 +370,23 @@ var AdlMidi = class {
|
|
|
345
370
|
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getNumFourOpChannels" });
|
|
346
371
|
});
|
|
347
372
|
}
|
|
373
|
+
/**
|
|
374
|
+
* Get the number of 4-operator channels obtained
|
|
375
|
+
* @returns {Promise<number>}
|
|
376
|
+
*/
|
|
377
|
+
async getNumFourOpChannelsObtained() {
|
|
378
|
+
return new Promise((resolve) => {
|
|
379
|
+
__privateMethod(this, _AdlMidi_instances, onceMessage_fn).call(
|
|
380
|
+
this,
|
|
381
|
+
"numFourOpChannelsObtained",
|
|
382
|
+
/** @param {{channels: number}} msg */
|
|
383
|
+
(msg) => {
|
|
384
|
+
resolve(msg.channels);
|
|
385
|
+
}
|
|
386
|
+
);
|
|
387
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getNumFourOpChannelsObtained" });
|
|
388
|
+
});
|
|
389
|
+
}
|
|
348
390
|
/**
|
|
349
391
|
* Enable/disable scaling of modulators by volume
|
|
350
392
|
* @param {boolean} enabled
|
|
@@ -408,32 +450,66 @@ var AdlMidi = class {
|
|
|
408
450
|
});
|
|
409
451
|
}
|
|
410
452
|
/**
|
|
411
|
-
* Set the volume model
|
|
453
|
+
* Set the volume range model
|
|
412
454
|
* @param {number} model - Volume model number
|
|
413
455
|
*/
|
|
414
|
-
|
|
415
|
-
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "
|
|
456
|
+
setVolumeRangeModel(model) {
|
|
457
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "setVolumeRangeModel", model });
|
|
416
458
|
}
|
|
417
459
|
/**
|
|
418
|
-
* Enable/disable
|
|
460
|
+
* Enable/disable soft stereo panning
|
|
419
461
|
* @param {boolean} enabled
|
|
420
462
|
*/
|
|
421
|
-
|
|
422
|
-
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "
|
|
463
|
+
setSoftPanEnabled(enabled) {
|
|
464
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "setSoftPanEnabled", enabled });
|
|
423
465
|
}
|
|
424
466
|
/**
|
|
425
467
|
* Enable/disable deep vibrato
|
|
426
468
|
* @param {boolean} enabled
|
|
427
469
|
*/
|
|
428
|
-
|
|
429
|
-
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "
|
|
470
|
+
setDeepVibrato(enabled) {
|
|
471
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "setDeepVibrato", enabled });
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Get deep vibrato state
|
|
475
|
+
* @returns {Promise<boolean>}
|
|
476
|
+
*/
|
|
477
|
+
async getDeepVibrato() {
|
|
478
|
+
return new Promise((resolve) => {
|
|
479
|
+
__privateMethod(this, _AdlMidi_instances, onceMessage_fn).call(
|
|
480
|
+
this,
|
|
481
|
+
"deepVibrato",
|
|
482
|
+
/** @param {{enabled: boolean}} msg */
|
|
483
|
+
(msg) => {
|
|
484
|
+
resolve(msg.enabled);
|
|
485
|
+
}
|
|
486
|
+
);
|
|
487
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getDeepVibrato" });
|
|
488
|
+
});
|
|
430
489
|
}
|
|
431
490
|
/**
|
|
432
491
|
* Enable/disable deep tremolo
|
|
433
492
|
* @param {boolean} enabled
|
|
434
493
|
*/
|
|
435
|
-
|
|
436
|
-
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "
|
|
494
|
+
setDeepTremolo(enabled) {
|
|
495
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "setDeepTremolo", enabled });
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Get deep tremolo state
|
|
499
|
+
* @returns {Promise<boolean>}
|
|
500
|
+
*/
|
|
501
|
+
async getDeepTremolo() {
|
|
502
|
+
return new Promise((resolve) => {
|
|
503
|
+
__privateMethod(this, _AdlMidi_instances, onceMessage_fn).call(
|
|
504
|
+
this,
|
|
505
|
+
"deepTremolo",
|
|
506
|
+
/** @param {{enabled: boolean}} msg */
|
|
507
|
+
(msg) => {
|
|
508
|
+
resolve(msg.enabled);
|
|
509
|
+
}
|
|
510
|
+
);
|
|
511
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getDeepTremolo" });
|
|
512
|
+
});
|
|
437
513
|
}
|
|
438
514
|
/**
|
|
439
515
|
* Run emulator with PCM rate to reduce CPU usage
|
|
@@ -449,7 +525,7 @@ var AdlMidi = class {
|
|
|
449
525
|
* - nuked profile: NUKED only
|
|
450
526
|
* - dosbox profile: DOSBOX only
|
|
451
527
|
* - light profile: NUKED, DOSBOX
|
|
452
|
-
* - full profile: NUKED, DOSBOX, OPAL, JAVA,
|
|
528
|
+
* - full profile: NUKED, DOSBOX, OPAL, JAVA, ESFMu, YMFM_OPL2, YMFM_OPL3
|
|
453
529
|
*
|
|
454
530
|
* @param {number} emulator - Emulator ID from the Emulator enum
|
|
455
531
|
* @returns {Promise<void>} Resolves when emulator is switched, rejects if unavailable
|
|
@@ -494,6 +570,23 @@ var AdlMidi = class {
|
|
|
494
570
|
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getEmulatorName" });
|
|
495
571
|
});
|
|
496
572
|
}
|
|
573
|
+
/**
|
|
574
|
+
* Get the last error info for the player instance
|
|
575
|
+
* @returns {Promise<string>}
|
|
576
|
+
*/
|
|
577
|
+
async getErrorInfo() {
|
|
578
|
+
return new Promise((resolve) => {
|
|
579
|
+
__privateMethod(this, _AdlMidi_instances, onceMessage_fn).call(
|
|
580
|
+
this,
|
|
581
|
+
"errorInfo",
|
|
582
|
+
/** @param {{info: string}} msg */
|
|
583
|
+
(msg) => {
|
|
584
|
+
resolve(msg.info);
|
|
585
|
+
}
|
|
586
|
+
);
|
|
587
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getErrorInfo" });
|
|
588
|
+
});
|
|
589
|
+
}
|
|
497
590
|
/**
|
|
498
591
|
* Get the version string of the linked libADLMIDI library
|
|
499
592
|
* @returns {Promise<string>}
|
|
@@ -566,17 +659,17 @@ var AdlMidi = class {
|
|
|
566
659
|
* Get the volume range model
|
|
567
660
|
* @returns {Promise<number>}
|
|
568
661
|
*/
|
|
569
|
-
async
|
|
662
|
+
async getVolumeRangeModel() {
|
|
570
663
|
return new Promise((resolve) => {
|
|
571
664
|
__privateMethod(this, _AdlMidi_instances, onceMessage_fn).call(
|
|
572
665
|
this,
|
|
573
|
-
"
|
|
666
|
+
"volumeRangeModel",
|
|
574
667
|
/** @param {{model: number}} msg */
|
|
575
668
|
(msg) => {
|
|
576
669
|
resolve(msg.model);
|
|
577
670
|
}
|
|
578
671
|
);
|
|
579
|
-
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "
|
|
672
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getVolumeRangeModel" });
|
|
580
673
|
});
|
|
581
674
|
}
|
|
582
675
|
/**
|
|
@@ -600,6 +693,146 @@ var AdlMidi = class {
|
|
|
600
693
|
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getEmbeddedBanks" });
|
|
601
694
|
});
|
|
602
695
|
}
|
|
696
|
+
// ================== Bank Management API ==================
|
|
697
|
+
/**
|
|
698
|
+
* Reserve a number of banks
|
|
699
|
+
* @param {number} count - Number of banks to reserve
|
|
700
|
+
* @returns {Promise<void>} Resolves on success, rejects on failure
|
|
701
|
+
*/
|
|
702
|
+
async reserveBanks(count) {
|
|
703
|
+
const reqId = __privateWrapper(this, _nextRequestId)._++;
|
|
704
|
+
return new Promise((resolve, reject) => {
|
|
705
|
+
__privateMethod(this, _AdlMidi_instances, onceCorrelatedMessage_fn).call(
|
|
706
|
+
this,
|
|
707
|
+
"banksReserved",
|
|
708
|
+
reqId,
|
|
709
|
+
/** @param {{success: boolean}} msg */
|
|
710
|
+
(msg) => {
|
|
711
|
+
if (msg.success) {
|
|
712
|
+
resolve();
|
|
713
|
+
} else {
|
|
714
|
+
reject(new Error("Failed to reserve banks"));
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
);
|
|
718
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "reserveBanks", count, reqId });
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Get the bank ID for a given bank identifier
|
|
723
|
+
* @param {BankId} bankId - Bank identifier
|
|
724
|
+
* @returns {Promise<{percussive: number, msb: number, lsb: number}|null>} Bank ID or null if not found
|
|
725
|
+
*/
|
|
726
|
+
async getBankId(bankId) {
|
|
727
|
+
const reqId = __privateWrapper(this, _nextRequestId)._++;
|
|
728
|
+
return new Promise((resolve) => {
|
|
729
|
+
__privateMethod(this, _AdlMidi_instances, onceCorrelatedMessage_fn).call(
|
|
730
|
+
this,
|
|
731
|
+
"bankId",
|
|
732
|
+
reqId,
|
|
733
|
+
/** @param {{id: {percussive: number, msb: number, lsb: number}|null}} msg */
|
|
734
|
+
(msg) => {
|
|
735
|
+
resolve(msg.id);
|
|
736
|
+
}
|
|
737
|
+
);
|
|
738
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getBankId", bankId, reqId });
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Remove a bank by its identifier
|
|
743
|
+
* @param {BankId} bankId - Bank identifier
|
|
744
|
+
* @returns {Promise<void>} Resolves on success, rejects on failure
|
|
745
|
+
*/
|
|
746
|
+
async removeBank(bankId) {
|
|
747
|
+
const reqId = __privateWrapper(this, _nextRequestId)._++;
|
|
748
|
+
return new Promise((resolve, reject) => {
|
|
749
|
+
__privateMethod(this, _AdlMidi_instances, onceCorrelatedMessage_fn).call(
|
|
750
|
+
this,
|
|
751
|
+
"bankRemoved",
|
|
752
|
+
reqId,
|
|
753
|
+
/** @param {{success: boolean}} msg */
|
|
754
|
+
(msg) => {
|
|
755
|
+
if (msg.success) {
|
|
756
|
+
resolve();
|
|
757
|
+
} else {
|
|
758
|
+
reject(new Error("Failed to remove bank"));
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
);
|
|
762
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "removeBank", bankId, reqId });
|
|
763
|
+
});
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Load an embedded bank into a custom bank slot
|
|
767
|
+
* @param {BankId} bankId - Target bank identifier
|
|
768
|
+
* @param {number} num - Embedded bank number to load
|
|
769
|
+
* @returns {Promise<void>} Resolves on success, rejects on failure
|
|
770
|
+
*/
|
|
771
|
+
async loadEmbeddedBank(bankId, num) {
|
|
772
|
+
const reqId = __privateWrapper(this, _nextRequestId)._++;
|
|
773
|
+
return new Promise((resolve, reject) => {
|
|
774
|
+
__privateMethod(this, _AdlMidi_instances, onceCorrelatedMessage_fn).call(
|
|
775
|
+
this,
|
|
776
|
+
"embeddedBankLoaded",
|
|
777
|
+
reqId,
|
|
778
|
+
/** @param {{success: boolean}} msg */
|
|
779
|
+
(msg) => {
|
|
780
|
+
if (msg.success) {
|
|
781
|
+
resolve();
|
|
782
|
+
} else {
|
|
783
|
+
reject(new Error("Failed to load embedded bank"));
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
);
|
|
787
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "loadEmbeddedBank", bankId, num, reqId });
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
// ================== SysEx API ==================
|
|
791
|
+
/**
|
|
792
|
+
* Send a System Exclusive (SysEx) message
|
|
793
|
+
* @param {Uint8Array|ArrayBuffer} data - SysEx message data
|
|
794
|
+
* @returns {Promise<void>} Resolves on success, rejects on failure
|
|
795
|
+
*/
|
|
796
|
+
async systemExclusive(data) {
|
|
797
|
+
const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
|
|
798
|
+
const reqId = __privateWrapper(this, _nextRequestId)._++;
|
|
799
|
+
return new Promise((resolve, reject) => {
|
|
800
|
+
__privateMethod(this, _AdlMidi_instances, onceCorrelatedMessage_fn).call(
|
|
801
|
+
this,
|
|
802
|
+
"systemExclusiveSent",
|
|
803
|
+
reqId,
|
|
804
|
+
/** @param {{success: boolean}} msg */
|
|
805
|
+
(msg) => {
|
|
806
|
+
if (msg.success) {
|
|
807
|
+
resolve();
|
|
808
|
+
} else {
|
|
809
|
+
reject(new Error("Failed to send system exclusive message"));
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
);
|
|
813
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "systemExclusive", data: Array.from(bytes), reqId });
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
// ================== Debug / Diagnostics API ==================
|
|
817
|
+
/**
|
|
818
|
+
* Describe the current state of all channels (debug utility)
|
|
819
|
+
* @returns {Promise<{text: string, attr: Uint8Array}>} Channel state text and raw per-channel attribute bytes
|
|
820
|
+
*/
|
|
821
|
+
async describeChannels() {
|
|
822
|
+
const reqId = __privateWrapper(this, _nextRequestId)._++;
|
|
823
|
+
return new Promise((resolve) => {
|
|
824
|
+
__privateMethod(this, _AdlMidi_instances, onceCorrelatedMessage_fn).call(
|
|
825
|
+
this,
|
|
826
|
+
"channelsDescribed",
|
|
827
|
+
reqId,
|
|
828
|
+
/** @param {{text: string, attr: number[]}} msg */
|
|
829
|
+
(msg) => {
|
|
830
|
+
resolve({ text: msg.text, attr: new Uint8Array(msg.attr) });
|
|
831
|
+
}
|
|
832
|
+
);
|
|
833
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "describeChannels", reqId });
|
|
834
|
+
});
|
|
835
|
+
}
|
|
603
836
|
/**
|
|
604
837
|
* Reset the synthesizer
|
|
605
838
|
* @returns {void}
|
|
@@ -664,6 +897,60 @@ var AdlMidi = class {
|
|
|
664
897
|
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getMusicCopyright" });
|
|
665
898
|
});
|
|
666
899
|
}
|
|
900
|
+
/**
|
|
901
|
+
* Get the number of track titles in the loaded MIDI file
|
|
902
|
+
* @returns {Promise<number>}
|
|
903
|
+
*/
|
|
904
|
+
async getTrackTitleCount() {
|
|
905
|
+
return new Promise((resolve) => {
|
|
906
|
+
__privateMethod(this, _AdlMidi_instances, onceMessage_fn).call(
|
|
907
|
+
this,
|
|
908
|
+
"trackTitleCount",
|
|
909
|
+
/** @param {{count: number}} msg */
|
|
910
|
+
(msg) => {
|
|
911
|
+
resolve(msg.count);
|
|
912
|
+
}
|
|
913
|
+
);
|
|
914
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getTrackTitleCount" });
|
|
915
|
+
});
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* Get a track title by index
|
|
919
|
+
* @param {number} index - Track title index
|
|
920
|
+
* @returns {Promise<string>}
|
|
921
|
+
*/
|
|
922
|
+
async getTrackTitle(index) {
|
|
923
|
+
const reqId = __privateWrapper(this, _nextRequestId)._++;
|
|
924
|
+
return new Promise((resolve) => {
|
|
925
|
+
__privateMethod(this, _AdlMidi_instances, onceCorrelatedMessage_fn).call(
|
|
926
|
+
this,
|
|
927
|
+
"trackTitle",
|
|
928
|
+
reqId,
|
|
929
|
+
/** @param {{title: string}} msg */
|
|
930
|
+
(msg) => {
|
|
931
|
+
resolve(msg.title);
|
|
932
|
+
}
|
|
933
|
+
);
|
|
934
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getTrackTitle", index, reqId });
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* Get the number of MIDI markers in the loaded file
|
|
939
|
+
* @returns {Promise<number>}
|
|
940
|
+
*/
|
|
941
|
+
async getMarkerCount() {
|
|
942
|
+
return new Promise((resolve) => {
|
|
943
|
+
__privateMethod(this, _AdlMidi_instances, onceMessage_fn).call(
|
|
944
|
+
this,
|
|
945
|
+
"markerCount",
|
|
946
|
+
/** @param {{count: number}} msg */
|
|
947
|
+
(msg) => {
|
|
948
|
+
resolve(msg.count);
|
|
949
|
+
}
|
|
950
|
+
);
|
|
951
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getMarkerCount" });
|
|
952
|
+
});
|
|
953
|
+
}
|
|
667
954
|
/**
|
|
668
955
|
* Start or resume MIDI file playback
|
|
669
956
|
* @returns {void}
|
|
@@ -691,8 +978,149 @@ var AdlMidi = class {
|
|
|
691
978
|
* @param {boolean} enabled - Whether to loop
|
|
692
979
|
* @returns {void}
|
|
693
980
|
*/
|
|
694
|
-
|
|
695
|
-
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "
|
|
981
|
+
setLoopEnabled(enabled) {
|
|
982
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "setLoopEnabled", enabled });
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Set the number of loop repetitions
|
|
986
|
+
* @param {number} count - Loop count (-1 = infinite, 0 = no loops, 1+ = number of loops)
|
|
987
|
+
*/
|
|
988
|
+
setLoopCount(count) {
|
|
989
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "setLoopCount", count });
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* Enable/disable loop hooks only mode
|
|
993
|
+
* @param {boolean} enabled
|
|
994
|
+
*/
|
|
995
|
+
setLoopHooksOnly(enabled) {
|
|
996
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "setLoopHooksOnly", enabled });
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* Get the loop start time in seconds
|
|
1000
|
+
* @returns {Promise<number>}
|
|
1001
|
+
*/
|
|
1002
|
+
async getLoopStartTime() {
|
|
1003
|
+
return new Promise((resolve) => {
|
|
1004
|
+
__privateMethod(this, _AdlMidi_instances, onceMessage_fn).call(
|
|
1005
|
+
this,
|
|
1006
|
+
"loopStartTime",
|
|
1007
|
+
/** @param {{time: number}} msg */
|
|
1008
|
+
(msg) => {
|
|
1009
|
+
resolve(msg.time);
|
|
1010
|
+
}
|
|
1011
|
+
);
|
|
1012
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getLoopStartTime" });
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
/**
|
|
1016
|
+
* Get the loop end time in seconds
|
|
1017
|
+
* @returns {Promise<number>}
|
|
1018
|
+
*/
|
|
1019
|
+
async getLoopEndTime() {
|
|
1020
|
+
return new Promise((resolve) => {
|
|
1021
|
+
__privateMethod(this, _AdlMidi_instances, onceMessage_fn).call(
|
|
1022
|
+
this,
|
|
1023
|
+
"loopEndTime",
|
|
1024
|
+
/** @param {{time: number}} msg */
|
|
1025
|
+
(msg) => {
|
|
1026
|
+
resolve(msg.time);
|
|
1027
|
+
}
|
|
1028
|
+
);
|
|
1029
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getLoopEndTime" });
|
|
1030
|
+
});
|
|
1031
|
+
}
|
|
1032
|
+
/**
|
|
1033
|
+
* Select a song number for multi-song MIDI files
|
|
1034
|
+
* @param {number} num - Song number (0-based)
|
|
1035
|
+
*/
|
|
1036
|
+
selectSongNum(num) {
|
|
1037
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "selectSongNum", num });
|
|
1038
|
+
}
|
|
1039
|
+
/**
|
|
1040
|
+
* Get the number of songs in the loaded MIDI file
|
|
1041
|
+
* @returns {Promise<number>}
|
|
1042
|
+
*/
|
|
1043
|
+
async getSongsCount() {
|
|
1044
|
+
return new Promise((resolve) => {
|
|
1045
|
+
__privateMethod(this, _AdlMidi_instances, onceMessage_fn).call(
|
|
1046
|
+
this,
|
|
1047
|
+
"songsCount",
|
|
1048
|
+
/** @param {{count: number}} msg */
|
|
1049
|
+
(msg) => {
|
|
1050
|
+
resolve(msg.count);
|
|
1051
|
+
}
|
|
1052
|
+
);
|
|
1053
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getSongsCount" });
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Get the number of tracks in the loaded MIDI file
|
|
1058
|
+
* @returns {Promise<number>}
|
|
1059
|
+
*/
|
|
1060
|
+
async getTrackCount() {
|
|
1061
|
+
return new Promise((resolve) => {
|
|
1062
|
+
__privateMethod(this, _AdlMidi_instances, onceMessage_fn).call(
|
|
1063
|
+
this,
|
|
1064
|
+
"trackCount",
|
|
1065
|
+
/** @param {{count: number}} msg */
|
|
1066
|
+
(msg) => {
|
|
1067
|
+
resolve(msg.count);
|
|
1068
|
+
}
|
|
1069
|
+
);
|
|
1070
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "getTrackCount" });
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Set track options (enable, mute, or solo)
|
|
1075
|
+
* Use the TrackOption enum: TrackOption.ON (1), TrackOption.OFF (2), TrackOption.SOLO (3).
|
|
1076
|
+
* Note: Passing 0 is a silent no-op that resolves without changing state.
|
|
1077
|
+
* @param {number} track - Track index
|
|
1078
|
+
* @param {number} options - Track option from TrackOption enum
|
|
1079
|
+
* @returns {Promise<void>} Resolves on success, rejects on failure
|
|
1080
|
+
*/
|
|
1081
|
+
async setTrackOptions(track, options) {
|
|
1082
|
+
const reqId = __privateWrapper(this, _nextRequestId)._++;
|
|
1083
|
+
return new Promise((resolve, reject) => {
|
|
1084
|
+
__privateMethod(this, _AdlMidi_instances, onceCorrelatedMessage_fn).call(
|
|
1085
|
+
this,
|
|
1086
|
+
"trackOptionsSet",
|
|
1087
|
+
reqId,
|
|
1088
|
+
/** @param {{success: boolean}} msg */
|
|
1089
|
+
(msg) => {
|
|
1090
|
+
if (msg.success) {
|
|
1091
|
+
resolve();
|
|
1092
|
+
} else {
|
|
1093
|
+
reject(new Error(`Failed to set track options for track ${track}`));
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
);
|
|
1097
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "setTrackOptions", track, options, reqId });
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Enable or disable a MIDI channel
|
|
1102
|
+
* @param {number} channel - MIDI channel (0-15)
|
|
1103
|
+
* @param {boolean} enabled - Whether to enable the channel
|
|
1104
|
+
* @returns {Promise<void>} Resolves on success, rejects on failure
|
|
1105
|
+
*/
|
|
1106
|
+
async setChannelEnabled(channel, enabled) {
|
|
1107
|
+
const reqId = __privateWrapper(this, _nextRequestId)._++;
|
|
1108
|
+
return new Promise((resolve, reject) => {
|
|
1109
|
+
__privateMethod(this, _AdlMidi_instances, onceCorrelatedMessage_fn).call(
|
|
1110
|
+
this,
|
|
1111
|
+
"channelEnabledSet",
|
|
1112
|
+
reqId,
|
|
1113
|
+
/** @param {{success: boolean}} msg */
|
|
1114
|
+
(msg) => {
|
|
1115
|
+
if (msg.success) {
|
|
1116
|
+
resolve();
|
|
1117
|
+
} else {
|
|
1118
|
+
reject(new Error(`Failed to set channel ${channel} enabled state`));
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
);
|
|
1122
|
+
__privateMethod(this, _AdlMidi_instances, send_fn).call(this, { type: "setChannelEnabled", channel, enabled, reqId });
|
|
1123
|
+
});
|
|
696
1124
|
}
|
|
697
1125
|
/**
|
|
698
1126
|
* Set the playback tempo multiplier
|
|
@@ -785,6 +1213,7 @@ var AdlMidi = class {
|
|
|
785
1213
|
};
|
|
786
1214
|
_ready = new WeakMap();
|
|
787
1215
|
_messageHandlers = new WeakMap();
|
|
1216
|
+
_nextRequestId = new WeakMap();
|
|
788
1217
|
_AdlMidi_instances = new WeakSet();
|
|
789
1218
|
/**
|
|
790
1219
|
* Internal message handler
|
|
@@ -814,6 +1243,25 @@ onceMessage_fn = function(type, handler) {
|
|
|
814
1243
|
};
|
|
815
1244
|
__privateGet(this, _messageHandlers).get(type)?.add(wrappedHandler);
|
|
816
1245
|
};
|
|
1246
|
+
/**
|
|
1247
|
+
* Register a one-time handler correlated by request ID.
|
|
1248
|
+
* Allows concurrent operations of the same type without reply misrouting.
|
|
1249
|
+
* @param {string} type - Message type
|
|
1250
|
+
* @param {number} reqId - Request ID to match against
|
|
1251
|
+
* @param {Function} handler - Handler function
|
|
1252
|
+
*/
|
|
1253
|
+
onceCorrelatedMessage_fn = function(type, reqId, handler) {
|
|
1254
|
+
if (!__privateGet(this, _messageHandlers).has(type)) {
|
|
1255
|
+
__privateGet(this, _messageHandlers).set(type, /* @__PURE__ */ new Set());
|
|
1256
|
+
}
|
|
1257
|
+
const filteredHandler = (msg) => {
|
|
1258
|
+
if (msg.reqId === reqId) {
|
|
1259
|
+
__privateGet(this, _messageHandlers).get(type)?.delete(filteredHandler);
|
|
1260
|
+
handler(msg);
|
|
1261
|
+
}
|
|
1262
|
+
};
|
|
1263
|
+
__privateGet(this, _messageHandlers).get(type)?.add(filteredHandler);
|
|
1264
|
+
};
|
|
817
1265
|
/**
|
|
818
1266
|
* Send a message to the processor
|
|
819
1267
|
* @param {Object} msg - Message to send
|
|
@@ -827,6 +1275,7 @@ var libadlmidi_default = AdlMidi;
|
|
|
827
1275
|
export {
|
|
828
1276
|
AdlMidi,
|
|
829
1277
|
Emulator,
|
|
1278
|
+
TrackOption,
|
|
830
1279
|
libadlmidi_default as default
|
|
831
1280
|
};
|
|
832
1281
|
//# sourceMappingURL=libadlmidi.js.map
|