audio-mixer-ui 0.4.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/audio-mixer-ui.js +587 -510
- package/dist/audio-mixer-ui.umd.cjs +10 -10
- package/dist/style.css +1 -1
- package/package.json +2 -2
package/dist/audio-mixer-ui.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { ref as x, watch as v, unref as r, onScopeDispose as UU, readonly as yl, mergeModels as il, useCssVars as $, computed as
|
|
1
|
+
import { ref as x, watch as v, unref as r, onScopeDispose as UU, readonly as yl, mergeModels as il, useCssVars as $, computed as G, useTemplateRef as O, useModel as _, createElementBlock as Y, openBlock as X, normalizeClass as L, createElementVNode as h, createCommentVNode as f, Fragment as al, renderList as Sl, normalizeStyle as Il, renderSlot as Vl, toDisplayString as K, onUnmounted as cl, watchEffect as El, onMounted as el, createVNode as C, withCtx as D, createTextVNode as ol, withDirectives as vl, withKeys as FU, vModelText as Kl, withModifiers as kl, createBlock as nl } from "vue";
|
|
2
2
|
import { defineStore as sl } from "pinia";
|
|
3
3
|
var gl = function() {
|
|
4
4
|
if (typeof Map < "u")
|
|
5
5
|
return Map;
|
|
6
6
|
function d(l, U) {
|
|
7
7
|
var F = -1;
|
|
8
|
-
return l.some(function(Z,
|
|
9
|
-
return Z[0] === U ? (F =
|
|
8
|
+
return l.some(function(Z, Q) {
|
|
9
|
+
return Z[0] === U ? (F = Q, !0) : !1;
|
|
10
10
|
}), F;
|
|
11
11
|
}
|
|
12
12
|
return (
|
|
@@ -39,14 +39,14 @@ var gl = function() {
|
|
|
39
39
|
this.__entries__.splice(0);
|
|
40
40
|
}, l.prototype.forEach = function(U, F) {
|
|
41
41
|
F === void 0 && (F = null);
|
|
42
|
-
for (var Z = 0,
|
|
43
|
-
var
|
|
44
|
-
U.call(F,
|
|
42
|
+
for (var Z = 0, Q = this.__entries__; Z < Q.length; Z++) {
|
|
43
|
+
var V = Q[Z];
|
|
44
|
+
U.call(F, V[1], V[0]);
|
|
45
45
|
}
|
|
46
46
|
}, l;
|
|
47
47
|
}()
|
|
48
48
|
);
|
|
49
|
-
}(),
|
|
49
|
+
}(), ul = typeof window < "u" && typeof document < "u" && window.document === document, ml = function() {
|
|
50
50
|
return typeof global < "u" && global.Math === Math ? global : typeof self < "u" && self.Math === Math ? self : typeof window < "u" && window.Math === Math ? window : Function("return this")();
|
|
51
51
|
}(), dU = function() {
|
|
52
52
|
return typeof requestAnimationFrame == "function" ? requestAnimationFrame.bind(ml) : function(d) {
|
|
@@ -57,11 +57,11 @@ var gl = function() {
|
|
|
57
57
|
}(), ZU = 2;
|
|
58
58
|
function QU(d, l) {
|
|
59
59
|
var U = !1, F = !1, Z = 0;
|
|
60
|
-
function
|
|
60
|
+
function Q() {
|
|
61
61
|
U && (U = !1, d()), F && t();
|
|
62
62
|
}
|
|
63
|
-
function
|
|
64
|
-
dU(
|
|
63
|
+
function V() {
|
|
64
|
+
dU(Q);
|
|
65
65
|
}
|
|
66
66
|
function t() {
|
|
67
67
|
var R = Date.now();
|
|
@@ -70,7 +70,7 @@ function QU(d, l) {
|
|
|
70
70
|
return;
|
|
71
71
|
F = !0;
|
|
72
72
|
} else
|
|
73
|
-
U = !0, F = !1, setTimeout(
|
|
73
|
+
U = !0, F = !1, setTimeout(V, l);
|
|
74
74
|
Z = R;
|
|
75
75
|
}
|
|
76
76
|
return t;
|
|
@@ -97,17 +97,17 @@ var VU = 20, tU = ["top", "right", "bottom", "left", "width", "height", "size",
|
|
|
97
97
|
return U.broadcastActive();
|
|
98
98
|
}), l.length > 0;
|
|
99
99
|
}, d.prototype.connect_ = function() {
|
|
100
|
-
!
|
|
100
|
+
!ul || this.connected_ || (document.addEventListener("transitionend", this.onTransitionEnd_), window.addEventListener("resize", this.refresh), RU ? (this.mutationsObserver_ = new MutationObserver(this.refresh), this.mutationsObserver_.observe(document, {
|
|
101
101
|
attributes: !0,
|
|
102
102
|
childList: !0,
|
|
103
103
|
characterData: !0,
|
|
104
104
|
subtree: !0
|
|
105
105
|
})) : (document.addEventListener("DOMSubtreeModified", this.refresh), this.mutationEventsAdded_ = !0), this.connected_ = !0);
|
|
106
106
|
}, d.prototype.disconnect_ = function() {
|
|
107
|
-
!
|
|
107
|
+
!ul || !this.connected_ || (document.removeEventListener("transitionend", this.onTransitionEnd_), window.removeEventListener("resize", this.refresh), this.mutationsObserver_ && this.mutationsObserver_.disconnect(), this.mutationEventsAdded_ && document.removeEventListener("DOMSubtreeModified", this.refresh), this.mutationsObserver_ = null, this.mutationEventsAdded_ = !1, this.connected_ = !1);
|
|
108
108
|
}, d.prototype.onTransitionEnd_ = function(l) {
|
|
109
|
-
var U = l.propertyName, F = U === void 0 ? "" : U, Z = tU.some(function(
|
|
110
|
-
return !!~F.indexOf(
|
|
109
|
+
var U = l.propertyName, F = U === void 0 ? "" : U, Z = tU.some(function(Q) {
|
|
110
|
+
return !!~F.indexOf(Q);
|
|
111
111
|
});
|
|
112
112
|
Z && this.refresh();
|
|
113
113
|
}, d.getInstance = function() {
|
|
@@ -136,14 +136,14 @@ function Tl(d) {
|
|
|
136
136
|
for (var l = [], U = 1; U < arguments.length; U++)
|
|
137
137
|
l[U - 1] = arguments[U];
|
|
138
138
|
return l.reduce(function(F, Z) {
|
|
139
|
-
var
|
|
140
|
-
return F + Wl(
|
|
139
|
+
var Q = d["border-" + Z + "-width"];
|
|
140
|
+
return F + Wl(Q);
|
|
141
141
|
}, 0);
|
|
142
142
|
}
|
|
143
143
|
function nU(d) {
|
|
144
144
|
for (var l = ["top", "right", "bottom", "left"], U = {}, F = 0, Z = l; F < Z.length; F++) {
|
|
145
|
-
var
|
|
146
|
-
U[
|
|
145
|
+
var Q = Z[F], V = d["padding-" + Q];
|
|
146
|
+
U[Q] = Wl(V);
|
|
147
147
|
}
|
|
148
148
|
return U;
|
|
149
149
|
}
|
|
@@ -155,9 +155,9 @@ function WU(d) {
|
|
|
155
155
|
var l = d.clientWidth, U = d.clientHeight;
|
|
156
156
|
if (!l && !U)
|
|
157
157
|
return Dl;
|
|
158
|
-
var F = dl(d).getComputedStyle(d), Z = nU(F),
|
|
159
|
-
if (F.boxSizing === "border-box" && (Math.round(t +
|
|
160
|
-
var a = Math.round(t +
|
|
158
|
+
var F = dl(d).getComputedStyle(d), Z = nU(F), Q = Z.left + Z.right, V = Z.top + Z.bottom, t = Wl(F.width), R = Wl(F.height);
|
|
159
|
+
if (F.boxSizing === "border-box" && (Math.round(t + Q) !== l && (t -= Tl(F, "left", "right") + Q), Math.round(R + V) !== U && (R -= Tl(F, "top", "bottom") + V)), !cU(d)) {
|
|
160
|
+
var a = Math.round(t + Q) - l, n = Math.round(R + V) - U;
|
|
161
161
|
Math.abs(a) !== 1 && (t -= a), Math.abs(n) !== 1 && (R -= n);
|
|
162
162
|
}
|
|
163
163
|
return hl(Z.left, Z.top, t, R);
|
|
@@ -173,11 +173,11 @@ function cU(d) {
|
|
|
173
173
|
return d === dl(d).document.documentElement;
|
|
174
174
|
}
|
|
175
175
|
function eU(d) {
|
|
176
|
-
return
|
|
176
|
+
return ul ? bU(d) ? mU(d) : WU(d) : Dl;
|
|
177
177
|
}
|
|
178
178
|
function sU(d) {
|
|
179
|
-
var l = d.x, U = d.y, F = d.width, Z = d.height,
|
|
180
|
-
return Hl(
|
|
179
|
+
var l = d.x, U = d.y, F = d.width, Z = d.height, Q = typeof DOMRectReadOnly < "u" ? DOMRectReadOnly : Object, V = Object.create(Q.prototype);
|
|
180
|
+
return Hl(V, {
|
|
181
181
|
x: l,
|
|
182
182
|
y: U,
|
|
183
183
|
width: F,
|
|
@@ -186,7 +186,7 @@ function sU(d) {
|
|
|
186
186
|
right: l + F,
|
|
187
187
|
bottom: Z + U,
|
|
188
188
|
left: l
|
|
189
|
-
}),
|
|
189
|
+
}), V;
|
|
190
190
|
}
|
|
191
191
|
function hl(d, l, U, F) {
|
|
192
192
|
return { x: d, y: l, width: U, height: F };
|
|
@@ -284,7 +284,7 @@ var hU = (
|
|
|
284
284
|
return (l = jl.get(this))[d].apply(l, arguments);
|
|
285
285
|
};
|
|
286
286
|
});
|
|
287
|
-
var
|
|
287
|
+
var uU = function() {
|
|
288
288
|
return typeof ml.ResizeObserver < "u" ? ml.ResizeObserver : Pl;
|
|
289
289
|
}();
|
|
290
290
|
function ll(d) {
|
|
@@ -295,13 +295,13 @@ function ll(d) {
|
|
|
295
295
|
};
|
|
296
296
|
return v(() => r(d), () => {
|
|
297
297
|
Z();
|
|
298
|
-
const
|
|
299
|
-
if (!
|
|
300
|
-
F = new
|
|
298
|
+
const V = r(d);
|
|
299
|
+
if (!V) return;
|
|
300
|
+
F = new uU((R) => {
|
|
301
301
|
const a = R[0];
|
|
302
302
|
a && (l.value = a.contentRect.width, U.value = a.contentRect.height);
|
|
303
|
-
}), F.observe(
|
|
304
|
-
const t =
|
|
303
|
+
}), F.observe(V);
|
|
304
|
+
const t = V.getBoundingClientRect();
|
|
305
305
|
l.value = t.width, U.value = t.height;
|
|
306
306
|
}, { immediate: !0 }), UU(Z), {
|
|
307
307
|
width: yl(l),
|
|
@@ -313,7 +313,7 @@ const g = (d, l) => {
|
|
|
313
313
|
for (const [F, Z] of l)
|
|
314
314
|
U[F] = Z;
|
|
315
315
|
return U;
|
|
316
|
-
},
|
|
316
|
+
}, GU = {
|
|
317
317
|
key: 0,
|
|
318
318
|
class: "level"
|
|
319
319
|
}, iU = {
|
|
@@ -335,12 +335,12 @@ const g = (d, l) => {
|
|
|
335
335
|
setup(d) {
|
|
336
336
|
$((i) => ({
|
|
337
337
|
"083f3e45": c.value,
|
|
338
|
-
d4833630:
|
|
338
|
+
d4833630: W.value,
|
|
339
339
|
d6eaa016: J.value,
|
|
340
340
|
12894835: s.value,
|
|
341
341
|
"3e9a6a44": N.value
|
|
342
342
|
}));
|
|
343
|
-
const l = d, U = O("root"), { width: F, height: Z } = ll(U),
|
|
343
|
+
const l = d, U = O("root"), { width: F, height: Z } = ll(U), Q = G(() => Math.min(F.value, Z.value)), V = G(() => Math.max(F.value, Z.value)), t = G(() => F.value > Z.value), R = G(() => t.value ? "h-slide" : "v-slide"), a = _(d, "value"), n = G(() => Q.value * 0.8), m = G(() => Q.value * l.thumbLength * 0.8), W = G(() => (t.value ? m : n).value + "px"), c = G(() => (t.value ? n : m).value + "px"), s = G(() => Q.value * 0.1 + "px"), N = G(() => (V.value - m.value) * (a.value - l.min) / (l.max - l.min) + "px"), J = G(() => t.value ? "90deg" : "0deg"), p = x(!1), M = x(0), y = (i) => {
|
|
344
344
|
if (!U.value) return a.value;
|
|
345
345
|
const z = U.value.getBoundingClientRect(), P = i.touches ? i.touches[0].clientX : i.clientX, B = i.touches ? i.touches[0].clientY : i.clientY;
|
|
346
346
|
let S;
|
|
@@ -353,7 +353,7 @@ const g = (d, l) => {
|
|
|
353
353
|
}
|
|
354
354
|
const T = l.min + S * (l.max - l.min);
|
|
355
355
|
return l.step > 0 ? Math.round(T / l.step) * l.step : T;
|
|
356
|
-
},
|
|
356
|
+
}, u = (i) => {
|
|
357
357
|
i.preventDefault(), p.value = !0, M.value = a.value, a.value = y(i), U.value && U.value.setPointerCapture && U.value.setPointerCapture(i.pointerId), document.addEventListener("mousemove", k), document.addEventListener("mouseup", E);
|
|
358
358
|
}, k = (i) => {
|
|
359
359
|
p.value && (i.preventDefault(), a.value = y(i));
|
|
@@ -377,12 +377,12 @@ const g = (d, l) => {
|
|
|
377
377
|
class: L(R.value),
|
|
378
378
|
ref_key: "root",
|
|
379
379
|
ref: U,
|
|
380
|
-
onMousedown:
|
|
380
|
+
onMousedown: u,
|
|
381
381
|
onTouchstart: H,
|
|
382
382
|
style: { userSelect: "none", touchAction: "none" }
|
|
383
383
|
}, [
|
|
384
384
|
z[0] || (z[0] = h("div", { class: "track" }, null, -1)),
|
|
385
|
-
d.showLevel ? (X(), Y("div",
|
|
385
|
+
d.showLevel ? (X(), Y("div", GU, [
|
|
386
386
|
(X(), Y(al, null, Sl(10, (P) => h("div", {
|
|
387
387
|
class: L(["led", "led" + P])
|
|
388
388
|
}, [
|
|
@@ -407,16 +407,16 @@ const g = (d, l) => {
|
|
|
407
407
|
},
|
|
408
408
|
setup(d) {
|
|
409
409
|
$((t) => ({
|
|
410
|
-
"5fddb56d":
|
|
410
|
+
"5fddb56d": V.value
|
|
411
411
|
}));
|
|
412
|
-
const l = O("el"), { width: U, height: F } = ll(l), Z =
|
|
412
|
+
const l = O("el"), { width: U, height: F } = ll(l), Z = G(() => Math.min(U.value, F.value)), Q = G(() => U.value > F.value ? "h-text" : "v-text"), V = G(() => Z.value * 3 / 4 + "px");
|
|
413
413
|
return (t, R) => (X(), Y("div", {
|
|
414
414
|
ref_key: "el",
|
|
415
415
|
ref: l,
|
|
416
416
|
class: "outer"
|
|
417
417
|
}, [
|
|
418
418
|
h("div", {
|
|
419
|
-
class: L({ [
|
|
419
|
+
class: L({ [Q.value]: !0, [d.align]: !0 })
|
|
420
420
|
}, [
|
|
421
421
|
Vl(t.$slots, "default", {}, void 0, !0)
|
|
422
422
|
], 2)
|
|
@@ -432,7 +432,7 @@ const g = (d, l) => {
|
|
|
432
432
|
},
|
|
433
433
|
emits: ["update:mute", "update:solo"],
|
|
434
434
|
setup(d) {
|
|
435
|
-
const l = _(d, "mute"), U = _(d, "solo"), F = O("outer"), { width: Z, height:
|
|
435
|
+
const l = _(d, "mute"), U = _(d, "solo"), F = O("outer"), { width: Z, height: Q } = ll(F), V = G(() => Z.value > Q.value * 1.9);
|
|
436
436
|
function t() {
|
|
437
437
|
l.value = !l.value, U.value = !1;
|
|
438
438
|
}
|
|
@@ -451,7 +451,7 @@ const g = (d, l) => {
|
|
|
451
451
|
h("div", {
|
|
452
452
|
class: "s-label",
|
|
453
453
|
onClick: R
|
|
454
|
-
}, K(
|
|
454
|
+
}, K(V.value ? "SOLO" : "S"), 1),
|
|
455
455
|
h("div", {
|
|
456
456
|
class: L(["mute", { on: l.value }]),
|
|
457
457
|
onClick: t
|
|
@@ -459,10 +459,10 @@ const g = (d, l) => {
|
|
|
459
459
|
h("div", {
|
|
460
460
|
class: "m-label",
|
|
461
461
|
onClick: t
|
|
462
|
-
}, K(
|
|
462
|
+
}, K(V.value ? "MUTE" : "M"), 1)
|
|
463
463
|
], 512));
|
|
464
464
|
}
|
|
465
|
-
}, XU = /* @__PURE__ */ g(oU, [["__scopeId", "data-v-143eade0"]]),
|
|
465
|
+
}, XU = /* @__PURE__ */ g(oU, [["__scopeId", "data-v-143eade0"]]), Gl = {
|
|
466
466
|
// Enable development UI features (animations, random data, etc.)
|
|
467
467
|
enabled: !1,
|
|
468
468
|
// Specific feature flags
|
|
@@ -474,7 +474,7 @@ const g = (d, l) => {
|
|
|
474
474
|
// Enable other debug/dev features as needed
|
|
475
475
|
debugMode: !1
|
|
476
476
|
}
|
|
477
|
-
}, kF = () =>
|
|
477
|
+
}, kF = () => Gl.enabled, Ol = (d) => Gl.enabled && Gl.features[d], Ul = sl("audioState", {
|
|
478
478
|
state: () => ({
|
|
479
479
|
// Playback state
|
|
480
480
|
isPlaying: !1,
|
|
@@ -883,14 +883,14 @@ class Nl {
|
|
|
883
883
|
console.warn("Metronome buffer not available");
|
|
884
884
|
return;
|
|
885
885
|
}
|
|
886
|
-
const
|
|
887
|
-
|
|
888
|
-
const
|
|
889
|
-
|
|
886
|
+
const Q = this.audioContext.createBufferSource();
|
|
887
|
+
Q.buffer = Z;
|
|
888
|
+
const V = this.audioContext.createGain();
|
|
889
|
+
V.gain.value = F, Q.connect(V);
|
|
890
890
|
const t = this.getMetronomeOutput();
|
|
891
|
-
t ?
|
|
891
|
+
t ? V.connect(t) : V.connect(this.audioContext.destination);
|
|
892
892
|
const R = Math.max(l, this.audioContext.currentTime);
|
|
893
|
-
|
|
893
|
+
Q.start(R);
|
|
894
894
|
} catch (Z) {
|
|
895
895
|
console.warn("Buffer metronome playback failed:", Z);
|
|
896
896
|
}
|
|
@@ -917,11 +917,11 @@ class Nl {
|
|
|
917
917
|
]), [F, Z] = await Promise.all([
|
|
918
918
|
l.arrayBuffer(),
|
|
919
919
|
U.arrayBuffer()
|
|
920
|
-
]), [
|
|
920
|
+
]), [Q, V] = await Promise.all([
|
|
921
921
|
this.audioContext.decodeAudioData(F),
|
|
922
922
|
this.audioContext.decodeAudioData(Z)
|
|
923
923
|
]);
|
|
924
|
-
this.regularTickBuffer =
|
|
924
|
+
this.regularTickBuffer = Q, this.accentTickBuffer = V;
|
|
925
925
|
return;
|
|
926
926
|
}
|
|
927
927
|
} catch (l) {
|
|
@@ -1014,20 +1014,20 @@ class pl {
|
|
|
1014
1014
|
*/
|
|
1015
1015
|
playNote(l, U, F, Z) {
|
|
1016
1016
|
this._validateActive();
|
|
1017
|
-
const
|
|
1017
|
+
const Q = this.engine.audioContext.currentTime, V = `${this.partId}_${l}_${U}_${Date.now()}`;
|
|
1018
1018
|
let t = l, R = Z;
|
|
1019
|
-
if (l <
|
|
1020
|
-
const c =
|
|
1021
|
-
t =
|
|
1019
|
+
if (l < Q) {
|
|
1020
|
+
const c = Q - l;
|
|
1021
|
+
t = Q, R = Math.max(0, Z - c);
|
|
1022
1022
|
}
|
|
1023
1023
|
if (R <= 0)
|
|
1024
|
-
return
|
|
1025
|
-
const a = Math.max(0, (t -
|
|
1026
|
-
this.noteOn(U, F), this.scheduledEvents.delete(`${
|
|
1027
|
-
}, a), m = a + R * 1e3,
|
|
1028
|
-
this.noteOff(U), this.scheduledEvents.delete(`${
|
|
1024
|
+
return V;
|
|
1025
|
+
const a = Math.max(0, (t - Q) * 1e3), n = setTimeout(() => {
|
|
1026
|
+
this.noteOn(U, F), this.scheduledEvents.delete(`${V}_on`);
|
|
1027
|
+
}, a), m = a + R * 1e3, W = setTimeout(() => {
|
|
1028
|
+
this.noteOff(U), this.scheduledEvents.delete(`${V}_off`);
|
|
1029
1029
|
}, m);
|
|
1030
|
-
return this.scheduledEvents.set(`${
|
|
1030
|
+
return this.scheduledEvents.set(`${V}_on`, n), this.scheduledEvents.set(`${V}_off`, W), V;
|
|
1031
1031
|
}
|
|
1032
1032
|
/**
|
|
1033
1033
|
* Play a preview note (for pitch reference before singing)
|
|
@@ -1040,10 +1040,10 @@ class pl {
|
|
|
1040
1040
|
*/
|
|
1041
1041
|
playPreviewNote(l, U = {}) {
|
|
1042
1042
|
this._validateActive();
|
|
1043
|
-
const F = U.startTime ?? this.engine.audioContext.currentTime + 0.01, Z = U.duration ?? 0.5,
|
|
1044
|
-
let
|
|
1045
|
-
U.instrument !== void 0 && (
|
|
1046
|
-
this.isDestroyed || this.setInstrument(
|
|
1043
|
+
const F = U.startTime ?? this.engine.audioContext.currentTime + 0.01, Z = U.duration ?? 0.5, Q = U.velocity ?? 100;
|
|
1044
|
+
let V = null;
|
|
1045
|
+
U.instrument !== void 0 && (V = this.getInstrument(), this.setInstrument(U.instrument)), this.playNote(F, l, Q, Z), V !== null && setTimeout(() => {
|
|
1046
|
+
this.isDestroyed || this.setInstrument(V);
|
|
1047
1047
|
}, (Z + 0.1) * 1e3);
|
|
1048
1048
|
}
|
|
1049
1049
|
/**
|
|
@@ -1390,10 +1390,10 @@ class kU extends pl {
|
|
|
1390
1390
|
*/
|
|
1391
1391
|
playNote(l, U, F, Z) {
|
|
1392
1392
|
this._validateActive();
|
|
1393
|
-
const
|
|
1394
|
-
if (
|
|
1393
|
+
const Q = `${this.partId}_${l}_${U}_${Date.now()}`, V = this.engine._getSynthesizer();
|
|
1394
|
+
if (V && V.post) {
|
|
1395
1395
|
const t = Math.round(F * this.currentVolume);
|
|
1396
|
-
|
|
1396
|
+
V.post({
|
|
1397
1397
|
channelNumber: this.midiChannel,
|
|
1398
1398
|
type: "midiMessage",
|
|
1399
1399
|
data: {
|
|
@@ -1405,7 +1405,7 @@ class kU extends pl {
|
|
|
1405
1405
|
// SpessaSynth will schedule this precisely!
|
|
1406
1406
|
}
|
|
1407
1407
|
}
|
|
1408
|
-
}),
|
|
1408
|
+
}), V.post({
|
|
1409
1409
|
channelNumber: this.midiChannel,
|
|
1410
1410
|
type: "midiMessage",
|
|
1411
1411
|
data: {
|
|
@@ -1420,7 +1420,7 @@ class kU extends pl {
|
|
|
1420
1420
|
});
|
|
1421
1421
|
} else
|
|
1422
1422
|
return super.playNote(l, U, F, Z);
|
|
1423
|
-
return
|
|
1423
|
+
return Q;
|
|
1424
1424
|
}
|
|
1425
1425
|
/**
|
|
1426
1426
|
* Override allNotesOff to use SpessaSynth messaging system
|
|
@@ -1591,21 +1591,21 @@ class rU extends Nl {
|
|
|
1591
1591
|
const F = U.headers.get("content-length"), Z = F ? parseInt(F, 10) : null;
|
|
1592
1592
|
if (!Z || !U.body)
|
|
1593
1593
|
return await U.arrayBuffer();
|
|
1594
|
-
const
|
|
1595
|
-
let
|
|
1594
|
+
const Q = U.body.getReader();
|
|
1595
|
+
let V = 0;
|
|
1596
1596
|
const t = [];
|
|
1597
1597
|
for (; ; ) {
|
|
1598
|
-
const { done: n, value: m } = await
|
|
1598
|
+
const { done: n, value: m } = await Q.read();
|
|
1599
1599
|
if (n) break;
|
|
1600
|
-
t.push(m),
|
|
1601
|
-
const
|
|
1600
|
+
t.push(m), V += m.length;
|
|
1601
|
+
const W = V / Z, c = Math.round(W * 100);
|
|
1602
1602
|
this._emitProgress(
|
|
1603
1603
|
"loading-soundfont",
|
|
1604
|
-
`Downloading soundfont: ${c}% (${Math.round(
|
|
1605
|
-
|
|
1604
|
+
`Downloading soundfont: ${c}% (${Math.round(V / 1024)} KB / ${Math.round(Z / 1024)} KB)`,
|
|
1605
|
+
W
|
|
1606
1606
|
);
|
|
1607
1607
|
}
|
|
1608
|
-
const R = new Uint8Array(
|
|
1608
|
+
const R = new Uint8Array(V);
|
|
1609
1609
|
let a = 0;
|
|
1610
1610
|
for (const n of t)
|
|
1611
1611
|
R.set(n, a), a += n.length;
|
|
@@ -1653,15 +1653,15 @@ class rU extends Nl {
|
|
|
1653
1653
|
*/
|
|
1654
1654
|
async playMetronomeTick(l, U, F) {
|
|
1655
1655
|
try {
|
|
1656
|
-
const Z = this.getMetronomeChannel(),
|
|
1657
|
-
if (!Z || !
|
|
1656
|
+
const Z = this.getMetronomeChannel(), Q = this._getSynthesizer();
|
|
1657
|
+
if (!Z || !Q)
|
|
1658
1658
|
return super.playMetronomeTick(l, U, F);
|
|
1659
|
-
const
|
|
1660
|
-
|
|
1661
|
-
channelNumber:
|
|
1659
|
+
const V = 15, t = U ? 86 : 60, R = Math.round(Math.min(127, Math.max(0, F * (U ? 127 : 100)))), a = this.audioContext.currentTime, n = Math.max(l, a), m = n - a;
|
|
1660
|
+
Q.post ? (Q.post({
|
|
1661
|
+
channelNumber: V,
|
|
1662
1662
|
type: "midiMessage",
|
|
1663
1663
|
data: {
|
|
1664
|
-
messageData: [144 |
|
|
1664
|
+
messageData: [144 | V, t, R],
|
|
1665
1665
|
channelOffset: 0,
|
|
1666
1666
|
force: !1,
|
|
1667
1667
|
options: {
|
|
@@ -1669,11 +1669,11 @@ class rU extends Nl {
|
|
|
1669
1669
|
// Sample-accurate metronome timing!
|
|
1670
1670
|
}
|
|
1671
1671
|
}
|
|
1672
|
-
}),
|
|
1673
|
-
channelNumber:
|
|
1672
|
+
}), Q.post({
|
|
1673
|
+
channelNumber: V,
|
|
1674
1674
|
type: "midiMessage",
|
|
1675
1675
|
data: {
|
|
1676
|
-
messageData: [128 |
|
|
1676
|
+
messageData: [128 | V, t, 0],
|
|
1677
1677
|
channelOffset: 0,
|
|
1678
1678
|
force: !1,
|
|
1679
1679
|
options: {
|
|
@@ -1681,11 +1681,11 @@ class rU extends Nl {
|
|
|
1681
1681
|
// Precise tick duration!
|
|
1682
1682
|
}
|
|
1683
1683
|
}
|
|
1684
|
-
})) : m <= 0.01 ? (
|
|
1685
|
-
|
|
1684
|
+
})) : m <= 0.01 ? (Q.noteOn && Q.noteOn(V, t, R), setTimeout(() => {
|
|
1685
|
+
Q.noteOff && Q.noteOff(V, t);
|
|
1686
1686
|
}, 100)) : setTimeout(() => {
|
|
1687
|
-
|
|
1688
|
-
|
|
1687
|
+
Q.noteOn && Q.noteOn(V, t, R), setTimeout(() => {
|
|
1688
|
+
Q.noteOff && Q.noteOff(V, t);
|
|
1689
1689
|
}, 100);
|
|
1690
1690
|
}, m * 1e3);
|
|
1691
1691
|
} catch (Z) {
|
|
@@ -1768,19 +1768,19 @@ class LU {
|
|
|
1768
1768
|
* Parses URL query parameters (track, prog) from legacy format
|
|
1769
1769
|
* @private
|
|
1770
1770
|
* @param {Array} legacyParts - Array of part objects with url, name, volume
|
|
1771
|
-
* @returns {Object} Parts object with
|
|
1771
|
+
* @returns {Object} Parts object with channel and instrument
|
|
1772
1772
|
*/
|
|
1773
1773
|
_convertLegacyParts(l) {
|
|
1774
1774
|
const U = {};
|
|
1775
1775
|
for (const F of l) {
|
|
1776
1776
|
if (!F.name || !F.url)
|
|
1777
1777
|
continue;
|
|
1778
|
-
const Z = F.name.toLowerCase(),
|
|
1779
|
-
if (
|
|
1780
|
-
const t = parseInt(
|
|
1781
|
-
t !== 0 && (
|
|
1778
|
+
const Z = F.name.toLowerCase(), Q = this._parseUrlParams(F.url), V = {};
|
|
1779
|
+
if (Q.track !== void 0 && (V.channel = parseInt(Q.track, 10)), Q.prog !== void 0) {
|
|
1780
|
+
const t = parseInt(Q.prog, 10);
|
|
1781
|
+
t !== 0 && (V.instrument = t);
|
|
1782
1782
|
}
|
|
1783
|
-
|
|
1783
|
+
V.channel !== void 0 && (U[Z] = V);
|
|
1784
1784
|
}
|
|
1785
1785
|
return U;
|
|
1786
1786
|
}
|
|
@@ -1795,9 +1795,9 @@ class LU {
|
|
|
1795
1795
|
if (F === -1)
|
|
1796
1796
|
return U;
|
|
1797
1797
|
const Z = l.substring(F + 1).split("&");
|
|
1798
|
-
for (const
|
|
1799
|
-
const [
|
|
1800
|
-
|
|
1798
|
+
for (const Q of Z) {
|
|
1799
|
+
const [V, t] = Q.split("=");
|
|
1800
|
+
V && t !== void 0 && (U[V] = t);
|
|
1801
1801
|
}
|
|
1802
1802
|
return U;
|
|
1803
1803
|
}
|
|
@@ -1809,16 +1809,16 @@ class LU {
|
|
|
1809
1809
|
const U = new Uint8Array(l);
|
|
1810
1810
|
if (!(U[0] === 77 && U[1] === 84 && U[2] === 104 && U[3] === 100))
|
|
1811
1811
|
throw new Error("Not a valid MIDI file");
|
|
1812
|
-
const F = this._bytesToNumber(U.slice(4, 8)), Z = this._bytesToNumber(U.slice(8, 10)),
|
|
1812
|
+
const F = this._bytesToNumber(U.slice(4, 8)), Z = this._bytesToNumber(U.slice(8, 10)), Q = this._bytesToNumber(U.slice(10, 12)), V = this._bytesToNumber(U.slice(12, 14)), t = V & 32768 ? null : V, R = {
|
|
1813
1813
|
format: Z,
|
|
1814
1814
|
ticksPerBeat: t,
|
|
1815
1815
|
tracks: [],
|
|
1816
1816
|
duration: 0
|
|
1817
1817
|
};
|
|
1818
1818
|
let a = 8 + F;
|
|
1819
|
-
for (let n = 0; n <
|
|
1819
|
+
for (let n = 0; n < Q; n++)
|
|
1820
1820
|
if (U[a] === 77 && U[a + 1] === 84 && U[a + 2] === 114 && U[a + 3] === 107) {
|
|
1821
|
-
const m = this._bytesToNumber(U.slice(a + 4, a + 8)),
|
|
1821
|
+
const m = this._bytesToNumber(U.slice(a + 4, a + 8)), W = U.slice(a + 8, a + 8 + m), c = this._parseTrack(W);
|
|
1822
1822
|
R.tracks.push(c), a += 8 + m;
|
|
1823
1823
|
} else
|
|
1824
1824
|
throw new Error(`Invalid track header at position ${a}`);
|
|
@@ -1836,20 +1836,20 @@ class LU {
|
|
|
1836
1836
|
events: [],
|
|
1837
1837
|
duration: 0
|
|
1838
1838
|
};
|
|
1839
|
-
let F = 0, Z = 0,
|
|
1839
|
+
let F = 0, Z = 0, Q = null;
|
|
1840
1840
|
for (; F < l.length; ) {
|
|
1841
|
-
let
|
|
1841
|
+
let V = 0, t = 0;
|
|
1842
1842
|
do
|
|
1843
|
-
t = l[F++],
|
|
1843
|
+
t = l[F++], V = V << 7 | t & 127;
|
|
1844
1844
|
while (t & 128);
|
|
1845
|
-
Z +=
|
|
1845
|
+
Z += V, t = l[F++];
|
|
1846
1846
|
let R = t;
|
|
1847
1847
|
if (t & 128)
|
|
1848
|
-
|
|
1848
|
+
Q = R;
|
|
1849
1849
|
else {
|
|
1850
|
-
if (
|
|
1850
|
+
if (Q === null)
|
|
1851
1851
|
throw new Error("Running status byte encountered before status byte");
|
|
1852
|
-
R =
|
|
1852
|
+
R = Q, F--;
|
|
1853
1853
|
}
|
|
1854
1854
|
if (R === 255) {
|
|
1855
1855
|
const a = l[F++], n = this._readVariableLengthValue(l, F);
|
|
@@ -1873,7 +1873,7 @@ class LU {
|
|
|
1873
1873
|
});
|
|
1874
1874
|
break;
|
|
1875
1875
|
case 81:
|
|
1876
|
-
const
|
|
1876
|
+
const W = this._bytesToNumber(m), c = Math.round(6e7 / W);
|
|
1877
1877
|
U.events.push({
|
|
1878
1878
|
type: "tempo",
|
|
1879
1879
|
bpm: c,
|
|
@@ -1977,13 +1977,13 @@ class LU {
|
|
|
1977
1977
|
ticksPerBeat: l.ticksPerBeat
|
|
1978
1978
|
};
|
|
1979
1979
|
l.tracks.forEach((F, Z) => {
|
|
1980
|
-
if (F.name && !U.title && (U.title = F.name), F.events.filter((
|
|
1981
|
-
const
|
|
1982
|
-
(
|
|
1980
|
+
if (F.name && !U.title && (U.title = F.name), F.events.filter((Q) => Q.type === "text").forEach((Q) => {
|
|
1981
|
+
const V = Q.text.toLowerCase();
|
|
1982
|
+
(V.includes("compos") || V.includes("by")) && !U.composer && (U.composer = Q.text);
|
|
1983
1983
|
}), F.name) {
|
|
1984
|
-
const
|
|
1985
|
-
for (const
|
|
1986
|
-
if (
|
|
1984
|
+
const Q = F.name.toLowerCase();
|
|
1985
|
+
for (const V of this.partNames)
|
|
1986
|
+
if (Q.includes(V)) {
|
|
1987
1987
|
U.partNames.push({
|
|
1988
1988
|
index: Z,
|
|
1989
1989
|
name: F.name
|
|
@@ -2013,24 +2013,24 @@ class LU {
|
|
|
2013
2013
|
m.type === "noteOff" && m.tick > Z && (Z = m.tick);
|
|
2014
2014
|
});
|
|
2015
2015
|
}), Z === 0 && (Z = U * 8);
|
|
2016
|
-
const
|
|
2016
|
+
const Q = [], V = F.filter((n) => n.type === "timeSignature").sort((n, m) => n.tick - m.tick);
|
|
2017
2017
|
let t = { numerator: 4, denominator: 4 }, R = 0, a = 0;
|
|
2018
2018
|
for (; R < Z; ) {
|
|
2019
|
-
for (; a <
|
|
2020
|
-
t =
|
|
2019
|
+
for (; a < V.length && V[a].tick <= R; )
|
|
2020
|
+
t = V[a], a++;
|
|
2021
2021
|
let n;
|
|
2022
2022
|
n = R + U * 4 * t.numerator / t.denominator;
|
|
2023
|
-
const m = t.numerator,
|
|
2023
|
+
const m = t.numerator, W = [], c = U * (4 / t.denominator);
|
|
2024
2024
|
for (let s = 0; s < m; s++) {
|
|
2025
2025
|
const N = R + s * c, J = this._ticksToTime(N, l);
|
|
2026
|
-
|
|
2026
|
+
W.push(J);
|
|
2027
2027
|
}
|
|
2028
|
-
|
|
2028
|
+
Q.push({
|
|
2029
2029
|
sig: [t.numerator, t.denominator],
|
|
2030
|
-
beats:
|
|
2030
|
+
beats: W
|
|
2031
2031
|
}), R = n;
|
|
2032
2032
|
}
|
|
2033
|
-
this.parsedData.barStructure =
|
|
2033
|
+
this.parsedData.barStructure = Q;
|
|
2034
2034
|
}
|
|
2035
2035
|
/**
|
|
2036
2036
|
* Extract notes for each voice part
|
|
@@ -2039,71 +2039,156 @@ class LU {
|
|
|
2039
2039
|
_extractParts(l) {
|
|
2040
2040
|
const U = {}, F = l.ticksPerBeat;
|
|
2041
2041
|
if (this.metadataOverrides.parts)
|
|
2042
|
-
for (const [Z,
|
|
2043
|
-
if (
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2042
|
+
for (const [Z, Q] of Object.entries(this.metadataOverrides.parts)) {
|
|
2043
|
+
if (Q.channel !== void 0 && Q.channel !== null) {
|
|
2044
|
+
if (Q.channel === 15) {
|
|
2045
|
+
console.error(`Part "${Z}" uses channel 15 which is reserved for metronome. Skipping.`);
|
|
2046
|
+
continue;
|
|
2047
|
+
}
|
|
2048
|
+
if (Q.channel === 9 && console.warn(`Part "${Z}" uses channel 9 (drums/percussion). This may not be appropriate for vocal parts.`), Q.channel < 0 || Q.channel > 15) {
|
|
2049
|
+
console.error(`Part "${Z}" has invalid channel ${Q.channel}. MIDI channels must be 0-15. Skipping.`);
|
|
2050
|
+
continue;
|
|
2051
|
+
}
|
|
2051
2052
|
}
|
|
2052
|
-
if (!Q)
|
|
2053
|
+
if (Q.channel === void 0 && !Q.trackIndex && Q.trackIndex !== 0 && !Q.trackName)
|
|
2053
2054
|
continue;
|
|
2054
|
-
|
|
2055
|
-
|
|
2055
|
+
let V;
|
|
2056
|
+
if (Q.channel !== void 0 && Q.channel !== null) {
|
|
2057
|
+
if (V = this._extractPartDataByChannel(Q.channel, l, F), !V || V.notes.length === 0) {
|
|
2058
|
+
console.warn(`Part "${Z}" specified channel ${Q.channel} but no notes found on that channel. Skipping.`);
|
|
2059
|
+
continue;
|
|
2060
|
+
}
|
|
2061
|
+
} else if (Q.trackIndex !== void 0 && Q.trackIndex !== null) {
|
|
2062
|
+
const t = Q.trackIndex;
|
|
2063
|
+
if (t >= 0 && t < l.tracks.length) {
|
|
2064
|
+
const R = l.tracks[t];
|
|
2065
|
+
V = this._extractPartDataFromTrack(R, t, l, F);
|
|
2066
|
+
} else {
|
|
2067
|
+
console.warn(`Part "${Z}" specified trackIndex ${t} but track not found. Skipping.`);
|
|
2068
|
+
continue;
|
|
2069
|
+
}
|
|
2070
|
+
} else if (Q.trackName) {
|
|
2071
|
+
const t = l.tracks.findIndex((R) => R.name === Q.trackName);
|
|
2072
|
+
if (t !== -1) {
|
|
2073
|
+
const R = l.tracks[t];
|
|
2074
|
+
V = this._extractPartDataFromTrack(R, t, l, F);
|
|
2075
|
+
} else {
|
|
2076
|
+
console.warn(`Part "${Z}" specified trackName "${Q.trackName}" but track not found. Skipping.`);
|
|
2077
|
+
continue;
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
V && (Q.instrument !== void 0 && Q.instrument !== null && (V.defaultInstrument = this._resolveInstrument(Q.instrument)), U[Z] = V);
|
|
2056
2081
|
}
|
|
2057
2082
|
else
|
|
2058
|
-
l.tracks.forEach((Z,
|
|
2083
|
+
l.tracks.forEach((Z, Q) => {
|
|
2059
2084
|
if (!Z.notes.length) return;
|
|
2060
|
-
let
|
|
2085
|
+
let V = null;
|
|
2061
2086
|
if (Z.name) {
|
|
2062
2087
|
const a = Z.name.toLowerCase();
|
|
2063
2088
|
for (const n of this.partNames)
|
|
2064
2089
|
if (n.length === 1) {
|
|
2065
2090
|
if (a === n) {
|
|
2066
|
-
|
|
2091
|
+
V = n;
|
|
2067
2092
|
break;
|
|
2068
2093
|
}
|
|
2069
2094
|
} else if (a.includes(n)) {
|
|
2070
|
-
|
|
2095
|
+
V = n;
|
|
2071
2096
|
break;
|
|
2072
2097
|
}
|
|
2073
2098
|
}
|
|
2074
|
-
|
|
2075
|
-
let t =
|
|
2099
|
+
V || (V = Z.name || `Track ${Q + 1}`), V === "s" && (V = "soprano"), V === "a" && (V = "alto"), V === "t" && (V = "tenor"), V === "b" && (V = "bass");
|
|
2100
|
+
let t = V, R = 2;
|
|
2076
2101
|
for (; U[t]; )
|
|
2077
|
-
t = `${
|
|
2078
|
-
|
|
2102
|
+
t = `${V} ${R}`, R++;
|
|
2103
|
+
V = t, U[V] = this._extractPartDataFromTrack(Z, Q, l, F);
|
|
2079
2104
|
});
|
|
2080
2105
|
this.parsedData.parts = U;
|
|
2081
2106
|
}
|
|
2107
|
+
/**
|
|
2108
|
+
* Extract part data by MIDI channel (merges notes from all tracks using this channel)
|
|
2109
|
+
* @private
|
|
2110
|
+
*/
|
|
2111
|
+
_extractPartDataByChannel(l, U, F) {
|
|
2112
|
+
const Z = [], Q = [], V = [], t = [];
|
|
2113
|
+
U.tracks.forEach((a, n) => {
|
|
2114
|
+
const m = {};
|
|
2115
|
+
a.notes.forEach((W) => {
|
|
2116
|
+
if (W.channel === l) {
|
|
2117
|
+
if (W.type === "noteOn")
|
|
2118
|
+
m[W.noteNumber] = {
|
|
2119
|
+
tick: W.tick,
|
|
2120
|
+
velocity: W.velocity
|
|
2121
|
+
};
|
|
2122
|
+
else if (W.type === "noteOff" && m[W.noteNumber]) {
|
|
2123
|
+
const c = m[W.noteNumber], s = W.tick - c.tick;
|
|
2124
|
+
Z.push({
|
|
2125
|
+
pitch: W.noteNumber,
|
|
2126
|
+
name: this._midiNoteToName(W.noteNumber),
|
|
2127
|
+
startTick: c.tick,
|
|
2128
|
+
endTick: W.tick,
|
|
2129
|
+
duration: s,
|
|
2130
|
+
startTime: this._ticksToTime(c.tick, U),
|
|
2131
|
+
endTime: this._ticksToTime(W.tick, U),
|
|
2132
|
+
velocity: c.velocity,
|
|
2133
|
+
channel: l,
|
|
2134
|
+
sourceTrackIndex: n
|
|
2135
|
+
}), delete m[W.noteNumber];
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
}), a.lyrics.forEach((W) => {
|
|
2139
|
+
Q.push({
|
|
2140
|
+
text: W.text,
|
|
2141
|
+
tick: W.tick,
|
|
2142
|
+
time: W.tick / F
|
|
2143
|
+
});
|
|
2144
|
+
}), a.events.filter((W) => W.type === "programChange" && W.channel === l).forEach((W) => {
|
|
2145
|
+
V.push({
|
|
2146
|
+
programNumber: W.programNumber,
|
|
2147
|
+
tick: W.tick,
|
|
2148
|
+
time: this._ticksToTime(W.tick, U),
|
|
2149
|
+
sourceTrackIndex: n
|
|
2150
|
+
});
|
|
2151
|
+
}), a.notes.some((W) => W.channel === l) && t.push(n);
|
|
2152
|
+
}), Z.sort((a, n) => a.startTick - n.startTick), Q.sort((a, n) => a.tick - n.tick), V.sort((a, n) => a.tick - n.tick);
|
|
2153
|
+
const R = V.length > 0 ? V[0].programNumber : 0;
|
|
2154
|
+
return {
|
|
2155
|
+
notes: Z,
|
|
2156
|
+
lyrics: Q,
|
|
2157
|
+
channel: l,
|
|
2158
|
+
trackIndices: t,
|
|
2159
|
+
// All track indices that contributed
|
|
2160
|
+
programChanges: V,
|
|
2161
|
+
defaultInstrument: R
|
|
2162
|
+
};
|
|
2163
|
+
}
|
|
2082
2164
|
/**
|
|
2083
2165
|
* Extract part data from a MIDI track
|
|
2084
2166
|
* @private
|
|
2085
2167
|
*/
|
|
2086
2168
|
_extractPartDataFromTrack(l, U, F, Z) {
|
|
2087
|
-
const
|
|
2169
|
+
const Q = [], V = {};
|
|
2088
2170
|
l.notes.forEach((n) => {
|
|
2089
2171
|
if (n.type === "noteOn")
|
|
2090
|
-
|
|
2172
|
+
V[n.noteNumber] = {
|
|
2091
2173
|
tick: n.tick,
|
|
2092
|
-
velocity: n.velocity
|
|
2174
|
+
velocity: n.velocity,
|
|
2175
|
+
channel: n.channel
|
|
2093
2176
|
};
|
|
2094
|
-
else if (n.type === "noteOff" &&
|
|
2095
|
-
const m =
|
|
2096
|
-
|
|
2177
|
+
else if (n.type === "noteOff" && V[n.noteNumber]) {
|
|
2178
|
+
const m = V[n.noteNumber], W = n.tick - m.tick;
|
|
2179
|
+
Q.push({
|
|
2097
2180
|
pitch: n.noteNumber,
|
|
2098
2181
|
name: this._midiNoteToName(n.noteNumber),
|
|
2099
2182
|
startTick: m.tick,
|
|
2100
2183
|
endTick: n.tick,
|
|
2101
|
-
duration:
|
|
2184
|
+
duration: W,
|
|
2102
2185
|
// Convert ticks to actual time considering tempo changes
|
|
2103
2186
|
startTime: this._ticksToTime(m.tick, F),
|
|
2104
2187
|
endTime: this._ticksToTime(n.tick, F),
|
|
2105
|
-
velocity: m.velocity
|
|
2106
|
-
|
|
2188
|
+
velocity: m.velocity,
|
|
2189
|
+
channel: m.channel,
|
|
2190
|
+
sourceTrackIndex: U
|
|
2191
|
+
}), delete V[n.noteNumber];
|
|
2107
2192
|
}
|
|
2108
2193
|
});
|
|
2109
2194
|
const t = l.lyrics.map((n) => ({
|
|
@@ -2112,14 +2197,14 @@ class LU {
|
|
|
2112
2197
|
time: n.tick / Z
|
|
2113
2198
|
// Time in quarter notes
|
|
2114
2199
|
}));
|
|
2115
|
-
|
|
2200
|
+
Q.sort((n, m) => n.startTick - m.startTick);
|
|
2116
2201
|
const R = l.events.filter((n) => n.type === "programChange").map((n) => ({
|
|
2117
2202
|
programNumber: n.programNumber,
|
|
2118
2203
|
tick: n.tick,
|
|
2119
2204
|
time: this._ticksToTime(n.tick, F)
|
|
2120
2205
|
})).sort((n, m) => n.tick - m.tick), a = R.length > 0 ? R[0].programNumber : 0;
|
|
2121
2206
|
return {
|
|
2122
|
-
notes:
|
|
2207
|
+
notes: Q,
|
|
2123
2208
|
lyrics: t,
|
|
2124
2209
|
trackIndex: U,
|
|
2125
2210
|
programChanges: R,
|
|
@@ -2181,11 +2266,11 @@ class LU {
|
|
|
2181
2266
|
* @private
|
|
2182
2267
|
*/
|
|
2183
2268
|
_readVariableLengthValue(l, U) {
|
|
2184
|
-
let F = 0, Z,
|
|
2269
|
+
let F = 0, Z, Q = 0;
|
|
2185
2270
|
do
|
|
2186
|
-
Z = l[U +
|
|
2271
|
+
Z = l[U + Q++], F = F << 7 | Z & 127;
|
|
2187
2272
|
while (Z & 128);
|
|
2188
|
-
return { value: F, bytesRead:
|
|
2273
|
+
return { value: F, bytesRead: Q };
|
|
2189
2274
|
}
|
|
2190
2275
|
/**
|
|
2191
2276
|
* Convert ticks to time in seconds considering tempo changes within bars
|
|
@@ -2198,20 +2283,20 @@ class LU {
|
|
|
2198
2283
|
a.type === "tempo" && Z.push(a);
|
|
2199
2284
|
});
|
|
2200
2285
|
}), Z.sort((R, a) => R.tick - a.tick);
|
|
2201
|
-
let
|
|
2286
|
+
let Q = 0, V = 0, t = 120;
|
|
2202
2287
|
for (const R of Z) {
|
|
2203
2288
|
if (R.tick > l) break;
|
|
2204
|
-
if (R.tick >
|
|
2205
|
-
const a = (R.tick -
|
|
2206
|
-
|
|
2289
|
+
if (R.tick > V) {
|
|
2290
|
+
const a = (R.tick - V) / F * (60 / t);
|
|
2291
|
+
Q += a, V = R.tick;
|
|
2207
2292
|
}
|
|
2208
2293
|
t = R.bpm;
|
|
2209
2294
|
}
|
|
2210
|
-
if (l >
|
|
2211
|
-
const R = (l -
|
|
2212
|
-
|
|
2295
|
+
if (l > V) {
|
|
2296
|
+
const R = (l - V) / F * (60 / t);
|
|
2297
|
+
Q += R;
|
|
2213
2298
|
}
|
|
2214
|
-
return
|
|
2299
|
+
return Q;
|
|
2215
2300
|
}
|
|
2216
2301
|
}
|
|
2217
2302
|
class CU {
|
|
@@ -2239,18 +2324,18 @@ class CU {
|
|
|
2239
2324
|
*/
|
|
2240
2325
|
generateBarOrder(l, U) {
|
|
2241
2326
|
const F = [], Z = {};
|
|
2242
|
-
for (const
|
|
2243
|
-
const
|
|
2244
|
-
if (!
|
|
2245
|
-
throw new Error(`Invalid section index: ${
|
|
2246
|
-
const t =
|
|
2327
|
+
for (const Q of U) {
|
|
2328
|
+
const V = l[Q.section];
|
|
2329
|
+
if (!V)
|
|
2330
|
+
throw new Error(`Invalid section index: ${Q.section}`);
|
|
2331
|
+
const t = Q.section;
|
|
2247
2332
|
Z[t] || (Z[t] = 0), Z[t]++;
|
|
2248
|
-
const R = Z[t], a =
|
|
2249
|
-
for (let
|
|
2250
|
-
this._shouldPlayBar(
|
|
2251
|
-
barNumber:
|
|
2333
|
+
const R = Z[t], a = Q.from !== void 0 ? Q.from : this._getSectionStartBar(l, Q.section), n = Q.to !== void 0 ? Q.to : V.to, m = Q.as || 1;
|
|
2334
|
+
for (let W = a; W <= n; W++)
|
|
2335
|
+
this._shouldPlayBar(V, W, m) && F.push({
|
|
2336
|
+
barNumber: W,
|
|
2252
2337
|
repeat: R,
|
|
2253
|
-
sectionIndex:
|
|
2338
|
+
sectionIndex: Q.section,
|
|
2254
2339
|
voltaTime: m
|
|
2255
2340
|
});
|
|
2256
2341
|
}
|
|
@@ -2264,13 +2349,13 @@ class CU {
|
|
|
2264
2349
|
*/
|
|
2265
2350
|
generateBarOrderFromLegacyBars(l, U) {
|
|
2266
2351
|
const F = [];
|
|
2267
|
-
let Z = 1,
|
|
2352
|
+
let Z = 1, Q = 0, V;
|
|
2268
2353
|
for (const t of l) {
|
|
2269
|
-
t.from !== void 0 && (Z = t.from === -1 ? 0 : t.from,
|
|
2354
|
+
t.from !== void 0 && (Z = t.from === -1 ? 0 : t.from, Q = 0), t.timeSig !== void 0 && (V = t.timeSig);
|
|
2270
2355
|
const R = t.repeat || 1;
|
|
2271
2356
|
let a = t.beats;
|
|
2272
2357
|
for (; a > 0; ) {
|
|
2273
|
-
const n = (
|
|
2358
|
+
const n = (V !== void 0 ? V : this._getBeatsPerBar(Z, U)) - Q;
|
|
2274
2359
|
a >= n ? (F.push({
|
|
2275
2360
|
barNumber: Z,
|
|
2276
2361
|
repeat: R,
|
|
@@ -2278,10 +2363,10 @@ class CU {
|
|
|
2278
2363
|
// Legacy format doesn't have sections
|
|
2279
2364
|
voltaTime: 1
|
|
2280
2365
|
// Legacy format doesn't have voltas
|
|
2281
|
-
}), a -= n,
|
|
2366
|
+
}), a -= n, Q = 0, Z === 0 ? Z = 1 : Z++) : (Q += a, a = 0);
|
|
2282
2367
|
}
|
|
2283
2368
|
}
|
|
2284
|
-
return
|
|
2369
|
+
return Q > 0 && F.push({
|
|
2285
2370
|
barNumber: Z,
|
|
2286
2371
|
repeat: 1,
|
|
2287
2372
|
sectionIndex: 0,
|
|
@@ -2315,8 +2400,8 @@ class CU {
|
|
|
2315
2400
|
let Z;
|
|
2316
2401
|
if (F ? Z = l : Z = l - 1, Z < 0 || Z >= U.length)
|
|
2317
2402
|
return 4;
|
|
2318
|
-
const
|
|
2319
|
-
return
|
|
2403
|
+
const Q = U[Z];
|
|
2404
|
+
return Q.sig ? Q.sig[0] : 4;
|
|
2320
2405
|
}
|
|
2321
2406
|
/**
|
|
2322
2407
|
* Generate beat table from bar order and MIDI bar structure
|
|
@@ -2327,20 +2412,20 @@ class CU {
|
|
|
2327
2412
|
*/
|
|
2328
2413
|
generateBeatTable(l, U) {
|
|
2329
2414
|
const F = [], Z = {};
|
|
2330
|
-
let
|
|
2415
|
+
let Q = 0, V = 0;
|
|
2331
2416
|
const t = [...U];
|
|
2332
|
-
for (;
|
|
2333
|
-
const R = l[
|
|
2417
|
+
for (; V < l.length && Q < t.length; ) {
|
|
2418
|
+
const R = l[V], a = R.barNumber;
|
|
2334
2419
|
if (Z[a] === void 0) {
|
|
2335
|
-
const c = t[
|
|
2420
|
+
const c = t[Q];
|
|
2336
2421
|
if (!c || !c.sig)
|
|
2337
|
-
throw new Error(`Invalid MIDI bar structure at index ${
|
|
2422
|
+
throw new Error(`Invalid MIDI bar structure at index ${Q}`);
|
|
2338
2423
|
Z[a] = c.sig[0];
|
|
2339
2424
|
}
|
|
2340
2425
|
const n = Z[a];
|
|
2341
|
-
let m = t[
|
|
2342
|
-
for (;
|
|
2343
|
-
const c = t[
|
|
2426
|
+
let m = t[Q], W = m.sig[0];
|
|
2427
|
+
for (; W < n && Q + 1 < t.length; ) {
|
|
2428
|
+
const c = t[Q + 1], s = [
|
|
2344
2429
|
m.sig[0] + c.sig[0],
|
|
2345
2430
|
// Total beats
|
|
2346
2431
|
m.sig[1]
|
|
@@ -2352,31 +2437,31 @@ class CU {
|
|
|
2352
2437
|
m = {
|
|
2353
2438
|
sig: s,
|
|
2354
2439
|
beats: N
|
|
2355
|
-
}, t[
|
|
2440
|
+
}, t[Q] = m, t.splice(Q + 1, 1), W = s[0];
|
|
2356
2441
|
}
|
|
2357
|
-
if (
|
|
2358
|
-
const c = n, s =
|
|
2442
|
+
if (W > n) {
|
|
2443
|
+
const c = n, s = W - n, N = m.beats ? m.beats.slice(0, c) : [], J = m.beats ? m.beats.slice(c) : [], p = {
|
|
2359
2444
|
sig: [c, m.sig[1]],
|
|
2360
2445
|
beats: N
|
|
2361
2446
|
}, M = {
|
|
2362
2447
|
sig: [s, m.sig[1]],
|
|
2363
2448
|
beats: J
|
|
2364
2449
|
};
|
|
2365
|
-
t[
|
|
2450
|
+
t[Q] = p, t.splice(Q + 1, 0, M), m = p;
|
|
2366
2451
|
}
|
|
2367
|
-
this._generateBeatsForBar(F, R, m, n),
|
|
2452
|
+
this._generateBeatsForBar(F, R, m, n), Q++, V++;
|
|
2368
2453
|
}
|
|
2369
|
-
if (
|
|
2454
|
+
if (V < l.length) {
|
|
2370
2455
|
const R = F.length > 0 ? F[F.length - 1] : null;
|
|
2371
2456
|
let a = 0.5;
|
|
2372
2457
|
if (F.length >= 2) {
|
|
2373
|
-
const m = Math.min(8, F.length),
|
|
2374
|
-
a = (F[F.length - 1].time -
|
|
2458
|
+
const m = Math.min(8, F.length), W = F[F.length - m];
|
|
2459
|
+
a = (F[F.length - 1].time - W.time) / (m - 1);
|
|
2375
2460
|
}
|
|
2376
2461
|
let n = R ? R.time + a : 0;
|
|
2377
|
-
for (;
|
|
2378
|
-
const m = l[
|
|
2379
|
-
Z[
|
|
2462
|
+
for (; V < l.length; ) {
|
|
2463
|
+
const m = l[V], W = m.barNumber, c = Z[W] !== void 0 ? Z[W] : 4;
|
|
2464
|
+
Z[W] === void 0 && (Z[W] = c);
|
|
2380
2465
|
const s = [];
|
|
2381
2466
|
for (let J = 0; J < c; J++)
|
|
2382
2467
|
s.push(n), n += a;
|
|
@@ -2385,7 +2470,7 @@ class CU {
|
|
|
2385
2470
|
// Default to quarter notes
|
|
2386
2471
|
beats: s
|
|
2387
2472
|
};
|
|
2388
|
-
this._generateBeatsForBar(F, m, N, c),
|
|
2473
|
+
this._generateBeatsForBar(F, m, N, c), V++;
|
|
2389
2474
|
}
|
|
2390
2475
|
}
|
|
2391
2476
|
return F;
|
|
@@ -2395,13 +2480,13 @@ class CU {
|
|
|
2395
2480
|
* @private
|
|
2396
2481
|
*/
|
|
2397
2482
|
_generateBeatsForBar(l, U, F, Z) {
|
|
2398
|
-
const { beats:
|
|
2399
|
-
if (!
|
|
2483
|
+
const { beats: Q } = F;
|
|
2484
|
+
if (!Q || !Array.isArray(Q))
|
|
2400
2485
|
throw new Error(`Invalid MIDI bar: missing beats array. Got: ${JSON.stringify(F)}`);
|
|
2401
|
-
const
|
|
2486
|
+
const V = Q.slice(0, Z);
|
|
2402
2487
|
for (let t = 1; t <= Z; t++) {
|
|
2403
2488
|
const R = {
|
|
2404
|
-
time:
|
|
2489
|
+
time: V[t - 1],
|
|
2405
2490
|
repeat: U.repeat,
|
|
2406
2491
|
bar: U.barNumber,
|
|
2407
2492
|
beat: t,
|
|
@@ -2440,8 +2525,8 @@ class Jl {
|
|
|
2440
2525
|
if (!U)
|
|
2441
2526
|
throw new Error("Parsed MIDI data is required");
|
|
2442
2527
|
this.audioEngine = l, this._audioEngineReady = !!(l && l.isInitialized), this.instrumentMap = F || {}, this.parsedData = U, 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 = Xl(), this.beatMapper = new CU(), this.beats = [], this.structureMetadata = Z, this._calculateTotalDuration();
|
|
2443
|
-
const
|
|
2444
|
-
this.beats = this.beatMapper.mapBeats(U,
|
|
2528
|
+
const Q = Z || this._createDefaultStructureMetadata();
|
|
2529
|
+
this.beats = this.beatMapper.mapBeats(U, Q), this._audioEngineReady && (this._setupPartChannels(), this._resetNotePointers(), this._resetProgramPointers());
|
|
2445
2530
|
}
|
|
2446
2531
|
// ========================================
|
|
2447
2532
|
// PUBLIC API - Initialization Methods
|
|
@@ -2625,11 +2710,11 @@ class Jl {
|
|
|
2625
2710
|
*/
|
|
2626
2711
|
getAllNextNotes(l) {
|
|
2627
2712
|
const U = l ?? this.getCurrentTime(), F = {};
|
|
2628
|
-
for (const [Z,
|
|
2629
|
-
const
|
|
2630
|
-
F[Z] =
|
|
2631
|
-
pitch:
|
|
2632
|
-
startTime:
|
|
2713
|
+
for (const [Z, Q] of Object.entries(this.parsedData.parts)) {
|
|
2714
|
+
const V = Q.notes.find((t) => t.startTime >= U);
|
|
2715
|
+
F[Z] = V ? {
|
|
2716
|
+
pitch: V.pitch,
|
|
2717
|
+
startTime: V.startTime
|
|
2633
2718
|
} : null;
|
|
2634
2719
|
}
|
|
2635
2720
|
return F;
|
|
@@ -2670,17 +2755,17 @@ class Jl {
|
|
|
2670
2755
|
Object.keys(this.parsedData.parts).forEach((l) => {
|
|
2671
2756
|
const U = this.parsedData.parts[l], F = this.instrumentMap[l] || {}, Z = F.instrument !== void 0 ? F.instrument : U.defaultInstrument !== void 0 ? U.defaultInstrument : 0;
|
|
2672
2757
|
try {
|
|
2673
|
-
const
|
|
2758
|
+
const Q = this.audioEngine.createChannel(l, {
|
|
2674
2759
|
instrument: Z,
|
|
2675
2760
|
initialVolume: F.volume || 1
|
|
2676
2761
|
});
|
|
2677
|
-
this.partChannels.set(l,
|
|
2678
|
-
const
|
|
2679
|
-
|
|
2680
|
-
const t =
|
|
2681
|
-
t && t.connect(
|
|
2682
|
-
} catch (
|
|
2683
|
-
console.error(`Failed to create channel for part '${l}':`,
|
|
2762
|
+
this.partChannels.set(l, Q);
|
|
2763
|
+
const V = this.audioEngine.audioContext.createGain();
|
|
2764
|
+
V.gain.value = 1;
|
|
2765
|
+
const t = Q.getOutputNode();
|
|
2766
|
+
t && t.connect(V), this.partOutputs.set(l, V);
|
|
2767
|
+
} catch (Q) {
|
|
2768
|
+
console.error(`Failed to create channel for part '${l}':`, Q), this._emitEvent("error", Q);
|
|
2684
2769
|
}
|
|
2685
2770
|
});
|
|
2686
2771
|
}
|
|
@@ -2712,33 +2797,33 @@ class Jl {
|
|
|
2712
2797
|
if (!this._isPlaying) return;
|
|
2713
2798
|
const l = (this.audioEngine.audioContext.currentTime - this.playbackStartTime) * this.playbackSpeed, U = l + this.lookAheadTime;
|
|
2714
2799
|
for (const [F, Z] of this.partChannels) {
|
|
2715
|
-
const
|
|
2716
|
-
if (
|
|
2717
|
-
if (
|
|
2718
|
-
let
|
|
2719
|
-
const t =
|
|
2720
|
-
for (;
|
|
2721
|
-
|
|
2722
|
-
for (;
|
|
2723
|
-
const R = t[
|
|
2724
|
-
Z.setInstrument(R.programNumber),
|
|
2800
|
+
const Q = this.parsedData.parts[F];
|
|
2801
|
+
if (Q) {
|
|
2802
|
+
if (Q.programChanges && Q.programChanges.length > 0) {
|
|
2803
|
+
let V = this.partProgramPointers.get(F) || 0;
|
|
2804
|
+
const t = Q.programChanges;
|
|
2805
|
+
for (; V < t.length && t[V].time < l; )
|
|
2806
|
+
V++;
|
|
2807
|
+
for (; V < t.length && t[V].time <= U; ) {
|
|
2808
|
+
const R = t[V];
|
|
2809
|
+
Z.setInstrument(R.programNumber), V++;
|
|
2725
2810
|
}
|
|
2726
|
-
this.partProgramPointers.set(F,
|
|
2811
|
+
this.partProgramPointers.set(F, V);
|
|
2727
2812
|
}
|
|
2728
|
-
if (
|
|
2729
|
-
let
|
|
2730
|
-
const t =
|
|
2731
|
-
for (;
|
|
2732
|
-
|
|
2733
|
-
for (;
|
|
2734
|
-
const R = t[
|
|
2813
|
+
if (Q.notes) {
|
|
2814
|
+
let V = this.partNotePointers.get(F) || 0;
|
|
2815
|
+
const t = Q.notes;
|
|
2816
|
+
for (; V < t.length && t[V].endTime < l; )
|
|
2817
|
+
V++;
|
|
2818
|
+
for (; V < t.length && t[V].startTime <= U; ) {
|
|
2819
|
+
const R = t[V];
|
|
2735
2820
|
if (R.endTime - R.startTime >= 0.01) {
|
|
2736
2821
|
const a = this.playbackStartTime + R.startTime / this.playbackSpeed, n = (R.endTime - R.startTime) / this.playbackSpeed;
|
|
2737
2822
|
Z.playNote(a, R.pitch, R.velocity, n);
|
|
2738
2823
|
}
|
|
2739
|
-
|
|
2824
|
+
V++;
|
|
2740
2825
|
}
|
|
2741
|
-
this.partNotePointers.set(F,
|
|
2826
|
+
this.partNotePointers.set(F, V);
|
|
2742
2827
|
}
|
|
2743
2828
|
}
|
|
2744
2829
|
}
|
|
@@ -2771,10 +2856,10 @@ class Jl {
|
|
|
2771
2856
|
this.partProgramPointers.set(U, 0);
|
|
2772
2857
|
continue;
|
|
2773
2858
|
}
|
|
2774
|
-
let
|
|
2775
|
-
for (;
|
|
2776
|
-
|
|
2777
|
-
F.setInstrument(
|
|
2859
|
+
let Q = 0, V = Z.defaultInstrument;
|
|
2860
|
+
for (; Q < Z.programChanges.length && Z.programChanges[Q].time <= l; )
|
|
2861
|
+
V = Z.programChanges[Q].programNumber, Q++;
|
|
2862
|
+
F.setInstrument(V), this.partProgramPointers.set(U, Q);
|
|
2778
2863
|
}
|
|
2779
2864
|
}
|
|
2780
2865
|
/**
|
|
@@ -3225,15 +3310,15 @@ class xU {
|
|
|
3225
3310
|
throw new Error("Audio engine not ready. Call setAudioEngine() first.");
|
|
3226
3311
|
if (this.isCalibrating)
|
|
3227
3312
|
throw new Error("Calibration already in progress");
|
|
3228
|
-
const U = l.measurements || 5, F = l.sampleIntervalMs || 10, Z = l.threshold || 0.01,
|
|
3313
|
+
const U = l.measurements || 5, F = l.sampleIntervalMs || 10, Z = l.threshold || 0.01, Q = l.timeout || 3e3, V = l.silent !== void 0 ? l.silent : !0, t = l.updateBaseline !== void 0 ? l.updateBaseline : !0;
|
|
3229
3314
|
this.isCalibrating = !0;
|
|
3230
3315
|
try {
|
|
3231
|
-
|
|
3316
|
+
V && await this._setupSilentCalibration();
|
|
3232
3317
|
const R = await this._performLatencyMeasurement(
|
|
3233
3318
|
U,
|
|
3234
3319
|
F,
|
|
3235
3320
|
Z,
|
|
3236
|
-
|
|
3321
|
+
Q
|
|
3237
3322
|
);
|
|
3238
3323
|
this.measuredLatencyMs = R, t && await this._updateBaselineLatency(R);
|
|
3239
3324
|
const a = this.hasLatencyDrift();
|
|
@@ -3249,7 +3334,7 @@ class xU {
|
|
|
3249
3334
|
driftMs: R - this.baselineLatencyMs
|
|
3250
3335
|
})), R;
|
|
3251
3336
|
} finally {
|
|
3252
|
-
|
|
3337
|
+
V && this._teardownSilentCalibration(), this.isCalibrating = !1;
|
|
3253
3338
|
}
|
|
3254
3339
|
}
|
|
3255
3340
|
/**
|
|
@@ -3342,16 +3427,16 @@ class xU {
|
|
|
3342
3427
|
previewNextNotes(l = {}) {
|
|
3343
3428
|
if (!this.midiPlayer)
|
|
3344
3429
|
throw new Error("No MIDI data loaded");
|
|
3345
|
-
const U = l.delayBetweenParts ?? 0.3, F = l.duration ?? 0.5, Z = l.velocity ?? 100,
|
|
3430
|
+
const U = l.delayBetweenParts ?? 0.3, F = l.duration ?? 0.5, Z = l.velocity ?? 100, Q = this.midiPlayer.getAllNextNotes(), V = l.partOrder ?? this.getPartNames();
|
|
3346
3431
|
let t = this.audioEngine.audioContext.currentTime + 0.01;
|
|
3347
3432
|
const R = [];
|
|
3348
|
-
for (const a of
|
|
3349
|
-
const n =
|
|
3433
|
+
for (const a of V) {
|
|
3434
|
+
const n = Q[a];
|
|
3350
3435
|
if (!n) continue;
|
|
3351
3436
|
const m = this.midiPlayer.getPartChannel(a);
|
|
3352
3437
|
if (!m) continue;
|
|
3353
|
-
const
|
|
3354
|
-
|
|
3438
|
+
const W = this.midiPlayer.getPartOutput(a);
|
|
3439
|
+
W && W.gain.value === 0 || (m.playPreviewNote(n.pitch, {
|
|
3355
3440
|
startTime: t,
|
|
3356
3441
|
duration: F,
|
|
3357
3442
|
velocity: Z,
|
|
@@ -3483,17 +3568,17 @@ class xU {
|
|
|
3483
3568
|
startBeat: { bar: 1, beat: 1, timeSig: 4 }
|
|
3484
3569
|
};
|
|
3485
3570
|
const l = this.midiPlayer.beats, U = this.frozenTime, F = this.leadInConfig.bars;
|
|
3486
|
-
let Z = l.length - 1,
|
|
3571
|
+
let Z = l.length - 1, Q = 0.5;
|
|
3487
3572
|
for (; l[Z].time > U; ) Z--;
|
|
3488
|
-
const
|
|
3489
|
-
t ?
|
|
3490
|
-
const R = this.midiPlayer && this.midiPlayer.playbackSpeed || 1, a =
|
|
3573
|
+
const V = l[Z], t = l[Z + 1];
|
|
3574
|
+
t ? Q = t.time - V.time : Z > 0 && (Q = V.time - l[Z - 1].time);
|
|
3575
|
+
const R = this.midiPlayer && this.midiPlayer.playbackSpeed || 1, a = Q / R, n = V.timeSig === 1, m = n && t ? t.timeSig : V.timeSig, W = n ? m - 1 : V.beat > 1 ? V.beat - 1 : 0, c = F * m + W;
|
|
3491
3576
|
return {
|
|
3492
3577
|
totalBeats: c,
|
|
3493
3578
|
duration: c * a,
|
|
3494
3579
|
beatSequence: this._generateBeatSequence(c, a, m),
|
|
3495
3580
|
beatsPerBar: m,
|
|
3496
|
-
startBeat:
|
|
3581
|
+
startBeat: V
|
|
3497
3582
|
};
|
|
3498
3583
|
}
|
|
3499
3584
|
/**
|
|
@@ -3506,14 +3591,14 @@ class xU {
|
|
|
3506
3591
|
*/
|
|
3507
3592
|
_generateBeatSequence(l, U, F) {
|
|
3508
3593
|
const Z = [];
|
|
3509
|
-
for (let
|
|
3510
|
-
const
|
|
3594
|
+
for (let Q = 0; Q < l; Q++) {
|
|
3595
|
+
const V = Q % F + 1;
|
|
3511
3596
|
Z.push({
|
|
3512
|
-
beat:
|
|
3513
|
-
isAccent:
|
|
3514
|
-
time:
|
|
3597
|
+
beat: V,
|
|
3598
|
+
isAccent: V === 1,
|
|
3599
|
+
time: Q * U,
|
|
3515
3600
|
// Relative time from start of lead-in playback
|
|
3516
|
-
absoluteTime: this.leadInStartTime +
|
|
3601
|
+
absoluteTime: this.leadInStartTime + Q * U
|
|
3517
3602
|
// Absolute time (includes startup delay)
|
|
3518
3603
|
});
|
|
3519
3604
|
}
|
|
@@ -3530,18 +3615,18 @@ class xU {
|
|
|
3530
3615
|
this.leadInStartTime = this.audioEngine.audioContext.currentTime, this.leadInInterval = setInterval(() => {
|
|
3531
3616
|
const Z = this.audioEngine.audioContext.currentTime - this.leadInStartTime;
|
|
3532
3617
|
for (this.leadInProgress = Math.min(1, Z / this.leadInData.duration); this.leadInBeatIndex < U.length; ) {
|
|
3533
|
-
const
|
|
3534
|
-
if (
|
|
3618
|
+
const Q = U[this.leadInBeatIndex], V = Q.time - Z;
|
|
3619
|
+
if (V > 0.05)
|
|
3535
3620
|
break;
|
|
3536
|
-
if (!this.leadInScheduledBeats.has(this.leadInBeatIndex) &&
|
|
3537
|
-
const t =
|
|
3621
|
+
if (!this.leadInScheduledBeats.has(this.leadInBeatIndex) && V >= -0.05 && V <= 0.05) {
|
|
3622
|
+
const t = V <= 0 ? this.audioEngine.audioContext.currentTime + 0.01 : (
|
|
3538
3623
|
// Add small offset for immediate beats
|
|
3539
|
-
this.audioEngine.audioContext.currentTime +
|
|
3624
|
+
this.audioEngine.audioContext.currentTime + V
|
|
3540
3625
|
);
|
|
3541
|
-
this._scheduleTickAtTime(t,
|
|
3626
|
+
this._scheduleTickAtTime(t, Q.isAccent);
|
|
3542
3627
|
const R = {
|
|
3543
3628
|
bar: Math.floor(this.leadInBeatIndex / this.leadInData.beatsPerBar) + 1,
|
|
3544
|
-
beat:
|
|
3629
|
+
beat: Q.beat,
|
|
3545
3630
|
repeat: 1,
|
|
3546
3631
|
time: this.frozenTime,
|
|
3547
3632
|
isLeadIn: !0
|
|
@@ -3590,8 +3675,8 @@ class xU {
|
|
|
3590
3675
|
if (this.state === "playing")
|
|
3591
3676
|
try {
|
|
3592
3677
|
this.midiPlayer.play(), l && this._startMetronome();
|
|
3593
|
-
} catch (
|
|
3594
|
-
this.state = "stopped", this._emitEvent("error",
|
|
3678
|
+
} catch (Q) {
|
|
3679
|
+
this.state = "stopped", this._emitEvent("error", Q);
|
|
3595
3680
|
}
|
|
3596
3681
|
};
|
|
3597
3682
|
F ? Z() : setTimeout(Z, this.startupConfig.delayMs), this.timeUpdateInterval || this._startTimeUpdateLoop();
|
|
@@ -3634,13 +3719,13 @@ class xU {
|
|
|
3634
3719
|
if (!U || U.length === 0)
|
|
3635
3720
|
return;
|
|
3636
3721
|
const F = this.midiPlayer.getCurrentTime(), Z = 0.1;
|
|
3637
|
-
for (let
|
|
3638
|
-
const
|
|
3722
|
+
for (let Q = this.nextBeatIndex; Q < U.length; Q++) {
|
|
3723
|
+
const V = U[Q], t = this.midiPlayer.playbackSpeed || 1, R = l + (V.time - F) / t;
|
|
3639
3724
|
if (R > this.audioEngine.audioContext.currentTime + Z)
|
|
3640
3725
|
break;
|
|
3641
3726
|
if (R >= this.audioEngine.audioContext.currentTime - 0.01) {
|
|
3642
|
-
const a = Math.max(R, this.audioEngine.audioContext.currentTime + 1e-3), n =
|
|
3643
|
-
this._scheduleTickAtTime(a, n), this.nextBeatIndex =
|
|
3727
|
+
const a = Math.max(R, this.audioEngine.audioContext.currentTime + 1e-3), n = V.isDownbeat || V.beat === 1;
|
|
3728
|
+
this._scheduleTickAtTime(a, n), this.nextBeatIndex = Q + 1;
|
|
3644
3729
|
}
|
|
3645
3730
|
}
|
|
3646
3731
|
}
|
|
@@ -3657,11 +3742,11 @@ class xU {
|
|
|
3657
3742
|
this.nextBeatIndex++;
|
|
3658
3743
|
const F = l + 0.15;
|
|
3659
3744
|
for (; this.nextBeatIndex < U.length; ) {
|
|
3660
|
-
const Z = U[this.nextBeatIndex],
|
|
3745
|
+
const Z = U[this.nextBeatIndex], Q = Z.time - l;
|
|
3661
3746
|
if (Z.time > F)
|
|
3662
3747
|
break;
|
|
3663
|
-
if (
|
|
3664
|
-
const
|
|
3748
|
+
if (Q >= -0.025 && Q <= 0.15) {
|
|
3749
|
+
const V = this.audioEngine.audioContext.currentTime + 5e-3, t = this.audioEngine.audioContext.currentTime + Math.max(Q, 5e-3), R = Math.max(V, t), a = Z.beat === 1;
|
|
3665
3750
|
this._scheduleTickAtTime(R, a);
|
|
3666
3751
|
}
|
|
3667
3752
|
this.nextBeatIndex++;
|
|
@@ -3860,10 +3945,10 @@ class xU {
|
|
|
3860
3945
|
trumpet: { instrument: "trumpet", volume: 0.7 }
|
|
3861
3946
|
};
|
|
3862
3947
|
return Object.keys(l).forEach((Z) => {
|
|
3863
|
-
const
|
|
3948
|
+
const Q = Z.toLowerCase(), V = F[Q] || F.piano;
|
|
3864
3949
|
U[Z] = {
|
|
3865
|
-
instrument:
|
|
3866
|
-
volume:
|
|
3950
|
+
instrument: V.instrument,
|
|
3951
|
+
volume: V.volume
|
|
3867
3952
|
};
|
|
3868
3953
|
}), U;
|
|
3869
3954
|
}
|
|
@@ -3884,17 +3969,17 @@ class xU {
|
|
|
3884
3969
|
const U = this.audioEngine.getMetronomeAnalyser();
|
|
3885
3970
|
if (!U)
|
|
3886
3971
|
throw new Error("Metronome analyser not available for signal capture");
|
|
3887
|
-
const F = l.sampleIntervalMs || 2, Z = l.captureDurationMs || 1500,
|
|
3888
|
-
await this.audioEngine.playMetronomeTick(
|
|
3889
|
-
const
|
|
3972
|
+
const F = l.sampleIntervalMs || 2, Z = l.captureDurationMs || 1500, Q = this.audioEngine.audioContext.currentTime + 0.1;
|
|
3973
|
+
await this.audioEngine.playMetronomeTick(Q, !0, 1);
|
|
3974
|
+
const V = await this._captureAnalyserTimeSeries(
|
|
3890
3975
|
U,
|
|
3891
|
-
|
|
3976
|
+
Q,
|
|
3892
3977
|
F,
|
|
3893
3978
|
Z
|
|
3894
3979
|
);
|
|
3895
3980
|
return {
|
|
3896
|
-
scheduledTime:
|
|
3897
|
-
samples:
|
|
3981
|
+
scheduledTime: Q,
|
|
3982
|
+
samples: V,
|
|
3898
3983
|
sampleIntervalMs: F,
|
|
3899
3984
|
captureDurationMs: Z
|
|
3900
3985
|
};
|
|
@@ -3909,17 +3994,17 @@ class xU {
|
|
|
3909
3994
|
* @private
|
|
3910
3995
|
*/
|
|
3911
3996
|
async _performLatencyMeasurement(l, U, F, Z) {
|
|
3912
|
-
const
|
|
3913
|
-
if (!
|
|
3997
|
+
const Q = this.audioEngine.getMetronomeAnalyser();
|
|
3998
|
+
if (!Q)
|
|
3914
3999
|
throw new Error("Metronome analyser not available for latency measurement");
|
|
3915
|
-
const
|
|
4000
|
+
const V = this.audioEngine.audioContext, t = [];
|
|
3916
4001
|
console.log(`Starting calibration: ${l} measurements, ${U}ms sampling, ${F} threshold`);
|
|
3917
4002
|
for (let m = 0; m < l; m++) {
|
|
3918
|
-
const
|
|
3919
|
-
await this.audioEngine.playMetronomeTick(
|
|
4003
|
+
const W = V.currentTime + 0.15;
|
|
4004
|
+
await this.audioEngine.playMetronomeTick(W, !0, 1);
|
|
3920
4005
|
const c = await this._detectOnsetByThreshold(
|
|
3921
|
-
|
|
3922
|
-
|
|
4006
|
+
Q,
|
|
4007
|
+
W,
|
|
3923
4008
|
U,
|
|
3924
4009
|
F,
|
|
3925
4010
|
Z
|
|
@@ -3935,7 +4020,7 @@ class xU {
|
|
|
3935
4020
|
throw new Error(`Failed to detect any metronome onsets. Try lowering threshold (current: ${F}) or check audio routing.`);
|
|
3936
4021
|
let R = t;
|
|
3937
4022
|
if (t.length >= 5) {
|
|
3938
|
-
const m = [...t].sort((
|
|
4023
|
+
const m = [...t].sort((W, c) => W - c);
|
|
3939
4024
|
R = m.slice(
|
|
3940
4025
|
Math.floor(m.length * 0.2),
|
|
3941
4026
|
// Remove bottom 20%
|
|
@@ -3943,8 +4028,8 @@ class xU {
|
|
|
3943
4028
|
// Remove top 20%
|
|
3944
4029
|
), console.log(`Discarded ${t.length - R.length} outliers`);
|
|
3945
4030
|
}
|
|
3946
|
-
const a = R.reduce((m,
|
|
3947
|
-
R.reduce((m,
|
|
4031
|
+
const a = R.reduce((m, W) => m + W, 0) / R.length, n = Math.sqrt(
|
|
4032
|
+
R.reduce((m, W) => m + Math.pow(W - a, 2), 0) / R.length
|
|
3948
4033
|
);
|
|
3949
4034
|
return console.log(`Average latency: ${a.toFixed(1)}ms ± ${n.toFixed(1)}ms (n=${R.length})`), Math.round(a);
|
|
3950
4035
|
}
|
|
@@ -3959,14 +4044,14 @@ class xU {
|
|
|
3959
4044
|
* @returns {Promise<Object|null>} Detection result {latencyMs, rms, peak} or null if timeout
|
|
3960
4045
|
* @private
|
|
3961
4046
|
*/
|
|
3962
|
-
async _detectOnsetByThreshold(l, U, F, Z,
|
|
3963
|
-
const
|
|
4047
|
+
async _detectOnsetByThreshold(l, U, F, Z, Q) {
|
|
4048
|
+
const V = this.audioEngine.audioContext, t = l.fftSize, R = new Float32Array(t), a = Math.max(0, (U - V.currentTime) * 1e3 - 20);
|
|
3964
4049
|
await new Promise((m) => setTimeout(m, a));
|
|
3965
4050
|
const n = performance.now();
|
|
3966
4051
|
return new Promise((m) => {
|
|
3967
|
-
const
|
|
3968
|
-
if (performance.now() - n >
|
|
3969
|
-
clearInterval(
|
|
4052
|
+
const W = setInterval(() => {
|
|
4053
|
+
if (performance.now() - n > Q) {
|
|
4054
|
+
clearInterval(W), m(null);
|
|
3970
4055
|
return;
|
|
3971
4056
|
}
|
|
3972
4057
|
l.getFloatTimeDomainData(R);
|
|
@@ -3977,8 +4062,8 @@ class xU {
|
|
|
3977
4062
|
}
|
|
3978
4063
|
const N = Math.sqrt(c / t);
|
|
3979
4064
|
if (N >= Z) {
|
|
3980
|
-
clearInterval(
|
|
3981
|
-
const J =
|
|
4065
|
+
clearInterval(W);
|
|
4066
|
+
const J = V.currentTime, p = (J - U) * 1e3;
|
|
3982
4067
|
m({
|
|
3983
4068
|
latencyMs: p,
|
|
3984
4069
|
rms: N,
|
|
@@ -3999,20 +4084,20 @@ class xU {
|
|
|
3999
4084
|
* @private
|
|
4000
4085
|
*/
|
|
4001
4086
|
async _captureAnalyserTimeSeries(l, U, F, Z) {
|
|
4002
|
-
const
|
|
4087
|
+
const Q = this.audioEngine.audioContext, V = l.fftSize, t = new Float32Array(V), R = [], a = performance.now(), n = Math.max(0, (U - Q.currentTime) * 1e3 - 20);
|
|
4003
4088
|
return await new Promise((m) => setTimeout(m, n)), new Promise((m) => {
|
|
4004
|
-
const
|
|
4089
|
+
const W = setInterval(() => {
|
|
4005
4090
|
if (performance.now() - a - n >= Z) {
|
|
4006
|
-
clearInterval(
|
|
4091
|
+
clearInterval(W), m(R);
|
|
4007
4092
|
return;
|
|
4008
4093
|
}
|
|
4009
4094
|
l.getFloatTimeDomainData(t);
|
|
4010
4095
|
let c = 0, s = 0;
|
|
4011
|
-
for (let p = 0; p <
|
|
4096
|
+
for (let p = 0; p < V; p++) {
|
|
4012
4097
|
const M = Math.abs(t[p]);
|
|
4013
4098
|
c += t[p] * t[p], M > s && (s = M);
|
|
4014
4099
|
}
|
|
4015
|
-
const N = Math.sqrt(c /
|
|
4100
|
+
const N = Math.sqrt(c / V), J = Q.currentTime;
|
|
4016
4101
|
R.push({
|
|
4017
4102
|
time: J,
|
|
4018
4103
|
relativeTime: (J - U) * 1e3,
|
|
@@ -4049,8 +4134,8 @@ class MU {
|
|
|
4049
4134
|
try {
|
|
4050
4135
|
await this.audioEngine.initialize(Z), console.log(`Loaded soundfont: ${Z}`), U = !0;
|
|
4051
4136
|
break;
|
|
4052
|
-
} catch (
|
|
4053
|
-
console.warn(`Failed to load soundfont ${Z}:`,
|
|
4137
|
+
} catch (Q) {
|
|
4138
|
+
console.warn(`Failed to load soundfont ${Z}:`, Q.message), F = Q;
|
|
4054
4139
|
}
|
|
4055
4140
|
if (!U) {
|
|
4056
4141
|
const Z = "No soundfont could be loaded";
|
|
@@ -4140,8 +4225,8 @@ class MU {
|
|
|
4140
4225
|
F.gain.value = 1;
|
|
4141
4226
|
const Z = this.audioContext.createAnalyser();
|
|
4142
4227
|
Z.fftSize = 256, Z.smoothingTimeConstant = 0.3, U.connect(F), F.connect(Z), Z.connect(this.masterGain);
|
|
4143
|
-
const
|
|
4144
|
-
this.partGainNodes.set(
|
|
4228
|
+
const Q = this.sanitizePartName(l);
|
|
4229
|
+
this.partGainNodes.set(Q, F), this.partAnalyserNodes.set(Q, Z), console.log(`Audio routing established for part: ${l}`);
|
|
4145
4230
|
}
|
|
4146
4231
|
}
|
|
4147
4232
|
// Set up metronome audio routing (separate from parts)
|
|
@@ -4187,12 +4272,10 @@ class MU {
|
|
|
4187
4272
|
}
|
|
4188
4273
|
// Set up event delegation from PlaybackManager to DummyAudioEngine format
|
|
4189
4274
|
setupPlaybackManagerEventDelegation() {
|
|
4190
|
-
this.playbackManager.on("timeupdate", ({
|
|
4191
|
-
this.currentTime = l, this.eventBus.emit("timeChanged", {
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
}), this.playbackManager.on("beatAudible", ({ bar: l, beat: U, isLeadIn: F, repeat: Z, time: V }) => {
|
|
4195
|
-
this.eventBus.emit("barChanged", { bar: l, beat: U, repeat: Z, time: V, isLeadIn: F });
|
|
4275
|
+
this.playbackManager.on("timeupdate", ({ audioTime: l, leadInProgress: U }) => {
|
|
4276
|
+
this.currentTime = l, this.eventBus.emit("timeChanged", { currentTime: l, leadInProgress: U });
|
|
4277
|
+
}), this.playbackManager.on("beatAudible", ({ bar: l, beat: U, isLeadIn: F, repeat: Z, time: Q }) => {
|
|
4278
|
+
this.eventBus.emit("barChanged", { bar: l, beat: U, repeat: Z, time: Q, isLeadIn: F });
|
|
4196
4279
|
}), this.playbackManager.on("leadInStarted", ({ totalBeats: l, duration: U, bars: F }) => {
|
|
4197
4280
|
this.eventBus.emit("leadInStarted", { bars: F, totalBeats: l, duration: U });
|
|
4198
4281
|
}), this.playbackManager.on("leadInEnded", () => {
|
|
@@ -4317,7 +4400,7 @@ class MU {
|
|
|
4317
4400
|
// Helper method to determine if a part should be effectively muted
|
|
4318
4401
|
isPartEffectivelyMuted(l) {
|
|
4319
4402
|
const U = this.sanitizePartName(l), F = this.parts.get(U);
|
|
4320
|
-
return !F || F.muted ? !0 : Array.from(this.parts.values()).some((
|
|
4403
|
+
return !F || F.muted ? !0 : Array.from(this.parts.values()).some((Q) => Q.solo) && !F.solo;
|
|
4321
4404
|
}
|
|
4322
4405
|
// Update audio state for a specific part
|
|
4323
4406
|
updatePartAudioState(l) {
|
|
@@ -4341,14 +4424,14 @@ class MU {
|
|
|
4341
4424
|
if (!F)
|
|
4342
4425
|
return 0;
|
|
4343
4426
|
try {
|
|
4344
|
-
const Z = F.frequencyBinCount,
|
|
4345
|
-
F.getByteFrequencyData(
|
|
4346
|
-
let
|
|
4427
|
+
const Z = F.frequencyBinCount, Q = new Uint8Array(Z);
|
|
4428
|
+
F.getByteFrequencyData(Q);
|
|
4429
|
+
let V = 0;
|
|
4347
4430
|
for (let R = 0; R < Z; R++) {
|
|
4348
|
-
const a =
|
|
4349
|
-
|
|
4431
|
+
const a = Q[R] / 255;
|
|
4432
|
+
V += a * a;
|
|
4350
4433
|
}
|
|
4351
|
-
const t = Math.sqrt(
|
|
4434
|
+
const t = Math.sqrt(V / Z);
|
|
4352
4435
|
return Math.min(1, Math.pow(t * 2, 0.7));
|
|
4353
4436
|
} catch (Z) {
|
|
4354
4437
|
return console.warn(`Failed to get level for part ${l}:`, Z), 0;
|
|
@@ -4430,72 +4513,66 @@ class MU {
|
|
|
4430
4513
|
}
|
|
4431
4514
|
const e = new MU();
|
|
4432
4515
|
function Rl() {
|
|
4433
|
-
const d = Ul(), l = tl(), U = NU(), F = ({ currentTime:
|
|
4434
|
-
d.setCurrentTime(
|
|
4435
|
-
}, Z = ({ isPlaying:
|
|
4436
|
-
d.setPlaybackState(
|
|
4437
|
-
},
|
|
4438
|
-
|
|
4439
|
-
},
|
|
4440
|
-
d.setPlaybackSpeed(
|
|
4441
|
-
}, t = ({ volume:
|
|
4442
|
-
d.setMasterVolume(
|
|
4443
|
-
}, R = ({ partName:
|
|
4444
|
-
d.setPartVolume(
|
|
4445
|
-
}, a = ({ partName:
|
|
4446
|
-
d.setPartMuted(
|
|
4447
|
-
}, n = ({ partName:
|
|
4448
|
-
d.setPartSolo(
|
|
4449
|
-
}, m = ({ bars:
|
|
4450
|
-
d.setLeadInActive(!0,
|
|
4451
|
-
},
|
|
4516
|
+
const d = Ul(), l = tl(), U = NU(), F = ({ currentTime: b }) => {
|
|
4517
|
+
d.setCurrentTime(b);
|
|
4518
|
+
}, Z = ({ isPlaying: b }) => {
|
|
4519
|
+
d.setPlaybackState(b), U.setTransportState(b ? "playing" : "stopped");
|
|
4520
|
+
}, Q = (b) => {
|
|
4521
|
+
b && (d.isLeadInActive ? b.isLeadIn && b.beat !== void 0 && d.setCurrentBar(null, b.beat, null) : (d.setCurrentBar(b.bar, b.beat, b.repeat), U.updateLastBarPosition(b.bar)));
|
|
4522
|
+
}, V = ({ speed: b }) => {
|
|
4523
|
+
d.setPlaybackSpeed(b);
|
|
4524
|
+
}, t = ({ volume: b }) => {
|
|
4525
|
+
d.setMasterVolume(b);
|
|
4526
|
+
}, R = ({ partName: b, volume: o }) => {
|
|
4527
|
+
d.setPartVolume(b, o);
|
|
4528
|
+
}, a = ({ partName: b, muted: o }) => {
|
|
4529
|
+
d.setPartMuted(b, o);
|
|
4530
|
+
}, n = ({ partName: b, solo: o }) => {
|
|
4531
|
+
d.setPartSolo(b, o);
|
|
4532
|
+
}, m = ({ bars: b }) => {
|
|
4533
|
+
d.setLeadInActive(!0, b);
|
|
4534
|
+
}, W = () => {
|
|
4452
4535
|
d.setLeadInActive(!1);
|
|
4453
4536
|
}, c = () => {
|
|
4454
4537
|
d.setStartingNotesActive(!0);
|
|
4455
4538
|
}, s = () => {
|
|
4456
4539
|
d.setStartingNotesActive(!1);
|
|
4457
|
-
}, N = ({ mark:
|
|
4458
|
-
U.updateLastPracticeMarkUsed(
|
|
4459
|
-
}, J = ({ parts:
|
|
4460
|
-
d.initializeParts(
|
|
4461
|
-
}, p = ({ finalTime:
|
|
4462
|
-
d.setPlaybackState(!1), U.setTransportState("stopped"), console.log(`Song ended at time: ${
|
|
4463
|
-
}, M = ({ duration:
|
|
4464
|
-
console.log("Updating total duration in store to:",
|
|
4465
|
-
}, y = ({ beats:
|
|
4466
|
-
console.log(`Updating music data store with ${
|
|
4467
|
-
},
|
|
4468
|
-
e.on("timeChanged", F), e.on("playbackStateChanged", Z), e.on("barChanged",
|
|
4540
|
+
}, N = ({ mark: b }) => {
|
|
4541
|
+
U.updateLastPracticeMarkUsed(b);
|
|
4542
|
+
}, J = ({ parts: b }) => {
|
|
4543
|
+
d.initializeParts(b), l.setParts(b);
|
|
4544
|
+
}, p = ({ finalTime: b }) => {
|
|
4545
|
+
d.setPlaybackState(!1), U.setTransportState("stopped"), console.log(`Song ended at time: ${b}`);
|
|
4546
|
+
}, M = ({ duration: b }) => {
|
|
4547
|
+
console.log("Updating total duration in store to:", b), l.setTotalDuration(b);
|
|
4548
|
+
}, y = ({ beats: b, practiceMarks: o, maxBar: q }) => {
|
|
4549
|
+
console.log(`Updating music data store with ${b.length} beats and ${Object.keys(o).length} practice marks`), l.updateBeats(b), l.practiceMarks = o, l.maxBar = q;
|
|
4550
|
+
}, u = () => {
|
|
4551
|
+
e.on("timeChanged", F), e.on("playbackStateChanged", Z), e.on("barChanged", Q), e.on("speedChanged", V), e.on("masterVolumeChanged", t), e.on("partVolumeChanged", R), e.on("partMutedChanged", a), e.on("partSoloChanged", n), e.on("leadInStarted", m), e.on("leadInCompleted", W), e.on("startingNotesStarted", c), e.on("startingNotesCompleted", s), e.on("practiceMarkChanged", N), e.on("initialized", J), e.on("songEnded", p), e.on("durationUpdated", M), e.on("musicDataExtracted", y);
|
|
4469
4552
|
}, k = () => {
|
|
4470
|
-
e.off("timeChanged", F), e.off("playbackStateChanged", Z), e.off("barChanged",
|
|
4553
|
+
e.off("timeChanged", F), e.off("playbackStateChanged", Z), e.off("barChanged", Q), e.off("speedChanged", V), e.off("masterVolumeChanged", t), e.off("partVolumeChanged", R), e.off("partMutedChanged", a), e.off("partSoloChanged", n), e.off("leadInStarted", m), e.off("leadInCompleted", W), e.off("startingNotesStarted", c), e.off("startingNotesCompleted", s), e.off("practiceMarkChanged", N), e.off("initialized", J), e.off("songEnded", p), e.off("durationUpdated", M), e.off("musicDataExtracted", y);
|
|
4471
4554
|
};
|
|
4472
4555
|
(() => {
|
|
4473
4556
|
El(() => {
|
|
4474
|
-
const
|
|
4557
|
+
const b = d.masterVolume;
|
|
4475
4558
|
try {
|
|
4476
|
-
e.getMasterVolume() !==
|
|
4559
|
+
e.getMasterVolume() !== b && e.setMasterVolume(b);
|
|
4477
4560
|
} catch (o) {
|
|
4478
4561
|
console.warn("Master volume sync skipped during initialization:", o.message);
|
|
4479
4562
|
}
|
|
4480
4563
|
}), El(() => {
|
|
4481
|
-
const
|
|
4564
|
+
const b = d.metronomeVolume;
|
|
4482
4565
|
try {
|
|
4483
|
-
e.getMetronomeVolume() !==
|
|
4566
|
+
e.getMetronomeVolume() !== b && e.setMetronomeVolume(b);
|
|
4484
4567
|
} catch (o) {
|
|
4485
4568
|
console.warn("Metronome volume sync skipped during initialization:", o.message);
|
|
4486
4569
|
}
|
|
4487
4570
|
});
|
|
4488
4571
|
})();
|
|
4489
|
-
const H = async (
|
|
4572
|
+
const H = async (b) => {
|
|
4490
4573
|
try {
|
|
4491
|
-
if (d.setLoaded(!1),
|
|
4492
|
-
|
|
4493
|
-
else if (await e.initialize({
|
|
4494
|
-
beats: W.beats,
|
|
4495
|
-
practiceMarks: W.marks || W.practiceMarks,
|
|
4496
|
-
parts: W.parts
|
|
4497
|
-
}), W.beats && W.beats.length > 0) {
|
|
4498
|
-
const o = W.beats[0];
|
|
4574
|
+
if (d.setLoaded(!1), u(), l.loadMusicData(b), await e.initialize(b), !b.midiData && b.beats && b.beats.length > 0) {
|
|
4575
|
+
const o = b.beats[0];
|
|
4499
4576
|
d.setCurrentBar(o.bar, o.beat, o.repeat), e.setTime(o.time);
|
|
4500
4577
|
}
|
|
4501
4578
|
e.updateToggleStates(d.metronomeEnabled, d.leadInEnabled), d.setLoaded(!0);
|
|
@@ -4508,37 +4585,37 @@ function Rl() {
|
|
|
4508
4585
|
e.stop();
|
|
4509
4586
|
}, Zl = () => {
|
|
4510
4587
|
e.pause();
|
|
4511
|
-
}, i = (
|
|
4512
|
-
e.setTime(
|
|
4513
|
-
}, z = (
|
|
4514
|
-
e.setBar(
|
|
4515
|
-
}, P = (
|
|
4516
|
-
e.goToPracticeMark(
|
|
4517
|
-
}, B = (
|
|
4518
|
-
e.setPlaybackSpeed(
|
|
4519
|
-
}, S = (
|
|
4520
|
-
e.setMasterVolume(
|
|
4521
|
-
}, T = (
|
|
4522
|
-
e.setPartVolume(
|
|
4523
|
-
}, I = (
|
|
4524
|
-
e.setPartMuted(
|
|
4525
|
-
}, w = (
|
|
4526
|
-
e.setPartSolo(
|
|
4527
|
-
}, Ql = (
|
|
4528
|
-
e.playLeadIn(
|
|
4588
|
+
}, i = (b) => {
|
|
4589
|
+
e.setTime(b);
|
|
4590
|
+
}, z = (b, o = 0) => {
|
|
4591
|
+
e.setBar(b, o);
|
|
4592
|
+
}, P = (b) => {
|
|
4593
|
+
e.goToPracticeMark(b);
|
|
4594
|
+
}, B = (b) => {
|
|
4595
|
+
e.setPlaybackSpeed(b);
|
|
4596
|
+
}, S = (b) => {
|
|
4597
|
+
e.setMasterVolume(b);
|
|
4598
|
+
}, T = (b, o) => {
|
|
4599
|
+
e.setPartVolume(b, o);
|
|
4600
|
+
}, I = (b, o) => {
|
|
4601
|
+
e.setPartMuted(b, o);
|
|
4602
|
+
}, w = (b, o) => {
|
|
4603
|
+
e.setPartSolo(b, o);
|
|
4604
|
+
}, Ql = (b = 1) => {
|
|
4605
|
+
e.playLeadIn(b);
|
|
4529
4606
|
}, Bl = () => {
|
|
4530
4607
|
e.playStartingNotes();
|
|
4531
|
-
}, Yl = (
|
|
4532
|
-
o && U.leadInEnabled ? (z(
|
|
4533
|
-
}, _l = (
|
|
4534
|
-
const q = l.getBarForMark(
|
|
4608
|
+
}, Yl = (b, o = !0, q = 0) => {
|
|
4609
|
+
o && U.leadInEnabled ? (z(b, q), Ql(U.leadInBars)) : (z(b, q), A());
|
|
4610
|
+
}, _l = (b, o = !0) => {
|
|
4611
|
+
const q = l.getBarForMark(b);
|
|
4535
4612
|
q && Yl(q, o);
|
|
4536
4613
|
}, $l = () => {
|
|
4537
|
-
const
|
|
4538
|
-
return d.setMetronomeEnabled(
|
|
4614
|
+
const b = !d.metronomeEnabled;
|
|
4615
|
+
return d.setMetronomeEnabled(b), e.setMetronomeEnabled(b), b;
|
|
4539
4616
|
}, lU = () => {
|
|
4540
|
-
const
|
|
4541
|
-
return d.setLeadInEnabled(
|
|
4617
|
+
const b = !d.leadInEnabled;
|
|
4618
|
+
return d.setLeadInEnabled(b), e.updateToggleStates(d.metronomeEnabled, b), b;
|
|
4542
4619
|
};
|
|
4543
4620
|
return cl(() => {
|
|
4544
4621
|
k();
|
|
@@ -4560,15 +4637,15 @@ function Rl() {
|
|
|
4560
4637
|
setPartVolume: T,
|
|
4561
4638
|
setPartMuted: I,
|
|
4562
4639
|
setPartSolo: w,
|
|
4563
|
-
getPartLevel: (
|
|
4640
|
+
getPartLevel: (b) => e.getPartLevel(b),
|
|
4564
4641
|
// Special features
|
|
4565
4642
|
playLeadIn: Ql,
|
|
4566
4643
|
playStartingNotes: Bl,
|
|
4567
4644
|
// Feature toggles
|
|
4568
4645
|
toggleMetronome: $l,
|
|
4569
4646
|
toggleLeadIn: lU,
|
|
4570
|
-
setMetronomeEnabled: (
|
|
4571
|
-
d.setMetronomeEnabled(
|
|
4647
|
+
setMetronomeEnabled: (b) => {
|
|
4648
|
+
d.setMetronomeEnabled(b), e.setMetronomeEnabled(b);
|
|
4572
4649
|
},
|
|
4573
4650
|
// Complex operations
|
|
4574
4651
|
playFromBar: Yl,
|
|
@@ -4608,43 +4685,43 @@ const zU = {
|
|
|
4608
4685
|
}));
|
|
4609
4686
|
const l = d;
|
|
4610
4687
|
Ul();
|
|
4611
|
-
const U = Rl(), F = _(d, "volume"), Z = _(d, "mute"),
|
|
4688
|
+
const U = Rl(), F = _(d, "volume"), Z = _(d, "mute"), Q = _(d, "solo");
|
|
4612
4689
|
v(F, (c) => {
|
|
4613
4690
|
U.setPartVolume(l.name, c);
|
|
4614
4691
|
}), v(Z, (c) => {
|
|
4615
4692
|
U.setPartMuted(l.name, c);
|
|
4616
|
-
}), v(
|
|
4693
|
+
}), v(Q, (c) => {
|
|
4617
4694
|
U.setPartSolo(l.name, c);
|
|
4618
4695
|
});
|
|
4619
|
-
const
|
|
4696
|
+
const V = O("el"), { width: t, height: R } = ll(V), a = G(() => Math.min(t.value, R.value) + "px"), n = G(
|
|
4620
4697
|
() => t.value > R.value ? "mobile" : t.value < 60 ? "tablet" : "desktop"
|
|
4621
4698
|
);
|
|
4622
4699
|
let m = null;
|
|
4623
|
-
const
|
|
4700
|
+
const W = x(0);
|
|
4624
4701
|
return el(() => {
|
|
4625
4702
|
m = setInterval(() => {
|
|
4626
4703
|
if (Z.value)
|
|
4627
|
-
|
|
4704
|
+
W.value = 0;
|
|
4628
4705
|
else
|
|
4629
4706
|
try {
|
|
4630
|
-
|
|
4707
|
+
W.value = U.getPartLevel(l.name);
|
|
4631
4708
|
} catch {
|
|
4632
|
-
Ol("randomLevelIndicators") ?
|
|
4709
|
+
Ol("randomLevelIndicators") ? W.value = Math.random() * F.value : W.value = 0;
|
|
4633
4710
|
}
|
|
4634
4711
|
}, 16);
|
|
4635
4712
|
}), cl(() => {
|
|
4636
4713
|
m && (clearInterval(m), m = null);
|
|
4637
4714
|
}), (c, s) => (X(), Y("div", {
|
|
4638
4715
|
ref_key: "el",
|
|
4639
|
-
ref:
|
|
4716
|
+
ref: V,
|
|
4640
4717
|
class: L([n.value, "part"])
|
|
4641
4718
|
}, [
|
|
4642
4719
|
C(XU, {
|
|
4643
4720
|
class: "tri",
|
|
4644
4721
|
mute: Z.value,
|
|
4645
4722
|
"onUpdate:mute": s[0] || (s[0] = (N) => Z.value = N),
|
|
4646
|
-
solo:
|
|
4647
|
-
"onUpdate:solo": s[1] || (s[1] = (N) =>
|
|
4723
|
+
solo: Q.value,
|
|
4724
|
+
"onUpdate:solo": s[1] || (s[1] = (N) => Q.value = N)
|
|
4648
4725
|
}, null, 8, ["mute", "solo"]),
|
|
4649
4726
|
C(wl, {
|
|
4650
4727
|
align: "left",
|
|
@@ -4656,7 +4733,7 @@ const zU = {
|
|
|
4656
4733
|
_: 1
|
|
4657
4734
|
}),
|
|
4658
4735
|
C(bl, {
|
|
4659
|
-
level:
|
|
4736
|
+
level: W.value,
|
|
4660
4737
|
"show-level": !0,
|
|
4661
4738
|
class: "vol",
|
|
4662
4739
|
value: F.value,
|
|
@@ -4674,29 +4751,29 @@ const zU = {
|
|
|
4674
4751
|
b117cda6: p.value,
|
|
4675
4752
|
"7cd7b1c8": M.value
|
|
4676
4753
|
}));
|
|
4677
|
-
const l = O("el"), U = O("rpt"), { width: F, height: Z } = ll(l),
|
|
4754
|
+
const l = O("el"), U = O("rpt"), { width: F, height: Z } = ll(l), Q = tl(), V = Ul(), t = Rl(), R = x("1"), a = x("A"), n = x(0), m = x(2), W = x(!1), c = x(!1), s = x(!1), N = x(!0);
|
|
4678
4755
|
let J = null;
|
|
4679
4756
|
v(() => {
|
|
4680
4757
|
var B;
|
|
4681
|
-
return ((B =
|
|
4758
|
+
return ((B = Q.beats) == null ? void 0 : B.length) > 0;
|
|
4682
4759
|
}, (B) => {
|
|
4683
|
-
console.log(B), B && !
|
|
4684
|
-
}), v(() =>
|
|
4685
|
-
m.value =
|
|
4760
|
+
console.log(B), B && !W.value && (R.value = V.currentBar.toString(), n.value = V.currentRepeat, m.value = Q.getRepeatCountForBar(V.currentBar), k(V.currentBar), W.value = !0);
|
|
4761
|
+
}), v(() => V.currentBar, (B) => {
|
|
4762
|
+
m.value = Q.getRepeatCountForBar(B);
|
|
4686
4763
|
}), v(R, () => {
|
|
4687
4764
|
R.value = R.value.replace(/\D/g, ""), R.value.length > 3 && (R.value = R.value.slice(0, 3));
|
|
4688
|
-
}), v(() =>
|
|
4765
|
+
}), v(() => V.currentBar, (B) => {
|
|
4689
4766
|
R.value = B.toString(), k(B);
|
|
4690
|
-
}), v(() =>
|
|
4767
|
+
}), v(() => V.currentBeat, () => {
|
|
4691
4768
|
N.value = !0, setTimeout(() => {
|
|
4692
4769
|
N.value = !1;
|
|
4693
4770
|
}, 50);
|
|
4694
4771
|
}), v(c, () => {
|
|
4695
4772
|
c.value && P();
|
|
4696
4773
|
});
|
|
4697
|
-
const p =
|
|
4774
|
+
const p = G(() => Math.min(Z.value / 2.25, F.value / 4.5) + "px"), M = G(() => Math.min(F.value / 15, Z.value / 6.4) + "px"), y = G(() => Object.keys(Q.practiceMarks).sort()), u = G(() => y.value.length > 0);
|
|
4698
4775
|
function k(B) {
|
|
4699
|
-
const S = Object.keys(
|
|
4776
|
+
const S = Object.keys(Q.practiceMarks).filter((T) => Q.practiceMarks[T] <= B).sort((T, I) => Q.practiceMarks[I] - Q.practiceMarks[T]);
|
|
4700
4777
|
S.length > 0 && (a.value = S[0]);
|
|
4701
4778
|
}
|
|
4702
4779
|
function E() {
|
|
@@ -4710,13 +4787,13 @@ const zU = {
|
|
|
4710
4787
|
S && S.stopPropagation(), a.value = B, c.value = !1, t.goToPracticeMark(B);
|
|
4711
4788
|
}
|
|
4712
4789
|
function j() {
|
|
4713
|
-
m.value > 1 && (s.value = !0),
|
|
4790
|
+
m.value > 1 && (s.value = !0), V.currentRepeat < m.value && t.setBar(V.currentBar, V.currentRepeat + 1);
|
|
4714
4791
|
}
|
|
4715
4792
|
function Zl() {
|
|
4716
|
-
m.value > 1 && (s.value = !0),
|
|
4793
|
+
m.value > 1 && (s.value = !0), V.currentRepeat > 1 && t.setBar(V.currentBar, V.currentRepeat - 1);
|
|
4717
4794
|
}
|
|
4718
4795
|
function i(B) {
|
|
4719
|
-
|
|
4796
|
+
u.value && (B.stopPropagation(), s.value = !1, c.value = !c.value);
|
|
4720
4797
|
}
|
|
4721
4798
|
function z(B) {
|
|
4722
4799
|
var S, T;
|
|
@@ -4734,8 +4811,8 @@ const zU = {
|
|
|
4734
4811
|
}
|
|
4735
4812
|
return el(() => {
|
|
4736
4813
|
document.addEventListener("click", z), Ol("beatAnimation") && (J = setInterval(() => {
|
|
4737
|
-
const B =
|
|
4738
|
-
|
|
4814
|
+
const B = V.currentBeat % Q.timeSignature + 1;
|
|
4815
|
+
V.setCurrentBar(V.currentBar, B, V.currentRepeat);
|
|
4739
4816
|
}, 800));
|
|
4740
4817
|
}), cl(() => {
|
|
4741
4818
|
document.removeEventListener("click", z), J && (clearInterval(J), J = null);
|
|
@@ -4746,10 +4823,10 @@ const zU = {
|
|
|
4746
4823
|
}, [
|
|
4747
4824
|
S[6] || (S[6] = h("div", { class: "frame" }, null, -1)),
|
|
4748
4825
|
h("div", {
|
|
4749
|
-
class: L(["mark-input", { empty: !a.value, edit: c.value, disabled: !
|
|
4826
|
+
class: L(["mark-input", { empty: !a.value, edit: c.value, disabled: !u.value }]),
|
|
4750
4827
|
onClick: i
|
|
4751
4828
|
}, [
|
|
4752
|
-
h("div", vU, K(
|
|
4829
|
+
h("div", vU, K(u.value ? a.value : "-"), 1)
|
|
4753
4830
|
], 2),
|
|
4754
4831
|
S[7] || (S[7] = h("div", { class: "mark-title" }, "Mark", -1)),
|
|
4755
4832
|
c.value ? f("", !0) : (X(), Y(al, { key: 0 }, [
|
|
@@ -4770,16 +4847,16 @@ const zU = {
|
|
|
4770
4847
|
ref: U,
|
|
4771
4848
|
class: L(["rpt-input", { edit: s.value, available: m.value > 1 }])
|
|
4772
4849
|
}, [
|
|
4773
|
-
h("div", KU, K(r(
|
|
4850
|
+
h("div", KU, K(r(V).currentRepeat || "-"), 1),
|
|
4774
4851
|
(X(), Y("svg", {
|
|
4775
|
-
class: L(["inc", { disabled: r(
|
|
4852
|
+
class: L(["inc", { disabled: r(V).currentRepeat >= m.value }]),
|
|
4776
4853
|
viewBox: "0 -100 100 100",
|
|
4777
4854
|
onClick: kl(j, ["prevent"])
|
|
4778
4855
|
}, S[1] || (S[1] = [
|
|
4779
4856
|
h("path", { d: "m10-20 40-60 40 60H10Z" }, null, -1)
|
|
4780
4857
|
]), 2)),
|
|
4781
4858
|
(X(), Y("svg", {
|
|
4782
|
-
class: L(["dec", { disabled: r(
|
|
4859
|
+
class: L(["dec", { disabled: r(V).currentRepeat <= 1 }]),
|
|
4783
4860
|
viewBox: "0 -100 100 100",
|
|
4784
4861
|
onClick: kl(Zl, ["prevent"])
|
|
4785
4862
|
}, S[2] || (S[2] = [
|
|
@@ -4788,7 +4865,7 @@ const zU = {
|
|
|
4788
4865
|
], 2),
|
|
4789
4866
|
S[4] || (S[4] = h("div", { class: "rpt-title" }, "Rpt", -1)),
|
|
4790
4867
|
h("div", gU, [
|
|
4791
|
-
h("div", HU, K(r(
|
|
4868
|
+
h("div", HU, K(r(V).currentBeat), 1)
|
|
4792
4869
|
]),
|
|
4793
4870
|
S[5] || (S[5] = h("div", { class: "beat-title" }, "Beat", -1))
|
|
4794
4871
|
], 64)),
|
|
@@ -4876,17 +4953,17 @@ const zU = {
|
|
|
4876
4953
|
"30d64f7d": t.value,
|
|
4877
4954
|
b8fbe65e: d.focusColor
|
|
4878
4955
|
}));
|
|
4879
|
-
const l = d, U = O("el"), { width: F, height: Z } = ll(U),
|
|
4880
|
-
v(
|
|
4881
|
-
const n = l.transformSliderToDisplay(
|
|
4882
|
-
|
|
4883
|
-
}), v(
|
|
4884
|
-
|
|
4956
|
+
const l = d, U = O("el"), { width: F, height: Z } = ll(U), Q = _(d, "value"), V = x(l.formatValue(l.transformSliderToDisplay(Q.value)));
|
|
4957
|
+
v(Q, () => {
|
|
4958
|
+
const n = l.transformSliderToDisplay(Q.value);
|
|
4959
|
+
V.value = l.formatValue(n);
|
|
4960
|
+
}), v(V, () => {
|
|
4961
|
+
V.value = l.validateInput(V.value), l.maxChars && V.value.length > l.maxChars && (V.value = V.value.slice(0, l.maxChars));
|
|
4885
4962
|
});
|
|
4886
|
-
const t =
|
|
4963
|
+
const t = G(() => Math.min(Z.value / 2.25, F.value / 2.2) + "px"), R = G(() => Math.min(F.value / 3, Z.value / 6.4) + "px");
|
|
4887
4964
|
function a() {
|
|
4888
|
-
const n = l.parseValue(
|
|
4889
|
-
|
|
4965
|
+
const n = l.parseValue(V.value), m = l.transformDisplayToSlider(n);
|
|
4966
|
+
Q.value = Math.min(Math.max(m, l.sliderMin), l.sliderMax);
|
|
4890
4967
|
}
|
|
4891
4968
|
return (n, m) => (X(), Y("div", {
|
|
4892
4969
|
class: "outer",
|
|
@@ -4897,18 +4974,18 @@ const zU = {
|
|
|
4897
4974
|
vl(h("input", {
|
|
4898
4975
|
type: "text",
|
|
4899
4976
|
class: "input",
|
|
4900
|
-
"onUpdate:modelValue": m[0] || (m[0] = (
|
|
4977
|
+
"onUpdate:modelValue": m[0] || (m[0] = (W) => V.value = W),
|
|
4901
4978
|
inputmode: "decimal",
|
|
4902
4979
|
pattern: "\\d*",
|
|
4903
4980
|
onChange: a
|
|
4904
4981
|
}, null, 544), [
|
|
4905
|
-
[Kl,
|
|
4982
|
+
[Kl, V.value]
|
|
4906
4983
|
]),
|
|
4907
4984
|
h("div", fU, K(d.title), 1),
|
|
4908
4985
|
C(bl, {
|
|
4909
4986
|
class: "slider",
|
|
4910
|
-
value:
|
|
4911
|
-
"onUpdate:value": m[1] || (m[1] = (
|
|
4987
|
+
value: Q.value,
|
|
4988
|
+
"onUpdate:value": m[1] || (m[1] = (W) => Q.value = W),
|
|
4912
4989
|
"thumb-length": d.thumbLength,
|
|
4913
4990
|
max: d.sliderMax,
|
|
4914
4991
|
min: d.sliderMin
|
|
@@ -4918,13 +4995,13 @@ const zU = {
|
|
|
4918
4995
|
}, ql = /* @__PURE__ */ g(AU, [["__scopeId", "data-v-79c7a539"]]), qU = {
|
|
4919
4996
|
__name: "SpeedInput",
|
|
4920
4997
|
setup(d) {
|
|
4921
|
-
const l = Ul(), U = Rl(), F =
|
|
4998
|
+
const l = Ul(), U = Rl(), F = G({
|
|
4922
4999
|
get: () => Math.log2(l.playbackSpeed) * 0.5 + 0.5,
|
|
4923
5000
|
set: (a) => {
|
|
4924
5001
|
const n = Math.pow(2, a * 2 - 1);
|
|
4925
5002
|
U.setPlaybackSpeed(n);
|
|
4926
5003
|
}
|
|
4927
|
-
}), Z = (a) => Math.floor(Math.pow(2, a * 2 - 1) * 100 + 0.5) + "",
|
|
5004
|
+
}), Z = (a) => Math.floor(Math.pow(2, a * 2 - 1) * 100 + 0.5) + "", Q = (a) => parseFloat(a), V = (a) => a.replace(/\D/g, ""), t = (a) => a, R = (a) => {
|
|
4928
5005
|
const n = Math.log2(a / 100) * 0.5 + 0.5;
|
|
4929
5006
|
return Math.min(Math.max(n, 0), 1);
|
|
4930
5007
|
};
|
|
@@ -4935,8 +5012,8 @@ const zU = {
|
|
|
4935
5012
|
color: "#336",
|
|
4936
5013
|
"text-color": "#aad",
|
|
4937
5014
|
"format-value": Z,
|
|
4938
|
-
"parse-value":
|
|
4939
|
-
"validate-input":
|
|
5015
|
+
"parse-value": Q,
|
|
5016
|
+
"validate-input": V,
|
|
4940
5017
|
"transform-slider-to-display": t,
|
|
4941
5018
|
"transform-display-to-slider": R,
|
|
4942
5019
|
"thumb-length": 2,
|
|
@@ -4946,7 +5023,7 @@ const zU = {
|
|
|
4946
5023
|
}, _U = {
|
|
4947
5024
|
__name: "TimeInput",
|
|
4948
5025
|
setup(d) {
|
|
4949
|
-
const l = Ul(), U = tl(), F = Rl(), Z = (a) => a.toFixed(1),
|
|
5026
|
+
const l = Ul(), U = tl(), F = Rl(), Z = (a) => a.toFixed(1), Q = (a) => parseFloat(a), V = (a) => a.replace(/[^0-9.]/g, ""), t = (a) => a, R = (a) => a;
|
|
4950
5027
|
return (a, n) => (X(), nl(ql, {
|
|
4951
5028
|
value: r(l).currentTime,
|
|
4952
5029
|
"onUpdate:value": [
|
|
@@ -4961,8 +5038,8 @@ const zU = {
|
|
|
4961
5038
|
"slider-max": r(U).totalDuration,
|
|
4962
5039
|
"slider-min": 0,
|
|
4963
5040
|
"format-value": Z,
|
|
4964
|
-
"parse-value":
|
|
4965
|
-
"validate-input":
|
|
5041
|
+
"parse-value": Q,
|
|
5042
|
+
"validate-input": V,
|
|
4966
5043
|
"transform-slider-to-display": t,
|
|
4967
5044
|
"transform-display-to-slider": R,
|
|
4968
5045
|
"thumb-length": 2
|
|
@@ -4972,7 +5049,7 @@ const zU = {
|
|
|
4972
5049
|
__name: "AudioButton",
|
|
4973
5050
|
setup(d) {
|
|
4974
5051
|
const l = x(!1), U = () => l.value = !0, F = () => l.value = !1;
|
|
4975
|
-
return (Z,
|
|
5052
|
+
return (Z, Q) => (X(), Y("div", {
|
|
4976
5053
|
class: L(["button-outer", { down: l.value }]),
|
|
4977
5054
|
onPointerdown: U,
|
|
4978
5055
|
onPointerup: F,
|
|
@@ -4993,22 +5070,22 @@ const zU = {
|
|
|
4993
5070
|
function Z() {
|
|
4994
5071
|
U.isPlaying ? F.stop() : F.play();
|
|
4995
5072
|
}
|
|
4996
|
-
function
|
|
4997
|
-
const y = U.currentTime,
|
|
5073
|
+
function Q() {
|
|
5074
|
+
const y = U.currentTime, u = l.beats.filter((E) => E.beat === 1).sort((E, H) => E.time - H.time);
|
|
4998
5075
|
let k = null;
|
|
4999
|
-
for (let E =
|
|
5000
|
-
if (
|
|
5001
|
-
k =
|
|
5076
|
+
for (let E = u.length - 1; E >= 0; E--)
|
|
5077
|
+
if (u[E].time < y) {
|
|
5078
|
+
k = u[E];
|
|
5002
5079
|
break;
|
|
5003
5080
|
}
|
|
5004
5081
|
k && F.setBar(k.bar, k.repeat);
|
|
5005
5082
|
}
|
|
5006
|
-
function
|
|
5007
|
-
const y = U.currentTime,
|
|
5083
|
+
function V() {
|
|
5084
|
+
const y = U.currentTime, u = l.beats.filter((E) => E.beat === 1).sort((E, H) => E.time - H.time);
|
|
5008
5085
|
let k = null;
|
|
5009
|
-
for (let E = 0; E <
|
|
5010
|
-
if (
|
|
5011
|
-
k =
|
|
5086
|
+
for (let E = 0; E < u.length; E++)
|
|
5087
|
+
if (u[E].time > y) {
|
|
5088
|
+
k = u[E];
|
|
5012
5089
|
break;
|
|
5013
5090
|
}
|
|
5014
5091
|
k && F.setBar(k.bar, k.repeat);
|
|
@@ -5016,8 +5093,8 @@ const zU = {
|
|
|
5016
5093
|
function t() {
|
|
5017
5094
|
F.playStartingNotes();
|
|
5018
5095
|
}
|
|
5019
|
-
const R =
|
|
5020
|
-
function
|
|
5096
|
+
const R = G(() => U.metronomeEnabled), a = G(() => U.leadInEnabled), n = x(!1), m = x(null);
|
|
5097
|
+
function W() {
|
|
5021
5098
|
n.value = !n.value, n.value && F.audioEngine.initializeAudioSystem().catch((y) => {
|
|
5022
5099
|
console.warn("Audio system pre-initialization failed:", y);
|
|
5023
5100
|
});
|
|
@@ -5039,14 +5116,14 @@ const zU = {
|
|
|
5039
5116
|
function J() {
|
|
5040
5117
|
F.toggleLeadIn();
|
|
5041
5118
|
}
|
|
5042
|
-
const p =
|
|
5119
|
+
const p = G({
|
|
5043
5120
|
get: () => U.masterVolume,
|
|
5044
5121
|
set: (y) => U.setMasterVolume(y)
|
|
5045
|
-
}), M =
|
|
5122
|
+
}), M = G({
|
|
5046
5123
|
get: () => U.metronomeVolume,
|
|
5047
5124
|
set: (y) => U.setMetronomeVolume(y)
|
|
5048
5125
|
});
|
|
5049
|
-
return (y,
|
|
5126
|
+
return (y, u) => (X(), Y("div", UF, [
|
|
5050
5127
|
h("div", FF, [
|
|
5051
5128
|
C(wl, {
|
|
5052
5129
|
class: "text",
|
|
@@ -5065,8 +5142,8 @@ const zU = {
|
|
|
5065
5142
|
(X(), Y("svg", {
|
|
5066
5143
|
class: "menu",
|
|
5067
5144
|
viewBox: "0 -960 960 960",
|
|
5068
|
-
onClick:
|
|
5069
|
-
},
|
|
5145
|
+
onClick: W
|
|
5146
|
+
}, u[2] || (u[2] = [
|
|
5070
5147
|
h("path", { d: "M120-240v-80h720v80H120Zm0-200v-80h720v80H120Zm0-200v-80h720v80H120Z" }, null, -1)
|
|
5071
5148
|
]))),
|
|
5072
5149
|
n.value && y.$slots.menu ? (X(), Y("div", {
|
|
@@ -5082,25 +5159,25 @@ const zU = {
|
|
|
5082
5159
|
class: "main",
|
|
5083
5160
|
colour: "red",
|
|
5084
5161
|
value: p.value,
|
|
5085
|
-
"onUpdate:value":
|
|
5162
|
+
"onUpdate:value": u[0] || (u[0] = (k) => p.value = k)
|
|
5086
5163
|
}, null, 8, ["value"]),
|
|
5087
5164
|
C(bl, {
|
|
5088
5165
|
class: "tick",
|
|
5089
5166
|
colour: "blue",
|
|
5090
5167
|
value: M.value,
|
|
5091
|
-
"onUpdate:value":
|
|
5168
|
+
"onUpdate:value": u[1] || (u[1] = (k) => M.value = k)
|
|
5092
5169
|
}, null, 8, ["value"]),
|
|
5093
|
-
|
|
5094
|
-
|
|
5170
|
+
u[8] || (u[8] = h("div", { class: "main-t" }, "Main", -1)),
|
|
5171
|
+
u[9] || (u[9] = h("div", { class: "tick-t" }, "Tick", -1)),
|
|
5095
5172
|
C(OU, { class: "bar" }),
|
|
5096
5173
|
C(_U, { class: "time" }),
|
|
5097
5174
|
C(qU, { class: "speed" }),
|
|
5098
5175
|
h("div", dF, [
|
|
5099
5176
|
C(Fl, {
|
|
5100
5177
|
class: "button",
|
|
5101
|
-
onClick:
|
|
5178
|
+
onClick: Q
|
|
5102
5179
|
}, {
|
|
5103
|
-
default: D(() =>
|
|
5180
|
+
default: D(() => u[3] || (u[3] = [
|
|
5104
5181
|
h("svg", {
|
|
5105
5182
|
class: "icon",
|
|
5106
5183
|
viewBox: "0 0 48 48"
|
|
@@ -5126,9 +5203,9 @@ const zU = {
|
|
|
5126
5203
|
}),
|
|
5127
5204
|
C(Fl, {
|
|
5128
5205
|
class: "button",
|
|
5129
|
-
onClick:
|
|
5206
|
+
onClick: V
|
|
5130
5207
|
}, {
|
|
5131
|
-
default: D(() =>
|
|
5208
|
+
default: D(() => u[4] || (u[4] = [
|
|
5132
5209
|
h("svg", {
|
|
5133
5210
|
class: "icon",
|
|
5134
5211
|
viewBox: "0 0 48 48"
|
|
@@ -5147,7 +5224,7 @@ const zU = {
|
|
|
5147
5224
|
(X(), Y("svg", {
|
|
5148
5225
|
class: L(["icon", R.value ? "on" : "off"]),
|
|
5149
5226
|
viewBox: "-128 -128 768 768"
|
|
5150
|
-
},
|
|
5227
|
+
}, u[5] || (u[5] = [
|
|
5151
5228
|
h("path", { d: "m 463.84136,154.89339 c -6.42,-6.42 -16.83,-6.42 -23.251,0 -71.31197,70.35135 -136.61146,132.25426 -208.741,199.7 h -105.82 c 23.35495,-140.1063 67.13099,-217.59716 120.727,-318.357996 0.86,-0.803 2.209,-0.801 3.067,-10e-4 20.50653,37.383983 48.51152,88.812606 72.26194,147.190756 1.186,9.002 12.2214,17.4338 23.3242,11.71391 9.002,-1.186 11.1594,-12.2324 9.9724,-21.2344 -21.69905,-53.89113 -30.43965,-85.078342 -83.11454,-161.702266 -13.446,-12.55299965 -34.508,-12.55699965 -47.954,10e-4 C 126.80877,149.30021 96.099465,324.74626 77.091365,474.25139 c -2.829,21.473 13.907,40.535 35.543995,40.535 h 271.311 c 21.661,0 38.373,-19.087 35.544,-40.535 -8.26237,-52.34207 -14.88466,-100.7074 -24.7871,-157.02622 -6.40949,-11.78839 -8.3911,-14.9907 -17.4031,-13.8037 -9.002,1.186 -13.59751,8.0528 -12.41051,17.0548 l 5.66371,34.11712 h -83.159 c 64.35441,-63.86663 129.29308,-130.29894 176.448,-176.449 6.42,-6.42 6.42,-16.83 -10e-4,-23.251 z m -88.956,232.582 12.004,91.074 c 0.112,0.846 -0.148,1.701 -0.708,2.341 -0.566,0.645 -1.38,1.014 -2.235,1.014 h -271.311 c -0.855,0 -1.668,-0.369 -2.231,-1.011 -0.564,-0.643 -0.824,-1.499 -0.712,-2.347 l 12.003,-91.072 h 253.19 z" }, null, -1)
|
|
5152
5229
|
]), 2))
|
|
5153
5230
|
]),
|
|
@@ -5161,7 +5238,7 @@ const zU = {
|
|
|
5161
5238
|
(X(), Y("svg", {
|
|
5162
5239
|
class: L(["icon", a.value ? "on" : "off"]),
|
|
5163
5240
|
viewBox: "-2 -2 28 28"
|
|
5164
|
-
},
|
|
5241
|
+
}, u[6] || (u[6] = [
|
|
5165
5242
|
h("path", { d: "m 8.9838564,1.5166215 v 2 h 5.9999996 v -2 z m 2.9999996,3 c -4.9699996,0 -8.9999996,4.0299999 -8.9999996,8.9999995 0,4.97 4.02,9 8.9999996,9 4.98,0 9,-4.03 9,-9 0,-2.12 -0.740703,-4.0693745 -1.970703,-5.6093745 l 1.419922,-1.421875 c -0.43,-0.51 -0.900156,-0.9882031 -1.410156,-1.4082031 l -1.419922,1.4199219 c -1.55,-1.24 -3.499141,-1.9804688 -5.619141,-1.9804688 z m -1.789062,4.7480469 6,4.4999996 -6,4.5 z" }, null, -1)
|
|
5166
5243
|
]), 2))
|
|
5167
5244
|
]),
|
|
@@ -5171,7 +5248,7 @@ const zU = {
|
|
|
5171
5248
|
class: "button",
|
|
5172
5249
|
onClick: t
|
|
5173
5250
|
}, {
|
|
5174
|
-
default: D(() =>
|
|
5251
|
+
default: D(() => u[7] || (u[7] = [
|
|
5175
5252
|
h("svg", {
|
|
5176
5253
|
class: "icon",
|
|
5177
5254
|
viewBox: "0 -960 960 960"
|
|
@@ -5219,8 +5296,8 @@ const zU = {
|
|
|
5219
5296
|
}
|
|
5220
5297
|
},
|
|
5221
5298
|
setup(d) {
|
|
5222
|
-
const l = d, U =
|
|
5223
|
-
return (
|
|
5299
|
+
const l = d, U = G(() => l.progress !== null), F = G(() => l.progress === null ? 0 : Math.max(0, Math.min(100, l.progress * 100))), Z = G(() => l.hasError ? l.errorMessage : l.message);
|
|
5300
|
+
return (Q, V) => (X(), Y("div", RF, [
|
|
5224
5301
|
U.value ? (X(), Y("div", aF, [
|
|
5225
5302
|
h("div", {
|
|
5226
5303
|
class: "progress-fill",
|
|
@@ -5298,7 +5375,7 @@ const zU = {
|
|
|
5298
5375
|
}), cF = { class: "container" }, eF = { class: "panel" }, sF = {
|
|
5299
5376
|
key: 0,
|
|
5300
5377
|
class: "blur"
|
|
5301
|
-
}, rl = 40, Ll = 40, Cl = 100, hF = 50, xl = 400, Ml = 570, zl = 570, BF = 350, JF = 330,
|
|
5378
|
+
}, rl = 40, Ll = 40, Cl = 100, hF = 50, xl = 400, Ml = 570, zl = 570, BF = 350, JF = 330, uF = 360, GF = 360, iF = {
|
|
5302
5379
|
__name: "MixerLayout",
|
|
5303
5380
|
props: {
|
|
5304
5381
|
/** Whether to show initialization progress (default: true) */
|
|
@@ -5308,30 +5385,30 @@ const zU = {
|
|
|
5308
5385
|
}
|
|
5309
5386
|
},
|
|
5310
5387
|
setup(d) {
|
|
5311
|
-
$((
|
|
5312
|
-
|
|
5313
|
-
"
|
|
5314
|
-
"
|
|
5388
|
+
$((W) => ({
|
|
5389
|
+
"53ffcc08": a.value,
|
|
5390
|
+
"53f8f922": n.value,
|
|
5391
|
+
"2b0b3d37": m.value
|
|
5315
5392
|
}));
|
|
5316
5393
|
const l = d, U = tl(), F = Ul(), Z = bF();
|
|
5317
5394
|
el(() => {
|
|
5318
5395
|
Z.initializeListeners();
|
|
5319
5396
|
});
|
|
5320
|
-
const
|
|
5321
|
-
const
|
|
5322
|
-
return
|
|
5323
|
-
}), a =
|
|
5397
|
+
const Q = O("container"), { width: V } = ll(Q), t = G(() => F.isLoaded), R = G(() => {
|
|
5398
|
+
const W = V.value, c = U.parts.length;
|
|
5399
|
+
return W < 640 || W < rl * c + xl ? 0 : W < Ll * c + Ml ? 1 : W < Cl * c + zl ? 2 : 3;
|
|
5400
|
+
}), a = G(() => {
|
|
5324
5401
|
switch (R.value) {
|
|
5325
5402
|
case 0:
|
|
5326
5403
|
return `${BF}px ` + `${hF}px `.repeat(U.parts.length);
|
|
5327
5404
|
case 1:
|
|
5328
5405
|
return `${JF}px`;
|
|
5329
5406
|
case 2:
|
|
5330
|
-
return `${GF}px`;
|
|
5331
|
-
default:
|
|
5332
5407
|
return `${uF}px`;
|
|
5408
|
+
default:
|
|
5409
|
+
return `${GF}px`;
|
|
5333
5410
|
}
|
|
5334
|
-
}), n =
|
|
5411
|
+
}), n = G(() => {
|
|
5335
5412
|
switch (R.value) {
|
|
5336
5413
|
case 0:
|
|
5337
5414
|
return "100vw";
|
|
@@ -5342,14 +5419,14 @@ const zU = {
|
|
|
5342
5419
|
default:
|
|
5343
5420
|
return `${Cl}px `.repeat(U.parts.length) + `${zl}px`;
|
|
5344
5421
|
}
|
|
5345
|
-
}), m =
|
|
5346
|
-
const
|
|
5347
|
-
return R.value > 0 ? '"' +
|
|
5422
|
+
}), m = G(() => {
|
|
5423
|
+
const W = [...U.parts.keys()];
|
|
5424
|
+
return R.value > 0 ? '"' + W.map((c) => "part" + c).join(" ") + ' controls"' : '"controls" ' + W.map((c) => '"part' + c + '"').join(" ");
|
|
5348
5425
|
});
|
|
5349
|
-
return (
|
|
5426
|
+
return (W, c) => (X(), Y("div", {
|
|
5350
5427
|
class: "outer",
|
|
5351
5428
|
ref_key: "container",
|
|
5352
|
-
ref:
|
|
5429
|
+
ref: Q
|
|
5353
5430
|
}, [
|
|
5354
5431
|
h("div", cF, [
|
|
5355
5432
|
h("div", eF, [
|
|
@@ -5371,7 +5448,7 @@ const zU = {
|
|
|
5371
5448
|
class: "controls"
|
|
5372
5449
|
}, {
|
|
5373
5450
|
menu: D(() => [
|
|
5374
|
-
Vl(
|
|
5451
|
+
Vl(W.$slots, "menu", {}, void 0, !0)
|
|
5375
5452
|
]),
|
|
5376
5453
|
_: 3
|
|
5377
5454
|
}, 8, ["title"]),
|
|
@@ -5388,7 +5465,7 @@ const zU = {
|
|
|
5388
5465
|
])
|
|
5389
5466
|
], 512));
|
|
5390
5467
|
}
|
|
5391
|
-
}, TF = /* @__PURE__ */ g(iF, [["__scopeId", "data-v-
|
|
5468
|
+
}, TF = /* @__PURE__ */ g(iF, [["__scopeId", "data-v-cd7cb6a9"]]), SF = { class: "outer" }, oF = { class: "mid" }, XF = { class: "inner" }, NF = {
|
|
5392
5469
|
key: 0,
|
|
5393
5470
|
class: "content"
|
|
5394
5471
|
}, pF = {
|
|
@@ -5570,7 +5647,7 @@ export {
|
|
|
5570
5647
|
bl as AudioSlider,
|
|
5571
5648
|
OU as BarInput,
|
|
5572
5649
|
ql as BaseNumericInput,
|
|
5573
|
-
|
|
5650
|
+
Gl as DEV_MODE,
|
|
5574
5651
|
YF as DummyAudioEngine,
|
|
5575
5652
|
WF as InitializationProgress,
|
|
5576
5653
|
tF as MixerControls,
|