audio-mixer-engine 0.2.0 → 0.3.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 +50 -45
- package/dist/audio-mixer-engine.cjs.js +1 -1
- package/dist/audio-mixer-engine.es.js +380 -623
- package/package.json +1 -1
- package/src/lib/audio-engine.js +85 -142
- package/src/lib/beat-mapper.js +1 -84
- package/src/lib/midi-player.js +4 -33
- package/src/lib/playback-manager.js +12 -114
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
class b {
|
|
1
|
+
const k = "data:audio/mpeg;base64,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", C = "data:audio/mpeg;base64,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qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//tkxPIADij5M+wwzYmAm6X9hJmwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//s0xPaAClDTI6OxLwCwkeLoEJkoqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sUxNoDwAAB/gAAACAAADSAAAAEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq";
|
|
2
|
+
class p {
|
|
2
3
|
/**
|
|
3
4
|
* Create a new AudioEngine instance
|
|
4
5
|
* @param {AudioContext} audioContext - Web Audio API context
|
|
5
6
|
* @param {Object} options - Engine-specific options
|
|
6
7
|
*/
|
|
7
8
|
constructor(t, e = {}) {
|
|
8
|
-
if (new.target ===
|
|
9
|
+
if (new.target === p)
|
|
9
10
|
throw new Error("AudioEngine is abstract and cannot be instantiated directly");
|
|
10
11
|
this.audioContext = t, this.options = e, this.isInitialized = !1, this.channels = /* @__PURE__ */ new WeakMap(), this.activeChannels = /* @__PURE__ */ new Set();
|
|
11
12
|
}
|
|
@@ -55,8 +56,8 @@ class b {
|
|
|
55
56
|
a.gain.value = i, n.connect(a);
|
|
56
57
|
const r = this.getMetronomeOutput();
|
|
57
58
|
r ? a.connect(r) : a.connect(this.audioContext.destination);
|
|
58
|
-
const
|
|
59
|
-
n.start(
|
|
59
|
+
const q = Math.max(t, this.audioContext.currentTime);
|
|
60
|
+
n.start(q);
|
|
60
61
|
} catch (s) {
|
|
61
62
|
console.warn("Buffer metronome playback failed:", s);
|
|
62
63
|
}
|
|
@@ -78,8 +79,8 @@ class b {
|
|
|
78
79
|
try {
|
|
79
80
|
if (typeof fetch < "u") {
|
|
80
81
|
const [t, e] = await Promise.all([
|
|
81
|
-
fetch(
|
|
82
|
-
fetch(
|
|
82
|
+
fetch(k),
|
|
83
|
+
fetch(C)
|
|
83
84
|
]), [i, s] = await Promise.all([
|
|
84
85
|
t.arrayBuffer(),
|
|
85
86
|
e.arrayBuffer()
|
|
@@ -134,9 +135,9 @@ class b {
|
|
|
134
135
|
this.activeChannels.delete(t), this.channels.delete(t);
|
|
135
136
|
}
|
|
136
137
|
}
|
|
137
|
-
class
|
|
138
|
+
class g {
|
|
138
139
|
constructor(t, e, i = {}) {
|
|
139
|
-
if (new.target ===
|
|
140
|
+
if (new.target === g)
|
|
140
141
|
throw new Error("ChannelHandle is abstract and cannot be instantiated directly");
|
|
141
142
|
this.engine = t, this.partId = e, this.options = { initialVolume: 1, ...i }, this.isDestroyed = !1, this.noteRefCounts = /* @__PURE__ */ new Map(), this.scheduledEvents = /* @__PURE__ */ new Map(), this.activeNotes = /* @__PURE__ */ new Set();
|
|
142
143
|
}
|
|
@@ -181,18 +182,18 @@ class y {
|
|
|
181
182
|
playNote(t, e, i, s) {
|
|
182
183
|
this._validateActive();
|
|
183
184
|
const n = this.engine.audioContext.currentTime, a = `${this.partId}_${t}_${e}_${Date.now()}`;
|
|
184
|
-
let r = t,
|
|
185
|
+
let r = t, q = s;
|
|
185
186
|
if (t < n) {
|
|
186
|
-
const
|
|
187
|
-
r = n,
|
|
187
|
+
const A = n - t;
|
|
188
|
+
r = n, q = Math.max(0, s - A);
|
|
188
189
|
}
|
|
189
|
-
if (
|
|
190
|
+
if (q <= 0)
|
|
190
191
|
return a;
|
|
191
|
-
const
|
|
192
|
+
const o = Math.max(0, (r - n) * 1e3), l = setTimeout(() => {
|
|
192
193
|
this.noteOn(e, i), this.scheduledEvents.delete(`${a}_on`);
|
|
193
|
-
},
|
|
194
|
+
}, o), h = o + q * 1e3, c = setTimeout(() => {
|
|
194
195
|
this.noteOff(e), this.scheduledEvents.delete(`${a}_off`);
|
|
195
|
-
},
|
|
196
|
+
}, h);
|
|
196
197
|
return this.scheduledEvents.set(`${a}_on`, l), this.scheduledEvents.set(`${a}_off`, c), a;
|
|
197
198
|
}
|
|
198
199
|
/**
|
|
@@ -287,7 +288,158 @@ class y {
|
|
|
287
288
|
throw new Error("AudioEngine is not initialized");
|
|
288
289
|
}
|
|
289
290
|
}
|
|
290
|
-
|
|
291
|
+
const T = {
|
|
292
|
+
// Piano family (0-7)
|
|
293
|
+
piano: 0,
|
|
294
|
+
bright_piano: 1,
|
|
295
|
+
electric_grand: 2,
|
|
296
|
+
honky_tonk: 3,
|
|
297
|
+
electric_piano_1: 4,
|
|
298
|
+
electric_piano_2: 5,
|
|
299
|
+
harpsichord: 6,
|
|
300
|
+
clavinet: 7,
|
|
301
|
+
// Chromatic percussion (8-15)
|
|
302
|
+
celesta: 8,
|
|
303
|
+
glockenspiel: 9,
|
|
304
|
+
music_box: 10,
|
|
305
|
+
vibraphone: 11,
|
|
306
|
+
marimba: 12,
|
|
307
|
+
xylophone: 13,
|
|
308
|
+
tubular_bells: 14,
|
|
309
|
+
dulcimer: 15,
|
|
310
|
+
// Organ (16-23)
|
|
311
|
+
drawbar_organ: 16,
|
|
312
|
+
percussive_organ: 17,
|
|
313
|
+
rock_organ: 18,
|
|
314
|
+
church_organ: 19,
|
|
315
|
+
reed_organ: 20,
|
|
316
|
+
accordion: 21,
|
|
317
|
+
harmonica: 22,
|
|
318
|
+
tango_accordion: 23,
|
|
319
|
+
organ: 19,
|
|
320
|
+
// Guitar (24-31)
|
|
321
|
+
nylon_guitar: 24,
|
|
322
|
+
steel_guitar: 25,
|
|
323
|
+
electric_guitar_jazz: 26,
|
|
324
|
+
electric_guitar_clean: 27,
|
|
325
|
+
electric_guitar_muted: 28,
|
|
326
|
+
overdriven_guitar: 29,
|
|
327
|
+
distortion_guitar: 30,
|
|
328
|
+
guitar_harmonics: 31,
|
|
329
|
+
guitar: 24,
|
|
330
|
+
// Bass (32-39)
|
|
331
|
+
acoustic_bass: 32,
|
|
332
|
+
electric_bass_finger: 33,
|
|
333
|
+
electric_bass_pick: 34,
|
|
334
|
+
fretless_bass: 35,
|
|
335
|
+
slap_bass_1: 36,
|
|
336
|
+
slap_bass_2: 37,
|
|
337
|
+
synth_bass_1: 38,
|
|
338
|
+
synth_bass_2: 39,
|
|
339
|
+
bass: 32,
|
|
340
|
+
// Strings (40-47)
|
|
341
|
+
violin: 40,
|
|
342
|
+
viola: 41,
|
|
343
|
+
cello: 42,
|
|
344
|
+
contrabass: 43,
|
|
345
|
+
tremolo_strings: 44,
|
|
346
|
+
pizzicato_strings: 45,
|
|
347
|
+
orchestral_harp: 46,
|
|
348
|
+
timpani: 47,
|
|
349
|
+
strings: 48,
|
|
350
|
+
strings_ensemble: 48,
|
|
351
|
+
// Ensemble (48-55)
|
|
352
|
+
slow_strings: 49,
|
|
353
|
+
synth_strings_1: 50,
|
|
354
|
+
synth_strings_2: 51,
|
|
355
|
+
choir_aahs: 52,
|
|
356
|
+
voice_oohs: 53,
|
|
357
|
+
synth_voice: 54,
|
|
358
|
+
orchestra_hit: 55,
|
|
359
|
+
// Brass (56-63)
|
|
360
|
+
trumpet: 56,
|
|
361
|
+
trombone: 57,
|
|
362
|
+
tuba: 58,
|
|
363
|
+
muted_trumpet: 59,
|
|
364
|
+
french_horn: 60,
|
|
365
|
+
brass_section: 61,
|
|
366
|
+
synth_brass_1: 62,
|
|
367
|
+
synth_brass_2: 63,
|
|
368
|
+
// Reed (64-71)
|
|
369
|
+
soprano_sax: 64,
|
|
370
|
+
alto_sax: 65,
|
|
371
|
+
tenor_sax: 66,
|
|
372
|
+
baritone_sax: 67,
|
|
373
|
+
oboe: 68,
|
|
374
|
+
english_horn: 69,
|
|
375
|
+
bassoon: 70,
|
|
376
|
+
clarinet: 71,
|
|
377
|
+
saxophone: 64,
|
|
378
|
+
// Pipe (72-79)
|
|
379
|
+
piccolo: 72,
|
|
380
|
+
flute: 73,
|
|
381
|
+
recorder: 74,
|
|
382
|
+
pan_flute: 75,
|
|
383
|
+
blown_bottle: 76,
|
|
384
|
+
shakuhachi: 77,
|
|
385
|
+
whistle: 78,
|
|
386
|
+
ocarina: 79,
|
|
387
|
+
// Synth lead (80-87)
|
|
388
|
+
lead_1_square: 80,
|
|
389
|
+
lead_2_sawtooth: 81,
|
|
390
|
+
lead_3_calliope: 82,
|
|
391
|
+
lead_4_chiff: 83,
|
|
392
|
+
lead_5_charang: 84,
|
|
393
|
+
lead_6_voice: 85,
|
|
394
|
+
lead_7_fifths: 86,
|
|
395
|
+
lead_8_bass: 87,
|
|
396
|
+
// Synth pad (88-95)
|
|
397
|
+
pad_1_new_age: 88,
|
|
398
|
+
pad_2_warm: 89,
|
|
399
|
+
pad_3_polysynth: 90,
|
|
400
|
+
pad_4_choir: 91,
|
|
401
|
+
pad_5_bowed: 92,
|
|
402
|
+
pad_6_metallic: 93,
|
|
403
|
+
pad_7_halo: 94,
|
|
404
|
+
pad_8_sweep: 95,
|
|
405
|
+
// Synth effects (96-103)
|
|
406
|
+
fx_1_rain: 96,
|
|
407
|
+
fx_2_soundtrack: 97,
|
|
408
|
+
fx_3_crystal: 98,
|
|
409
|
+
fx_4_atmosphere: 99,
|
|
410
|
+
fx_5_brightness: 100,
|
|
411
|
+
fx_6_goblins: 101,
|
|
412
|
+
fx_7_echoes: 102,
|
|
413
|
+
fx_8_sci_fi: 103,
|
|
414
|
+
// Ethnic (104-111)
|
|
415
|
+
sitar: 104,
|
|
416
|
+
banjo: 105,
|
|
417
|
+
shamisen: 106,
|
|
418
|
+
koto: 107,
|
|
419
|
+
kalimba: 108,
|
|
420
|
+
bag_pipe: 109,
|
|
421
|
+
fiddle: 110,
|
|
422
|
+
shanai: 111,
|
|
423
|
+
// Percussive (112-119)
|
|
424
|
+
tinkle_bell: 112,
|
|
425
|
+
agogo: 113,
|
|
426
|
+
steel_drums: 114,
|
|
427
|
+
woodblock: 115,
|
|
428
|
+
taiko_drum: 116,
|
|
429
|
+
melodic_tom: 117,
|
|
430
|
+
synth_drum: 118,
|
|
431
|
+
reverse_cymbal: 119,
|
|
432
|
+
// Sound effects (120-127)
|
|
433
|
+
guitar_fret_noise: 120,
|
|
434
|
+
breath_noise: 121,
|
|
435
|
+
seashore: 122,
|
|
436
|
+
bird_tweet: 123,
|
|
437
|
+
telephone_ring: 124,
|
|
438
|
+
helicopter: 125,
|
|
439
|
+
applause: 126,
|
|
440
|
+
gunshot: 127
|
|
441
|
+
}, x = Object.entries(T).reduce((m, [t, e]) => (m[e] = t, m), {});
|
|
442
|
+
class w {
|
|
291
443
|
/**
|
|
292
444
|
* Map common instrument names to MIDI program numbers
|
|
293
445
|
* @param {string|number} instrument - Instrument name or program number
|
|
@@ -295,158 +447,8 @@ class B {
|
|
|
295
447
|
*/
|
|
296
448
|
static getInstrumentProgram(t) {
|
|
297
449
|
if (typeof t == "number") return t;
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
piano: 0,
|
|
301
|
-
bright_piano: 1,
|
|
302
|
-
electric_grand: 2,
|
|
303
|
-
honky_tonk: 3,
|
|
304
|
-
electric_piano_1: 4,
|
|
305
|
-
electric_piano_2: 5,
|
|
306
|
-
harpsichord: 6,
|
|
307
|
-
clavinet: 7,
|
|
308
|
-
// Chromatic percussion (8-15)
|
|
309
|
-
celesta: 8,
|
|
310
|
-
glockenspiel: 9,
|
|
311
|
-
music_box: 10,
|
|
312
|
-
vibraphone: 11,
|
|
313
|
-
marimba: 12,
|
|
314
|
-
xylophone: 13,
|
|
315
|
-
tubular_bells: 14,
|
|
316
|
-
dulcimer: 15,
|
|
317
|
-
// Organ (16-23)
|
|
318
|
-
drawbar_organ: 16,
|
|
319
|
-
percussive_organ: 17,
|
|
320
|
-
rock_organ: 18,
|
|
321
|
-
church_organ: 19,
|
|
322
|
-
reed_organ: 20,
|
|
323
|
-
accordion: 21,
|
|
324
|
-
harmonica: 22,
|
|
325
|
-
tango_accordion: 23,
|
|
326
|
-
organ: 19,
|
|
327
|
-
// Guitar (24-31)
|
|
328
|
-
nylon_guitar: 24,
|
|
329
|
-
steel_guitar: 25,
|
|
330
|
-
electric_guitar_jazz: 26,
|
|
331
|
-
electric_guitar_clean: 27,
|
|
332
|
-
electric_guitar_muted: 28,
|
|
333
|
-
overdriven_guitar: 29,
|
|
334
|
-
distortion_guitar: 30,
|
|
335
|
-
guitar_harmonics: 31,
|
|
336
|
-
guitar: 24,
|
|
337
|
-
// Bass (32-39)
|
|
338
|
-
acoustic_bass: 32,
|
|
339
|
-
electric_bass_finger: 33,
|
|
340
|
-
electric_bass_pick: 34,
|
|
341
|
-
fretless_bass: 35,
|
|
342
|
-
slap_bass_1: 36,
|
|
343
|
-
slap_bass_2: 37,
|
|
344
|
-
synth_bass_1: 38,
|
|
345
|
-
synth_bass_2: 39,
|
|
346
|
-
bass: 32,
|
|
347
|
-
// Strings (40-47)
|
|
348
|
-
violin: 40,
|
|
349
|
-
viola: 41,
|
|
350
|
-
cello: 42,
|
|
351
|
-
contrabass: 43,
|
|
352
|
-
tremolo_strings: 44,
|
|
353
|
-
pizzicato_strings: 45,
|
|
354
|
-
orchestral_harp: 46,
|
|
355
|
-
timpani: 47,
|
|
356
|
-
strings: 48,
|
|
357
|
-
strings_ensemble: 48,
|
|
358
|
-
// Ensemble (48-55)
|
|
359
|
-
slow_strings: 49,
|
|
360
|
-
synth_strings_1: 50,
|
|
361
|
-
synth_strings_2: 51,
|
|
362
|
-
choir_aahs: 52,
|
|
363
|
-
voice_oohs: 53,
|
|
364
|
-
synth_voice: 54,
|
|
365
|
-
orchestra_hit: 55,
|
|
366
|
-
// Brass (56-63)
|
|
367
|
-
trumpet: 56,
|
|
368
|
-
trombone: 57,
|
|
369
|
-
tuba: 58,
|
|
370
|
-
muted_trumpet: 59,
|
|
371
|
-
french_horn: 60,
|
|
372
|
-
brass_section: 61,
|
|
373
|
-
synth_brass_1: 62,
|
|
374
|
-
synth_brass_2: 63,
|
|
375
|
-
// Reed (64-71)
|
|
376
|
-
soprano_sax: 64,
|
|
377
|
-
alto_sax: 65,
|
|
378
|
-
tenor_sax: 66,
|
|
379
|
-
baritone_sax: 67,
|
|
380
|
-
oboe: 68,
|
|
381
|
-
english_horn: 69,
|
|
382
|
-
bassoon: 70,
|
|
383
|
-
clarinet: 71,
|
|
384
|
-
saxophone: 64,
|
|
385
|
-
// Pipe (72-79)
|
|
386
|
-
piccolo: 72,
|
|
387
|
-
flute: 73,
|
|
388
|
-
recorder: 74,
|
|
389
|
-
pan_flute: 75,
|
|
390
|
-
blown_bottle: 76,
|
|
391
|
-
shakuhachi: 77,
|
|
392
|
-
whistle: 78,
|
|
393
|
-
ocarina: 79,
|
|
394
|
-
// Synth lead (80-87)
|
|
395
|
-
lead_1_square: 80,
|
|
396
|
-
lead_2_sawtooth: 81,
|
|
397
|
-
lead_3_calliope: 82,
|
|
398
|
-
lead_4_chiff: 83,
|
|
399
|
-
lead_5_charang: 84,
|
|
400
|
-
lead_6_voice: 85,
|
|
401
|
-
lead_7_fifths: 86,
|
|
402
|
-
lead_8_bass: 87,
|
|
403
|
-
// Synth pad (88-95)
|
|
404
|
-
pad_1_new_age: 88,
|
|
405
|
-
pad_2_warm: 89,
|
|
406
|
-
pad_3_polysynth: 90,
|
|
407
|
-
pad_4_choir: 91,
|
|
408
|
-
pad_5_bowed: 92,
|
|
409
|
-
pad_6_metallic: 93,
|
|
410
|
-
pad_7_halo: 94,
|
|
411
|
-
pad_8_sweep: 95,
|
|
412
|
-
// Synth effects (96-103)
|
|
413
|
-
fx_1_rain: 96,
|
|
414
|
-
fx_2_soundtrack: 97,
|
|
415
|
-
fx_3_crystal: 98,
|
|
416
|
-
fx_4_atmosphere: 99,
|
|
417
|
-
fx_5_brightness: 100,
|
|
418
|
-
fx_6_goblins: 101,
|
|
419
|
-
fx_7_echoes: 102,
|
|
420
|
-
fx_8_sci_fi: 103,
|
|
421
|
-
// Ethnic (104-111)
|
|
422
|
-
sitar: 104,
|
|
423
|
-
banjo: 105,
|
|
424
|
-
shamisen: 106,
|
|
425
|
-
koto: 107,
|
|
426
|
-
kalimba: 108,
|
|
427
|
-
bag_pipe: 109,
|
|
428
|
-
fiddle: 110,
|
|
429
|
-
shanai: 111,
|
|
430
|
-
// Percussive (112-119)
|
|
431
|
-
tinkle_bell: 112,
|
|
432
|
-
agogo: 113,
|
|
433
|
-
steel_drums: 114,
|
|
434
|
-
woodblock: 115,
|
|
435
|
-
taiko_drum: 116,
|
|
436
|
-
melodic_tom: 117,
|
|
437
|
-
synth_drum: 118,
|
|
438
|
-
reverse_cymbal: 119,
|
|
439
|
-
// Sound effects (120-127)
|
|
440
|
-
guitar_fret_noise: 120,
|
|
441
|
-
breath_noise: 121,
|
|
442
|
-
seashore: 122,
|
|
443
|
-
bird_tweet: 123,
|
|
444
|
-
telephone_ring: 124,
|
|
445
|
-
helicopter: 125,
|
|
446
|
-
applause: 126,
|
|
447
|
-
gunshot: 127
|
|
448
|
-
}[t.toLowerCase()];
|
|
449
|
-
return i !== void 0 ? i : 0;
|
|
450
|
+
const e = T[t.toLowerCase()];
|
|
451
|
+
return e !== void 0 ? e : 0;
|
|
450
452
|
}
|
|
451
453
|
/**
|
|
452
454
|
* Get instrument name from MIDI program number (for display purposes)
|
|
@@ -454,152 +456,7 @@ class B {
|
|
|
454
456
|
* @returns {string} Instrument name or fallback
|
|
455
457
|
*/
|
|
456
458
|
static getProgramName(t) {
|
|
457
|
-
return [
|
|
458
|
-
// Piano family (0-7)
|
|
459
|
-
"Piano",
|
|
460
|
-
"Bright Piano",
|
|
461
|
-
"Electric Grand",
|
|
462
|
-
"Honky-tonk Piano",
|
|
463
|
-
"Electric Piano 1",
|
|
464
|
-
"Electric Piano 2",
|
|
465
|
-
"Harpsichord",
|
|
466
|
-
"Clavinet",
|
|
467
|
-
// Chromatic percussion (8-15)
|
|
468
|
-
"Celesta",
|
|
469
|
-
"Glockenspiel",
|
|
470
|
-
"Music Box",
|
|
471
|
-
"Vibraphone",
|
|
472
|
-
"Marimba",
|
|
473
|
-
"Xylophone",
|
|
474
|
-
"Tubular Bells",
|
|
475
|
-
"Dulcimer",
|
|
476
|
-
// Organ (16-23)
|
|
477
|
-
"Drawbar Organ",
|
|
478
|
-
"Percussive Organ",
|
|
479
|
-
"Rock Organ",
|
|
480
|
-
"Church Organ",
|
|
481
|
-
"Reed Organ",
|
|
482
|
-
"Accordion",
|
|
483
|
-
"Harmonica",
|
|
484
|
-
"Tango Accordion",
|
|
485
|
-
// Guitar (24-31)
|
|
486
|
-
"Nylon Guitar",
|
|
487
|
-
"Steel Guitar",
|
|
488
|
-
"Electric Guitar (jazz)",
|
|
489
|
-
"Electric Guitar (clean)",
|
|
490
|
-
"Electric Guitar (muted)",
|
|
491
|
-
"Overdriven Guitar",
|
|
492
|
-
"Distortion Guitar",
|
|
493
|
-
"Guitar Harmonics",
|
|
494
|
-
// Bass (32-39)
|
|
495
|
-
"Acoustic Bass",
|
|
496
|
-
"Electric Bass (finger)",
|
|
497
|
-
"Electric Bass (pick)",
|
|
498
|
-
"Fretless Bass",
|
|
499
|
-
"Slap Bass 1",
|
|
500
|
-
"Slap Bass 2",
|
|
501
|
-
"Synth Bass 1",
|
|
502
|
-
"Synth Bass 2",
|
|
503
|
-
// Strings (40-47)
|
|
504
|
-
"Violin",
|
|
505
|
-
"Viola",
|
|
506
|
-
"Cello",
|
|
507
|
-
"Contrabass",
|
|
508
|
-
"Tremolo Strings",
|
|
509
|
-
"Pizzicato Strings",
|
|
510
|
-
"Orchestral Harp",
|
|
511
|
-
"Timpani",
|
|
512
|
-
// Ensemble (48-55)
|
|
513
|
-
"String Ensemble 1",
|
|
514
|
-
"String Ensemble 2",
|
|
515
|
-
"Synth Strings 1",
|
|
516
|
-
"Synth Strings 2",
|
|
517
|
-
"Choir Aahs",
|
|
518
|
-
"Voice Oohs",
|
|
519
|
-
"Synth Voice",
|
|
520
|
-
"Orchestra Hit",
|
|
521
|
-
// Brass (56-63)
|
|
522
|
-
"Trumpet",
|
|
523
|
-
"Trombone",
|
|
524
|
-
"Tuba",
|
|
525
|
-
"Muted Trumpet",
|
|
526
|
-
"French Horn",
|
|
527
|
-
"Brass Section",
|
|
528
|
-
"Synth Brass 1",
|
|
529
|
-
"Synth Brass 2",
|
|
530
|
-
// Reed (64-71)
|
|
531
|
-
"Soprano Sax",
|
|
532
|
-
"Alto Sax",
|
|
533
|
-
"Tenor Sax",
|
|
534
|
-
"Baritone Sax",
|
|
535
|
-
"Oboe",
|
|
536
|
-
"English Horn",
|
|
537
|
-
"Bassoon",
|
|
538
|
-
"Clarinet",
|
|
539
|
-
// Pipe (72-79)
|
|
540
|
-
"Piccolo",
|
|
541
|
-
"Flute",
|
|
542
|
-
"Recorder",
|
|
543
|
-
"Pan Flute",
|
|
544
|
-
"Blown Bottle",
|
|
545
|
-
"Shakuhachi",
|
|
546
|
-
"Whistle",
|
|
547
|
-
"Ocarina",
|
|
548
|
-
// Synth lead (80-87)
|
|
549
|
-
"Lead 1 (square)",
|
|
550
|
-
"Lead 2 (sawtooth)",
|
|
551
|
-
"Lead 3 (calliope)",
|
|
552
|
-
"Lead 4 (chiff)",
|
|
553
|
-
"Lead 5 (charang)",
|
|
554
|
-
"Lead 6 (voice)",
|
|
555
|
-
"Lead 7 (fifths)",
|
|
556
|
-
"Lead 8 (bass + lead)",
|
|
557
|
-
// Synth pad (88-95)
|
|
558
|
-
"Pad 1 (new age)",
|
|
559
|
-
"Pad 2 (warm)",
|
|
560
|
-
"Pad 3 (polysynth)",
|
|
561
|
-
"Pad 4 (choir)",
|
|
562
|
-
"Pad 5 (bowed)",
|
|
563
|
-
"Pad 6 (metallic)",
|
|
564
|
-
"Pad 7 (halo)",
|
|
565
|
-
"Pad 8 (sweep)",
|
|
566
|
-
// Synth effects (96-103)
|
|
567
|
-
"FX 1 (rain)",
|
|
568
|
-
"FX 2 (soundtrack)",
|
|
569
|
-
"FX 3 (crystal)",
|
|
570
|
-
"FX 4 (atmosphere)",
|
|
571
|
-
"FX 5 (brightness)",
|
|
572
|
-
"FX 6 (goblins)",
|
|
573
|
-
"FX 7 (echoes)",
|
|
574
|
-
"FX 8 (sci-fi)",
|
|
575
|
-
// Ethnic (104-111)
|
|
576
|
-
"Sitar",
|
|
577
|
-
"Banjo",
|
|
578
|
-
"Shamisen",
|
|
579
|
-
"Koto",
|
|
580
|
-
"Kalimba",
|
|
581
|
-
"Bag pipe",
|
|
582
|
-
"Fiddle",
|
|
583
|
-
"Shanai",
|
|
584
|
-
// Percussive (112-119)
|
|
585
|
-
"Tinkle Bell",
|
|
586
|
-
"Agogo",
|
|
587
|
-
"Steel Drums",
|
|
588
|
-
"Woodblock",
|
|
589
|
-
"Taiko Drum",
|
|
590
|
-
"Melodic Tom",
|
|
591
|
-
"Synth Drum",
|
|
592
|
-
"Reverse Cymbal",
|
|
593
|
-
// Sound effects (120-127)
|
|
594
|
-
"Guitar Fret Noise",
|
|
595
|
-
"Breath Noise",
|
|
596
|
-
"Seashore",
|
|
597
|
-
"Bird Tweet",
|
|
598
|
-
"Telephone Ring",
|
|
599
|
-
"Helicopter",
|
|
600
|
-
"Applause",
|
|
601
|
-
"Gunshot"
|
|
602
|
-
][t] || `Program ${t}`;
|
|
459
|
+
return x[t] || `Program ${t}`;
|
|
603
460
|
}
|
|
604
461
|
/**
|
|
605
462
|
* Generate a unique note ID
|
|
@@ -612,7 +469,7 @@ class B {
|
|
|
612
469
|
return `${t}_${e}_${Math.round(i)}`;
|
|
613
470
|
}
|
|
614
471
|
}
|
|
615
|
-
class v extends
|
|
472
|
+
class v extends g {
|
|
616
473
|
constructor(t, e, i, s = {}) {
|
|
617
474
|
super(t, e, s), this.midiChannel = i, this.currentVolume = s.initialVolume || 1, this.currentInstrument = s.instrument || "piano", this.outputGain = null, this._setupOutputNode(), this.setVolume(this.currentVolume), s.instrument && this.setInstrument(s.instrument);
|
|
618
475
|
}
|
|
@@ -643,7 +500,7 @@ class v extends y {
|
|
|
643
500
|
}
|
|
644
501
|
async setInstrument(t) {
|
|
645
502
|
this._validateActive();
|
|
646
|
-
const e =
|
|
503
|
+
const e = w.getInstrumentProgram(t);
|
|
647
504
|
this.currentInstrument = t;
|
|
648
505
|
const i = this.engine._getSynthesizer();
|
|
649
506
|
i && i.programChange ? i.programChange(this.midiChannel, e) : console.warn("Cannot set instrument: synthesizer not available or no programChange method");
|
|
@@ -690,7 +547,7 @@ class v extends y {
|
|
|
690
547
|
t ? this.outputGain = t : (console.warn(`No individual output available for MIDI channel ${this.midiChannel}, using fallback`), this.outputGain = this.engine.audioContext.createGain(), this.outputGain.gain.value = this.currentVolume);
|
|
691
548
|
}
|
|
692
549
|
}
|
|
693
|
-
class M extends
|
|
550
|
+
class M extends p {
|
|
694
551
|
constructor(t, e = {}) {
|
|
695
552
|
super(t, e), this.synthesizer = null, this.soundfont = null, this.channelCounter = 0, this.partToMidiChannel = /* @__PURE__ */ new Map(), this.midiChannelToPart = /* @__PURE__ */ new Map(), this.individualOutputs = [];
|
|
696
553
|
}
|
|
@@ -808,7 +665,7 @@ class M extends b {
|
|
|
808
665
|
throw new Error(`Failed to load soundfont: ${e.status} ${e.statusText}`);
|
|
809
666
|
return await e.arrayBuffer();
|
|
810
667
|
} else {
|
|
811
|
-
const e = await Promise.resolve().then(() =>
|
|
668
|
+
const e = await Promise.resolve().then(() => y), i = await Promise.resolve().then(() => y), s = i.isAbsolute(t) ? t : i.resolve(process.cwd(), t);
|
|
812
669
|
return e.readFileSync(s).buffer;
|
|
813
670
|
}
|
|
814
671
|
}
|
|
@@ -858,11 +715,11 @@ class M extends b {
|
|
|
858
715
|
const s = this.getMetronomeChannel(), n = this._getSynthesizer();
|
|
859
716
|
if (!s || !n)
|
|
860
717
|
return super.playMetronomeTick(t, e, i);
|
|
861
|
-
const a = 15, r = e ? 86 : 60,
|
|
862
|
-
c <= 0.01 ? (n.noteOn && n.noteOn(a, r,
|
|
718
|
+
const a = 15, r = e ? 86 : 60, o = Math.round(Math.min(127, Math.max(0, i * (e ? 127 : 100)))), l = this.audioContext.currentTime, c = Math.max(t, l) - l;
|
|
719
|
+
c <= 0.01 ? (n.noteOn && n.noteOn(a, r, o), setTimeout(() => {
|
|
863
720
|
n.noteOff && n.noteOff(a, r);
|
|
864
721
|
}, 100)) : setTimeout(() => {
|
|
865
|
-
n.noteOn && n.noteOn(a, r,
|
|
722
|
+
n.noteOn && n.noteOn(a, r, o), setTimeout(() => {
|
|
866
723
|
n.noteOff && n.noteOff(a, r);
|
|
867
724
|
}, 100);
|
|
868
725
|
}, c * 1e3);
|
|
@@ -878,7 +735,7 @@ class M extends b {
|
|
|
878
735
|
return !this.individualOutputs || this.individualOutputs.length < 16 ? null : this.individualOutputs[15];
|
|
879
736
|
}
|
|
880
737
|
}
|
|
881
|
-
class
|
|
738
|
+
class B {
|
|
882
739
|
constructor() {
|
|
883
740
|
this.partNames = [
|
|
884
741
|
"soprano",
|
|
@@ -923,20 +780,20 @@ class P {
|
|
|
923
780
|
const e = new Uint8Array(t);
|
|
924
781
|
if (!(e[0] === 77 && e[1] === 84 && e[2] === 104 && e[3] === 100))
|
|
925
782
|
throw new Error("Not a valid MIDI file");
|
|
926
|
-
const i = this._bytesToNumber(e.slice(4, 8)), s = this._bytesToNumber(e.slice(8, 10)), n = this._bytesToNumber(e.slice(10, 12)), a = this._bytesToNumber(e.slice(12, 14)), r = a & 32768 ? null : a,
|
|
783
|
+
const i = this._bytesToNumber(e.slice(4, 8)), s = this._bytesToNumber(e.slice(8, 10)), n = this._bytesToNumber(e.slice(10, 12)), a = this._bytesToNumber(e.slice(12, 14)), r = a & 32768 ? null : a, q = {
|
|
927
784
|
format: s,
|
|
928
785
|
ticksPerBeat: r,
|
|
929
786
|
tracks: [],
|
|
930
787
|
duration: 0
|
|
931
788
|
};
|
|
932
|
-
let
|
|
789
|
+
let o = 8 + i;
|
|
933
790
|
for (let l = 0; l < n; l++)
|
|
934
|
-
if (e[
|
|
935
|
-
const
|
|
936
|
-
|
|
791
|
+
if (e[o] === 77 && e[o + 1] === 84 && e[o + 2] === 114 && e[o + 3] === 107) {
|
|
792
|
+
const h = this._bytesToNumber(e.slice(o + 4, o + 8)), c = e.slice(o + 8, o + 8 + h), A = this._parseTrack(c);
|
|
793
|
+
q.tracks.push(A), o += 8 + h;
|
|
937
794
|
} else
|
|
938
|
-
throw new Error(`Invalid track header at position ${
|
|
939
|
-
return
|
|
795
|
+
throw new Error(`Invalid track header at position ${o}`);
|
|
796
|
+
return q;
|
|
940
797
|
}
|
|
941
798
|
/**
|
|
942
799
|
* Parse a single MIDI track
|
|
@@ -957,47 +814,47 @@ class P {
|
|
|
957
814
|
r = t[i++], a = a << 7 | r & 127;
|
|
958
815
|
while (r & 128);
|
|
959
816
|
s += a, r = t[i++];
|
|
960
|
-
let
|
|
817
|
+
let q = r;
|
|
961
818
|
if ((r & 128) === 0) {
|
|
962
819
|
if (n === null)
|
|
963
820
|
throw new Error("Running status byte encountered before status byte");
|
|
964
|
-
|
|
821
|
+
q = n, i--;
|
|
965
822
|
} else
|
|
966
|
-
n =
|
|
967
|
-
if (
|
|
968
|
-
const
|
|
823
|
+
n = q;
|
|
824
|
+
if (q === 255) {
|
|
825
|
+
const o = t[i++], l = this._readVariableLengthValue(t, i);
|
|
969
826
|
i += l.bytesRead;
|
|
970
|
-
const
|
|
971
|
-
switch (i += l.value,
|
|
827
|
+
const h = t.slice(i, i + l.value);
|
|
828
|
+
switch (i += l.value, o) {
|
|
972
829
|
case 3:
|
|
973
|
-
e.name = this._bytesToString(
|
|
830
|
+
e.name = this._bytesToString(h);
|
|
974
831
|
break;
|
|
975
832
|
case 1:
|
|
976
833
|
e.events.push({
|
|
977
834
|
type: "text",
|
|
978
|
-
text: this._bytesToString(
|
|
835
|
+
text: this._bytesToString(h),
|
|
979
836
|
tick: s
|
|
980
837
|
});
|
|
981
838
|
break;
|
|
982
839
|
case 5:
|
|
983
840
|
e.lyrics.push({
|
|
984
|
-
text: this._bytesToString(
|
|
841
|
+
text: this._bytesToString(h),
|
|
985
842
|
tick: s
|
|
986
843
|
});
|
|
987
844
|
break;
|
|
988
845
|
case 81:
|
|
989
|
-
const c = this._bytesToNumber(
|
|
846
|
+
const c = this._bytesToNumber(h), A = Math.round(6e7 / c);
|
|
990
847
|
e.events.push({
|
|
991
848
|
type: "tempo",
|
|
992
|
-
bpm:
|
|
849
|
+
bpm: A,
|
|
993
850
|
tick: s
|
|
994
851
|
});
|
|
995
852
|
break;
|
|
996
853
|
case 88:
|
|
997
854
|
e.events.push({
|
|
998
855
|
type: "timeSignature",
|
|
999
|
-
numerator:
|
|
1000
|
-
denominator: Math.pow(2,
|
|
856
|
+
numerator: h[0],
|
|
857
|
+
denominator: Math.pow(2, h[1]),
|
|
1001
858
|
tick: s
|
|
1002
859
|
});
|
|
1003
860
|
break;
|
|
@@ -1005,75 +862,75 @@ class P {
|
|
|
1005
862
|
e.duration = s;
|
|
1006
863
|
break;
|
|
1007
864
|
}
|
|
1008
|
-
} else if ((
|
|
1009
|
-
const
|
|
1010
|
-
|
|
865
|
+
} else if ((q & 240) === 144) {
|
|
866
|
+
const o = q & 15, l = t[i++], h = t[i++];
|
|
867
|
+
h > 0 ? e.notes.push({
|
|
1011
868
|
type: "noteOn",
|
|
1012
869
|
noteNumber: l,
|
|
1013
|
-
velocity:
|
|
870
|
+
velocity: h,
|
|
1014
871
|
tick: s,
|
|
1015
|
-
channel:
|
|
872
|
+
channel: o
|
|
1016
873
|
}) : e.notes.push({
|
|
1017
874
|
type: "noteOff",
|
|
1018
875
|
noteNumber: l,
|
|
1019
876
|
tick: s,
|
|
1020
|
-
channel:
|
|
877
|
+
channel: o
|
|
1021
878
|
});
|
|
1022
|
-
} else if ((
|
|
1023
|
-
const
|
|
879
|
+
} else if ((q & 240) === 128) {
|
|
880
|
+
const o = q & 15, l = t[i++];
|
|
1024
881
|
t[i++], e.notes.push({
|
|
1025
882
|
type: "noteOff",
|
|
1026
883
|
noteNumber: l,
|
|
1027
884
|
tick: s,
|
|
1028
|
-
channel:
|
|
885
|
+
channel: o
|
|
1029
886
|
});
|
|
1030
|
-
} else if (
|
|
1031
|
-
const
|
|
1032
|
-
i +=
|
|
1033
|
-
} else if ((
|
|
1034
|
-
const
|
|
887
|
+
} else if (q === 240 || q === 247) {
|
|
888
|
+
const o = this._readVariableLengthValue(t, i);
|
|
889
|
+
i += o.bytesRead + o.value;
|
|
890
|
+
} else if ((q & 240) === 176) {
|
|
891
|
+
const o = q & 15, l = t[i++], h = t[i++];
|
|
1035
892
|
e.events.push({
|
|
1036
893
|
type: "controller",
|
|
1037
894
|
controllerNumber: l,
|
|
1038
|
-
value:
|
|
1039
|
-
channel:
|
|
895
|
+
value: h,
|
|
896
|
+
channel: o,
|
|
1040
897
|
tick: s
|
|
1041
898
|
});
|
|
1042
|
-
} else if ((
|
|
1043
|
-
const
|
|
899
|
+
} else if ((q & 240) === 192) {
|
|
900
|
+
const o = q & 15, l = t[i++];
|
|
1044
901
|
e.events.push({
|
|
1045
902
|
type: "programChange",
|
|
1046
903
|
programNumber: l,
|
|
1047
|
-
channel:
|
|
904
|
+
channel: o,
|
|
1048
905
|
tick: s
|
|
1049
906
|
});
|
|
1050
|
-
} else if ((
|
|
1051
|
-
const
|
|
907
|
+
} else if ((q & 240) === 208) {
|
|
908
|
+
const o = q & 15, l = t[i++];
|
|
1052
909
|
e.events.push({
|
|
1053
910
|
type: "channelAftertouch",
|
|
1054
911
|
pressure: l,
|
|
1055
|
-
channel:
|
|
912
|
+
channel: o,
|
|
1056
913
|
tick: s
|
|
1057
914
|
});
|
|
1058
|
-
} else if ((
|
|
1059
|
-
const
|
|
915
|
+
} else if ((q & 240) === 224) {
|
|
916
|
+
const o = q & 15, l = t[i++], c = (t[i++] << 7 | l) - 8192;
|
|
1060
917
|
e.events.push({
|
|
1061
918
|
type: "pitchBend",
|
|
1062
919
|
value: c,
|
|
1063
|
-
channel:
|
|
920
|
+
channel: o,
|
|
1064
921
|
tick: s
|
|
1065
922
|
});
|
|
1066
|
-
} else if ((
|
|
1067
|
-
const
|
|
923
|
+
} else if ((q & 240) === 160) {
|
|
924
|
+
const o = q & 15, l = t[i++], h = t[i++];
|
|
1068
925
|
e.events.push({
|
|
1069
926
|
type: "noteAftertouch",
|
|
1070
927
|
noteNumber: l,
|
|
1071
|
-
pressure:
|
|
1072
|
-
channel:
|
|
928
|
+
pressure: h,
|
|
929
|
+
channel: o,
|
|
1073
930
|
tick: s
|
|
1074
931
|
});
|
|
1075
932
|
} else
|
|
1076
|
-
console.warn(`Unknown event type: ${
|
|
933
|
+
console.warn(`Unknown event type: ${q.toString(16)} at position ${i - 1}`), i++;
|
|
1077
934
|
}
|
|
1078
935
|
return e;
|
|
1079
936
|
}
|
|
@@ -1114,34 +971,34 @@ class P {
|
|
|
1114
971
|
_extractBarStructure(t) {
|
|
1115
972
|
const e = t.ticksPerBeat || 480, i = [];
|
|
1116
973
|
t.tracks.forEach((l) => {
|
|
1117
|
-
l.events.forEach((
|
|
1118
|
-
(
|
|
974
|
+
l.events.forEach((h) => {
|
|
975
|
+
(h.type === "timeSignature" || h.type === "tempo") && i.push(h);
|
|
1119
976
|
});
|
|
1120
|
-
}), i.sort((l,
|
|
977
|
+
}), i.sort((l, h) => l.tick - h.tick);
|
|
1121
978
|
let s = 0;
|
|
1122
979
|
t.tracks.forEach((l) => {
|
|
1123
|
-
l.notes && l.notes.forEach((
|
|
1124
|
-
|
|
980
|
+
l.notes && l.notes.forEach((h) => {
|
|
981
|
+
h.type === "noteOff" && h.tick > s && (s = h.tick);
|
|
1125
982
|
});
|
|
1126
983
|
}), s === 0 && (s = e * 8);
|
|
1127
|
-
const n = [], a = i.filter((l) => l.type === "timeSignature").sort((l,
|
|
1128
|
-
let r = { numerator: 4, denominator: 4 },
|
|
1129
|
-
for (;
|
|
1130
|
-
for (;
|
|
1131
|
-
r = a[
|
|
984
|
+
const n = [], a = i.filter((l) => l.type === "timeSignature").sort((l, h) => l.tick - h.tick);
|
|
985
|
+
let r = { numerator: 4, denominator: 4 }, q = 0, o = 0;
|
|
986
|
+
for (; q < s; ) {
|
|
987
|
+
for (; o < a.length && a[o].tick <= q; )
|
|
988
|
+
r = a[o], o++;
|
|
1132
989
|
let l;
|
|
1133
|
-
l =
|
|
1134
|
-
(
|
|
990
|
+
l = q + e * 4 * r.numerator / r.denominator, i.filter(
|
|
991
|
+
(u) => u.type === "tempo" && u.tick >= q && u.tick < l
|
|
1135
992
|
);
|
|
1136
|
-
const
|
|
1137
|
-
for (let
|
|
1138
|
-
const d =
|
|
993
|
+
const h = r.numerator, c = [], A = e * (4 / r.denominator);
|
|
994
|
+
for (let u = 0; u < h; u++) {
|
|
995
|
+
const d = q + u * A, f = this._ticksToTime(d, t);
|
|
1139
996
|
c.push(f);
|
|
1140
997
|
}
|
|
1141
998
|
n.push({
|
|
1142
999
|
sig: [r.numerator, r.denominator],
|
|
1143
1000
|
beats: c
|
|
1144
|
-
}),
|
|
1001
|
+
}), q = l;
|
|
1145
1002
|
}
|
|
1146
1003
|
this.parsedData.barStructure = n;
|
|
1147
1004
|
}
|
|
@@ -1155,63 +1012,63 @@ class P {
|
|
|
1155
1012
|
if (!s.notes.length) return;
|
|
1156
1013
|
let a = null;
|
|
1157
1014
|
if (s.name) {
|
|
1158
|
-
const
|
|
1015
|
+
const u = s.name.toLowerCase();
|
|
1159
1016
|
for (const d of this.partNames)
|
|
1160
1017
|
if (d.length === 1) {
|
|
1161
|
-
if (
|
|
1018
|
+
if (u === d) {
|
|
1162
1019
|
a = d;
|
|
1163
1020
|
break;
|
|
1164
1021
|
}
|
|
1165
|
-
} else if (
|
|
1022
|
+
} else if (u.includes(d)) {
|
|
1166
1023
|
a = d;
|
|
1167
1024
|
break;
|
|
1168
1025
|
}
|
|
1169
1026
|
}
|
|
1170
1027
|
a || (a = s.name || `Track ${n + 1}`), a === "s" && (a = "soprano"), a === "a" && (a = "alto"), a === "t" && (a = "tenor"), a === "b" && (a = "bass");
|
|
1171
|
-
let r = a,
|
|
1028
|
+
let r = a, q = 2;
|
|
1172
1029
|
for (; e[r]; )
|
|
1173
|
-
r = `${a} ${
|
|
1030
|
+
r = `${a} ${q}`, q++;
|
|
1174
1031
|
a = r;
|
|
1175
|
-
const
|
|
1176
|
-
s.notes.forEach((
|
|
1177
|
-
if (
|
|
1178
|
-
l[
|
|
1179
|
-
tick:
|
|
1180
|
-
velocity:
|
|
1032
|
+
const o = [], l = {};
|
|
1033
|
+
s.notes.forEach((u) => {
|
|
1034
|
+
if (u.type === "noteOn")
|
|
1035
|
+
l[u.noteNumber] = {
|
|
1036
|
+
tick: u.tick,
|
|
1037
|
+
velocity: u.velocity
|
|
1181
1038
|
};
|
|
1182
|
-
else if (
|
|
1183
|
-
const d = l[
|
|
1184
|
-
|
|
1185
|
-
pitch:
|
|
1186
|
-
name: this._midiNoteToName(
|
|
1039
|
+
else if (u.type === "noteOff" && l[u.noteNumber]) {
|
|
1040
|
+
const d = l[u.noteNumber], f = u.tick - d.tick;
|
|
1041
|
+
o.push({
|
|
1042
|
+
pitch: u.noteNumber,
|
|
1043
|
+
name: this._midiNoteToName(u.noteNumber),
|
|
1187
1044
|
startTick: d.tick,
|
|
1188
|
-
endTick:
|
|
1045
|
+
endTick: u.tick,
|
|
1189
1046
|
duration: f,
|
|
1190
1047
|
// Convert ticks to actual time considering tempo changes
|
|
1191
1048
|
startTime: this._ticksToTime(d.tick, t),
|
|
1192
|
-
endTime: this._ticksToTime(
|
|
1049
|
+
endTime: this._ticksToTime(u.tick, t),
|
|
1193
1050
|
velocity: d.velocity
|
|
1194
|
-
}), delete l[
|
|
1051
|
+
}), delete l[u.noteNumber];
|
|
1195
1052
|
}
|
|
1196
1053
|
});
|
|
1197
|
-
const
|
|
1198
|
-
text:
|
|
1199
|
-
tick:
|
|
1200
|
-
time:
|
|
1054
|
+
const h = s.lyrics.map((u) => ({
|
|
1055
|
+
text: u.text,
|
|
1056
|
+
tick: u.tick,
|
|
1057
|
+
time: u.tick / i
|
|
1201
1058
|
// Time in quarter notes
|
|
1202
1059
|
}));
|
|
1203
|
-
|
|
1204
|
-
const c = s.events.filter((
|
|
1205
|
-
programNumber:
|
|
1206
|
-
tick:
|
|
1207
|
-
time: this._ticksToTime(
|
|
1208
|
-
})).sort((
|
|
1060
|
+
o.sort((u, d) => u.startTick - d.startTick);
|
|
1061
|
+
const c = s.events.filter((u) => u.type === "programChange").map((u) => ({
|
|
1062
|
+
programNumber: u.programNumber,
|
|
1063
|
+
tick: u.tick,
|
|
1064
|
+
time: this._ticksToTime(u.tick, t)
|
|
1065
|
+
})).sort((u, d) => u.tick - d.tick), A = c.length > 0 ? c[0].programNumber : 0;
|
|
1209
1066
|
e[a] = {
|
|
1210
|
-
notes:
|
|
1211
|
-
lyrics:
|
|
1067
|
+
notes: o,
|
|
1068
|
+
lyrics: h,
|
|
1212
1069
|
trackIndex: n,
|
|
1213
1070
|
programChanges: c,
|
|
1214
|
-
defaultInstrument:
|
|
1071
|
+
defaultInstrument: A
|
|
1215
1072
|
};
|
|
1216
1073
|
}), this.parsedData.parts = e;
|
|
1217
1074
|
}
|
|
@@ -1257,28 +1114,28 @@ class P {
|
|
|
1257
1114
|
*/
|
|
1258
1115
|
_ticksToTime(t, e) {
|
|
1259
1116
|
const i = e.ticksPerBeat || 480, s = [];
|
|
1260
|
-
e.tracks.forEach((
|
|
1261
|
-
|
|
1262
|
-
|
|
1117
|
+
e.tracks.forEach((q) => {
|
|
1118
|
+
q.events.forEach((o) => {
|
|
1119
|
+
o.type === "tempo" && s.push(o);
|
|
1263
1120
|
});
|
|
1264
|
-
}), s.sort((
|
|
1121
|
+
}), s.sort((q, o) => q.tick - o.tick);
|
|
1265
1122
|
let n = 0, a = 0, r = 120;
|
|
1266
|
-
for (const
|
|
1267
|
-
if (
|
|
1268
|
-
if (
|
|
1269
|
-
const l = (
|
|
1270
|
-
n += l, a =
|
|
1123
|
+
for (const q of s) {
|
|
1124
|
+
if (q.tick > t) break;
|
|
1125
|
+
if (q.tick > a) {
|
|
1126
|
+
const l = (q.tick - a) / i * (60 / r);
|
|
1127
|
+
n += l, a = q.tick;
|
|
1271
1128
|
}
|
|
1272
|
-
r =
|
|
1129
|
+
r = q.bpm;
|
|
1273
1130
|
}
|
|
1274
1131
|
if (t > a) {
|
|
1275
|
-
const
|
|
1276
|
-
n +=
|
|
1132
|
+
const o = (t - a) / i * (60 / r);
|
|
1133
|
+
n += o;
|
|
1277
1134
|
}
|
|
1278
1135
|
return n;
|
|
1279
1136
|
}
|
|
1280
1137
|
}
|
|
1281
|
-
class
|
|
1138
|
+
class E {
|
|
1282
1139
|
constructor() {
|
|
1283
1140
|
this.barOrder = [], this.beatTable = [];
|
|
1284
1141
|
}
|
|
@@ -1309,13 +1166,13 @@ class S {
|
|
|
1309
1166
|
throw new Error(`Invalid section index: ${n.section}`);
|
|
1310
1167
|
const r = n.section;
|
|
1311
1168
|
s[r] || (s[r] = 0), s[r]++;
|
|
1312
|
-
const
|
|
1313
|
-
for (let c =
|
|
1314
|
-
this._shouldPlayBar(a, c,
|
|
1169
|
+
const q = s[r], o = n.from !== void 0 ? n.from : this._getSectionStartBar(t, n.section), l = n.to !== void 0 ? n.to : a.to, h = n.as || 1;
|
|
1170
|
+
for (let c = o; c <= l; c++)
|
|
1171
|
+
this._shouldPlayBar(a, c, h) && i.push({
|
|
1315
1172
|
barNumber: c,
|
|
1316
|
-
repeat:
|
|
1173
|
+
repeat: q,
|
|
1317
1174
|
sectionIndex: n.section,
|
|
1318
|
-
voltaTime:
|
|
1175
|
+
voltaTime: h
|
|
1319
1176
|
});
|
|
1320
1177
|
}
|
|
1321
1178
|
return i;
|
|
@@ -1328,76 +1185,45 @@ class S {
|
|
|
1328
1185
|
* @returns {Array} Beat table with time, repeat, bar, and beat information
|
|
1329
1186
|
*/
|
|
1330
1187
|
generateBeatTable(t, e) {
|
|
1331
|
-
return this._needsComplexAlgorithm(t, e) ? this._generateBeatTableComplex(t, e) : this._generateBeatTableSimple(t, e);
|
|
1332
|
-
}
|
|
1333
|
-
/**
|
|
1334
|
-
* Determine if we need the complex barBeats tracking algorithm
|
|
1335
|
-
* @private
|
|
1336
|
-
*/
|
|
1337
|
-
_needsComplexAlgorithm(t, e) {
|
|
1338
|
-
const i = t.map((r) => r.barNumber), n = new Set(i).size < i.length, a = Math.abs(t.length - e.length) > 1;
|
|
1339
|
-
return n || a;
|
|
1340
|
-
}
|
|
1341
|
-
/**
|
|
1342
|
-
* Simple direct mapping for basic cases
|
|
1343
|
-
* @private
|
|
1344
|
-
*/
|
|
1345
|
-
_generateBeatTableSimple(t, e) {
|
|
1346
|
-
const i = [], s = e[0] && e[0].sig && e[0].sig[0] === 1, n = t.length > 0 && t[0].barNumber === 0, a = s && n;
|
|
1347
|
-
for (let r = 0; r < t.length; r++) {
|
|
1348
|
-
const o = t[r];
|
|
1349
|
-
let q;
|
|
1350
|
-
if (a ? q = e[o.barNumber] : q = e[r + (s && !n ? 1 : 0)], !q)
|
|
1351
|
-
throw new Error(`No MIDI bar data for bar ${o.barNumber}`);
|
|
1352
|
-
this._generateBeatsForBar(i, o, q, q.sig[0]);
|
|
1353
|
-
}
|
|
1354
|
-
return i;
|
|
1355
|
-
}
|
|
1356
|
-
/**
|
|
1357
|
-
* Complex algorithm from BEATMAPPING.md for handling mismatches and repeats
|
|
1358
|
-
* @private
|
|
1359
|
-
*/
|
|
1360
|
-
_generateBeatTableComplex(t, e) {
|
|
1361
|
-
var l;
|
|
1362
1188
|
const i = [], s = {};
|
|
1363
1189
|
let n = 0, a = 0;
|
|
1364
|
-
const r = [...e]
|
|
1365
|
-
for (
|
|
1366
|
-
const
|
|
1367
|
-
if (s[
|
|
1368
|
-
const
|
|
1369
|
-
if (!
|
|
1190
|
+
const r = [...e];
|
|
1191
|
+
for (; a < t.length && n < r.length; ) {
|
|
1192
|
+
const q = t[a], o = q.barNumber;
|
|
1193
|
+
if (s[o] === void 0) {
|
|
1194
|
+
const A = r[n];
|
|
1195
|
+
if (!A || !A.sig)
|
|
1370
1196
|
throw new Error(`Invalid MIDI bar structure at index ${n}`);
|
|
1371
|
-
s[
|
|
1197
|
+
s[o] = A.sig[0];
|
|
1372
1198
|
}
|
|
1373
|
-
const
|
|
1374
|
-
let h = r[n],
|
|
1375
|
-
for (;
|
|
1376
|
-
const
|
|
1377
|
-
h.sig[0] +
|
|
1199
|
+
const l = s[o];
|
|
1200
|
+
let h = r[n], c = h.sig[0];
|
|
1201
|
+
for (; c < l && n + 1 < r.length; ) {
|
|
1202
|
+
const A = r[n + 1], u = [
|
|
1203
|
+
h.sig[0] + A.sig[0],
|
|
1378
1204
|
// Total beats
|
|
1379
1205
|
h.sig[1]
|
|
1380
1206
|
// Keep original note value
|
|
1381
|
-
],
|
|
1207
|
+
], d = [
|
|
1382
1208
|
...h.beats || [],
|
|
1383
|
-
...
|
|
1209
|
+
...A.beats || []
|
|
1384
1210
|
];
|
|
1385
1211
|
h = {
|
|
1386
|
-
sig:
|
|
1387
|
-
beats:
|
|
1388
|
-
}, r[n] = h, r.splice(n + 1, 1),
|
|
1212
|
+
sig: u,
|
|
1213
|
+
beats: d
|
|
1214
|
+
}, r[n] = h, r.splice(n + 1, 1), c = u[0];
|
|
1389
1215
|
}
|
|
1390
|
-
if (
|
|
1391
|
-
const
|
|
1392
|
-
sig: [
|
|
1393
|
-
beats:
|
|
1394
|
-
},
|
|
1395
|
-
sig: [
|
|
1396
|
-
beats:
|
|
1216
|
+
if (c > l) {
|
|
1217
|
+
const A = l, u = c - l, d = h.beats ? h.beats.slice(0, A) : [], f = h.beats ? h.beats.slice(A) : [], b = {
|
|
1218
|
+
sig: [A, h.sig[1]],
|
|
1219
|
+
beats: d
|
|
1220
|
+
}, I = {
|
|
1221
|
+
sig: [u, h.sig[1]],
|
|
1222
|
+
beats: f
|
|
1397
1223
|
};
|
|
1398
|
-
r[n] =
|
|
1224
|
+
r[n] = b, r.splice(n + 1, 0, I), h = b;
|
|
1399
1225
|
}
|
|
1400
|
-
this._generateBeatsForBar(i,
|
|
1226
|
+
this._generateBeatsForBar(i, q, h, l), n++, a++;
|
|
1401
1227
|
}
|
|
1402
1228
|
if (a < t.length)
|
|
1403
1229
|
throw new Error(`Ran out of MIDI bars before completing score. Score bar ${a}/${t.length}, MIDI bar ${n}/${r.length}`);
|
|
@@ -1413,14 +1239,14 @@ class S {
|
|
|
1413
1239
|
throw new Error(`Invalid MIDI bar: missing beats array. Got: ${JSON.stringify(i)}`);
|
|
1414
1240
|
const a = n.slice(0, s);
|
|
1415
1241
|
for (let r = 1; r <= s; r++) {
|
|
1416
|
-
const
|
|
1242
|
+
const o = {
|
|
1417
1243
|
time: a[r - 1],
|
|
1418
1244
|
repeat: e.repeat,
|
|
1419
1245
|
bar: e.barNumber,
|
|
1420
1246
|
beat: r,
|
|
1421
1247
|
timeSig: s
|
|
1422
1248
|
};
|
|
1423
|
-
t.push(
|
|
1249
|
+
t.push(o);
|
|
1424
1250
|
}
|
|
1425
1251
|
}
|
|
1426
1252
|
/**
|
|
@@ -1441,38 +1267,38 @@ class S {
|
|
|
1441
1267
|
return s === -1 ? !0 : s + 1 === i;
|
|
1442
1268
|
}
|
|
1443
1269
|
}
|
|
1444
|
-
function
|
|
1445
|
-
return { all:
|
|
1446
|
-
var i =
|
|
1447
|
-
i ? i.push(e) :
|
|
1270
|
+
function _(m) {
|
|
1271
|
+
return { all: m = m || /* @__PURE__ */ new Map(), on: function(t, e) {
|
|
1272
|
+
var i = m.get(t);
|
|
1273
|
+
i ? i.push(e) : m.set(t, [e]);
|
|
1448
1274
|
}, off: function(t, e) {
|
|
1449
|
-
var i =
|
|
1450
|
-
i && (e ? i.splice(i.indexOf(e) >>> 0, 1) :
|
|
1275
|
+
var i = m.get(t);
|
|
1276
|
+
i && (e ? i.splice(i.indexOf(e) >>> 0, 1) : m.set(t, []));
|
|
1451
1277
|
}, emit: function(t, e) {
|
|
1452
|
-
var i =
|
|
1278
|
+
var i = m.get(t);
|
|
1453
1279
|
i && i.slice().map(function(s) {
|
|
1454
1280
|
s(e);
|
|
1455
|
-
}), (i =
|
|
1281
|
+
}), (i = m.get("*")) && i.slice().map(function(s) {
|
|
1456
1282
|
s(t, e);
|
|
1457
1283
|
});
|
|
1458
1284
|
} };
|
|
1459
1285
|
}
|
|
1460
|
-
class
|
|
1286
|
+
class S {
|
|
1461
1287
|
/**
|
|
1462
1288
|
* Create a new MidiPlayer instance
|
|
1463
1289
|
* @param {AudioEngine} audioEngine - Initialized audio engine instance
|
|
1464
|
-
* @param {Object} instrumentMap - Mapping of part names to instrument configurations
|
|
1465
1290
|
* @param {Object} parsedMidiData - Output from MidiParser
|
|
1291
|
+
* @param {Object} instrumentMap - Mapping of part names to instrument configurations
|
|
1466
1292
|
* @param {Object} [structureMetadata] - Optional score structure for beat mapping
|
|
1467
1293
|
*/
|
|
1468
|
-
constructor(t, e, i, s = null) {
|
|
1294
|
+
constructor(t, e, i = null, s = null) {
|
|
1469
1295
|
if (!t || !t.isInitialized)
|
|
1470
1296
|
throw new Error("Initialized AudioEngine is required");
|
|
1471
|
-
if (!
|
|
1297
|
+
if (!e)
|
|
1472
1298
|
throw new Error("Parsed MIDI data is required");
|
|
1473
|
-
this.audioEngine = t, this.instrumentMap =
|
|
1299
|
+
this.audioEngine = t, this.instrumentMap = i || {}, this.parsedData = e, this._isPlaying = !1, this._currentTime = 0, this._totalDuration = 0, this.playbackSpeed = 1, this.partChannels = /* @__PURE__ */ new Map(), this.partOutputs = /* @__PURE__ */ new Map(), this.playbackStartTime = 0, this.lookAheadTime = 0.05, this.scheduleInterval = null, this.partNotePointers = /* @__PURE__ */ new Map(), this.partProgramPointers = /* @__PURE__ */ new Map(), this.eventBus = _(), this.beatMapper = new E(), this.beats = [], this._setupPartChannels(), this._calculateTotalDuration(), this._resetNotePointers(), this._resetProgramPointers();
|
|
1474
1300
|
const n = s || this._createDefaultStructureMetadata();
|
|
1475
|
-
this.beats = this.beatMapper.mapBeats(
|
|
1301
|
+
this.beats = this.beatMapper.mapBeats(e, n);
|
|
1476
1302
|
}
|
|
1477
1303
|
// ========================================
|
|
1478
1304
|
// PUBLIC API METHODS (unchanged interface)
|
|
@@ -1676,25 +1502,25 @@ class E {
|
|
|
1676
1502
|
if (a) {
|
|
1677
1503
|
if (a.programChanges && a.programChanges.length > 0) {
|
|
1678
1504
|
let r = this.partProgramPointers.get(s) || 0;
|
|
1679
|
-
const
|
|
1680
|
-
for (; r <
|
|
1505
|
+
const q = a.programChanges;
|
|
1506
|
+
for (; r < q.length && q[r].time < e; )
|
|
1681
1507
|
r++;
|
|
1682
|
-
for (; r <
|
|
1683
|
-
const
|
|
1684
|
-
n.setInstrument(
|
|
1508
|
+
for (; r < q.length && q[r].time <= i; ) {
|
|
1509
|
+
const o = q[r];
|
|
1510
|
+
n.setInstrument(o.programNumber), r++;
|
|
1685
1511
|
}
|
|
1686
1512
|
this.partProgramPointers.set(s, r);
|
|
1687
1513
|
}
|
|
1688
1514
|
if (a.notes) {
|
|
1689
1515
|
let r = this.partNotePointers.get(s) || 0;
|
|
1690
|
-
const
|
|
1691
|
-
for (; r <
|
|
1516
|
+
const q = a.notes;
|
|
1517
|
+
for (; r < q.length && q[r].endTime < e; )
|
|
1692
1518
|
r++;
|
|
1693
|
-
for (; r <
|
|
1694
|
-
const
|
|
1695
|
-
if (
|
|
1696
|
-
const l = this.playbackStartTime +
|
|
1697
|
-
n.playNote(l,
|
|
1519
|
+
for (; r < q.length && q[r].startTime <= i; ) {
|
|
1520
|
+
const o = q[r];
|
|
1521
|
+
if (o.endTime - o.startTime >= 0.01) {
|
|
1522
|
+
const l = this.playbackStartTime + o.startTime / this.playbackSpeed, h = (o.endTime - o.startTime) / this.playbackSpeed;
|
|
1523
|
+
n.playNote(l, o.pitch, o.velocity, h);
|
|
1698
1524
|
}
|
|
1699
1525
|
r++;
|
|
1700
1526
|
}
|
|
@@ -1787,23 +1613,9 @@ class E {
|
|
|
1787
1613
|
* @private
|
|
1788
1614
|
*/
|
|
1789
1615
|
_createDefaultStructureMetadata() {
|
|
1790
|
-
const t = this.parsedData.barStructure || [];
|
|
1791
|
-
let e = 1;
|
|
1792
|
-
if (t.length > 1)
|
|
1793
|
-
e = t.length;
|
|
1794
|
-
else {
|
|
1795
|
-
this._totalDuration > 0 ? e = Math.max(1, Math.ceil(this._totalDuration / 2)) : e = 1, this.parsedData.barStructure = [null];
|
|
1796
|
-
for (let r = 1; r <= e; r++) {
|
|
1797
|
-
const o = (r - 1) * 2;
|
|
1798
|
-
this.parsedData.barStructure[r] = {
|
|
1799
|
-
sig: [4, 4],
|
|
1800
|
-
beats: [o, o + 0.5, o + 1, o + 1.5]
|
|
1801
|
-
};
|
|
1802
|
-
}
|
|
1803
|
-
}
|
|
1804
1616
|
return {
|
|
1805
1617
|
sections: [
|
|
1806
|
-
{ from: 1, to:
|
|
1618
|
+
{ from: 1, to: this.parsedData.barStructure.length }
|
|
1807
1619
|
// Single section covering all bars
|
|
1808
1620
|
],
|
|
1809
1621
|
order: [
|
|
@@ -1823,8 +1635,7 @@ class E {
|
|
|
1823
1635
|
}), this.partOutputs.clear(), this.partNotePointers.clear(), this.partProgramPointers.clear(), this.eventBus.all.clear();
|
|
1824
1636
|
}
|
|
1825
1637
|
}
|
|
1826
|
-
const _ = "data:audio/mpeg;base64,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", I = "data:audio/mpeg;base64,//uUxAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAAMAAAQIAA0NDQ0NDQ0NE5OTk5OTk5OaWlpaWlpaWmAgICAgICAgICTk5OTk5OTk6qqqqqqqqqqu7u7u7u7u7u7zs7Ozs7Ozs7f39/f39/f3+/v7+/v7+/v7/n5+fn5+fn5//////////8AAABQTEFNRTMuMTAwBLkAAAAAAAAAABUgJAUHgQAB4AAAECAxW679AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//vUxAAACCABc/QAAASlsCq/NbBI//6YZkIUAAFLgQBA4oRqEAYLghE58ufUCCwQdg4cLg+fB8/KAMHwfPlAfB8Hwff/5cH3g+fy4Pg/+XPwQd/wQBD86Y8gkBAAEAAAAAAAAAgQrkCrEVHmoOI2GbVQgUVLGCAZk2giahgNUJfWEmZuCS6GQYHryLrek+YWAQUYGDJjZBcUZc/xZkxAJDiUv6cjCAkIBQcZEWkwrFnMRBNIDzDyqSPuYmdBd1NGE0AqpQKAGNiEXfAKhBiYOYGUjJkZ2AOyjaY0ImdI5lZETByCVvGepnGECLcW5goFEIwAAELA6QMjdpbgFAlHSELMYI6NhsXTlT0a85tNYaSysWCRGDNkX038MuQl7DiPSmsBRZZNyBo9HaWVW8U9F1wzIXGXk40RpLrPIy1qVQ1IHRXk7MxS3Pu14lTdsYzHOw7VlM7jjhVs6f7KYf65qepsuZYXYxJolGpbL5TLbNNSZXJm9p0M//iMsVQ7/6VK3d/rV2AgQAApEaRpCKTcVUUkVtqqLCJGtNg6y2jtwHDESSvk2Fw6N3+aXf7R0rLYHiC7AwuXLmKwOjqYF4Cw7uz6Q6jxc1eIrkEUD8+uLyva193XIM/kiYtbDp9tqTes/PzSb/uzzOWyZ2XrvWm1tmkXf87tJ/PepWrAEAoCaGjykkhihRd+7cjO7+xYQCJAAKmD4IYmMAkRJVGVgoqxsihA6IvC3dmL8QhTKbyvzcWEi1Yqn8Nxw+iSr5SxjlLdCXdF3Chq2GqmhH0HapSVXVjm0PmJjclY5ot8mZWeQo3Sli4Zr0gsEtIUA8FfWI9fP2eSDq6qlkGky9PhZFUT037KSvLeE8c2K8NvKfrAzDCxhsJ7mU9Vm07FWjX2tLxLQq2lvjQyS8yqG7DN9iqu/9xVUBAAABcGjNABl2BF8EOIWCATqRY08Bfh2GIJetn1bj8qt5zG4On8b9aPU0lrzLtNyztT9/lJVks/Wfh/luS1ajgshnKktaVD8Ujr7PfE//uUxMAAESEfTf2GAAKRL2l9h5o57CVDL1DUxE+16N/ZlErt0d6INCzx1MGSos2JUt3lWfLY5nki11ZSM6xtb3vTNd4HNv2PHg2roFE57bqRmzkX8dHGwUKEj00aazgk3DW3/7cM4oAXR8yqCLcwz1t2RCQUfk4mRuE/8tV2zdsVaBI3LojIxMcJgfx1zuK5vy3l1NN67gZjqF3iZF7JYhSpOY7UOy+nVNFM/VDGaZ3IQTIvjgSxHMbinYjE9ZWx6u2VOMivcV2m5bQIG9xSsb008hZkgymncftVx7hz2Rw/djtH3XsESkzENp/uY29u/2N17bvE/3K/tHpXvh6tn//6OHIgAAAnSNloBpAdRMhzluDPRIY5G1PMW1qMdGH+rLq+7w5m6FLCg7f7kP4nRnwIbPqAr3z+Sq5NEkz8M1GJBIpzMfL6qmwnkgnBnm8cgpbGf0JPSu4OYzZuJ8kmaNg2REliphhaQ1GNv2xwcoQkOczv23S5NOZDUaqY3db6//uUxN6Ak91LQ+wkfkpzLCi9h5o5m/kuQyJqdDKobXybFrBuLP2ZUVq8t3obzf/FeCNVgs9F5McOOmAhPUmiE0LFTZsTd5PPvG4KGI1mrDT7xZbWfMGWK4sTUXVfXEmoGG4/Fhsam3nSMA8mV7HQiZSPj/UNE4uFAsi3GeP1DyXqGEpWF9ZWiw5YU8jQAFwTqnZjplvvecwlhCe6n+RUtMErkJqWac+55tuWygx3UMW3XReqPwXZV9Xe79dshSru/e5HYRAAABdHqgdkdLIsIwNWlfDptNIBi+6q0GPS1prUB3I9agHNVpjZY08jLWAn1Asorb1qgRm6JMnkisbU6sVJq4W1twY2hvfs8NcqQqhiOYuKdEaS78/WFedz6osvG5yMR+1x1a1MS7ifEJpqpQcjeUGQTtd48omOqDGQuP7+W+/ZzzlFrinuP3j73Zr/3/Xz4twbleyOyTu97+/rSHBAVMZSQMqAREhdluKKDIZKPAQa1ZsklZOwFvo2yu1P//uExPYA0xEhQ+ek3gpHpCh5h5n5M3Sq5CW7uLj40BOOZlHgvYfxp9RZnadQwuTUnF0tRn7jhS1eMKQQpPHKcosSFtjMu3JRSxomIkDRDLB0OzxwwAodOIFFDal4zoQh9xUQmt+3kwqINMQcOmFtY7+L+VOxqzUXfKVevPvpcUdZVpKR8+Jz+1I63+/9eGEwAADLgoRDkhMWDZvH66VrO3JUGVutvizKB38fFVpreIUVGy2h3h0z9uKFp3Mb+0WDhss4HatoqOu3G0zFRib5GLbM4EzUb1TskJqa/CizSmo4hEQIFoQFyOZrGczw0Y/STG673ZA5IfmVs4UuaSBrTcMPTM5iII/zpKb87Xeu5rWv/e3zXn92LLiYIABexmOWmGikUwIJAXEntrwM7DKkoWFsYvj8rSD3LxcOnK/R+aLkEUGRdatbWULavvLikQcq//t0xP4Ak6FXP+y80cpiKig9l6H5RVFThop0KGGkgRGh0CwAgaDowc2nqVZRxQKRxRhDvXPCJvSS0iFI85U1+lmnNNOt64jha/7MFnFjRcq+x21mGoNV1UFWs2u22/6/aezV7f/+eINQQAVfQ5oBMXoZE9i7IPa2wZpK3YNo3Sau3kksskwNzLClcIIlSdXPtjjJs9fvMUkskrMlVE+LTnCpzv2cM2OTSJSc5krnXLMywyazLJWbtZ4au75+7aeX2/+V0/uPUdS3O7d3jWihOnC0MeKaZjXaLft85pbb57173f+RdIqAASvBmEzBisCQM0FZzTmvLujaergs8YNFZCuuDZU7bC5oKicRFULDSaTRghituw9ahmpIE5DIk7WX//uExOiAEUUhQ+w9D8okJqg9hiF54TxZEqxMmqScWJblwliNhGiYNkhnFX7qt/aV3QmB4ngkyP2J9ypCsWRXyTzPWkBEOA4NOnXKbKr//v+tpGDBAUwA1QSAmSX6dh3Y7Wd1MFnSVTktIT5eR2GaNxAOssKW4iaIeHsuOCCRKKpoeiZTh4IwJiKRuGZmN+SqOUCQKiQkB0VNy2S/hOW1yNtWtT62P82cfNovPjYvJh7JPib2kek0/dnfmv3jhJ6R8Zmu2/cyKfEsJxdbu9kXRmAAAHQCgrmAZQKJkLPGnRqBX+eVKpu7ZHFZkwNzB8QAFnRgqVhJEo/JTG25S3cnqScozDAZCYsOLEnOVaM4wPgPC4egqB9mDghpYcSeQNUT1sHvPvHN6ZdZsqKsMJjr7TI5kPTx1vMqs1+2guYHVnNUppvFrENscWYqzLu8qaRC//tkxPwAD61HQ+wkz8HdI+g9hI45gAS6BQcpTFqwRZcUONEHuQgyUG/n0dMLssFh8g8SJ3xCyjTdJpK1fVI3HZjM6E8txp3oGAVmqBw0RxkDt5cQjqEHKMJUcfF2nsvG0jYEEiouOG7m7ZtxJFy3M/9RpKEoh1KcZeu5KNpruysy8pVLBCdoB8kWLEx1S2IRvuMGXIlIoDf9gTxzs42MEdEBG0FoTpOcsJ2ixOihPbglHJnCSyBBEVZ/kKhKWIgNdcjGFkOeGrJlmBTJ5sqVsIT/4l38xIvAkm97OUV7x5gaenmUACAqQrC5xf1/3q3U//t0xO8AD70/Q+wkz+n5qGe9hKHtlsq7qqqakzcTDmwTWWuUEbDbnqtqtEb1afUxbmIMYiqi8bc8sJprNvdqi0NSyTUy69E7tmLYctB048TkJJITyTnV4QAxhEtzQ2/W/bYJkjw1HEgbf3//bfnnMIstHcz//1utqycFBToz9Zsftjy2ij/0z26l3mplGMDM1ACg5A6L2xqnxxw5cm2kNyX8RB+KTaK0JCBSwXpItftMy+crSfhDn98K0ycmFainmxRmnJnLsQDpfafL4c5MezncwxXVW41Vmu0smDHUckgSBwWtD42jqRW6CX3PyhmMACSVLELdkcLADC4/qy1L+Ht/uqLR8dHZVARYhQuMX3hx+zr2RRT6alzWRC7iBlCo//tkxPYADdkbO+elD2nQHud9pJn9TFUW552h+PSM431ETSTCJpbbra/leecUJ0D5UgCilASQAMP/CHi5OJhc5x5gGCe+N5bvM/sDJS+Vv8y3rfRYKi4jDSMS4i9KTEFNRTMuMTAwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpMQU1FMy4xMDCqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//tkxPIADij5M+wwzYmAm6X9hJmwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//s0xPaAClDTI6OxLwCwkeLoEJkoqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sUxNoDwAAB/gAAACAAADSAAAAEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq";
|
|
1827
|
-
class O {
|
|
1638
|
+
class P {
|
|
1828
1639
|
/**
|
|
1829
1640
|
* Create a new PlaybackManager instance
|
|
1830
1641
|
* @param {MidiPlayer} midiPlayer - Initialized MidiPlayer instance
|
|
@@ -1843,7 +1654,7 @@ class O {
|
|
|
1843
1654
|
constructor(t, e = {}) {
|
|
1844
1655
|
if (!t)
|
|
1845
1656
|
throw new Error("MidiPlayer is required");
|
|
1846
|
-
this.midiPlayer = t, this.audioEngine = t.audioEngine, this.eventBus =
|
|
1657
|
+
this.midiPlayer = t, this.audioEngine = t.audioEngine, this.eventBus = _(), this.metronomeConfig = {
|
|
1847
1658
|
enabled: !1,
|
|
1848
1659
|
tickInstrument: 115,
|
|
1849
1660
|
// woodblock
|
|
@@ -1858,7 +1669,7 @@ class O {
|
|
|
1858
1669
|
}, this.startupConfig = {
|
|
1859
1670
|
delayMs: 25,
|
|
1860
1671
|
...e.startup
|
|
1861
|
-
}, this.state = "stopped", this.frozenTime = 0, this.leadInData = null, this.leadInStartTime = null, this.leadInProgress = null, this.leadInInterval = null, this.timeUpdateInterval = null, this.metronomeScheduleInterval = null, this.nextBeatIndex = 0, this.
|
|
1672
|
+
}, this.state = "stopped", this.frozenTime = 0, this.leadInData = null, this.leadInStartTime = null, this.leadInProgress = null, this.leadInInterval = null, this.timeUpdateInterval = null, this.metronomeScheduleInterval = null, this.nextBeatIndex = 0, this._setupEventDelegation(), this._validateConfig();
|
|
1862
1673
|
}
|
|
1863
1674
|
// ========================================
|
|
1864
1675
|
// PUBLIC API - Core Playback Methods
|
|
@@ -2085,11 +1896,7 @@ class O {
|
|
|
2085
1896
|
* Stop all sounds immediately
|
|
2086
1897
|
*/
|
|
2087
1898
|
allSoundsOff() {
|
|
2088
|
-
|
|
2089
|
-
try {
|
|
2090
|
-
this.currentMetronomeSource.disconnect(), this.currentMetronomeSource.stop(), this.currentMetronomeSource = null;
|
|
2091
|
-
} catch {
|
|
2092
|
-
}
|
|
1899
|
+
this.midiPlayer.allSoundsOff();
|
|
2093
1900
|
}
|
|
2094
1901
|
// ========================================
|
|
2095
1902
|
// PUBLIC API - Delegation Methods
|
|
@@ -2123,36 +1930,6 @@ class O {
|
|
|
2123
1930
|
// ========================================
|
|
2124
1931
|
// PRIVATE IMPLEMENTATION METHODS
|
|
2125
1932
|
// ========================================
|
|
2126
|
-
/**
|
|
2127
|
-
* Set up metronome audio using direct audio files
|
|
2128
|
-
* @private
|
|
2129
|
-
*/
|
|
2130
|
-
async _setupMetronomeAudio() {
|
|
2131
|
-
try {
|
|
2132
|
-
this.metronomeOutput = this.audioEngine.audioContext.createGain(), this.metronomeOutput.gain.value = this.metronomeConfig.volume, this.metronomeBuffers = null, this.currentMetronomeSource = null;
|
|
2133
|
-
} catch (t) {
|
|
2134
|
-
throw console.error("Failed to setup metronome audio:", t), new Error("Failed to initialize metronome audio: " + t.message);
|
|
2135
|
-
}
|
|
2136
|
-
}
|
|
2137
|
-
/**
|
|
2138
|
-
* Ensure metronome audio buffers are loaded
|
|
2139
|
-
* @private
|
|
2140
|
-
*/
|
|
2141
|
-
async _ensureMetronomeBuffersLoaded() {
|
|
2142
|
-
if (!this.metronomeBuffers)
|
|
2143
|
-
try {
|
|
2144
|
-
if (typeof window > "u" || typeof fetch > "u" || !_ || !I) {
|
|
2145
|
-
console.log("Test environment detected, using mock metronome buffers"), this.metronomeBuffers = [null, null];
|
|
2146
|
-
return;
|
|
2147
|
-
}
|
|
2148
|
-
this.metronomeBuffers = await Promise.all([
|
|
2149
|
-
fetch(_).then((t) => t.arrayBuffer()).then((t) => this.audioEngine.audioContext.decodeAudioData(t)),
|
|
2150
|
-
fetch(I).then((t) => t.arrayBuffer()).then((t) => this.audioEngine.audioContext.decodeAudioData(t))
|
|
2151
|
-
]);
|
|
2152
|
-
} catch (t) {
|
|
2153
|
-
throw console.error("Failed to load metronome sound buffers:", t), this.metronomeBuffers = [null, null], t;
|
|
2154
|
-
}
|
|
2155
|
-
}
|
|
2156
1933
|
/**
|
|
2157
1934
|
* Set up event delegation from MidiPlayer
|
|
2158
1935
|
* @private
|
|
@@ -2211,30 +1988,17 @@ class O {
|
|
|
2211
1988
|
*/
|
|
2212
1989
|
_calculateLeadInBeats() {
|
|
2213
1990
|
const t = this.midiPlayer.beats, e = this.frozenTime, i = this.leadInConfig.bars;
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
beatSequence: this._generateBeatSequence(h, 0.5, 4),
|
|
2220
|
-
beatsPerBar: 4
|
|
2221
|
-
};
|
|
2222
|
-
}
|
|
2223
|
-
let s = t[0], n = 0.5;
|
|
2224
|
-
for (let c = t.length - 1; c >= 0; c--)
|
|
2225
|
-
if (t[c].time <= e) {
|
|
2226
|
-
s = t[c], c + 1 < t.length ? n = t[c + 1].time - s.time : c > 0 && (n = s.time - t[c - 1].time);
|
|
2227
|
-
break;
|
|
2228
|
-
}
|
|
2229
|
-
const a = Math.max(0, s.bar - 1), o = (this.midiPlayer.parsedData.barStructure || [])[a] || { bpm: 120 }, q = s.timeSig;
|
|
2230
|
-
Array.isArray(o.bpm) ? o.bpm[0] : o.bpm;
|
|
2231
|
-
const l = s.beat > 1 ? s.beat - 1 : 0, u = i * q + l;
|
|
1991
|
+
let s = t.length - 1, n = 0.5;
|
|
1992
|
+
for (; t[s].time > e; ) s--;
|
|
1993
|
+
const a = t[s], r = t[s + 1];
|
|
1994
|
+
r ? n = r.time - a.time : s > 0 && (n = a.time - t[s - 1].time);
|
|
1995
|
+
const q = a.timeSig === 1, o = q && r ? r.timeSig : a.timeSig, l = q ? o - 1 : a.beat > 1 ? a.beat - 1 : 0, h = i * o + l;
|
|
2232
1996
|
return {
|
|
2233
|
-
totalBeats:
|
|
2234
|
-
duration:
|
|
2235
|
-
beatSequence: this._generateBeatSequence(
|
|
2236
|
-
beatsPerBar:
|
|
2237
|
-
startBeat:
|
|
1997
|
+
totalBeats: h,
|
|
1998
|
+
duration: h * n,
|
|
1999
|
+
beatSequence: this._generateBeatSequence(h, n, o),
|
|
2000
|
+
beatsPerBar: o,
|
|
2001
|
+
startBeat: a
|
|
2238
2002
|
};
|
|
2239
2003
|
}
|
|
2240
2004
|
/**
|
|
@@ -2367,7 +2131,7 @@ class O {
|
|
|
2367
2131
|
* @private
|
|
2368
2132
|
*/
|
|
2369
2133
|
_scheduleMetronomeTicksAt(t) {
|
|
2370
|
-
if (!this.metronomeConfig.enabled
|
|
2134
|
+
if (!this.metronomeConfig.enabled)
|
|
2371
2135
|
return;
|
|
2372
2136
|
const e = this.midiPlayer.beats;
|
|
2373
2137
|
if (!e || e.length === 0)
|
|
@@ -2378,8 +2142,8 @@ class O {
|
|
|
2378
2142
|
if (r > this.audioEngine.audioContext.currentTime + s)
|
|
2379
2143
|
break;
|
|
2380
2144
|
if (r >= this.audioEngine.audioContext.currentTime - 0.01) {
|
|
2381
|
-
const
|
|
2382
|
-
this._scheduleTickAtTime(
|
|
2145
|
+
const q = Math.max(r, this.audioEngine.audioContext.currentTime + 1e-3), o = a.isDownbeat || a.beat === 1;
|
|
2146
|
+
this._scheduleTickAtTime(q, o), this.nextBeatIndex = n + 1;
|
|
2383
2147
|
}
|
|
2384
2148
|
}
|
|
2385
2149
|
}
|
|
@@ -2388,7 +2152,7 @@ class O {
|
|
|
2388
2152
|
* @private
|
|
2389
2153
|
*/
|
|
2390
2154
|
_scheduleMetronomeTicks() {
|
|
2391
|
-
if (!this.metronomeConfig.enabled
|
|
2155
|
+
if (!this.metronomeConfig.enabled)
|
|
2392
2156
|
return;
|
|
2393
2157
|
const t = this.midiPlayer.getCurrentTime(), e = this.midiPlayer.beats;
|
|
2394
2158
|
if (!e || e.length === 0) return;
|
|
@@ -2400,8 +2164,8 @@ class O {
|
|
|
2400
2164
|
if (n.time > s)
|
|
2401
2165
|
break;
|
|
2402
2166
|
if (a >= -0.025 && a <= 0.15) {
|
|
2403
|
-
const r = this.audioEngine.audioContext.currentTime + 5e-3,
|
|
2404
|
-
this._scheduleTickAtTime(
|
|
2167
|
+
const r = this.audioEngine.audioContext.currentTime + 5e-3, q = this.audioEngine.audioContext.currentTime + Math.max(a, 5e-3), o = Math.max(r, q), l = n.beat === 1;
|
|
2168
|
+
this._scheduleTickAtTime(o, l);
|
|
2405
2169
|
}
|
|
2406
2170
|
this.nextBeatIndex++;
|
|
2407
2171
|
}
|
|
@@ -2503,27 +2267,20 @@ class O {
|
|
|
2503
2267
|
* Clean up resources and destroy the manager
|
|
2504
2268
|
*/
|
|
2505
2269
|
destroy() {
|
|
2506
|
-
|
|
2507
|
-
try {
|
|
2508
|
-
this.currentMetronomeSource.disconnect(), this.currentMetronomeSource.stop();
|
|
2509
|
-
} catch {
|
|
2510
|
-
}
|
|
2511
|
-
this.currentMetronomeSource = null;
|
|
2512
|
-
}
|
|
2513
|
-
this.metronomeOutput && this.metronomeOutput.disconnect(), this.eventBus.all.clear();
|
|
2270
|
+
this.stop(), this._stopLeadIn(), this._stopMetronome(), this._stopTimeUpdateLoop(), this.eventBus.all.clear();
|
|
2514
2271
|
}
|
|
2515
2272
|
}
|
|
2516
|
-
const
|
|
2273
|
+
const y = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2517
2274
|
__proto__: null
|
|
2518
2275
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2519
2276
|
export {
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2277
|
+
p as AudioEngine,
|
|
2278
|
+
w as AudioEngineUtils,
|
|
2279
|
+
E as BeatMapper,
|
|
2280
|
+
g as ChannelHandle,
|
|
2281
|
+
B as MidiParser,
|
|
2282
|
+
S as MidiPlayer,
|
|
2283
|
+
P as PlaybackManager,
|
|
2527
2284
|
M as SpessaSynthAudioEngine,
|
|
2528
2285
|
v as SpessaSynthChannelHandle
|
|
2529
2286
|
};
|