audio-mixer-ui 0.5.1 → 0.5.3
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 +1009 -923
- package/dist/audio-mixer-ui.umd.cjs +9 -9
- 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
|
-
function
|
|
6
|
+
function Z(l, U) {
|
|
7
7
|
var F = -1;
|
|
8
|
-
return l.some(function(
|
|
9
|
-
return
|
|
8
|
+
return l.some(function(d, Q) {
|
|
9
|
+
return d[0] === U ? (F = Q, !0) : !1;
|
|
10
10
|
}), F;
|
|
11
11
|
}
|
|
12
12
|
return (
|
|
@@ -25,204 +25,204 @@ var gl = function() {
|
|
|
25
25
|
enumerable: !0,
|
|
26
26
|
configurable: !0
|
|
27
27
|
}), l.prototype.get = function(U) {
|
|
28
|
-
var F =
|
|
29
|
-
return
|
|
28
|
+
var F = Z(this.__entries__, U), d = this.__entries__[F];
|
|
29
|
+
return d && d[1];
|
|
30
30
|
}, l.prototype.set = function(U, F) {
|
|
31
|
-
var
|
|
32
|
-
~
|
|
31
|
+
var d = Z(this.__entries__, U);
|
|
32
|
+
~d ? this.__entries__[d][1] = F : this.__entries__.push([U, F]);
|
|
33
33
|
}, l.prototype.delete = function(U) {
|
|
34
|
-
var F = this.__entries__,
|
|
35
|
-
~
|
|
34
|
+
var F = this.__entries__, d = Z(F, U);
|
|
35
|
+
~d && F.splice(d, 1);
|
|
36
36
|
}, l.prototype.has = function(U) {
|
|
37
|
-
return !!~
|
|
37
|
+
return !!~Z(this.__entries__, U);
|
|
38
38
|
}, l.prototype.clear = 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
|
|
43
|
-
var
|
|
44
|
-
U.call(F,
|
|
42
|
+
for (var d = 0, Q = this.__entries__; d < Q.length; d++) {
|
|
43
|
+
var V = Q[d];
|
|
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
|
-
return typeof requestAnimationFrame == "function" ? requestAnimationFrame.bind(ml) : function(
|
|
52
|
+
return typeof requestAnimationFrame == "function" ? requestAnimationFrame.bind(ml) : function(Z) {
|
|
53
53
|
return setTimeout(function() {
|
|
54
|
-
return
|
|
54
|
+
return Z(Date.now());
|
|
55
55
|
}, 1e3 / 60);
|
|
56
56
|
};
|
|
57
57
|
}(), ZU = 2;
|
|
58
|
-
function QU(
|
|
59
|
-
var U = !1, F = !1,
|
|
60
|
-
function V() {
|
|
61
|
-
U && (U = !1, d()), F && t();
|
|
62
|
-
}
|
|
58
|
+
function QU(Z, l) {
|
|
59
|
+
var U = !1, F = !1, d = 0;
|
|
63
60
|
function Q() {
|
|
64
|
-
|
|
61
|
+
U && (U = !1, Z()), F && t();
|
|
62
|
+
}
|
|
63
|
+
function V() {
|
|
64
|
+
dU(Q);
|
|
65
65
|
}
|
|
66
66
|
function t() {
|
|
67
67
|
var R = Date.now();
|
|
68
68
|
if (U) {
|
|
69
|
-
if (R -
|
|
69
|
+
if (R - d < ZU)
|
|
70
70
|
return;
|
|
71
71
|
F = !0;
|
|
72
72
|
} else
|
|
73
|
-
U = !0, F = !1, setTimeout(
|
|
74
|
-
|
|
73
|
+
U = !0, F = !1, setTimeout(V, l);
|
|
74
|
+
d = R;
|
|
75
75
|
}
|
|
76
76
|
return t;
|
|
77
77
|
}
|
|
78
78
|
var VU = 20, tU = ["top", "right", "bottom", "left", "width", "height", "size", "weight"], RU = typeof MutationObserver < "u", aU = (
|
|
79
79
|
/** @class */
|
|
80
80
|
function() {
|
|
81
|
-
function
|
|
81
|
+
function Z() {
|
|
82
82
|
this.connected_ = !1, this.mutationEventsAdded_ = !1, this.mutationsObserver_ = null, this.observers_ = [], this.onTransitionEnd_ = this.onTransitionEnd_.bind(this), this.refresh = QU(this.refresh.bind(this), VU);
|
|
83
83
|
}
|
|
84
|
-
return
|
|
84
|
+
return Z.prototype.addObserver = function(l) {
|
|
85
85
|
~this.observers_.indexOf(l) || this.observers_.push(l), this.connected_ || this.connect_();
|
|
86
|
-
},
|
|
86
|
+
}, Z.prototype.removeObserver = function(l) {
|
|
87
87
|
var U = this.observers_, F = U.indexOf(l);
|
|
88
88
|
~F && U.splice(F, 1), !U.length && this.connected_ && this.disconnect_();
|
|
89
|
-
},
|
|
89
|
+
}, Z.prototype.refresh = function() {
|
|
90
90
|
var l = this.updateObservers_();
|
|
91
91
|
l && this.refresh();
|
|
92
|
-
},
|
|
92
|
+
}, Z.prototype.updateObservers_ = function() {
|
|
93
93
|
var l = this.observers_.filter(function(U) {
|
|
94
94
|
return U.gatherActive(), U.hasActive();
|
|
95
95
|
});
|
|
96
96
|
return l.forEach(function(U) {
|
|
97
97
|
return U.broadcastActive();
|
|
98
98
|
}), l.length > 0;
|
|
99
|
-
},
|
|
100
|
-
!
|
|
99
|
+
}, Z.prototype.connect_ = function() {
|
|
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
|
-
},
|
|
107
|
-
!
|
|
108
|
-
},
|
|
109
|
-
var U = l.propertyName, F = U === void 0 ? "" : U,
|
|
110
|
-
return !!~F.indexOf(
|
|
106
|
+
}, Z.prototype.disconnect_ = function() {
|
|
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
|
+
}, Z.prototype.onTransitionEnd_ = function(l) {
|
|
109
|
+
var U = l.propertyName, F = U === void 0 ? "" : U, d = tU.some(function(Q) {
|
|
110
|
+
return !!~F.indexOf(Q);
|
|
111
111
|
});
|
|
112
|
-
|
|
113
|
-
},
|
|
114
|
-
return this.instance_ || (this.instance_ = new
|
|
115
|
-
},
|
|
112
|
+
d && this.refresh();
|
|
113
|
+
}, Z.getInstance = function() {
|
|
114
|
+
return this.instance_ || (this.instance_ = new Z()), this.instance_;
|
|
115
|
+
}, Z.instance_ = null, Z;
|
|
116
116
|
}()
|
|
117
|
-
), Hl = function(
|
|
117
|
+
), Hl = function(Z, l) {
|
|
118
118
|
for (var U = 0, F = Object.keys(l); U < F.length; U++) {
|
|
119
|
-
var
|
|
120
|
-
Object.defineProperty(
|
|
121
|
-
value: l[
|
|
119
|
+
var d = F[U];
|
|
120
|
+
Object.defineProperty(Z, d, {
|
|
121
|
+
value: l[d],
|
|
122
122
|
enumerable: !1,
|
|
123
123
|
writable: !1,
|
|
124
124
|
configurable: !0
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
|
-
return
|
|
128
|
-
}, dl = function(
|
|
129
|
-
var l =
|
|
127
|
+
return Z;
|
|
128
|
+
}, dl = function(Z) {
|
|
129
|
+
var l = Z && Z.ownerDocument && Z.ownerDocument.defaultView;
|
|
130
130
|
return l || ml;
|
|
131
131
|
}, Dl = hl(0, 0, 0, 0);
|
|
132
|
-
function Wl(
|
|
133
|
-
return parseFloat(
|
|
132
|
+
function Wl(Z) {
|
|
133
|
+
return parseFloat(Z) || 0;
|
|
134
134
|
}
|
|
135
|
-
function Tl(
|
|
135
|
+
function Tl(Z) {
|
|
136
136
|
for (var l = [], U = 1; U < arguments.length; U++)
|
|
137
137
|
l[U - 1] = arguments[U];
|
|
138
|
-
return l.reduce(function(F,
|
|
139
|
-
var
|
|
140
|
-
return F + Wl(
|
|
138
|
+
return l.reduce(function(F, d) {
|
|
139
|
+
var Q = Z["border-" + d + "-width"];
|
|
140
|
+
return F + Wl(Q);
|
|
141
141
|
}, 0);
|
|
142
142
|
}
|
|
143
|
-
function nU(
|
|
144
|
-
for (var l = ["top", "right", "bottom", "left"], U = {}, F = 0,
|
|
145
|
-
var
|
|
146
|
-
U[
|
|
143
|
+
function nU(Z) {
|
|
144
|
+
for (var l = ["top", "right", "bottom", "left"], U = {}, F = 0, d = l; F < d.length; F++) {
|
|
145
|
+
var Q = d[F], V = Z["padding-" + Q];
|
|
146
|
+
U[Q] = Wl(V);
|
|
147
147
|
}
|
|
148
148
|
return U;
|
|
149
149
|
}
|
|
150
|
-
function mU(
|
|
151
|
-
var l =
|
|
150
|
+
function mU(Z) {
|
|
151
|
+
var l = Z.getBBox();
|
|
152
152
|
return hl(0, 0, l.width, l.height);
|
|
153
153
|
}
|
|
154
|
-
function WU(
|
|
155
|
-
var l =
|
|
154
|
+
function WU(Z) {
|
|
155
|
+
var l = Z.clientWidth, U = Z.clientHeight;
|
|
156
156
|
if (!l && !U)
|
|
157
157
|
return Dl;
|
|
158
|
-
var F = dl(
|
|
159
|
-
if (F.boxSizing === "border-box" && (Math.round(t +
|
|
160
|
-
var a = Math.round(t +
|
|
158
|
+
var F = dl(Z).getComputedStyle(Z), d = nU(F), Q = d.left + d.right, V = d.top + d.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(Z)) {
|
|
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
|
-
return hl(
|
|
163
|
+
return hl(d.left, d.top, t, R);
|
|
164
164
|
}
|
|
165
165
|
var bU = /* @__PURE__ */ function() {
|
|
166
|
-
return typeof SVGGraphicsElement < "u" ? function(
|
|
167
|
-
return
|
|
168
|
-
} : function(
|
|
169
|
-
return
|
|
166
|
+
return typeof SVGGraphicsElement < "u" ? function(Z) {
|
|
167
|
+
return Z instanceof dl(Z).SVGGraphicsElement;
|
|
168
|
+
} : function(Z) {
|
|
169
|
+
return Z instanceof dl(Z).SVGElement && typeof Z.getBBox == "function";
|
|
170
170
|
};
|
|
171
171
|
}();
|
|
172
|
-
function cU(
|
|
173
|
-
return
|
|
172
|
+
function cU(Z) {
|
|
173
|
+
return Z === dl(Z).document.documentElement;
|
|
174
174
|
}
|
|
175
|
-
function eU(
|
|
176
|
-
return
|
|
175
|
+
function eU(Z) {
|
|
176
|
+
return ul ? bU(Z) ? mU(Z) : WU(Z) : Dl;
|
|
177
177
|
}
|
|
178
|
-
function sU(
|
|
179
|
-
var l =
|
|
180
|
-
return Hl(
|
|
178
|
+
function sU(Z) {
|
|
179
|
+
var l = Z.x, U = Z.y, F = Z.width, d = Z.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,
|
|
184
|
-
height:
|
|
184
|
+
height: d,
|
|
185
185
|
top: U,
|
|
186
186
|
right: l + F,
|
|
187
|
-
bottom:
|
|
187
|
+
bottom: d + U,
|
|
188
188
|
left: l
|
|
189
|
-
}),
|
|
189
|
+
}), V;
|
|
190
190
|
}
|
|
191
|
-
function hl(
|
|
192
|
-
return { x:
|
|
191
|
+
function hl(Z, l, U, F) {
|
|
192
|
+
return { x: Z, y: l, width: U, height: F };
|
|
193
193
|
}
|
|
194
194
|
var hU = (
|
|
195
195
|
/** @class */
|
|
196
196
|
function() {
|
|
197
|
-
function
|
|
197
|
+
function Z(l) {
|
|
198
198
|
this.broadcastWidth = 0, this.broadcastHeight = 0, this.contentRect_ = hl(0, 0, 0, 0), this.target = l;
|
|
199
199
|
}
|
|
200
|
-
return
|
|
200
|
+
return Z.prototype.isActive = function() {
|
|
201
201
|
var l = eU(this.target);
|
|
202
202
|
return this.contentRect_ = l, l.width !== this.broadcastWidth || l.height !== this.broadcastHeight;
|
|
203
|
-
},
|
|
203
|
+
}, Z.prototype.broadcastRect = function() {
|
|
204
204
|
var l = this.contentRect_;
|
|
205
205
|
return this.broadcastWidth = l.width, this.broadcastHeight = l.height, l;
|
|
206
|
-
},
|
|
206
|
+
}, Z;
|
|
207
207
|
}()
|
|
208
208
|
), BU = (
|
|
209
209
|
/** @class */
|
|
210
210
|
/* @__PURE__ */ function() {
|
|
211
|
-
function
|
|
211
|
+
function Z(l, U) {
|
|
212
212
|
var F = sU(U);
|
|
213
213
|
Hl(this, { target: l, contentRect: F });
|
|
214
214
|
}
|
|
215
|
-
return
|
|
215
|
+
return Z;
|
|
216
216
|
}()
|
|
217
217
|
), JU = (
|
|
218
218
|
/** @class */
|
|
219
219
|
function() {
|
|
220
|
-
function
|
|
220
|
+
function Z(l, U, F) {
|
|
221
221
|
if (this.activeObservations_ = [], this.observations_ = new gl(), typeof l != "function")
|
|
222
222
|
throw new TypeError("The callback provided as parameter 1 is not a function.");
|
|
223
223
|
this.callback_ = l, this.controller_ = U, this.callbackCtx_ = F;
|
|
224
224
|
}
|
|
225
|
-
return
|
|
225
|
+
return Z.prototype.observe = function(l) {
|
|
226
226
|
if (!arguments.length)
|
|
227
227
|
throw new TypeError("1 argument required, but only 0 present.");
|
|
228
228
|
if (!(typeof Element > "u" || !(Element instanceof Object))) {
|
|
@@ -231,7 +231,7 @@ var hU = (
|
|
|
231
231
|
var U = this.observations_;
|
|
232
232
|
U.has(l) || (U.set(l, new hU(l)), this.controller_.addObserver(this), this.controller_.refresh());
|
|
233
233
|
}
|
|
234
|
-
},
|
|
234
|
+
}, Z.prototype.unobserve = function(l) {
|
|
235
235
|
if (!arguments.length)
|
|
236
236
|
throw new TypeError("1 argument required, but only 0 present.");
|
|
237
237
|
if (!(typeof Element > "u" || !(Element instanceof Object))) {
|
|
@@ -240,80 +240,80 @@ var hU = (
|
|
|
240
240
|
var U = this.observations_;
|
|
241
241
|
U.has(l) && (U.delete(l), U.size || this.controller_.removeObserver(this));
|
|
242
242
|
}
|
|
243
|
-
},
|
|
243
|
+
}, Z.prototype.disconnect = function() {
|
|
244
244
|
this.clearActive(), this.observations_.clear(), this.controller_.removeObserver(this);
|
|
245
|
-
},
|
|
245
|
+
}, Z.prototype.gatherActive = function() {
|
|
246
246
|
var l = this;
|
|
247
247
|
this.clearActive(), this.observations_.forEach(function(U) {
|
|
248
248
|
U.isActive() && l.activeObservations_.push(U);
|
|
249
249
|
});
|
|
250
|
-
},
|
|
250
|
+
}, Z.prototype.broadcastActive = function() {
|
|
251
251
|
if (this.hasActive()) {
|
|
252
252
|
var l = this.callbackCtx_, U = this.activeObservations_.map(function(F) {
|
|
253
253
|
return new BU(F.target, F.broadcastRect());
|
|
254
254
|
});
|
|
255
255
|
this.callback_.call(l, U, l), this.clearActive();
|
|
256
256
|
}
|
|
257
|
-
},
|
|
257
|
+
}, Z.prototype.clearActive = function() {
|
|
258
258
|
this.activeObservations_.splice(0);
|
|
259
|
-
},
|
|
259
|
+
}, Z.prototype.hasActive = function() {
|
|
260
260
|
return this.activeObservations_.length > 0;
|
|
261
|
-
},
|
|
261
|
+
}, Z;
|
|
262
262
|
}()
|
|
263
263
|
), jl = typeof WeakMap < "u" ? /* @__PURE__ */ new WeakMap() : new gl(), Pl = (
|
|
264
264
|
/** @class */
|
|
265
265
|
/* @__PURE__ */ function() {
|
|
266
|
-
function
|
|
267
|
-
if (!(this instanceof
|
|
266
|
+
function Z(l) {
|
|
267
|
+
if (!(this instanceof Z))
|
|
268
268
|
throw new TypeError("Cannot call a class as a function.");
|
|
269
269
|
if (!arguments.length)
|
|
270
270
|
throw new TypeError("1 argument required, but only 0 present.");
|
|
271
271
|
var U = aU.getInstance(), F = new JU(l, U, this);
|
|
272
272
|
jl.set(this, F);
|
|
273
273
|
}
|
|
274
|
-
return
|
|
274
|
+
return Z;
|
|
275
275
|
}()
|
|
276
276
|
);
|
|
277
277
|
[
|
|
278
278
|
"observe",
|
|
279
279
|
"unobserve",
|
|
280
280
|
"disconnect"
|
|
281
|
-
].forEach(function(
|
|
282
|
-
Pl.prototype[
|
|
281
|
+
].forEach(function(Z) {
|
|
282
|
+
Pl.prototype[Z] = function() {
|
|
283
283
|
var l;
|
|
284
|
-
return (l = jl.get(this))[
|
|
284
|
+
return (l = jl.get(this))[Z].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
|
-
function ll(
|
|
290
|
+
function ll(Z) {
|
|
291
291
|
const l = x(0), U = x(0);
|
|
292
292
|
let F = null;
|
|
293
|
-
const
|
|
293
|
+
const d = () => {
|
|
294
294
|
F && (F.disconnect(), F = null);
|
|
295
295
|
};
|
|
296
|
-
return v(() => r(
|
|
297
|
-
|
|
298
|
-
const
|
|
299
|
-
if (!
|
|
300
|
-
F = new
|
|
296
|
+
return v(() => r(Z), () => {
|
|
297
|
+
d();
|
|
298
|
+
const V = r(Z);
|
|
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
|
-
}, { immediate: !0 }), UU(
|
|
306
|
+
}, { immediate: !0 }), UU(d), {
|
|
307
307
|
width: yl(l),
|
|
308
308
|
height: yl(U)
|
|
309
309
|
};
|
|
310
310
|
}
|
|
311
|
-
const g = (
|
|
312
|
-
const U =
|
|
313
|
-
for (const [F,
|
|
314
|
-
U[F] =
|
|
311
|
+
const g = (Z, l) => {
|
|
312
|
+
const U = Z.__vccOpts || Z;
|
|
313
|
+
for (const [F, d] of l)
|
|
314
|
+
U[F] = d;
|
|
315
315
|
return U;
|
|
316
|
-
},
|
|
316
|
+
}, GU = {
|
|
317
317
|
key: 0,
|
|
318
318
|
class: "level"
|
|
319
319
|
}, iU = {
|
|
@@ -332,15 +332,15 @@ const g = (d, l) => {
|
|
|
332
332
|
valueModifiers: {}
|
|
333
333
|
}),
|
|
334
334
|
emits: ["update:value"],
|
|
335
|
-
setup(
|
|
335
|
+
setup(Z) {
|
|
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 =
|
|
343
|
+
const l = Z, U = O("root"), { width: F, height: d } = ll(U), Q = G(() => Math.min(F.value, d.value)), V = G(() => Math.max(F.value, d.value)), t = G(() => F.value > d.value), R = G(() => t.value ? "h-slide" : "v-slide"), a = _(Z, "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
|
-
|
|
385
|
+
Z.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
|
}, [
|
|
@@ -393,7 +393,7 @@ const g = (d, l) => {
|
|
|
393
393
|
], 2)), 64))
|
|
394
394
|
])) : f("", !0),
|
|
395
395
|
h("div", {
|
|
396
|
-
class: L(["thumb", { dragging: p.value, [
|
|
396
|
+
class: L(["thumb", { dragging: p.value, [Z.colour]: !0, [Z.style]: !0 }])
|
|
397
397
|
}, null, 2)
|
|
398
398
|
], 34));
|
|
399
399
|
}
|
|
@@ -405,18 +405,18 @@ const g = (d, l) => {
|
|
|
405
405
|
default: "left"
|
|
406
406
|
}
|
|
407
407
|
},
|
|
408
|
-
setup(
|
|
408
|
+
setup(Z) {
|
|
409
409
|
$((t) => ({
|
|
410
|
-
"5fddb56d":
|
|
410
|
+
"5fddb56d": V.value
|
|
411
411
|
}));
|
|
412
|
-
const l = O("el"), { width: U, height: F } = ll(l),
|
|
412
|
+
const l = O("el"), { width: U, height: F } = ll(l), d = G(() => Math.min(U.value, F.value)), Q = G(() => U.value > F.value ? "h-text" : "v-text"), V = G(() => d.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, [Z.align]: !0 })
|
|
420
420
|
}, [
|
|
421
421
|
Vl(t.$slots, "default", {}, void 0, !0)
|
|
422
422
|
], 2)
|
|
@@ -431,8 +431,8 @@ const g = (d, l) => {
|
|
|
431
431
|
soloModifiers: {}
|
|
432
432
|
},
|
|
433
433
|
emits: ["update:mute", "update:solo"],
|
|
434
|
-
setup(
|
|
435
|
-
const l = _(
|
|
434
|
+
setup(Z) {
|
|
435
|
+
const l = _(Z, "mute"), U = _(Z, "solo"), F = O("outer"), { width: d, height: Q } = ll(F), V = G(() => d.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 = (Z) => Gl.enabled && Gl.features[Z], Ul = sl("audioState", {
|
|
478
478
|
state: () => ({
|
|
479
479
|
// Playback state
|
|
480
480
|
isPlaying: !1,
|
|
@@ -502,78 +502,78 @@ const g = (d, l) => {
|
|
|
502
502
|
}),
|
|
503
503
|
getters: {
|
|
504
504
|
// Format current time as MM:SS
|
|
505
|
-
formattedTime: (
|
|
506
|
-
const l = Math.floor(
|
|
505
|
+
formattedTime: (Z) => {
|
|
506
|
+
const l = Math.floor(Z.currentTime / 60), U = Math.floor(Z.currentTime % 60);
|
|
507
507
|
return `${l}:${U.toString().padStart(2, "0")}`;
|
|
508
508
|
},
|
|
509
509
|
// Get volume for a specific part
|
|
510
|
-
getPartVolume: (
|
|
510
|
+
getPartVolume: (Z) => (l) => Z.partVolumes[l] ?? 0.75,
|
|
511
511
|
// Check if part is muted
|
|
512
|
-
isPartMuted: (
|
|
512
|
+
isPartMuted: (Z) => (l) => Z.partMuted[l] ?? !1,
|
|
513
513
|
// Check if part is solo
|
|
514
|
-
isPartSolo: (
|
|
514
|
+
isPartSolo: (Z) => (l) => Z.partSolo[l] ?? !1,
|
|
515
515
|
// Check if any part has solo enabled (global solo state)
|
|
516
|
-
isAnySolo: (
|
|
516
|
+
isAnySolo: (Z) => Object.values(Z.partSolo).some((l) => l === !0),
|
|
517
517
|
// Current musical position as string
|
|
518
|
-
currentPosition: (
|
|
519
|
-
let l = `${
|
|
520
|
-
return
|
|
518
|
+
currentPosition: (Z) => {
|
|
519
|
+
let l = `${Z.currentBar}.${Z.currentBeat}`;
|
|
520
|
+
return Z.currentRepeat > 0 && (l += ` (R${Z.currentRepeat})`), l;
|
|
521
521
|
}
|
|
522
522
|
},
|
|
523
523
|
actions: {
|
|
524
524
|
// Playback state updates
|
|
525
|
-
setPlaybackState(
|
|
526
|
-
this.isPlaying =
|
|
525
|
+
setPlaybackState(Z) {
|
|
526
|
+
this.isPlaying = Z;
|
|
527
527
|
},
|
|
528
|
-
setCurrentTime(
|
|
529
|
-
this.currentTime =
|
|
528
|
+
setCurrentTime(Z) {
|
|
529
|
+
this.currentTime = Z;
|
|
530
530
|
},
|
|
531
|
-
setPlaybackSpeed(
|
|
532
|
-
this.playbackSpeed =
|
|
531
|
+
setPlaybackSpeed(Z) {
|
|
532
|
+
this.playbackSpeed = Z;
|
|
533
533
|
},
|
|
534
534
|
// Musical position updates
|
|
535
|
-
setCurrentBar(
|
|
536
|
-
typeof
|
|
535
|
+
setCurrentBar(Z, l = 1, U = 0) {
|
|
536
|
+
typeof Z == "number" && (this.currentBar = Z), typeof l == "number" && (this.currentBeat = l), typeof U == "number" && (this.currentRepeat = U);
|
|
537
537
|
},
|
|
538
538
|
// Volume controls
|
|
539
|
-
setMasterVolume(
|
|
540
|
-
this.masterVolume = Math.max(0, Math.min(1,
|
|
539
|
+
setMasterVolume(Z) {
|
|
540
|
+
this.masterVolume = Math.max(0, Math.min(1, Z));
|
|
541
541
|
},
|
|
542
|
-
setMetronomeVolume(
|
|
543
|
-
this.metronomeVolume = Math.max(0, Math.min(1,
|
|
542
|
+
setMetronomeVolume(Z) {
|
|
543
|
+
this.metronomeVolume = Math.max(0, Math.min(1, Z));
|
|
544
544
|
},
|
|
545
|
-
setPartVolume(
|
|
546
|
-
this.partVolumes[
|
|
545
|
+
setPartVolume(Z, l) {
|
|
546
|
+
this.partVolumes[Z] = Math.max(0, Math.min(1, l));
|
|
547
547
|
},
|
|
548
|
-
setPartMuted(
|
|
549
|
-
this.partMuted[
|
|
548
|
+
setPartMuted(Z, l) {
|
|
549
|
+
this.partMuted[Z] = l;
|
|
550
550
|
},
|
|
551
|
-
setPartSolo(
|
|
552
|
-
this.partSolo[
|
|
551
|
+
setPartSolo(Z, l) {
|
|
552
|
+
this.partSolo[Z] = l;
|
|
553
553
|
},
|
|
554
554
|
// Transport features
|
|
555
|
-
setLeadInActive(
|
|
556
|
-
this.isLeadInActive =
|
|
555
|
+
setLeadInActive(Z, l = 1) {
|
|
556
|
+
this.isLeadInActive = Z, this.leadInBars = l;
|
|
557
557
|
},
|
|
558
|
-
setStartingNotesActive(
|
|
559
|
-
this.isStartingNotesActive =
|
|
558
|
+
setStartingNotesActive(Z) {
|
|
559
|
+
this.isStartingNotesActive = Z;
|
|
560
560
|
},
|
|
561
561
|
// Feature toggles
|
|
562
|
-
setMetronomeEnabled(
|
|
563
|
-
this.metronomeEnabled =
|
|
562
|
+
setMetronomeEnabled(Z) {
|
|
563
|
+
this.metronomeEnabled = Z;
|
|
564
564
|
},
|
|
565
|
-
setLeadInEnabled(
|
|
566
|
-
this.leadInEnabled =
|
|
565
|
+
setLeadInEnabled(Z) {
|
|
566
|
+
this.leadInEnabled = Z;
|
|
567
567
|
},
|
|
568
568
|
// Initialize part states
|
|
569
|
-
initializeParts(
|
|
570
|
-
this.partVolumes = {}, this.partMuted = {}, this.partSolo = {},
|
|
569
|
+
initializeParts(Z) {
|
|
570
|
+
this.partVolumes = {}, this.partMuted = {}, this.partSolo = {}, Z.forEach((l) => {
|
|
571
571
|
this.partVolumes[l.name] = l.volume || 0.75, this.partMuted[l.name] = !1, this.partSolo[l.name] = !1;
|
|
572
572
|
});
|
|
573
573
|
},
|
|
574
574
|
// Initialization state (for blur overlay)
|
|
575
|
-
setLoaded(
|
|
576
|
-
this.isLoaded =
|
|
575
|
+
setLoaded(Z) {
|
|
576
|
+
this.isLoaded = Z;
|
|
577
577
|
}
|
|
578
578
|
}
|
|
579
579
|
}), tl = sl("musicData", {
|
|
@@ -592,30 +592,30 @@ const g = (d, l) => {
|
|
|
592
592
|
}),
|
|
593
593
|
getters: {
|
|
594
594
|
// Get practice mark letters as array
|
|
595
|
-
practiceMarkLetters: (
|
|
595
|
+
practiceMarkLetters: (Z) => Object.keys(Z.practiceMarks).sort(),
|
|
596
596
|
// Get bar number for practice mark
|
|
597
|
-
getBarForMark: (
|
|
597
|
+
getBarForMark: (Z) => (l) => Z.practiceMarks[l],
|
|
598
598
|
// Get all unique bar numbers
|
|
599
|
-
allBars: (
|
|
599
|
+
allBars: (Z) => {
|
|
600
600
|
const l = /* @__PURE__ */ new Set();
|
|
601
|
-
return
|
|
601
|
+
return Z.beats.forEach((U) => {
|
|
602
602
|
U.beat === 1 && l.add(U.bar);
|
|
603
603
|
}), Array.from(l).sort((U, F) => U - F);
|
|
604
604
|
},
|
|
605
605
|
// Check if a bar has repeats
|
|
606
|
-
hasRepeats: (
|
|
606
|
+
hasRepeats: (Z) => (l) => Z.beats.some((U) => U.bar === l && U.repeat > 0),
|
|
607
607
|
// Get the number of repeats for a specific bar
|
|
608
|
-
getRepeatCountForBar: (
|
|
608
|
+
getRepeatCountForBar: (Z) => (l) => {
|
|
609
609
|
const U = /* @__PURE__ */ new Set();
|
|
610
|
-
return
|
|
610
|
+
return Z.beats.forEach((F) => {
|
|
611
611
|
F.bar === l && U.add(F.repeat);
|
|
612
612
|
}), U.size;
|
|
613
613
|
}
|
|
614
614
|
},
|
|
615
615
|
actions: {
|
|
616
616
|
// Load musical data
|
|
617
|
-
loadMusicData(
|
|
618
|
-
this.title =
|
|
617
|
+
loadMusicData(Z) {
|
|
618
|
+
this.title = Z.title || "Untitled", this.beats = Z.beats || [], this.practiceMarks = Z.practiceMarks || Z.marks || {}, this.parts = (Z.parts || []).map((l) => ({
|
|
619
619
|
...l,
|
|
620
620
|
solo: l.solo || !1,
|
|
621
621
|
mute: l.mute || !1
|
|
@@ -623,38 +623,38 @@ const g = (d, l) => {
|
|
|
623
623
|
},
|
|
624
624
|
// Calculate total duration from beats
|
|
625
625
|
calculateDuration() {
|
|
626
|
-
this.beats.length > 0 && (this.totalDuration = Math.max(...this.beats.map((
|
|
626
|
+
this.beats.length > 0 && (this.totalDuration = Math.max(...this.beats.map((Z) => Z.time)));
|
|
627
627
|
},
|
|
628
628
|
// Find the highest bar number
|
|
629
629
|
calculateMaxBar() {
|
|
630
|
-
this.beats.length > 0 && (this.maxBar = Math.max(...this.beats.map((
|
|
630
|
+
this.beats.length > 0 && (this.maxBar = Math.max(...this.beats.map((Z) => Z.bar)));
|
|
631
631
|
},
|
|
632
632
|
// Extract time signature from first beat
|
|
633
633
|
extractTimeSignature() {
|
|
634
634
|
this.beats.length > 0 && this.beats[0].timeSig && (this.timeSignature = this.beats[0].timeSig), this.beats.length > 0 && this.beats[0].tempo && (this.baseTempo = this.beats[0].tempo);
|
|
635
635
|
},
|
|
636
636
|
// Update practice marks
|
|
637
|
-
setPracticeMark(
|
|
638
|
-
this.practiceMarks[
|
|
637
|
+
setPracticeMark(Z, l) {
|
|
638
|
+
this.practiceMarks[Z] = l;
|
|
639
639
|
},
|
|
640
|
-
removePracticeMark(
|
|
641
|
-
delete this.practiceMarks[
|
|
640
|
+
removePracticeMark(Z) {
|
|
641
|
+
delete this.practiceMarks[Z];
|
|
642
642
|
},
|
|
643
643
|
// Update beats data (for when MIDI parser provides new beat information)
|
|
644
|
-
updateBeats(
|
|
645
|
-
console.log("Updating beats in music data store"), this.beats =
|
|
644
|
+
updateBeats(Z) {
|
|
645
|
+
console.log("Updating beats in music data store"), this.beats = Z, this.calculateDuration(), this.calculateMaxBar(), this.extractTimeSignature();
|
|
646
646
|
},
|
|
647
647
|
// Update total duration (for when audio engine provides actual duration)
|
|
648
|
-
setTotalDuration(
|
|
649
|
-
console.log("Setting total duration in music data store to:",
|
|
648
|
+
setTotalDuration(Z) {
|
|
649
|
+
console.log("Setting total duration in music data store to:", Z), this.totalDuration = Z;
|
|
650
650
|
},
|
|
651
651
|
// Validate bar number
|
|
652
|
-
isValidBar(
|
|
653
|
-
return this.beats.some((U) => U.bar ===
|
|
652
|
+
isValidBar(Z, l = 0) {
|
|
653
|
+
return this.beats.some((U) => U.bar === Z && U.repeat === l);
|
|
654
654
|
},
|
|
655
655
|
// Update parts (for when audio engine discovers parts from MIDI)
|
|
656
|
-
setParts(
|
|
657
|
-
this.parts =
|
|
656
|
+
setParts(Z) {
|
|
657
|
+
this.parts = Z.map((l) => ({
|
|
658
658
|
name: l.name,
|
|
659
659
|
volume: l.volume || 0.75,
|
|
660
660
|
solo: l.solo || !1,
|
|
@@ -691,20 +691,20 @@ const g = (d, l) => {
|
|
|
691
691
|
}),
|
|
692
692
|
getters: {
|
|
693
693
|
// Check if currently playing
|
|
694
|
-
isPlaying: (
|
|
694
|
+
isPlaying: (Z) => Z.transportState === "playing",
|
|
695
695
|
// Check if paused
|
|
696
|
-
isPaused: (
|
|
696
|
+
isPaused: (Z) => Z.transportState === "paused",
|
|
697
697
|
// Check if stopped
|
|
698
|
-
isStopped: (
|
|
698
|
+
isStopped: (Z) => Z.transportState === "stopped",
|
|
699
699
|
// Check if loop is configured
|
|
700
|
-
isLoopConfigured: (
|
|
700
|
+
isLoopConfigured: (Z) => Z.loopEnabled && Z.loopStart && Z.loopEnd && Z.loopEnd > Z.loopStart,
|
|
701
701
|
// Get loop range as string
|
|
702
|
-
loopRange: (
|
|
702
|
+
loopRange: (Z) => !Z.loopEnabled || !Z.loopStart || !Z.loopEnd ? null : `${Z.loopStart}-${Z.loopEnd}`
|
|
703
703
|
},
|
|
704
704
|
actions: {
|
|
705
705
|
// Transport controls
|
|
706
|
-
setTransportState(
|
|
707
|
-
["stopped", "playing", "paused"].includes(
|
|
706
|
+
setTransportState(Z) {
|
|
707
|
+
["stopped", "playing", "paused"].includes(Z) && (this.transportState = Z);
|
|
708
708
|
},
|
|
709
709
|
play() {
|
|
710
710
|
this.setTransportState("playing");
|
|
@@ -716,55 +716,55 @@ const g = (d, l) => {
|
|
|
716
716
|
this.setTransportState("stopped");
|
|
717
717
|
},
|
|
718
718
|
// Navigation settings
|
|
719
|
-
setAutoPlay(
|
|
720
|
-
this.autoPlay =
|
|
719
|
+
setAutoPlay(Z) {
|
|
720
|
+
this.autoPlay = Z;
|
|
721
721
|
},
|
|
722
|
-
setLoop(
|
|
723
|
-
this.loopEnabled =
|
|
722
|
+
setLoop(Z, l = null, U = null) {
|
|
723
|
+
this.loopEnabled = Z, l !== null && (this.loopStart = l), U !== null && (this.loopEnd = U);
|
|
724
724
|
},
|
|
725
|
-
setLoopStart(
|
|
726
|
-
this.loopStart =
|
|
725
|
+
setLoopStart(Z) {
|
|
726
|
+
this.loopStart = Z, this.loopEnd && this.loopEnd <= Z && (this.loopEnd = Z + 4);
|
|
727
727
|
},
|
|
728
|
-
setLoopEnd(
|
|
729
|
-
this.loopEnd =
|
|
728
|
+
setLoopEnd(Z) {
|
|
729
|
+
this.loopEnd = Z, this.loopStart && this.loopStart >= Z && (this.loopStart = Math.max(1, Z - 4));
|
|
730
730
|
},
|
|
731
731
|
// Lead-in settings
|
|
732
|
-
setLeadInEnabled(
|
|
733
|
-
this.leadInEnabled =
|
|
732
|
+
setLeadInEnabled(Z) {
|
|
733
|
+
this.leadInEnabled = Z;
|
|
734
734
|
},
|
|
735
|
-
setLeadInBars(
|
|
736
|
-
this.leadInBars = Math.max(1, Math.min(4,
|
|
735
|
+
setLeadInBars(Z) {
|
|
736
|
+
this.leadInBars = Math.max(1, Math.min(4, Z));
|
|
737
737
|
},
|
|
738
738
|
// Starting notes settings
|
|
739
|
-
setStartingNotesEnabled(
|
|
740
|
-
this.startingNotesEnabled =
|
|
739
|
+
setStartingNotesEnabled(Z) {
|
|
740
|
+
this.startingNotesEnabled = Z;
|
|
741
741
|
},
|
|
742
|
-
setStartingNotesSequential(
|
|
743
|
-
this.startingNotesSequential =
|
|
742
|
+
setStartingNotesSequential(Z) {
|
|
743
|
+
this.startingNotesSequential = Z;
|
|
744
744
|
},
|
|
745
745
|
// Metronome settings
|
|
746
|
-
setMetronomeEnabled(
|
|
747
|
-
this.metronomeEnabled =
|
|
746
|
+
setMetronomeEnabled(Z) {
|
|
747
|
+
this.metronomeEnabled = Z;
|
|
748
748
|
},
|
|
749
|
-
setMetronomeVolume(
|
|
750
|
-
this.metronomeVolume = Math.max(0, Math.min(1,
|
|
749
|
+
setMetronomeVolume(Z) {
|
|
750
|
+
this.metronomeVolume = Math.max(0, Math.min(1, Z));
|
|
751
751
|
},
|
|
752
752
|
// UI visibility controls
|
|
753
|
-
setTransportControlsVisible(
|
|
754
|
-
this.showTransportControls =
|
|
753
|
+
setTransportControlsVisible(Z) {
|
|
754
|
+
this.showTransportControls = Z;
|
|
755
755
|
},
|
|
756
|
-
setPartControlsVisible(
|
|
757
|
-
this.showPartControls =
|
|
756
|
+
setPartControlsVisible(Z) {
|
|
757
|
+
this.showPartControls = Z;
|
|
758
758
|
},
|
|
759
|
-
setNavigationControlsVisible(
|
|
760
|
-
this.showNavigationControls =
|
|
759
|
+
setNavigationControlsVisible(Z) {
|
|
760
|
+
this.showNavigationControls = Z;
|
|
761
761
|
},
|
|
762
762
|
// Position tracking
|
|
763
|
-
updateLastBarPosition(
|
|
764
|
-
this.lastBarPosition =
|
|
763
|
+
updateLastBarPosition(Z) {
|
|
764
|
+
this.lastBarPosition = Z;
|
|
765
765
|
},
|
|
766
|
-
updateLastPracticeMarkUsed(
|
|
767
|
-
this.lastPracticeMarkUsed =
|
|
766
|
+
updateLastPracticeMarkUsed(Z) {
|
|
767
|
+
this.lastPracticeMarkUsed = Z;
|
|
768
768
|
},
|
|
769
769
|
// Reset to defaults
|
|
770
770
|
resetToDefaults() {
|
|
@@ -772,35 +772,35 @@ const g = (d, l) => {
|
|
|
772
772
|
}
|
|
773
773
|
}
|
|
774
774
|
});
|
|
775
|
-
function fl(
|
|
776
|
-
return { all:
|
|
777
|
-
var F =
|
|
778
|
-
F ? F.push(U) :
|
|
775
|
+
function fl(Z) {
|
|
776
|
+
return { all: Z = Z || /* @__PURE__ */ new Map(), on: function(l, U) {
|
|
777
|
+
var F = Z.get(l);
|
|
778
|
+
F ? F.push(U) : Z.set(l, [U]);
|
|
779
779
|
}, off: function(l, U) {
|
|
780
|
-
var F =
|
|
781
|
-
F && (U ? F.splice(F.indexOf(U) >>> 0, 1) :
|
|
780
|
+
var F = Z.get(l);
|
|
781
|
+
F && (U ? F.splice(F.indexOf(U) >>> 0, 1) : Z.set(l, []));
|
|
782
782
|
}, emit: function(l, U) {
|
|
783
|
-
var F =
|
|
784
|
-
F && F.slice().map(function(
|
|
785
|
-
|
|
786
|
-
}), (F =
|
|
787
|
-
|
|
783
|
+
var F = Z.get(l);
|
|
784
|
+
F && F.slice().map(function(d) {
|
|
785
|
+
d(U);
|
|
786
|
+
}), (F = Z.get("*")) && F.slice().map(function(d) {
|
|
787
|
+
d(l, U);
|
|
788
788
|
});
|
|
789
789
|
} };
|
|
790
790
|
}
|
|
791
|
-
function Xl(
|
|
792
|
-
return { all:
|
|
793
|
-
var F =
|
|
794
|
-
F ? F.push(U) :
|
|
791
|
+
function Xl(Z) {
|
|
792
|
+
return { all: Z = Z || /* @__PURE__ */ new Map(), on: function(l, U) {
|
|
793
|
+
var F = Z.get(l);
|
|
794
|
+
F ? F.push(U) : Z.set(l, [U]);
|
|
795
795
|
}, off: function(l, U) {
|
|
796
|
-
var F =
|
|
797
|
-
F && (U ? F.splice(F.indexOf(U) >>> 0, 1) :
|
|
796
|
+
var F = Z.get(l);
|
|
797
|
+
F && (U ? F.splice(F.indexOf(U) >>> 0, 1) : Z.set(l, []));
|
|
798
798
|
}, emit: function(l, U) {
|
|
799
|
-
var F =
|
|
800
|
-
F && F.slice().map(function(
|
|
801
|
-
|
|
802
|
-
}), (F =
|
|
803
|
-
|
|
799
|
+
var F = Z.get(l);
|
|
800
|
+
F && F.slice().map(function(d) {
|
|
801
|
+
d(U);
|
|
802
|
+
}), (F = Z.get("*")) && F.slice().map(function(d) {
|
|
803
|
+
d(l, U);
|
|
804
804
|
});
|
|
805
805
|
} };
|
|
806
806
|
}
|
|
@@ -840,8 +840,8 @@ class Nl {
|
|
|
840
840
|
* @protected
|
|
841
841
|
*/
|
|
842
842
|
_emitProgress(l, U, F = null) {
|
|
843
|
-
const
|
|
844
|
-
F !== null && (
|
|
843
|
+
const d = { stage: l, message: U };
|
|
844
|
+
F !== null && (d.progress = Math.max(0, Math.min(1, F))), this.eventBus.emit("initProgress", d);
|
|
845
845
|
}
|
|
846
846
|
/**
|
|
847
847
|
* Initialize the audio engine - load soundfont and set up synthesis
|
|
@@ -878,21 +878,21 @@ class Nl {
|
|
|
878
878
|
async playMetronomeTick(l, U, F) {
|
|
879
879
|
try {
|
|
880
880
|
await this._ensureMetronomeBuffersLoaded();
|
|
881
|
-
const
|
|
882
|
-
if (!
|
|
881
|
+
const d = U ? this.accentTickBuffer : this.regularTickBuffer;
|
|
882
|
+
if (!d) {
|
|
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 = d;
|
|
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
|
-
|
|
894
|
-
} catch (
|
|
895
|
-
console.warn("Buffer metronome playback failed:",
|
|
893
|
+
Q.start(R);
|
|
894
|
+
} catch (d) {
|
|
895
|
+
console.warn("Buffer metronome playback failed:", d);
|
|
896
896
|
}
|
|
897
897
|
}
|
|
898
898
|
/**
|
|
@@ -914,14 +914,14 @@ class Nl {
|
|
|
914
914
|
const [l, U] = await Promise.all([
|
|
915
915
|
fetch(pU),
|
|
916
916
|
fetch(YU)
|
|
917
|
-
]), [F,
|
|
917
|
+
]), [F, d] = 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
|
-
this.audioContext.decodeAudioData(
|
|
922
|
+
this.audioContext.decodeAudioData(d)
|
|
923
923
|
]);
|
|
924
|
-
this.regularTickBuffer =
|
|
924
|
+
this.regularTickBuffer = Q, this.accentTickBuffer = V;
|
|
925
925
|
return;
|
|
926
926
|
}
|
|
927
927
|
} catch (l) {
|
|
@@ -1012,22 +1012,22 @@ class pl {
|
|
|
1012
1012
|
* @param {number} duration - Note duration in seconds
|
|
1013
1013
|
* @returns {string} Event ID for cancellation
|
|
1014
1014
|
*/
|
|
1015
|
-
playNote(l, U, F,
|
|
1015
|
+
playNote(l, U, F, d) {
|
|
1016
1016
|
this._validateActive();
|
|
1017
|
-
const
|
|
1018
|
-
let t = l, R =
|
|
1019
|
-
if (l <
|
|
1020
|
-
const c =
|
|
1021
|
-
t =
|
|
1017
|
+
const Q = this.engine.audioContext.currentTime, V = `${this.partId}_${l}_${U}_${Date.now()}`;
|
|
1018
|
+
let t = l, R = d;
|
|
1019
|
+
if (l < Q) {
|
|
1020
|
+
const c = Q - l;
|
|
1021
|
+
t = Q, R = Math.max(0, d - 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,11 +1040,11 @@ class pl {
|
|
|
1040
1040
|
*/
|
|
1041
1041
|
playPreviewNote(l, U = {}) {
|
|
1042
1042
|
this._validateActive();
|
|
1043
|
-
const F = U.startTime ?? this.engine.audioContext.currentTime + 0.01,
|
|
1044
|
-
let
|
|
1045
|
-
U.instrument !== void 0 && (
|
|
1046
|
-
this.isDestroyed || this.setInstrument(
|
|
1047
|
-
}, (
|
|
1043
|
+
const F = U.startTime ?? this.engine.audioContext.currentTime + 0.01, d = 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, d), V !== null && setTimeout(() => {
|
|
1046
|
+
this.isDestroyed || this.setInstrument(V);
|
|
1047
|
+
}, (d + 0.1) * 1e3);
|
|
1048
1048
|
}
|
|
1049
1049
|
/**
|
|
1050
1050
|
* Stop all notes on this channel
|
|
@@ -1288,7 +1288,7 @@ const Al = {
|
|
|
1288
1288
|
helicopter: 125,
|
|
1289
1289
|
applause: 126,
|
|
1290
1290
|
gunshot: 127
|
|
1291
|
-
}, yU = Object.entries(Al).reduce((
|
|
1291
|
+
}, yU = Object.entries(Al).reduce((Z, [l, U]) => (Z[U] = l, Z), {});
|
|
1292
1292
|
class EU {
|
|
1293
1293
|
/**
|
|
1294
1294
|
* Map common instrument names to MIDI program numbers
|
|
@@ -1320,8 +1320,8 @@ class EU {
|
|
|
1320
1320
|
}
|
|
1321
1321
|
}
|
|
1322
1322
|
class kU extends pl {
|
|
1323
|
-
constructor(l, U, F,
|
|
1324
|
-
super(l, U,
|
|
1323
|
+
constructor(l, U, F, d = {}) {
|
|
1324
|
+
super(l, U, d), this.midiChannel = F, this.currentVolume = d.initialVolume || 1, this.currentInstrument = d.instrument || "piano", this.outputGain = null, this._setupOutputNode(), this.setVolume(this.currentVolume), d.instrument && this.setInstrument(d.instrument);
|
|
1325
1325
|
}
|
|
1326
1326
|
getOutputNode() {
|
|
1327
1327
|
return this.outputGain;
|
|
@@ -1335,8 +1335,8 @@ class kU extends pl {
|
|
|
1335
1335
|
_actualNoteOn(l, U) {
|
|
1336
1336
|
const F = this.engine._getSynthesizer();
|
|
1337
1337
|
if (F && F.noteOn) {
|
|
1338
|
-
const
|
|
1339
|
-
F.noteOn(this.midiChannel, l,
|
|
1338
|
+
const d = Math.round(U * this.currentVolume);
|
|
1339
|
+
F.noteOn(this.midiChannel, l, d);
|
|
1340
1340
|
}
|
|
1341
1341
|
}
|
|
1342
1342
|
/**
|
|
@@ -1388,12 +1388,12 @@ class kU extends pl {
|
|
|
1388
1388
|
* @param {number} duration - Note duration in seconds
|
|
1389
1389
|
* @returns {string} Event ID for compatibility
|
|
1390
1390
|
*/
|
|
1391
|
-
playNote(l, U, F,
|
|
1391
|
+
playNote(l, U, F, d) {
|
|
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: {
|
|
@@ -1413,14 +1413,14 @@ class kU extends pl {
|
|
|
1413
1413
|
channelOffset: 0,
|
|
1414
1414
|
force: !1,
|
|
1415
1415
|
options: {
|
|
1416
|
-
time: l +
|
|
1416
|
+
time: l + d
|
|
1417
1417
|
// Precise note-off timing!
|
|
1418
1418
|
}
|
|
1419
1419
|
}
|
|
1420
1420
|
});
|
|
1421
1421
|
} else
|
|
1422
|
-
return super.playNote(l, U, F,
|
|
1423
|
-
return
|
|
1422
|
+
return super.playNote(l, U, F, d);
|
|
1423
|
+
return Q;
|
|
1424
1424
|
}
|
|
1425
1425
|
/**
|
|
1426
1426
|
* Override allNotesOff to use SpessaSynth messaging system
|
|
@@ -1475,7 +1475,7 @@ class rU extends Nl {
|
|
|
1475
1475
|
this._emitProgress("loading-soundfont", "Soundfont provided"), F = l;
|
|
1476
1476
|
else
|
|
1477
1477
|
throw new Error("Invalid soundfont data type. Expected string path or ArrayBuffer.");
|
|
1478
|
-
this._emitProgress("loading-worklet", "Loading audio worklet processor..."), await this._loadAudioWorkletSafely(), console.log("AudioWorklet loaded. Note: Worklet processor may persist across page reloads."), this._emitProgress("creating-synth", "Setting up audio channels..."), this._setupIndividualOutputs(), this.dummyTarget = this.audioContext.createGain(), await new Promise((
|
|
1478
|
+
this._emitProgress("loading-worklet", "Loading audio worklet processor..."), await this._loadAudioWorkletSafely(), console.log("AudioWorklet loaded. Note: Worklet processor may persist across page reloads."), this._emitProgress("creating-synth", "Setting up audio channels..."), this._setupIndividualOutputs(), this.dummyTarget = this.audioContext.createGain(), await new Promise((d) => setTimeout(d, 50)), this._emitProgress("creating-synth", "Initializing synthesizer..."), this.synthesizer = new U(this.audioContext), this._emitProgress("loading-soundbank", "Loading soundbank into synthesizer..."), await this.synthesizer.soundBankManager.addSoundBank(F, "main"), await this.synthesizer.isReady, this._emitProgress("finalizing", "Finalizing audio setup..."), this._connectIndividualOutputs(), this._initializeMetronomeChannel(), this._emitProgress("ready", "Audio engine ready"), this.isInitialized = !0;
|
|
1479
1479
|
}
|
|
1480
1480
|
createChannel(l, U = {}) {
|
|
1481
1481
|
if (this._validateInitialized(), this.partToMidiChannel.has(l))
|
|
@@ -1484,13 +1484,13 @@ class rU extends Nl {
|
|
|
1484
1484
|
if (F >= 15)
|
|
1485
1485
|
throw new Error("Maximum number of musical part channels (15) exceeded. Channel 15 is reserved for metronome.");
|
|
1486
1486
|
this.channelCounter++, this.partToMidiChannel.set(l, F), this.midiChannelToPart.set(F, l);
|
|
1487
|
-
const
|
|
1487
|
+
const d = new kU(
|
|
1488
1488
|
this,
|
|
1489
1489
|
l,
|
|
1490
1490
|
F,
|
|
1491
1491
|
U
|
|
1492
1492
|
);
|
|
1493
|
-
return this._registerChannel(
|
|
1493
|
+
return this._registerChannel(d), U.instrument && d.setInstrument(U.instrument), d;
|
|
1494
1494
|
}
|
|
1495
1495
|
allSoundsOff() {
|
|
1496
1496
|
if (this.synthesizer) {
|
|
@@ -1588,24 +1588,24 @@ class rU extends Nl {
|
|
|
1588
1588
|
const U = await fetch(l);
|
|
1589
1589
|
if (!U.ok)
|
|
1590
1590
|
throw new Error(`Failed to load soundfont: ${U.status} ${U.statusText}`);
|
|
1591
|
-
const F = U.headers.get("content-length"),
|
|
1592
|
-
if (!
|
|
1591
|
+
const F = U.headers.get("content-length"), d = F ? parseInt(F, 10) : null;
|
|
1592
|
+
if (!d || !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 / d, 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(d / 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;
|
|
@@ -1624,7 +1624,7 @@ class rU extends Nl {
|
|
|
1624
1624
|
if (console.warn(`AudioWorklet loading failed (attempt ${l}/5):`, U.message), l === 5)
|
|
1625
1625
|
throw new Error(`AudioWorklet failed after 5 attempts: ${U.message}`);
|
|
1626
1626
|
const F = l * 500;
|
|
1627
|
-
await new Promise((
|
|
1627
|
+
await new Promise((d) => setTimeout(d, F));
|
|
1628
1628
|
}
|
|
1629
1629
|
}
|
|
1630
1630
|
/**
|
|
@@ -1653,15 +1653,15 @@ class rU extends Nl {
|
|
|
1653
1653
|
*/
|
|
1654
1654
|
async playMetronomeTick(l, U, F) {
|
|
1655
1655
|
try {
|
|
1656
|
-
const
|
|
1657
|
-
if (!
|
|
1656
|
+
const d = this.getMetronomeChannel(), Q = this._getSynthesizer();
|
|
1657
|
+
if (!d || !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,15 +1681,15 @@ 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
|
-
} catch (
|
|
1692
|
-
return console.warn("MIDI metronome failed, falling back to buffers:",
|
|
1691
|
+
} catch (d) {
|
|
1692
|
+
return console.warn("MIDI metronome failed, falling back to buffers:", d), super.playMetronomeTick(l, U, F);
|
|
1693
1693
|
}
|
|
1694
1694
|
}
|
|
1695
1695
|
/**
|
|
@@ -1768,19 +1768,15 @@ 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
|
|
1779
|
-
|
|
1780
|
-
const t = parseInt(V.prog, 10);
|
|
1781
|
-
t !== 0 && (Q.instrument = t);
|
|
1782
|
-
}
|
|
1783
|
-
Q.trackIndex !== void 0 && (U[Z] = Q);
|
|
1778
|
+
const d = F.name.toLowerCase(), Q = this._parseUrlParams(F.url), V = {};
|
|
1779
|
+
Q.track !== void 0 && (V.channel = parseInt(Q.track, 10)), Q.prog !== void 0 && (V.instrument = parseInt(Q.prog, 10)), V.channel !== void 0 && (U[d] = V);
|
|
1784
1780
|
}
|
|
1785
1781
|
return U;
|
|
1786
1782
|
}
|
|
@@ -1794,10 +1790,10 @@ class LU {
|
|
|
1794
1790
|
const U = {}, F = l.indexOf("?");
|
|
1795
1791
|
if (F === -1)
|
|
1796
1792
|
return U;
|
|
1797
|
-
const
|
|
1798
|
-
for (const
|
|
1799
|
-
const [
|
|
1800
|
-
|
|
1793
|
+
const d = l.substring(F + 1).split("&");
|
|
1794
|
+
for (const Q of d) {
|
|
1795
|
+
const [V, t] = Q.split("=");
|
|
1796
|
+
V && t !== void 0 && (U[V] = t);
|
|
1801
1797
|
}
|
|
1802
1798
|
return U;
|
|
1803
1799
|
}
|
|
@@ -1809,16 +1805,16 @@ class LU {
|
|
|
1809
1805
|
const U = new Uint8Array(l);
|
|
1810
1806
|
if (!(U[0] === 77 && U[1] === 84 && U[2] === 104 && U[3] === 100))
|
|
1811
1807
|
throw new Error("Not a valid MIDI file");
|
|
1812
|
-
const F = this._bytesToNumber(U.slice(4, 8)),
|
|
1813
|
-
format:
|
|
1808
|
+
const F = this._bytesToNumber(U.slice(4, 8)), d = 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 = {
|
|
1809
|
+
format: d,
|
|
1814
1810
|
ticksPerBeat: t,
|
|
1815
1811
|
tracks: [],
|
|
1816
1812
|
duration: 0
|
|
1817
1813
|
};
|
|
1818
1814
|
let a = 8 + F;
|
|
1819
|
-
for (let n = 0; n <
|
|
1815
|
+
for (let n = 0; n < Q; n++)
|
|
1820
1816
|
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)),
|
|
1817
|
+
const m = this._bytesToNumber(U.slice(a + 4, a + 8)), W = U.slice(a + 8, a + 8 + m), c = this._parseTrack(W);
|
|
1822
1818
|
R.tracks.push(c), a += 8 + m;
|
|
1823
1819
|
} else
|
|
1824
1820
|
throw new Error(`Invalid track header at position ${a}`);
|
|
@@ -1836,20 +1832,20 @@ class LU {
|
|
|
1836
1832
|
events: [],
|
|
1837
1833
|
duration: 0
|
|
1838
1834
|
};
|
|
1839
|
-
let F = 0,
|
|
1835
|
+
let F = 0, d = 0, Q = null;
|
|
1840
1836
|
for (; F < l.length; ) {
|
|
1841
|
-
let
|
|
1837
|
+
let V = 0, t = 0;
|
|
1842
1838
|
do
|
|
1843
|
-
t = l[F++],
|
|
1839
|
+
t = l[F++], V = V << 7 | t & 127;
|
|
1844
1840
|
while (t & 128);
|
|
1845
|
-
|
|
1841
|
+
d += V, t = l[F++];
|
|
1846
1842
|
let R = t;
|
|
1847
1843
|
if (t & 128)
|
|
1848
|
-
|
|
1844
|
+
Q = R;
|
|
1849
1845
|
else {
|
|
1850
|
-
if (
|
|
1846
|
+
if (Q === null)
|
|
1851
1847
|
throw new Error("Running status byte encountered before status byte");
|
|
1852
|
-
R =
|
|
1848
|
+
R = Q, F--;
|
|
1853
1849
|
}
|
|
1854
1850
|
if (R === 255) {
|
|
1855
1851
|
const a = l[F++], n = this._readVariableLengthValue(l, F);
|
|
@@ -1863,21 +1859,21 @@ class LU {
|
|
|
1863
1859
|
U.events.push({
|
|
1864
1860
|
type: "text",
|
|
1865
1861
|
text: this._bytesToString(m),
|
|
1866
|
-
tick:
|
|
1862
|
+
tick: d
|
|
1867
1863
|
});
|
|
1868
1864
|
break;
|
|
1869
1865
|
case 5:
|
|
1870
1866
|
U.lyrics.push({
|
|
1871
1867
|
text: this._bytesToString(m),
|
|
1872
|
-
tick:
|
|
1868
|
+
tick: d
|
|
1873
1869
|
});
|
|
1874
1870
|
break;
|
|
1875
1871
|
case 81:
|
|
1876
|
-
const
|
|
1872
|
+
const W = this._bytesToNumber(m), c = Math.round(6e7 / W);
|
|
1877
1873
|
U.events.push({
|
|
1878
1874
|
type: "tempo",
|
|
1879
1875
|
bpm: c,
|
|
1880
|
-
tick:
|
|
1876
|
+
tick: d
|
|
1881
1877
|
});
|
|
1882
1878
|
break;
|
|
1883
1879
|
case 88:
|
|
@@ -1885,11 +1881,11 @@ class LU {
|
|
|
1885
1881
|
type: "timeSignature",
|
|
1886
1882
|
numerator: m[0],
|
|
1887
1883
|
denominator: Math.pow(2, m[1]),
|
|
1888
|
-
tick:
|
|
1884
|
+
tick: d
|
|
1889
1885
|
});
|
|
1890
1886
|
break;
|
|
1891
1887
|
case 47:
|
|
1892
|
-
U.duration =
|
|
1888
|
+
U.duration = d;
|
|
1893
1889
|
break;
|
|
1894
1890
|
}
|
|
1895
1891
|
} else if ((R & 240) === 144) {
|
|
@@ -1898,12 +1894,12 @@ class LU {
|
|
|
1898
1894
|
type: "noteOn",
|
|
1899
1895
|
noteNumber: n,
|
|
1900
1896
|
velocity: m,
|
|
1901
|
-
tick:
|
|
1897
|
+
tick: d,
|
|
1902
1898
|
channel: a
|
|
1903
1899
|
}) : U.notes.push({
|
|
1904
1900
|
type: "noteOff",
|
|
1905
1901
|
noteNumber: n,
|
|
1906
|
-
tick:
|
|
1902
|
+
tick: d,
|
|
1907
1903
|
channel: a
|
|
1908
1904
|
});
|
|
1909
1905
|
} else if ((R & 240) === 128) {
|
|
@@ -1911,7 +1907,7 @@ class LU {
|
|
|
1911
1907
|
l[F++], U.notes.push({
|
|
1912
1908
|
type: "noteOff",
|
|
1913
1909
|
noteNumber: n,
|
|
1914
|
-
tick:
|
|
1910
|
+
tick: d,
|
|
1915
1911
|
channel: a
|
|
1916
1912
|
});
|
|
1917
1913
|
} else if (R === 240 || R === 247) {
|
|
@@ -1924,7 +1920,7 @@ class LU {
|
|
|
1924
1920
|
controllerNumber: n,
|
|
1925
1921
|
value: m,
|
|
1926
1922
|
channel: a,
|
|
1927
|
-
tick:
|
|
1923
|
+
tick: d
|
|
1928
1924
|
});
|
|
1929
1925
|
} else if ((R & 240) === 192) {
|
|
1930
1926
|
const a = R & 15, n = l[F++];
|
|
@@ -1932,7 +1928,7 @@ class LU {
|
|
|
1932
1928
|
type: "programChange",
|
|
1933
1929
|
programNumber: n,
|
|
1934
1930
|
channel: a,
|
|
1935
|
-
tick:
|
|
1931
|
+
tick: d
|
|
1936
1932
|
});
|
|
1937
1933
|
} else if ((R & 240) === 208) {
|
|
1938
1934
|
const a = R & 15, n = l[F++];
|
|
@@ -1940,7 +1936,7 @@ class LU {
|
|
|
1940
1936
|
type: "channelAftertouch",
|
|
1941
1937
|
pressure: n,
|
|
1942
1938
|
channel: a,
|
|
1943
|
-
tick:
|
|
1939
|
+
tick: d
|
|
1944
1940
|
});
|
|
1945
1941
|
} else if ((R & 240) === 224) {
|
|
1946
1942
|
const a = R & 15, n = l[F++], m = (l[F++] << 7 | n) - 8192;
|
|
@@ -1948,7 +1944,7 @@ class LU {
|
|
|
1948
1944
|
type: "pitchBend",
|
|
1949
1945
|
value: m,
|
|
1950
1946
|
channel: a,
|
|
1951
|
-
tick:
|
|
1947
|
+
tick: d
|
|
1952
1948
|
});
|
|
1953
1949
|
} else if ((R & 240) === 160) {
|
|
1954
1950
|
const a = R & 15, n = l[F++], m = l[F++];
|
|
@@ -1957,7 +1953,7 @@ class LU {
|
|
|
1957
1953
|
noteNumber: n,
|
|
1958
1954
|
pressure: m,
|
|
1959
1955
|
channel: a,
|
|
1960
|
-
tick:
|
|
1956
|
+
tick: d
|
|
1961
1957
|
});
|
|
1962
1958
|
} else
|
|
1963
1959
|
console.warn(`Unknown event type: ${R.toString(16)} at position ${F - 1}`), F++;
|
|
@@ -1976,16 +1972,16 @@ class LU {
|
|
|
1976
1972
|
format: l.format,
|
|
1977
1973
|
ticksPerBeat: l.ticksPerBeat
|
|
1978
1974
|
};
|
|
1979
|
-
l.tracks.forEach((F,
|
|
1980
|
-
if (F.name && !U.title && (U.title = F.name), F.events.filter((
|
|
1981
|
-
const
|
|
1982
|
-
(
|
|
1975
|
+
l.tracks.forEach((F, d) => {
|
|
1976
|
+
if (F.name && !U.title && (U.title = F.name), F.events.filter((Q) => Q.type === "text").forEach((Q) => {
|
|
1977
|
+
const V = Q.text.toLowerCase();
|
|
1978
|
+
(V.includes("compos") || V.includes("by")) && !U.composer && (U.composer = Q.text);
|
|
1983
1979
|
}), F.name) {
|
|
1984
|
-
const
|
|
1985
|
-
for (const
|
|
1986
|
-
if (
|
|
1980
|
+
const Q = F.name.toLowerCase();
|
|
1981
|
+
for (const V of this.partNames)
|
|
1982
|
+
if (Q.includes(V)) {
|
|
1987
1983
|
U.partNames.push({
|
|
1988
|
-
index:
|
|
1984
|
+
index: d,
|
|
1989
1985
|
name: F.name
|
|
1990
1986
|
});
|
|
1991
1987
|
break;
|
|
@@ -2007,30 +2003,30 @@ class LU {
|
|
|
2007
2003
|
(m.type === "timeSignature" || m.type === "tempo") && F.push(m);
|
|
2008
2004
|
});
|
|
2009
2005
|
}), F.sort((n, m) => n.tick - m.tick);
|
|
2010
|
-
let
|
|
2006
|
+
let d = 0;
|
|
2011
2007
|
l.tracks.forEach((n) => {
|
|
2012
2008
|
n.notes && n.notes.forEach((m) => {
|
|
2013
|
-
m.type === "noteOff" && m.tick >
|
|
2009
|
+
m.type === "noteOff" && m.tick > d && (d = m.tick);
|
|
2014
2010
|
});
|
|
2015
|
-
}),
|
|
2016
|
-
const
|
|
2011
|
+
}), d === 0 && (d = U * 8);
|
|
2012
|
+
const Q = [], V = F.filter((n) => n.type === "timeSignature").sort((n, m) => n.tick - m.tick);
|
|
2017
2013
|
let t = { numerator: 4, denominator: 4 }, R = 0, a = 0;
|
|
2018
|
-
for (; R <
|
|
2019
|
-
for (; a <
|
|
2020
|
-
t =
|
|
2014
|
+
for (; R < d; ) {
|
|
2015
|
+
for (; a < V.length && V[a].tick <= R; )
|
|
2016
|
+
t = V[a], a++;
|
|
2021
2017
|
let n;
|
|
2022
2018
|
n = R + U * 4 * t.numerator / t.denominator;
|
|
2023
|
-
const m = t.numerator,
|
|
2019
|
+
const m = t.numerator, W = [], c = U * (4 / t.denominator);
|
|
2024
2020
|
for (let s = 0; s < m; s++) {
|
|
2025
2021
|
const N = R + s * c, J = this._ticksToTime(N, l);
|
|
2026
|
-
|
|
2022
|
+
W.push(J);
|
|
2027
2023
|
}
|
|
2028
|
-
|
|
2024
|
+
Q.push({
|
|
2029
2025
|
sig: [t.numerator, t.denominator],
|
|
2030
|
-
beats:
|
|
2026
|
+
beats: W
|
|
2031
2027
|
}), R = n;
|
|
2032
2028
|
}
|
|
2033
|
-
this.parsedData.barStructure =
|
|
2029
|
+
this.parsedData.barStructure = Q;
|
|
2034
2030
|
}
|
|
2035
2031
|
/**
|
|
2036
2032
|
* Extract notes for each voice part
|
|
@@ -2039,87 +2035,172 @@ class LU {
|
|
|
2039
2035
|
_extractParts(l) {
|
|
2040
2036
|
const U = {}, F = l.ticksPerBeat;
|
|
2041
2037
|
if (this.metadataOverrides.parts)
|
|
2042
|
-
for (const [
|
|
2043
|
-
if (
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2038
|
+
for (const [d, Q] of Object.entries(this.metadataOverrides.parts)) {
|
|
2039
|
+
if (Q.channel !== void 0 && Q.channel !== null) {
|
|
2040
|
+
if (Q.channel === 15) {
|
|
2041
|
+
console.error(`Part "${d}" uses channel 15 which is reserved for metronome. Skipping.`);
|
|
2042
|
+
continue;
|
|
2043
|
+
}
|
|
2044
|
+
if (Q.channel === 9 && console.warn(`Part "${d}" uses channel 9 (drums/percussion). This may not be appropriate for vocal parts.`), Q.channel < 0 || Q.channel > 15) {
|
|
2045
|
+
console.error(`Part "${d}" has invalid channel ${Q.channel}. MIDI channels must be 0-15. Skipping.`);
|
|
2046
|
+
continue;
|
|
2047
|
+
}
|
|
2051
2048
|
}
|
|
2052
|
-
if (!Q)
|
|
2049
|
+
if (Q.channel === void 0 && !Q.trackIndex && Q.trackIndex !== 0 && !Q.trackName)
|
|
2053
2050
|
continue;
|
|
2054
|
-
|
|
2055
|
-
|
|
2051
|
+
let V;
|
|
2052
|
+
if (Q.channel !== void 0 && Q.channel !== null) {
|
|
2053
|
+
if (V = this._extractPartDataByChannel(Q.channel, l, F), !V || V.notes.length === 0) {
|
|
2054
|
+
console.warn(`Part "${d}" specified channel ${Q.channel} but no notes found on that channel. Skipping.`);
|
|
2055
|
+
continue;
|
|
2056
|
+
}
|
|
2057
|
+
} else if (Q.trackIndex !== void 0 && Q.trackIndex !== null) {
|
|
2058
|
+
const t = Q.trackIndex;
|
|
2059
|
+
if (t >= 0 && t < l.tracks.length) {
|
|
2060
|
+
const R = l.tracks[t];
|
|
2061
|
+
V = this._extractPartDataFromTrack(R, t, l, F);
|
|
2062
|
+
} else {
|
|
2063
|
+
console.warn(`Part "${d}" specified trackIndex ${t} but track not found. Skipping.`);
|
|
2064
|
+
continue;
|
|
2065
|
+
}
|
|
2066
|
+
} else if (Q.trackName) {
|
|
2067
|
+
const t = l.tracks.findIndex((R) => R.name === Q.trackName);
|
|
2068
|
+
if (t !== -1) {
|
|
2069
|
+
const R = l.tracks[t];
|
|
2070
|
+
V = this._extractPartDataFromTrack(R, t, l, F);
|
|
2071
|
+
} else {
|
|
2072
|
+
console.warn(`Part "${d}" specified trackName "${Q.trackName}" but track not found. Skipping.`);
|
|
2073
|
+
continue;
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
V && (Q.instrument !== void 0 && Q.instrument !== null && (V.defaultInstrument = this._resolveInstrument(Q.instrument), V.programChanges = []), U[d] = V);
|
|
2056
2077
|
}
|
|
2057
2078
|
else
|
|
2058
|
-
l.tracks.forEach((
|
|
2059
|
-
if (!
|
|
2060
|
-
let
|
|
2061
|
-
if (
|
|
2062
|
-
const a =
|
|
2079
|
+
l.tracks.forEach((d, Q) => {
|
|
2080
|
+
if (!d.notes.length) return;
|
|
2081
|
+
let V = null;
|
|
2082
|
+
if (d.name) {
|
|
2083
|
+
const a = d.name.toLowerCase();
|
|
2063
2084
|
for (const n of this.partNames)
|
|
2064
2085
|
if (n.length === 1) {
|
|
2065
2086
|
if (a === n) {
|
|
2066
|
-
|
|
2087
|
+
V = n;
|
|
2067
2088
|
break;
|
|
2068
2089
|
}
|
|
2069
2090
|
} else if (a.includes(n)) {
|
|
2070
|
-
|
|
2091
|
+
V = n;
|
|
2071
2092
|
break;
|
|
2072
2093
|
}
|
|
2073
2094
|
}
|
|
2074
|
-
|
|
2075
|
-
let t =
|
|
2095
|
+
V || (V = d.name || `Track ${Q + 1}`), V === "s" && (V = "soprano"), V === "a" && (V = "alto"), V === "t" && (V = "tenor"), V === "b" && (V = "bass");
|
|
2096
|
+
let t = V, R = 2;
|
|
2076
2097
|
for (; U[t]; )
|
|
2077
|
-
t = `${
|
|
2078
|
-
|
|
2098
|
+
t = `${V} ${R}`, R++;
|
|
2099
|
+
V = t, U[V] = this._extractPartDataFromTrack(d, Q, l, F);
|
|
2079
2100
|
});
|
|
2080
2101
|
this.parsedData.parts = U;
|
|
2081
2102
|
}
|
|
2103
|
+
/**
|
|
2104
|
+
* Extract part data by MIDI channel (merges notes from all tracks using this channel)
|
|
2105
|
+
* @private
|
|
2106
|
+
*/
|
|
2107
|
+
_extractPartDataByChannel(l, U, F) {
|
|
2108
|
+
const d = [], Q = [], V = [], t = [];
|
|
2109
|
+
U.tracks.forEach((a, n) => {
|
|
2110
|
+
const m = {};
|
|
2111
|
+
a.notes.forEach((W) => {
|
|
2112
|
+
if (W.channel === l) {
|
|
2113
|
+
if (W.type === "noteOn")
|
|
2114
|
+
m[W.noteNumber] = {
|
|
2115
|
+
tick: W.tick,
|
|
2116
|
+
velocity: W.velocity
|
|
2117
|
+
};
|
|
2118
|
+
else if (W.type === "noteOff" && m[W.noteNumber]) {
|
|
2119
|
+
const c = m[W.noteNumber], s = W.tick - c.tick;
|
|
2120
|
+
d.push({
|
|
2121
|
+
pitch: W.noteNumber,
|
|
2122
|
+
name: this._midiNoteToName(W.noteNumber),
|
|
2123
|
+
startTick: c.tick,
|
|
2124
|
+
endTick: W.tick,
|
|
2125
|
+
duration: s,
|
|
2126
|
+
startTime: this._ticksToTime(c.tick, U),
|
|
2127
|
+
endTime: this._ticksToTime(W.tick, U),
|
|
2128
|
+
velocity: c.velocity,
|
|
2129
|
+
channel: l,
|
|
2130
|
+
sourceTrackIndex: n
|
|
2131
|
+
}), delete m[W.noteNumber];
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
}), a.lyrics.forEach((W) => {
|
|
2135
|
+
Q.push({
|
|
2136
|
+
text: W.text,
|
|
2137
|
+
tick: W.tick,
|
|
2138
|
+
time: W.tick / F
|
|
2139
|
+
});
|
|
2140
|
+
}), a.events.filter((W) => W.type === "programChange" && W.channel === l).forEach((W) => {
|
|
2141
|
+
V.push({
|
|
2142
|
+
programNumber: W.programNumber,
|
|
2143
|
+
tick: W.tick,
|
|
2144
|
+
time: this._ticksToTime(W.tick, U),
|
|
2145
|
+
sourceTrackIndex: n
|
|
2146
|
+
});
|
|
2147
|
+
}), a.notes.some((W) => W.channel === l) && t.push(n);
|
|
2148
|
+
}), d.sort((a, n) => a.startTick - n.startTick), Q.sort((a, n) => a.tick - n.tick), V.sort((a, n) => a.tick - n.tick);
|
|
2149
|
+
const R = V.length > 0 ? V[0].programNumber : 0;
|
|
2150
|
+
return {
|
|
2151
|
+
notes: d,
|
|
2152
|
+
lyrics: Q,
|
|
2153
|
+
channel: l,
|
|
2154
|
+
trackIndices: t,
|
|
2155
|
+
// All track indices that contributed
|
|
2156
|
+
programChanges: V,
|
|
2157
|
+
defaultInstrument: R
|
|
2158
|
+
};
|
|
2159
|
+
}
|
|
2082
2160
|
/**
|
|
2083
2161
|
* Extract part data from a MIDI track
|
|
2084
2162
|
* @private
|
|
2085
2163
|
*/
|
|
2086
|
-
_extractPartDataFromTrack(l, U, F,
|
|
2087
|
-
const
|
|
2164
|
+
_extractPartDataFromTrack(l, U, F, d) {
|
|
2165
|
+
const Q = [], V = {};
|
|
2088
2166
|
l.notes.forEach((n) => {
|
|
2089
2167
|
if (n.type === "noteOn")
|
|
2090
|
-
|
|
2168
|
+
V[n.noteNumber] = {
|
|
2091
2169
|
tick: n.tick,
|
|
2092
|
-
velocity: n.velocity
|
|
2170
|
+
velocity: n.velocity,
|
|
2171
|
+
channel: n.channel
|
|
2093
2172
|
};
|
|
2094
|
-
else if (n.type === "noteOff" &&
|
|
2095
|
-
const m =
|
|
2096
|
-
|
|
2173
|
+
else if (n.type === "noteOff" && V[n.noteNumber]) {
|
|
2174
|
+
const m = V[n.noteNumber], W = n.tick - m.tick;
|
|
2175
|
+
Q.push({
|
|
2097
2176
|
pitch: n.noteNumber,
|
|
2098
2177
|
name: this._midiNoteToName(n.noteNumber),
|
|
2099
2178
|
startTick: m.tick,
|
|
2100
2179
|
endTick: n.tick,
|
|
2101
|
-
duration:
|
|
2180
|
+
duration: W,
|
|
2102
2181
|
// Convert ticks to actual time considering tempo changes
|
|
2103
2182
|
startTime: this._ticksToTime(m.tick, F),
|
|
2104
2183
|
endTime: this._ticksToTime(n.tick, F),
|
|
2105
|
-
velocity: m.velocity
|
|
2106
|
-
|
|
2184
|
+
velocity: m.velocity,
|
|
2185
|
+
channel: m.channel,
|
|
2186
|
+
sourceTrackIndex: U
|
|
2187
|
+
}), delete V[n.noteNumber];
|
|
2107
2188
|
}
|
|
2108
2189
|
});
|
|
2109
2190
|
const t = l.lyrics.map((n) => ({
|
|
2110
2191
|
text: n.text,
|
|
2111
2192
|
tick: n.tick,
|
|
2112
|
-
time: n.tick /
|
|
2193
|
+
time: n.tick / d
|
|
2113
2194
|
// Time in quarter notes
|
|
2114
2195
|
}));
|
|
2115
|
-
|
|
2196
|
+
Q.sort((n, m) => n.startTick - m.startTick);
|
|
2116
2197
|
const R = l.events.filter((n) => n.type === "programChange").map((n) => ({
|
|
2117
2198
|
programNumber: n.programNumber,
|
|
2118
2199
|
tick: n.tick,
|
|
2119
2200
|
time: this._ticksToTime(n.tick, F)
|
|
2120
2201
|
})).sort((n, m) => n.tick - m.tick), a = R.length > 0 ? R[0].programNumber : 0;
|
|
2121
2202
|
return {
|
|
2122
|
-
notes:
|
|
2203
|
+
notes: Q,
|
|
2123
2204
|
lyrics: t,
|
|
2124
2205
|
trackIndex: U,
|
|
2125
2206
|
programChanges: R,
|
|
@@ -2181,37 +2262,37 @@ class LU {
|
|
|
2181
2262
|
* @private
|
|
2182
2263
|
*/
|
|
2183
2264
|
_readVariableLengthValue(l, U) {
|
|
2184
|
-
let F = 0,
|
|
2265
|
+
let F = 0, d, Q = 0;
|
|
2185
2266
|
do
|
|
2186
|
-
|
|
2187
|
-
while (
|
|
2188
|
-
return { value: F, bytesRead:
|
|
2267
|
+
d = l[U + Q++], F = F << 7 | d & 127;
|
|
2268
|
+
while (d & 128);
|
|
2269
|
+
return { value: F, bytesRead: Q };
|
|
2189
2270
|
}
|
|
2190
2271
|
/**
|
|
2191
2272
|
* Convert ticks to time in seconds considering tempo changes within bars
|
|
2192
2273
|
* @private
|
|
2193
2274
|
*/
|
|
2194
2275
|
_ticksToTime(l, U) {
|
|
2195
|
-
const F = U.ticksPerBeat || 480,
|
|
2276
|
+
const F = U.ticksPerBeat || 480, d = [];
|
|
2196
2277
|
U.tracks.forEach((R) => {
|
|
2197
2278
|
R.events.forEach((a) => {
|
|
2198
|
-
a.type === "tempo" &&
|
|
2279
|
+
a.type === "tempo" && d.push(a);
|
|
2199
2280
|
});
|
|
2200
|
-
}),
|
|
2201
|
-
let
|
|
2202
|
-
for (const R of
|
|
2281
|
+
}), d.sort((R, a) => R.tick - a.tick);
|
|
2282
|
+
let Q = 0, V = 0, t = 120;
|
|
2283
|
+
for (const R of d) {
|
|
2203
2284
|
if (R.tick > l) break;
|
|
2204
|
-
if (R.tick >
|
|
2205
|
-
const a = (R.tick -
|
|
2206
|
-
|
|
2285
|
+
if (R.tick > V) {
|
|
2286
|
+
const a = (R.tick - V) / F * (60 / t);
|
|
2287
|
+
Q += a, V = R.tick;
|
|
2207
2288
|
}
|
|
2208
2289
|
t = R.bpm;
|
|
2209
2290
|
}
|
|
2210
|
-
if (l >
|
|
2211
|
-
const R = (l -
|
|
2212
|
-
|
|
2291
|
+
if (l > V) {
|
|
2292
|
+
const R = (l - V) / F * (60 / t);
|
|
2293
|
+
Q += R;
|
|
2213
2294
|
}
|
|
2214
|
-
return
|
|
2295
|
+
return Q;
|
|
2215
2296
|
}
|
|
2216
2297
|
}
|
|
2217
2298
|
class CU {
|
|
@@ -2238,19 +2319,19 @@ class CU {
|
|
|
2238
2319
|
* @returns {Array} Bar order with bar numbers and repeat counts
|
|
2239
2320
|
*/
|
|
2240
2321
|
generateBarOrder(l, U) {
|
|
2241
|
-
const F = [],
|
|
2242
|
-
for (const
|
|
2243
|
-
const
|
|
2244
|
-
if (!
|
|
2245
|
-
throw new Error(`Invalid section index: ${
|
|
2246
|
-
const t =
|
|
2247
|
-
|
|
2248
|
-
const R =
|
|
2249
|
-
for (let
|
|
2250
|
-
this._shouldPlayBar(
|
|
2251
|
-
barNumber:
|
|
2322
|
+
const F = [], d = {};
|
|
2323
|
+
for (const Q of U) {
|
|
2324
|
+
const V = l[Q.section];
|
|
2325
|
+
if (!V)
|
|
2326
|
+
throw new Error(`Invalid section index: ${Q.section}`);
|
|
2327
|
+
const t = Q.section;
|
|
2328
|
+
d[t] || (d[t] = 0), d[t]++;
|
|
2329
|
+
const R = d[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;
|
|
2330
|
+
for (let W = a; W <= n; W++)
|
|
2331
|
+
this._shouldPlayBar(V, W, m) && F.push({
|
|
2332
|
+
barNumber: W,
|
|
2252
2333
|
repeat: R,
|
|
2253
|
-
sectionIndex:
|
|
2334
|
+
sectionIndex: Q.section,
|
|
2254
2335
|
voltaTime: m
|
|
2255
2336
|
});
|
|
2256
2337
|
}
|
|
@@ -2264,25 +2345,25 @@ class CU {
|
|
|
2264
2345
|
*/
|
|
2265
2346
|
generateBarOrderFromLegacyBars(l, U) {
|
|
2266
2347
|
const F = [];
|
|
2267
|
-
let
|
|
2348
|
+
let d = 1, Q = 0, V;
|
|
2268
2349
|
for (const t of l) {
|
|
2269
|
-
t.from !== void 0 && (
|
|
2350
|
+
t.from !== void 0 && (d = t.from === -1 ? 0 : t.from, Q = 0), t.timeSig !== void 0 && (V = t.timeSig);
|
|
2270
2351
|
const R = t.repeat || 1;
|
|
2271
2352
|
let a = t.beats;
|
|
2272
2353
|
for (; a > 0; ) {
|
|
2273
|
-
const n = (
|
|
2354
|
+
const n = (V !== void 0 ? V : this._getBeatsPerBar(d, U)) - Q;
|
|
2274
2355
|
a >= n ? (F.push({
|
|
2275
|
-
barNumber:
|
|
2356
|
+
barNumber: d,
|
|
2276
2357
|
repeat: R,
|
|
2277
2358
|
sectionIndex: 0,
|
|
2278
2359
|
// Legacy format doesn't have sections
|
|
2279
2360
|
voltaTime: 1
|
|
2280
2361
|
// Legacy format doesn't have voltas
|
|
2281
|
-
}), a -= n,
|
|
2362
|
+
}), a -= n, Q = 0, d === 0 ? d = 1 : d++) : (Q += a, a = 0);
|
|
2282
2363
|
}
|
|
2283
2364
|
}
|
|
2284
|
-
return
|
|
2285
|
-
barNumber:
|
|
2365
|
+
return Q > 0 && F.push({
|
|
2366
|
+
barNumber: d,
|
|
2286
2367
|
repeat: 1,
|
|
2287
2368
|
sectionIndex: 0,
|
|
2288
2369
|
voltaTime: 1
|
|
@@ -2312,11 +2393,11 @@ class CU {
|
|
|
2312
2393
|
*/
|
|
2313
2394
|
_getBeatsPerBar(l, U) {
|
|
2314
2395
|
const F = U.length > 0 && U[0].sig && U[0].sig[0] <= 2;
|
|
2315
|
-
let
|
|
2316
|
-
if (F ?
|
|
2396
|
+
let d;
|
|
2397
|
+
if (F ? d = l : d = l - 1, d < 0 || d >= U.length)
|
|
2317
2398
|
return 4;
|
|
2318
|
-
const
|
|
2319
|
-
return
|
|
2399
|
+
const Q = U[d];
|
|
2400
|
+
return Q.sig ? Q.sig[0] : 4;
|
|
2320
2401
|
}
|
|
2321
2402
|
/**
|
|
2322
2403
|
* Generate beat table from bar order and MIDI bar structure
|
|
@@ -2326,21 +2407,21 @@ class CU {
|
|
|
2326
2407
|
* @returns {Array} Beat table with time, repeat, bar, and beat information
|
|
2327
2408
|
*/
|
|
2328
2409
|
generateBeatTable(l, U) {
|
|
2329
|
-
const F = [],
|
|
2330
|
-
let
|
|
2410
|
+
const F = [], d = {};
|
|
2411
|
+
let Q = 0, V = 0;
|
|
2331
2412
|
const t = [...U];
|
|
2332
|
-
for (;
|
|
2333
|
-
const R = l[
|
|
2334
|
-
if (
|
|
2335
|
-
const c = t[
|
|
2413
|
+
for (; V < l.length && Q < t.length; ) {
|
|
2414
|
+
const R = l[V], a = R.barNumber;
|
|
2415
|
+
if (d[a] === void 0) {
|
|
2416
|
+
const c = t[Q];
|
|
2336
2417
|
if (!c || !c.sig)
|
|
2337
|
-
throw new Error(`Invalid MIDI bar structure at index ${
|
|
2338
|
-
|
|
2418
|
+
throw new Error(`Invalid MIDI bar structure at index ${Q}`);
|
|
2419
|
+
d[a] = c.sig[0];
|
|
2339
2420
|
}
|
|
2340
|
-
const n =
|
|
2341
|
-
let m = t[
|
|
2342
|
-
for (;
|
|
2343
|
-
const c = t[
|
|
2421
|
+
const n = d[a];
|
|
2422
|
+
let m = t[Q], W = m.sig[0];
|
|
2423
|
+
for (; W < n && Q + 1 < t.length; ) {
|
|
2424
|
+
const c = t[Q + 1], s = [
|
|
2344
2425
|
m.sig[0] + c.sig[0],
|
|
2345
2426
|
// Total beats
|
|
2346
2427
|
m.sig[1]
|
|
@@ -2352,31 +2433,31 @@ class CU {
|
|
|
2352
2433
|
m = {
|
|
2353
2434
|
sig: s,
|
|
2354
2435
|
beats: N
|
|
2355
|
-
}, t[
|
|
2436
|
+
}, t[Q] = m, t.splice(Q + 1, 1), W = s[0];
|
|
2356
2437
|
}
|
|
2357
|
-
if (
|
|
2358
|
-
const c = n, s =
|
|
2438
|
+
if (W > n) {
|
|
2439
|
+
const c = n, s = W - n, N = m.beats ? m.beats.slice(0, c) : [], J = m.beats ? m.beats.slice(c) : [], p = {
|
|
2359
2440
|
sig: [c, m.sig[1]],
|
|
2360
2441
|
beats: N
|
|
2361
2442
|
}, M = {
|
|
2362
2443
|
sig: [s, m.sig[1]],
|
|
2363
2444
|
beats: J
|
|
2364
2445
|
};
|
|
2365
|
-
t[
|
|
2446
|
+
t[Q] = p, t.splice(Q + 1, 0, M), m = p;
|
|
2366
2447
|
}
|
|
2367
|
-
this._generateBeatsForBar(F, R, m, n),
|
|
2448
|
+
this._generateBeatsForBar(F, R, m, n), Q++, V++;
|
|
2368
2449
|
}
|
|
2369
|
-
if (
|
|
2450
|
+
if (V < l.length) {
|
|
2370
2451
|
const R = F.length > 0 ? F[F.length - 1] : null;
|
|
2371
2452
|
let a = 0.5;
|
|
2372
2453
|
if (F.length >= 2) {
|
|
2373
|
-
const m = Math.min(8, F.length),
|
|
2374
|
-
a = (F[F.length - 1].time -
|
|
2454
|
+
const m = Math.min(8, F.length), W = F[F.length - m];
|
|
2455
|
+
a = (F[F.length - 1].time - W.time) / (m - 1);
|
|
2375
2456
|
}
|
|
2376
2457
|
let n = R ? R.time + a : 0;
|
|
2377
|
-
for (;
|
|
2378
|
-
const m = l[
|
|
2379
|
-
|
|
2458
|
+
for (; V < l.length; ) {
|
|
2459
|
+
const m = l[V], W = m.barNumber, c = d[W] !== void 0 ? d[W] : 4;
|
|
2460
|
+
d[W] === void 0 && (d[W] = c);
|
|
2380
2461
|
const s = [];
|
|
2381
2462
|
for (let J = 0; J < c; J++)
|
|
2382
2463
|
s.push(n), n += a;
|
|
@@ -2385,7 +2466,7 @@ class CU {
|
|
|
2385
2466
|
// Default to quarter notes
|
|
2386
2467
|
beats: s
|
|
2387
2468
|
};
|
|
2388
|
-
this._generateBeatsForBar(F, m, N, c),
|
|
2469
|
+
this._generateBeatsForBar(F, m, N, c), V++;
|
|
2389
2470
|
}
|
|
2390
2471
|
}
|
|
2391
2472
|
return F;
|
|
@@ -2394,18 +2475,18 @@ class CU {
|
|
|
2394
2475
|
* Generate beat entries for a single bar
|
|
2395
2476
|
* @private
|
|
2396
2477
|
*/
|
|
2397
|
-
_generateBeatsForBar(l, U, F,
|
|
2398
|
-
const { beats:
|
|
2399
|
-
if (!
|
|
2478
|
+
_generateBeatsForBar(l, U, F, d) {
|
|
2479
|
+
const { beats: Q } = F;
|
|
2480
|
+
if (!Q || !Array.isArray(Q))
|
|
2400
2481
|
throw new Error(`Invalid MIDI bar: missing beats array. Got: ${JSON.stringify(F)}`);
|
|
2401
|
-
const
|
|
2402
|
-
for (let t = 1; t <=
|
|
2482
|
+
const V = Q.slice(0, d);
|
|
2483
|
+
for (let t = 1; t <= d; t++) {
|
|
2403
2484
|
const R = {
|
|
2404
|
-
time:
|
|
2485
|
+
time: V[t - 1],
|
|
2405
2486
|
repeat: U.repeat,
|
|
2406
2487
|
bar: U.barNumber,
|
|
2407
2488
|
beat: t,
|
|
2408
|
-
timeSig:
|
|
2489
|
+
timeSig: d
|
|
2409
2490
|
};
|
|
2410
2491
|
l.push(R);
|
|
2411
2492
|
}
|
|
@@ -2424,8 +2505,8 @@ class CU {
|
|
|
2424
2505
|
_shouldPlayBar(l, U, F) {
|
|
2425
2506
|
if (!l.voltas)
|
|
2426
2507
|
return !0;
|
|
2427
|
-
const
|
|
2428
|
-
return
|
|
2508
|
+
const d = l.voltas.indexOf(U);
|
|
2509
|
+
return d === -1 ? !0 : d + 1 === F;
|
|
2429
2510
|
}
|
|
2430
2511
|
}
|
|
2431
2512
|
class Jl {
|
|
@@ -2436,12 +2517,12 @@ class Jl {
|
|
|
2436
2517
|
* @param {Object} instrumentMap - Mapping of part names to instrument configurations
|
|
2437
2518
|
* @param {Object} [structureMetadata] - Optional score structure for beat mapping
|
|
2438
2519
|
*/
|
|
2439
|
-
constructor(l = null, U, F = null,
|
|
2520
|
+
constructor(l = null, U, F = null, d = null) {
|
|
2440
2521
|
if (!U)
|
|
2441
2522
|
throw new Error("Parsed MIDI data is required");
|
|
2442
|
-
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 =
|
|
2443
|
-
const
|
|
2444
|
-
this.beats = this.beatMapper.mapBeats(U,
|
|
2523
|
+
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 = d, this._calculateTotalDuration();
|
|
2524
|
+
const Q = d || this._createDefaultStructureMetadata();
|
|
2525
|
+
this.beats = this.beatMapper.mapBeats(U, Q), this._audioEngineReady && (this._setupPartChannels(), this._resetNotePointers(), this._resetProgramPointers());
|
|
2445
2526
|
}
|
|
2446
2527
|
// ========================================
|
|
2447
2528
|
// PUBLIC API - Initialization Methods
|
|
@@ -2514,8 +2595,8 @@ class Jl {
|
|
|
2514
2595
|
throw new Error("Playback speed must be greater than 0");
|
|
2515
2596
|
const F = U && this._isPlaying;
|
|
2516
2597
|
F && this.pause();
|
|
2517
|
-
const
|
|
2518
|
-
this.playbackSpeed = l, F ? this.play() : this.playbackStartTime = this.audioEngine.audioContext.currentTime -
|
|
2598
|
+
const d = (this.audioEngine.audioContext.currentTime - this.playbackStartTime) * this.playbackSpeed;
|
|
2599
|
+
this.playbackSpeed = l, F ? this.play() : this.playbackStartTime = this.audioEngine.audioContext.currentTime - d / this.playbackSpeed;
|
|
2519
2600
|
}
|
|
2520
2601
|
/**
|
|
2521
2602
|
* Navigate to a specific bar position
|
|
@@ -2535,7 +2616,7 @@ class Jl {
|
|
|
2535
2616
|
getTimeFromBar(l, U = 0) {
|
|
2536
2617
|
U || (U = 1);
|
|
2537
2618
|
const F = this.beats.find(
|
|
2538
|
-
(
|
|
2619
|
+
(d) => d.bar === l && d.beat === 1 && d.repeat === U
|
|
2539
2620
|
);
|
|
2540
2621
|
return F ? F.time : null;
|
|
2541
2622
|
}
|
|
@@ -2625,11 +2706,11 @@ class Jl {
|
|
|
2625
2706
|
*/
|
|
2626
2707
|
getAllNextNotes(l) {
|
|
2627
2708
|
const U = l ?? this.getCurrentTime(), F = {};
|
|
2628
|
-
for (const [
|
|
2629
|
-
const
|
|
2630
|
-
F[
|
|
2631
|
-
pitch:
|
|
2632
|
-
startTime:
|
|
2709
|
+
for (const [d, Q] of Object.entries(this.parsedData.parts)) {
|
|
2710
|
+
const V = Q.notes.find((t) => t.startTime >= U);
|
|
2711
|
+
F[d] = V ? {
|
|
2712
|
+
pitch: V.pitch,
|
|
2713
|
+
startTime: V.startTime
|
|
2633
2714
|
} : null;
|
|
2634
2715
|
}
|
|
2635
2716
|
return F;
|
|
@@ -2668,19 +2749,19 @@ class Jl {
|
|
|
2668
2749
|
*/
|
|
2669
2750
|
_setupPartChannels() {
|
|
2670
2751
|
Object.keys(this.parsedData.parts).forEach((l) => {
|
|
2671
|
-
const U = this.parsedData.parts[l], F = this.instrumentMap[l] || {},
|
|
2752
|
+
const U = this.parsedData.parts[l], F = this.instrumentMap[l] || {}, d = F.instrument !== void 0 ? F.instrument : U.defaultInstrument !== void 0 ? U.defaultInstrument : 0;
|
|
2672
2753
|
try {
|
|
2673
|
-
const
|
|
2674
|
-
instrument:
|
|
2754
|
+
const Q = this.audioEngine.createChannel(l, {
|
|
2755
|
+
instrument: d,
|
|
2675
2756
|
initialVolume: F.volume || 1
|
|
2676
2757
|
});
|
|
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}':`,
|
|
2758
|
+
this.partChannels.set(l, Q);
|
|
2759
|
+
const V = this.audioEngine.audioContext.createGain();
|
|
2760
|
+
V.gain.value = 1;
|
|
2761
|
+
const t = Q.getOutputNode();
|
|
2762
|
+
t && t.connect(V), this.partOutputs.set(l, V);
|
|
2763
|
+
} catch (Q) {
|
|
2764
|
+
console.error(`Failed to create channel for part '${l}':`, Q), this._emitEvent("error", Q);
|
|
2684
2765
|
}
|
|
2685
2766
|
});
|
|
2686
2767
|
}
|
|
@@ -2711,34 +2792,34 @@ class Jl {
|
|
|
2711
2792
|
this.scheduleInterval || (this.scheduleInterval = setInterval(() => {
|
|
2712
2793
|
if (!this._isPlaying) return;
|
|
2713
2794
|
const l = (this.audioEngine.audioContext.currentTime - this.playbackStartTime) * this.playbackSpeed, U = l + this.lookAheadTime;
|
|
2714
|
-
for (const [F,
|
|
2715
|
-
const
|
|
2716
|
-
if (
|
|
2717
|
-
if (
|
|
2718
|
-
let
|
|
2719
|
-
const t =
|
|
2720
|
-
for (;
|
|
2721
|
-
|
|
2722
|
-
for (;
|
|
2723
|
-
const R = t[
|
|
2724
|
-
|
|
2795
|
+
for (const [F, d] of this.partChannels) {
|
|
2796
|
+
const Q = this.parsedData.parts[F];
|
|
2797
|
+
if (Q) {
|
|
2798
|
+
if (Q.programChanges && Q.programChanges.length > 0) {
|
|
2799
|
+
let V = this.partProgramPointers.get(F) || 0;
|
|
2800
|
+
const t = Q.programChanges;
|
|
2801
|
+
for (; V < t.length && t[V].time < l; )
|
|
2802
|
+
V++;
|
|
2803
|
+
for (; V < t.length && t[V].time <= U; ) {
|
|
2804
|
+
const R = t[V];
|
|
2805
|
+
d.setInstrument(R.programNumber), V++;
|
|
2725
2806
|
}
|
|
2726
|
-
this.partProgramPointers.set(F,
|
|
2807
|
+
this.partProgramPointers.set(F, V);
|
|
2727
2808
|
}
|
|
2728
|
-
if (
|
|
2729
|
-
let
|
|
2730
|
-
const t =
|
|
2731
|
-
for (;
|
|
2732
|
-
|
|
2733
|
-
for (;
|
|
2734
|
-
const R = t[
|
|
2809
|
+
if (Q.notes) {
|
|
2810
|
+
let V = this.partNotePointers.get(F) || 0;
|
|
2811
|
+
const t = Q.notes;
|
|
2812
|
+
for (; V < t.length && t[V].endTime < l; )
|
|
2813
|
+
V++;
|
|
2814
|
+
for (; V < t.length && t[V].startTime <= U; ) {
|
|
2815
|
+
const R = t[V];
|
|
2735
2816
|
if (R.endTime - R.startTime >= 0.01) {
|
|
2736
2817
|
const a = this.playbackStartTime + R.startTime / this.playbackSpeed, n = (R.endTime - R.startTime) / this.playbackSpeed;
|
|
2737
|
-
|
|
2818
|
+
d.playNote(a, R.pitch, R.velocity, n);
|
|
2738
2819
|
}
|
|
2739
|
-
|
|
2820
|
+
V++;
|
|
2740
2821
|
}
|
|
2741
|
-
this.partNotePointers.set(F,
|
|
2822
|
+
this.partNotePointers.set(F, V);
|
|
2742
2823
|
}
|
|
2743
2824
|
}
|
|
2744
2825
|
}
|
|
@@ -2753,10 +2834,10 @@ class Jl {
|
|
|
2753
2834
|
for (const [U] of this.partChannels) {
|
|
2754
2835
|
const F = this.parsedData.parts[U];
|
|
2755
2836
|
if (!F || !F.notes) continue;
|
|
2756
|
-
let
|
|
2757
|
-
for (;
|
|
2758
|
-
|
|
2759
|
-
this.partNotePointers.set(U,
|
|
2837
|
+
let d = 0;
|
|
2838
|
+
for (; d < F.notes.length && F.notes[d].endTime < l; )
|
|
2839
|
+
d++;
|
|
2840
|
+
this.partNotePointers.set(U, d);
|
|
2760
2841
|
}
|
|
2761
2842
|
}
|
|
2762
2843
|
/**
|
|
@@ -2766,15 +2847,15 @@ class Jl {
|
|
|
2766
2847
|
_resetProgramPointers() {
|
|
2767
2848
|
const l = this._currentTime;
|
|
2768
2849
|
for (const [U, F] of this.partChannels) {
|
|
2769
|
-
const
|
|
2770
|
-
if (!
|
|
2850
|
+
const d = this.parsedData.parts[U];
|
|
2851
|
+
if (!d || !d.programChanges) {
|
|
2771
2852
|
this.partProgramPointers.set(U, 0);
|
|
2772
2853
|
continue;
|
|
2773
2854
|
}
|
|
2774
|
-
let
|
|
2775
|
-
for (;
|
|
2776
|
-
|
|
2777
|
-
F.setInstrument(
|
|
2855
|
+
let Q = 0, V = d.defaultInstrument;
|
|
2856
|
+
for (; Q < d.programChanges.length && d.programChanges[Q].time <= l; )
|
|
2857
|
+
V = d.programChanges[Q].programNumber, Q++;
|
|
2858
|
+
F.setInstrument(V), this.partProgramPointers.set(U, Q);
|
|
2778
2859
|
}
|
|
2779
2860
|
}
|
|
2780
2861
|
/**
|
|
@@ -2815,8 +2896,8 @@ class Jl {
|
|
|
2815
2896
|
(this.eventBus.all.get(l) || []).forEach((F) => {
|
|
2816
2897
|
try {
|
|
2817
2898
|
F(U);
|
|
2818
|
-
} catch (
|
|
2819
|
-
console.error(`Error in ${l} event listener:`,
|
|
2899
|
+
} catch (d) {
|
|
2900
|
+
console.error(`Error in ${l} event listener:`, d);
|
|
2820
2901
|
}
|
|
2821
2902
|
});
|
|
2822
2903
|
}
|
|
@@ -3225,15 +3306,15 @@ class xU {
|
|
|
3225
3306
|
throw new Error("Audio engine not ready. Call setAudioEngine() first.");
|
|
3226
3307
|
if (this.isCalibrating)
|
|
3227
3308
|
throw new Error("Calibration already in progress");
|
|
3228
|
-
const U = l.measurements || 5, F = l.sampleIntervalMs || 10,
|
|
3309
|
+
const U = l.measurements || 5, F = l.sampleIntervalMs || 10, d = 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
3310
|
this.isCalibrating = !0;
|
|
3230
3311
|
try {
|
|
3231
|
-
|
|
3312
|
+
V && await this._setupSilentCalibration();
|
|
3232
3313
|
const R = await this._performLatencyMeasurement(
|
|
3233
3314
|
U,
|
|
3234
3315
|
F,
|
|
3235
|
-
|
|
3236
|
-
|
|
3316
|
+
d,
|
|
3317
|
+
Q
|
|
3237
3318
|
);
|
|
3238
3319
|
this.measuredLatencyMs = R, t && await this._updateBaselineLatency(R);
|
|
3239
3320
|
const a = this.hasLatencyDrift();
|
|
@@ -3249,7 +3330,7 @@ class xU {
|
|
|
3249
3330
|
driftMs: R - this.baselineLatencyMs
|
|
3250
3331
|
})), R;
|
|
3251
3332
|
} finally {
|
|
3252
|
-
|
|
3333
|
+
V && this._teardownSilentCalibration(), this.isCalibrating = !1;
|
|
3253
3334
|
}
|
|
3254
3335
|
}
|
|
3255
3336
|
/**
|
|
@@ -3342,19 +3423,19 @@ class xU {
|
|
|
3342
3423
|
previewNextNotes(l = {}) {
|
|
3343
3424
|
if (!this.midiPlayer)
|
|
3344
3425
|
throw new Error("No MIDI data loaded");
|
|
3345
|
-
const U = l.delayBetweenParts ?? 0.3, F = l.duration ?? 0.5,
|
|
3426
|
+
const U = l.delayBetweenParts ?? 0.3, F = l.duration ?? 0.5, d = l.velocity ?? 100, Q = this.midiPlayer.getAllNextNotes(), V = l.partOrder ?? this.getPartNames();
|
|
3346
3427
|
let t = this.audioEngine.audioContext.currentTime + 0.01;
|
|
3347
3428
|
const R = [];
|
|
3348
|
-
for (const a of
|
|
3349
|
-
const n =
|
|
3429
|
+
for (const a of V) {
|
|
3430
|
+
const n = Q[a];
|
|
3350
3431
|
if (!n) continue;
|
|
3351
3432
|
const m = this.midiPlayer.getPartChannel(a);
|
|
3352
3433
|
if (!m) continue;
|
|
3353
|
-
const
|
|
3354
|
-
|
|
3434
|
+
const W = this.midiPlayer.getPartOutput(a);
|
|
3435
|
+
W && W.gain.value === 0 || (m.playPreviewNote(n.pitch, {
|
|
3355
3436
|
startTime: t,
|
|
3356
3437
|
duration: F,
|
|
3357
|
-
velocity:
|
|
3438
|
+
velocity: d,
|
|
3358
3439
|
instrument: l.instrument
|
|
3359
3440
|
}), R.push({
|
|
3360
3441
|
partName: a,
|
|
@@ -3483,17 +3564,17 @@ class xU {
|
|
|
3483
3564
|
startBeat: { bar: 1, beat: 1, timeSig: 4 }
|
|
3484
3565
|
};
|
|
3485
3566
|
const l = this.midiPlayer.beats, U = this.frozenTime, F = this.leadInConfig.bars;
|
|
3486
|
-
let
|
|
3487
|
-
for (; l[
|
|
3488
|
-
const
|
|
3489
|
-
t ?
|
|
3490
|
-
const R = this.midiPlayer && this.midiPlayer.playbackSpeed || 1, a =
|
|
3567
|
+
let d = l.length - 1, Q = 0.5;
|
|
3568
|
+
for (; l[d].time > U; ) d--;
|
|
3569
|
+
const V = l[d], t = l[d + 1];
|
|
3570
|
+
t ? Q = t.time - V.time : d > 0 && (Q = V.time - l[d - 1].time);
|
|
3571
|
+
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
3572
|
return {
|
|
3492
3573
|
totalBeats: c,
|
|
3493
3574
|
duration: c * a,
|
|
3494
3575
|
beatSequence: this._generateBeatSequence(c, a, m),
|
|
3495
3576
|
beatsPerBar: m,
|
|
3496
|
-
startBeat:
|
|
3577
|
+
startBeat: V
|
|
3497
3578
|
};
|
|
3498
3579
|
}
|
|
3499
3580
|
/**
|
|
@@ -3505,19 +3586,19 @@ class xU {
|
|
|
3505
3586
|
* @private
|
|
3506
3587
|
*/
|
|
3507
3588
|
_generateBeatSequence(l, U, F) {
|
|
3508
|
-
const
|
|
3509
|
-
for (let
|
|
3510
|
-
const
|
|
3511
|
-
|
|
3512
|
-
beat:
|
|
3513
|
-
isAccent:
|
|
3514
|
-
time:
|
|
3589
|
+
const d = [];
|
|
3590
|
+
for (let Q = 0; Q < l; Q++) {
|
|
3591
|
+
const V = Q % F + 1;
|
|
3592
|
+
d.push({
|
|
3593
|
+
beat: V,
|
|
3594
|
+
isAccent: V === 1,
|
|
3595
|
+
time: Q * U,
|
|
3515
3596
|
// Relative time from start of lead-in playback
|
|
3516
|
-
absoluteTime: this.leadInStartTime +
|
|
3597
|
+
absoluteTime: this.leadInStartTime + Q * U
|
|
3517
3598
|
// Absolute time (includes startup delay)
|
|
3518
3599
|
});
|
|
3519
3600
|
}
|
|
3520
|
-
return
|
|
3601
|
+
return d;
|
|
3521
3602
|
}
|
|
3522
3603
|
/**
|
|
3523
3604
|
* Start lead-in tick scheduling using beat-index approach
|
|
@@ -3528,20 +3609,20 @@ class xU {
|
|
|
3528
3609
|
this.leadInBeatIndex = 0, this.leadInScheduledBeats = /* @__PURE__ */ new Set();
|
|
3529
3610
|
const U = this.leadInData.beatSequence, F = 10;
|
|
3530
3611
|
this.leadInStartTime = this.audioEngine.audioContext.currentTime, this.leadInInterval = setInterval(() => {
|
|
3531
|
-
const
|
|
3532
|
-
for (this.leadInProgress = Math.min(1,
|
|
3533
|
-
const
|
|
3534
|
-
if (
|
|
3612
|
+
const d = this.audioEngine.audioContext.currentTime - this.leadInStartTime;
|
|
3613
|
+
for (this.leadInProgress = Math.min(1, d / this.leadInData.duration); this.leadInBeatIndex < U.length; ) {
|
|
3614
|
+
const Q = U[this.leadInBeatIndex], V = Q.time - d;
|
|
3615
|
+
if (V > 0.05)
|
|
3535
3616
|
break;
|
|
3536
|
-
if (!this.leadInScheduledBeats.has(this.leadInBeatIndex) &&
|
|
3537
|
-
const t =
|
|
3617
|
+
if (!this.leadInScheduledBeats.has(this.leadInBeatIndex) && V >= -0.05 && V <= 0.05) {
|
|
3618
|
+
const t = V <= 0 ? this.audioEngine.audioContext.currentTime + 0.01 : (
|
|
3538
3619
|
// Add small offset for immediate beats
|
|
3539
|
-
this.audioEngine.audioContext.currentTime +
|
|
3620
|
+
this.audioEngine.audioContext.currentTime + V
|
|
3540
3621
|
);
|
|
3541
|
-
this._scheduleTickAtTime(t,
|
|
3622
|
+
this._scheduleTickAtTime(t, Q.isAccent);
|
|
3542
3623
|
const R = {
|
|
3543
3624
|
bar: Math.floor(this.leadInBeatIndex / this.leadInData.beatsPerBar) + 1,
|
|
3544
|
-
beat:
|
|
3625
|
+
beat: Q.beat,
|
|
3545
3626
|
repeat: 1,
|
|
3546
3627
|
time: this.frozenTime,
|
|
3547
3628
|
isLeadIn: !0
|
|
@@ -3586,15 +3667,15 @@ class xU {
|
|
|
3586
3667
|
this.state = "playing", this._resetMetronomeBeatTracking(), U && this._emitEvent("playbackStarted", {
|
|
3587
3668
|
startupDelayMs: F ? 0 : this.startupConfig.delayMs
|
|
3588
3669
|
});
|
|
3589
|
-
const
|
|
3670
|
+
const d = () => {
|
|
3590
3671
|
if (this.state === "playing")
|
|
3591
3672
|
try {
|
|
3592
3673
|
this.midiPlayer.play(), l && this._startMetronome();
|
|
3593
|
-
} catch (
|
|
3594
|
-
this.state = "stopped", this._emitEvent("error",
|
|
3674
|
+
} catch (Q) {
|
|
3675
|
+
this.state = "stopped", this._emitEvent("error", Q);
|
|
3595
3676
|
}
|
|
3596
3677
|
};
|
|
3597
|
-
F ?
|
|
3678
|
+
F ? d() : setTimeout(d, this.startupConfig.delayMs), this.timeUpdateInterval || this._startTimeUpdateLoop();
|
|
3598
3679
|
}
|
|
3599
3680
|
/**
|
|
3600
3681
|
* Start metronome during MIDI playback
|
|
@@ -3633,14 +3714,14 @@ class xU {
|
|
|
3633
3714
|
const U = this.midiPlayer.beats;
|
|
3634
3715
|
if (!U || U.length === 0)
|
|
3635
3716
|
return;
|
|
3636
|
-
const F = this.midiPlayer.getCurrentTime(),
|
|
3637
|
-
for (let
|
|
3638
|
-
const
|
|
3639
|
-
if (R > this.audioEngine.audioContext.currentTime +
|
|
3717
|
+
const F = this.midiPlayer.getCurrentTime(), d = 0.1;
|
|
3718
|
+
for (let Q = this.nextBeatIndex; Q < U.length; Q++) {
|
|
3719
|
+
const V = U[Q], t = this.midiPlayer.playbackSpeed || 1, R = l + (V.time - F) / t;
|
|
3720
|
+
if (R > this.audioEngine.audioContext.currentTime + d)
|
|
3640
3721
|
break;
|
|
3641
3722
|
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 =
|
|
3723
|
+
const a = Math.max(R, this.audioEngine.audioContext.currentTime + 1e-3), n = V.isDownbeat || V.beat === 1;
|
|
3724
|
+
this._scheduleTickAtTime(a, n), this.nextBeatIndex = Q + 1;
|
|
3644
3725
|
}
|
|
3645
3726
|
}
|
|
3646
3727
|
}
|
|
@@ -3657,11 +3738,11 @@ class xU {
|
|
|
3657
3738
|
this.nextBeatIndex++;
|
|
3658
3739
|
const F = l + 0.15;
|
|
3659
3740
|
for (; this.nextBeatIndex < U.length; ) {
|
|
3660
|
-
const
|
|
3661
|
-
if (
|
|
3741
|
+
const d = U[this.nextBeatIndex], Q = d.time - l;
|
|
3742
|
+
if (d.time > F)
|
|
3662
3743
|
break;
|
|
3663
|
-
if (
|
|
3664
|
-
const
|
|
3744
|
+
if (Q >= -0.025 && Q <= 0.15) {
|
|
3745
|
+
const V = this.audioEngine.audioContext.currentTime + 5e-3, t = this.audioEngine.audioContext.currentTime + Math.max(Q, 5e-3), R = Math.max(V, t), a = d.beat === 1;
|
|
3665
3746
|
this._scheduleTickAtTime(R, a);
|
|
3666
3747
|
}
|
|
3667
3748
|
this.nextBeatIndex++;
|
|
@@ -3766,8 +3847,8 @@ class xU {
|
|
|
3766
3847
|
(this.eventBus.all.get(l) || []).forEach((F) => {
|
|
3767
3848
|
try {
|
|
3768
3849
|
F(U);
|
|
3769
|
-
} catch (
|
|
3770
|
-
console.error(`Error in ${l} event listener:`,
|
|
3850
|
+
} catch (d) {
|
|
3851
|
+
console.error(`Error in ${l} event listener:`, d);
|
|
3771
3852
|
}
|
|
3772
3853
|
});
|
|
3773
3854
|
}
|
|
@@ -3836,7 +3917,10 @@ class xU {
|
|
|
3836
3917
|
* @private
|
|
3837
3918
|
*/
|
|
3838
3919
|
_completeMidiPlayerSetup() {
|
|
3839
|
-
this._partOutputsMap.clear(), Object.keys(this.midiPlayer.parsedData.parts).
|
|
3920
|
+
this._partOutputsMap.clear(), Object.keys(this.midiPlayer.parsedData.parts).sort((l, U) => {
|
|
3921
|
+
const F = this.midiPlayer.parsedData.parts[l], d = this.midiPlayer.parsedData.parts[U], Q = F.channel !== void 0 ? F.channel : F.trackIndex, V = d.channel !== void 0 ? d.channel : d.trackIndex;
|
|
3922
|
+
return Q - V;
|
|
3923
|
+
}).forEach((l) => {
|
|
3840
3924
|
const U = this.midiPlayer.getPartOutput(l);
|
|
3841
3925
|
U && this._partOutputsMap.set(l, U);
|
|
3842
3926
|
}), this._setupEventDelegation(), this.state = "ready";
|
|
@@ -3859,12 +3943,20 @@ class xU {
|
|
|
3859
3943
|
flute: { instrument: "flute", volume: 0.8 },
|
|
3860
3944
|
trumpet: { instrument: "trumpet", volume: 0.7 }
|
|
3861
3945
|
};
|
|
3862
|
-
return Object.keys(l).forEach((
|
|
3863
|
-
const
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3946
|
+
return Object.keys(l).forEach((d) => {
|
|
3947
|
+
const Q = l[d];
|
|
3948
|
+
if (Q.defaultInstrument !== void 0)
|
|
3949
|
+
U[d] = {
|
|
3950
|
+
instrument: Q.defaultInstrument,
|
|
3951
|
+
volume: 1
|
|
3952
|
+
};
|
|
3953
|
+
else {
|
|
3954
|
+
const V = d.toLowerCase(), t = F[V] || F.piano;
|
|
3955
|
+
U[d] = {
|
|
3956
|
+
instrument: t.instrument,
|
|
3957
|
+
volume: t.volume
|
|
3958
|
+
};
|
|
3959
|
+
}
|
|
3868
3960
|
}), U;
|
|
3869
3961
|
}
|
|
3870
3962
|
// ========================================
|
|
@@ -3884,19 +3976,19 @@ class xU {
|
|
|
3884
3976
|
const U = this.audioEngine.getMetronomeAnalyser();
|
|
3885
3977
|
if (!U)
|
|
3886
3978
|
throw new Error("Metronome analyser not available for signal capture");
|
|
3887
|
-
const F = l.sampleIntervalMs || 2,
|
|
3888
|
-
await this.audioEngine.playMetronomeTick(
|
|
3889
|
-
const
|
|
3979
|
+
const F = l.sampleIntervalMs || 2, d = l.captureDurationMs || 1500, Q = this.audioEngine.audioContext.currentTime + 0.1;
|
|
3980
|
+
await this.audioEngine.playMetronomeTick(Q, !0, 1);
|
|
3981
|
+
const V = await this._captureAnalyserTimeSeries(
|
|
3890
3982
|
U,
|
|
3891
|
-
|
|
3983
|
+
Q,
|
|
3892
3984
|
F,
|
|
3893
|
-
|
|
3985
|
+
d
|
|
3894
3986
|
);
|
|
3895
3987
|
return {
|
|
3896
|
-
scheduledTime:
|
|
3897
|
-
samples:
|
|
3988
|
+
scheduledTime: Q,
|
|
3989
|
+
samples: V,
|
|
3898
3990
|
sampleIntervalMs: F,
|
|
3899
|
-
captureDurationMs:
|
|
3991
|
+
captureDurationMs: d
|
|
3900
3992
|
};
|
|
3901
3993
|
}
|
|
3902
3994
|
/**
|
|
@@ -3908,21 +4000,21 @@ class xU {
|
|
|
3908
4000
|
* @returns {Promise<number>} Average latency in milliseconds
|
|
3909
4001
|
* @private
|
|
3910
4002
|
*/
|
|
3911
|
-
async _performLatencyMeasurement(l, U, F,
|
|
3912
|
-
const
|
|
3913
|
-
if (!
|
|
4003
|
+
async _performLatencyMeasurement(l, U, F, d) {
|
|
4004
|
+
const Q = this.audioEngine.getMetronomeAnalyser();
|
|
4005
|
+
if (!Q)
|
|
3914
4006
|
throw new Error("Metronome analyser not available for latency measurement");
|
|
3915
|
-
const
|
|
4007
|
+
const V = this.audioEngine.audioContext, t = [];
|
|
3916
4008
|
console.log(`Starting calibration: ${l} measurements, ${U}ms sampling, ${F} threshold`);
|
|
3917
4009
|
for (let m = 0; m < l; m++) {
|
|
3918
|
-
const
|
|
3919
|
-
await this.audioEngine.playMetronomeTick(
|
|
4010
|
+
const W = V.currentTime + 0.15;
|
|
4011
|
+
await this.audioEngine.playMetronomeTick(W, !0, 1);
|
|
3920
4012
|
const c = await this._detectOnsetByThreshold(
|
|
3921
|
-
|
|
3922
|
-
|
|
4013
|
+
Q,
|
|
4014
|
+
W,
|
|
3923
4015
|
U,
|
|
3924
4016
|
F,
|
|
3925
|
-
|
|
4017
|
+
d
|
|
3926
4018
|
);
|
|
3927
4019
|
if (c) {
|
|
3928
4020
|
const s = c.latencyMs;
|
|
@@ -3935,7 +4027,7 @@ class xU {
|
|
|
3935
4027
|
throw new Error(`Failed to detect any metronome onsets. Try lowering threshold (current: ${F}) or check audio routing.`);
|
|
3936
4028
|
let R = t;
|
|
3937
4029
|
if (t.length >= 5) {
|
|
3938
|
-
const m = [...t].sort((
|
|
4030
|
+
const m = [...t].sort((W, c) => W - c);
|
|
3939
4031
|
R = m.slice(
|
|
3940
4032
|
Math.floor(m.length * 0.2),
|
|
3941
4033
|
// Remove bottom 20%
|
|
@@ -3943,8 +4035,8 @@ class xU {
|
|
|
3943
4035
|
// Remove top 20%
|
|
3944
4036
|
), console.log(`Discarded ${t.length - R.length} outliers`);
|
|
3945
4037
|
}
|
|
3946
|
-
const a = R.reduce((m,
|
|
3947
|
-
R.reduce((m,
|
|
4038
|
+
const a = R.reduce((m, W) => m + W, 0) / R.length, n = Math.sqrt(
|
|
4039
|
+
R.reduce((m, W) => m + Math.pow(W - a, 2), 0) / R.length
|
|
3948
4040
|
);
|
|
3949
4041
|
return console.log(`Average latency: ${a.toFixed(1)}ms ± ${n.toFixed(1)}ms (n=${R.length})`), Math.round(a);
|
|
3950
4042
|
}
|
|
@@ -3959,14 +4051,14 @@ class xU {
|
|
|
3959
4051
|
* @returns {Promise<Object|null>} Detection result {latencyMs, rms, peak} or null if timeout
|
|
3960
4052
|
* @private
|
|
3961
4053
|
*/
|
|
3962
|
-
async _detectOnsetByThreshold(l, U, F,
|
|
3963
|
-
const
|
|
4054
|
+
async _detectOnsetByThreshold(l, U, F, d, Q) {
|
|
4055
|
+
const V = this.audioEngine.audioContext, t = l.fftSize, R = new Float32Array(t), a = Math.max(0, (U - V.currentTime) * 1e3 - 20);
|
|
3964
4056
|
await new Promise((m) => setTimeout(m, a));
|
|
3965
4057
|
const n = performance.now();
|
|
3966
4058
|
return new Promise((m) => {
|
|
3967
|
-
const
|
|
3968
|
-
if (performance.now() - n >
|
|
3969
|
-
clearInterval(
|
|
4059
|
+
const W = setInterval(() => {
|
|
4060
|
+
if (performance.now() - n > Q) {
|
|
4061
|
+
clearInterval(W), m(null);
|
|
3970
4062
|
return;
|
|
3971
4063
|
}
|
|
3972
4064
|
l.getFloatTimeDomainData(R);
|
|
@@ -3976,9 +4068,9 @@ class xU {
|
|
|
3976
4068
|
c += R[J] * R[J], p > s && (s = p);
|
|
3977
4069
|
}
|
|
3978
4070
|
const N = Math.sqrt(c / t);
|
|
3979
|
-
if (N >=
|
|
3980
|
-
clearInterval(
|
|
3981
|
-
const J =
|
|
4071
|
+
if (N >= d) {
|
|
4072
|
+
clearInterval(W);
|
|
4073
|
+
const J = V.currentTime, p = (J - U) * 1e3;
|
|
3982
4074
|
m({
|
|
3983
4075
|
latencyMs: p,
|
|
3984
4076
|
rms: N,
|
|
@@ -3998,21 +4090,21 @@ class xU {
|
|
|
3998
4090
|
* @returns {Promise<Array>} Array of samples {time, rms, peak, relativeTime}
|
|
3999
4091
|
* @private
|
|
4000
4092
|
*/
|
|
4001
|
-
async _captureAnalyserTimeSeries(l, U, F,
|
|
4002
|
-
const
|
|
4093
|
+
async _captureAnalyserTimeSeries(l, U, F, d) {
|
|
4094
|
+
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
4095
|
return await new Promise((m) => setTimeout(m, n)), new Promise((m) => {
|
|
4004
|
-
const
|
|
4005
|
-
if (performance.now() - a - n >=
|
|
4006
|
-
clearInterval(
|
|
4096
|
+
const W = setInterval(() => {
|
|
4097
|
+
if (performance.now() - a - n >= d) {
|
|
4098
|
+
clearInterval(W), m(R);
|
|
4007
4099
|
return;
|
|
4008
4100
|
}
|
|
4009
4101
|
l.getFloatTimeDomainData(t);
|
|
4010
4102
|
let c = 0, s = 0;
|
|
4011
|
-
for (let p = 0; p <
|
|
4103
|
+
for (let p = 0; p < V; p++) {
|
|
4012
4104
|
const M = Math.abs(t[p]);
|
|
4013
4105
|
c += t[p] * t[p], M > s && (s = M);
|
|
4014
4106
|
}
|
|
4015
|
-
const N = Math.sqrt(c /
|
|
4107
|
+
const N = Math.sqrt(c / V), J = Q.currentTime;
|
|
4016
4108
|
R.push({
|
|
4017
4109
|
time: J,
|
|
4018
4110
|
relativeTime: (J - U) * 1e3,
|
|
@@ -4036,8 +4128,8 @@ class MU {
|
|
|
4036
4128
|
// Initialize audio system
|
|
4037
4129
|
async initializeAudioSystem() {
|
|
4038
4130
|
if (this.isInitialized) return;
|
|
4039
|
-
this.audioContext = new (window.AudioContext || window.webkitAudioContext)(), this.audioContext.state === "suspended" && await this.audioContext.resume(), this.audioEngine = new rU(this.audioContext), this.audioEngine.on("initProgress", (
|
|
4040
|
-
this.eventBus.emit("initProgress",
|
|
4131
|
+
this.audioContext = new (window.AudioContext || window.webkitAudioContext)(), this.audioContext.state === "suspended" && await this.audioContext.resume(), this.audioEngine = new rU(this.audioContext), this.audioEngine.on("initProgress", (d) => {
|
|
4132
|
+
this.eventBus.emit("initProgress", d);
|
|
4041
4133
|
});
|
|
4042
4134
|
const l = [
|
|
4043
4135
|
"/FluidR3Mono_GM.sf3",
|
|
@@ -4045,20 +4137,20 @@ class MU {
|
|
|
4045
4137
|
"/soundfont.sf2"
|
|
4046
4138
|
];
|
|
4047
4139
|
let U = !1, F = null;
|
|
4048
|
-
for (const
|
|
4140
|
+
for (const d of l)
|
|
4049
4141
|
try {
|
|
4050
|
-
await this.audioEngine.initialize(
|
|
4142
|
+
await this.audioEngine.initialize(d), console.log(`Loaded soundfont: ${d}`), U = !0;
|
|
4051
4143
|
break;
|
|
4052
|
-
} catch (
|
|
4053
|
-
console.warn(`Failed to load soundfont ${
|
|
4144
|
+
} catch (Q) {
|
|
4145
|
+
console.warn(`Failed to load soundfont ${d}:`, Q.message), F = Q;
|
|
4054
4146
|
}
|
|
4055
4147
|
if (!U) {
|
|
4056
|
-
const
|
|
4148
|
+
const d = "No soundfont could be loaded";
|
|
4057
4149
|
throw this.eventBus.emit("initProgress", {
|
|
4058
4150
|
stage: "error",
|
|
4059
|
-
message:
|
|
4151
|
+
message: d,
|
|
4060
4152
|
error: F
|
|
4061
|
-
}), new Error(
|
|
4153
|
+
}), new Error(d);
|
|
4062
4154
|
}
|
|
4063
4155
|
this.setupMasterAudioGraph(), this.isInitialized = !0, console.log("AudioEngineService initialized successfully");
|
|
4064
4156
|
}
|
|
@@ -4073,7 +4165,7 @@ class MU {
|
|
|
4073
4165
|
else {
|
|
4074
4166
|
if (this.beats = l.beats || [], this.practiceMarks = l.marks || l.practiceMarks || {}, this.beats.length > 0) {
|
|
4075
4167
|
const U = this.beats[this.beats.length - 1], F = U.tempo > 0 ? 60 / U.tempo : 0.75;
|
|
4076
|
-
this.songDuration = U.time + F, this.maxBar = Math.max(...this.beats.map((
|
|
4168
|
+
this.songDuration = U.time + F, this.maxBar = Math.max(...this.beats.map((d) => d.bar));
|
|
4077
4169
|
} else
|
|
4078
4170
|
this.songDuration = 0, this.maxBar = 0;
|
|
4079
4171
|
this.setupLegacyParts(l.parts || []), this.eventBus.emit("initialized", { parts: Array.from(this.parts.values()) });
|
|
@@ -4111,8 +4203,8 @@ class MU {
|
|
|
4111
4203
|
// Silent calibration
|
|
4112
4204
|
});
|
|
4113
4205
|
console.log(`Measured audio latency: ${F} ms`), this.setupPlaybackManagerEventDelegation(), await this.playbackManager.load(l, U);
|
|
4114
|
-
const
|
|
4115
|
-
this.setupMidiParts(
|
|
4206
|
+
const d = this.playbackManager.getPartNames();
|
|
4207
|
+
this.setupMidiParts(d), this.eventBus.emit("initialized", { parts: Array.from(this.parts.values()) }), await this.setupPartAudioRouting(d), this.setupMetronomeAudioRouting(), this.extractMusicDataFromPlayer(), this.updateSongDurationFromPlayer(), console.log("MIDI playback with PlaybackManager setup complete");
|
|
4116
4208
|
} catch (F) {
|
|
4117
4209
|
throw console.error("Failed to setup MIDI playback:", F), F;
|
|
4118
4210
|
}
|
|
@@ -4138,10 +4230,10 @@ class MU {
|
|
|
4138
4230
|
for (const [l, U] of this.playbackManager.getPartOutputs()) {
|
|
4139
4231
|
const F = this.audioContext.createGain();
|
|
4140
4232
|
F.gain.value = 1;
|
|
4141
|
-
const
|
|
4142
|
-
|
|
4143
|
-
const
|
|
4144
|
-
this.partGainNodes.set(
|
|
4233
|
+
const d = this.audioContext.createAnalyser();
|
|
4234
|
+
d.fftSize = 256, d.smoothingTimeConstant = 0.3, U.connect(F), F.connect(d), d.connect(this.masterGain);
|
|
4235
|
+
const Q = this.sanitizePartName(l);
|
|
4236
|
+
this.partGainNodes.set(Q, F), this.partAnalyserNodes.set(Q, d), console.log(`Audio routing established for part: ${l}`);
|
|
4145
4237
|
}
|
|
4146
4238
|
}
|
|
4147
4239
|
// Set up metronome audio routing (separate from parts)
|
|
@@ -4189,8 +4281,8 @@ class MU {
|
|
|
4189
4281
|
setupPlaybackManagerEventDelegation() {
|
|
4190
4282
|
this.playbackManager.on("timeupdate", ({ audioTime: l, leadInProgress: U }) => {
|
|
4191
4283
|
this.currentTime = l, this.eventBus.emit("timeChanged", { currentTime: l, leadInProgress: U });
|
|
4192
|
-
}), this.playbackManager.on("beatAudible", ({ bar: l, beat: U, isLeadIn: F, repeat:
|
|
4193
|
-
this.eventBus.emit("barChanged", { bar: l, beat: U, repeat:
|
|
4284
|
+
}), this.playbackManager.on("beatAudible", ({ bar: l, beat: U, isLeadIn: F, repeat: d, time: Q }) => {
|
|
4285
|
+
this.eventBus.emit("barChanged", { bar: l, beat: U, repeat: d, time: Q, isLeadIn: F });
|
|
4194
4286
|
}), this.playbackManager.on("leadInStarted", ({ totalBeats: l, duration: U, bars: F }) => {
|
|
4195
4287
|
this.eventBus.emit("leadInStarted", { bars: F, totalBeats: l, duration: U });
|
|
4196
4288
|
}), this.playbackManager.on("leadInEnded", () => {
|
|
@@ -4301,28 +4393,28 @@ class MU {
|
|
|
4301
4393
|
return this.metronomeVolume || 0.7;
|
|
4302
4394
|
}
|
|
4303
4395
|
setPartVolume(l, U) {
|
|
4304
|
-
const F = this.sanitizePartName(l),
|
|
4305
|
-
|
|
4396
|
+
const F = this.sanitizePartName(l), d = this.parts.get(F);
|
|
4397
|
+
d ? (d.volume = Math.max(0, Math.min(1, U)), this.updatePartAudioState(F), this.eventBus.emit("partVolumeChanged", { partName: l, volume: U })) : (console.log(`Part not found: "${l}" (sanitized: "${F}")`), console.log("Available parts:", [...this.parts.keys()]));
|
|
4306
4398
|
}
|
|
4307
4399
|
setPartMuted(l, U) {
|
|
4308
|
-
const F = this.sanitizePartName(l),
|
|
4309
|
-
|
|
4400
|
+
const F = this.sanitizePartName(l), d = this.parts.get(F);
|
|
4401
|
+
d && (d.muted = U, this.updatePartAudioState(F), this.eventBus.emit("partMutedChanged", { partName: l, muted: U }));
|
|
4310
4402
|
}
|
|
4311
4403
|
setPartSolo(l, U) {
|
|
4312
|
-
const F = this.sanitizePartName(l),
|
|
4313
|
-
|
|
4404
|
+
const F = this.sanitizePartName(l), d = this.parts.get(F);
|
|
4405
|
+
d && (d.solo = U, this.updateAllPartsAudioState(), this.eventBus.emit("partSoloChanged", { partName: l, solo: U }));
|
|
4314
4406
|
}
|
|
4315
4407
|
// Helper method to determine if a part should be effectively muted
|
|
4316
4408
|
isPartEffectivelyMuted(l) {
|
|
4317
4409
|
const U = this.sanitizePartName(l), F = this.parts.get(U);
|
|
4318
|
-
return !F || F.muted ? !0 : Array.from(this.parts.values()).some((
|
|
4410
|
+
return !F || F.muted ? !0 : Array.from(this.parts.values()).some((Q) => Q.solo) && !F.solo;
|
|
4319
4411
|
}
|
|
4320
4412
|
// Update audio state for a specific part
|
|
4321
4413
|
updatePartAudioState(l) {
|
|
4322
4414
|
const U = this.parts.get(l), F = this.partGainNodes.get(l);
|
|
4323
4415
|
if (U && F) {
|
|
4324
|
-
const
|
|
4325
|
-
F.gain.value =
|
|
4416
|
+
const d = this.isPartEffectivelyMuted(U.name);
|
|
4417
|
+
F.gain.value = d ? 0 : U.volume;
|
|
4326
4418
|
}
|
|
4327
4419
|
}
|
|
4328
4420
|
// Update audio state for all parts (needed when solo state changes)
|
|
@@ -4339,17 +4431,17 @@ class MU {
|
|
|
4339
4431
|
if (!F)
|
|
4340
4432
|
return 0;
|
|
4341
4433
|
try {
|
|
4342
|
-
const
|
|
4343
|
-
F.getByteFrequencyData(
|
|
4344
|
-
let
|
|
4345
|
-
for (let R = 0; R <
|
|
4346
|
-
const a =
|
|
4347
|
-
|
|
4434
|
+
const d = F.frequencyBinCount, Q = new Uint8Array(d);
|
|
4435
|
+
F.getByteFrequencyData(Q);
|
|
4436
|
+
let V = 0;
|
|
4437
|
+
for (let R = 0; R < d; R++) {
|
|
4438
|
+
const a = Q[R] / 255;
|
|
4439
|
+
V += a * a;
|
|
4348
4440
|
}
|
|
4349
|
-
const t = Math.sqrt(
|
|
4441
|
+
const t = Math.sqrt(V / d);
|
|
4350
4442
|
return Math.min(1, Math.pow(t * 2, 0.7));
|
|
4351
|
-
} catch (
|
|
4352
|
-
return console.warn(`Failed to get level for part ${l}:`,
|
|
4443
|
+
} catch (d) {
|
|
4444
|
+
return console.warn(`Failed to get level for part ${l}:`, d), 0;
|
|
4353
4445
|
}
|
|
4354
4446
|
}
|
|
4355
4447
|
// Special features (maintain DummyAudioEngine interface)
|
|
@@ -4358,7 +4450,7 @@ class MU {
|
|
|
4358
4450
|
}
|
|
4359
4451
|
playStartingNotes() {
|
|
4360
4452
|
console.log(this.parts);
|
|
4361
|
-
const l = [...this.parts.values()], U = l.some((
|
|
4453
|
+
const l = [...this.parts.values()], U = l.some((d) => d.solo), F = l.filter((d) => U ? d.solo : !d.muted).map((d) => d.name);
|
|
4362
4454
|
console.log(l, U, F), this.playbackManager.previewNextNotes({
|
|
4363
4455
|
instrument: "piano",
|
|
4364
4456
|
// Use piano for clear pitch reference
|
|
@@ -4428,77 +4520,71 @@ class MU {
|
|
|
4428
4520
|
}
|
|
4429
4521
|
const e = new MU();
|
|
4430
4522
|
function Rl() {
|
|
4431
|
-
const
|
|
4432
|
-
|
|
4433
|
-
},
|
|
4434
|
-
|
|
4435
|
-
},
|
|
4436
|
-
|
|
4437
|
-
},
|
|
4438
|
-
|
|
4439
|
-
}, t = ({ volume:
|
|
4440
|
-
|
|
4441
|
-
}, R = ({ partName:
|
|
4442
|
-
|
|
4443
|
-
}, a = ({ partName:
|
|
4444
|
-
|
|
4445
|
-
}, n = ({ partName:
|
|
4446
|
-
|
|
4447
|
-
}, m = ({ bars:
|
|
4448
|
-
|
|
4449
|
-
},
|
|
4450
|
-
|
|
4523
|
+
const Z = Ul(), l = tl(), U = NU(), F = ({ currentTime: b }) => {
|
|
4524
|
+
Z.setCurrentTime(b);
|
|
4525
|
+
}, d = ({ isPlaying: b }) => {
|
|
4526
|
+
Z.setPlaybackState(b), U.setTransportState(b ? "playing" : "stopped");
|
|
4527
|
+
}, Q = (b) => {
|
|
4528
|
+
b && (Z.isLeadInActive ? b.isLeadIn && b.beat !== void 0 && Z.setCurrentBar(null, b.beat, null) : (Z.setCurrentBar(b.bar, b.beat, b.repeat), U.updateLastBarPosition(b.bar)));
|
|
4529
|
+
}, V = ({ speed: b }) => {
|
|
4530
|
+
Z.setPlaybackSpeed(b);
|
|
4531
|
+
}, t = ({ volume: b }) => {
|
|
4532
|
+
Z.setMasterVolume(b);
|
|
4533
|
+
}, R = ({ partName: b, volume: o }) => {
|
|
4534
|
+
Z.setPartVolume(b, o);
|
|
4535
|
+
}, a = ({ partName: b, muted: o }) => {
|
|
4536
|
+
Z.setPartMuted(b, o);
|
|
4537
|
+
}, n = ({ partName: b, solo: o }) => {
|
|
4538
|
+
Z.setPartSolo(b, o);
|
|
4539
|
+
}, m = ({ bars: b }) => {
|
|
4540
|
+
Z.setLeadInActive(!0, b);
|
|
4541
|
+
}, W = () => {
|
|
4542
|
+
Z.setLeadInActive(!1);
|
|
4451
4543
|
}, c = () => {
|
|
4452
|
-
|
|
4544
|
+
Z.setStartingNotesActive(!0);
|
|
4453
4545
|
}, s = () => {
|
|
4454
|
-
|
|
4455
|
-
}, N = ({ mark:
|
|
4456
|
-
U.updateLastPracticeMarkUsed(
|
|
4457
|
-
}, J = ({ parts:
|
|
4458
|
-
|
|
4459
|
-
}, p = ({ finalTime:
|
|
4460
|
-
|
|
4461
|
-
}, M = ({ duration:
|
|
4462
|
-
console.log("Updating total duration in store to:",
|
|
4463
|
-
}, y = ({ beats:
|
|
4464
|
-
console.log(`Updating music data store with ${
|
|
4465
|
-
},
|
|
4466
|
-
e.on("timeChanged", F), e.on("playbackStateChanged",
|
|
4546
|
+
Z.setStartingNotesActive(!1);
|
|
4547
|
+
}, N = ({ mark: b }) => {
|
|
4548
|
+
U.updateLastPracticeMarkUsed(b);
|
|
4549
|
+
}, J = ({ parts: b }) => {
|
|
4550
|
+
Z.initializeParts(b), l.setParts(b);
|
|
4551
|
+
}, p = ({ finalTime: b }) => {
|
|
4552
|
+
Z.setPlaybackState(!1), U.setTransportState("stopped"), console.log(`Song ended at time: ${b}`);
|
|
4553
|
+
}, M = ({ duration: b }) => {
|
|
4554
|
+
console.log("Updating total duration in store to:", b), l.setTotalDuration(b);
|
|
4555
|
+
}, y = ({ beats: b, practiceMarks: o, maxBar: q }) => {
|
|
4556
|
+
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;
|
|
4557
|
+
}, u = () => {
|
|
4558
|
+
e.on("timeChanged", F), e.on("playbackStateChanged", d), 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);
|
|
4467
4559
|
}, k = () => {
|
|
4468
|
-
e.off("timeChanged", F), e.off("playbackStateChanged",
|
|
4560
|
+
e.off("timeChanged", F), e.off("playbackStateChanged", d), 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);
|
|
4469
4561
|
};
|
|
4470
4562
|
(() => {
|
|
4471
4563
|
El(() => {
|
|
4472
|
-
const
|
|
4564
|
+
const b = Z.masterVolume;
|
|
4473
4565
|
try {
|
|
4474
|
-
e.getMasterVolume() !==
|
|
4566
|
+
e.getMasterVolume() !== b && e.setMasterVolume(b);
|
|
4475
4567
|
} catch (o) {
|
|
4476
4568
|
console.warn("Master volume sync skipped during initialization:", o.message);
|
|
4477
4569
|
}
|
|
4478
4570
|
}), El(() => {
|
|
4479
|
-
const
|
|
4571
|
+
const b = Z.metronomeVolume;
|
|
4480
4572
|
try {
|
|
4481
|
-
e.getMetronomeVolume() !==
|
|
4573
|
+
e.getMetronomeVolume() !== b && e.setMetronomeVolume(b);
|
|
4482
4574
|
} catch (o) {
|
|
4483
4575
|
console.warn("Metronome volume sync skipped during initialization:", o.message);
|
|
4484
4576
|
}
|
|
4485
4577
|
});
|
|
4486
4578
|
})();
|
|
4487
|
-
const H = async (
|
|
4579
|
+
const H = async (b) => {
|
|
4488
4580
|
try {
|
|
4489
|
-
if (
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
beats: W.beats,
|
|
4493
|
-
practiceMarks: W.marks || W.practiceMarks,
|
|
4494
|
-
parts: W.parts
|
|
4495
|
-
}), W.beats && W.beats.length > 0) {
|
|
4496
|
-
const o = W.beats[0];
|
|
4497
|
-
d.setCurrentBar(o.bar, o.beat, o.repeat), e.setTime(o.time);
|
|
4581
|
+
if (Z.setLoaded(!1), u(), l.loadMusicData(b), await e.initialize(b), !b.midiData && b.beats && b.beats.length > 0) {
|
|
4582
|
+
const o = b.beats[0];
|
|
4583
|
+
Z.setCurrentBar(o.bar, o.beat, o.repeat), e.setTime(o.time);
|
|
4498
4584
|
}
|
|
4499
|
-
e.updateToggleStates(
|
|
4585
|
+
e.updateToggleStates(Z.metronomeEnabled, Z.leadInEnabled), Z.setLoaded(!0);
|
|
4500
4586
|
} catch (o) {
|
|
4501
|
-
throw console.error("Failed to initialize audio engine:", o),
|
|
4587
|
+
throw console.error("Failed to initialize audio engine:", o), Z.setLoaded(!1), o;
|
|
4502
4588
|
}
|
|
4503
4589
|
}, A = () => {
|
|
4504
4590
|
e.play();
|
|
@@ -4506,37 +4592,37 @@ function Rl() {
|
|
|
4506
4592
|
e.stop();
|
|
4507
4593
|
}, Zl = () => {
|
|
4508
4594
|
e.pause();
|
|
4509
|
-
}, i = (
|
|
4510
|
-
e.setTime(
|
|
4511
|
-
}, z = (
|
|
4512
|
-
e.setBar(
|
|
4513
|
-
}, P = (
|
|
4514
|
-
e.goToPracticeMark(
|
|
4515
|
-
}, B = (
|
|
4516
|
-
e.setPlaybackSpeed(
|
|
4517
|
-
}, S = (
|
|
4518
|
-
e.setMasterVolume(
|
|
4519
|
-
}, T = (
|
|
4520
|
-
e.setPartVolume(
|
|
4521
|
-
}, I = (
|
|
4522
|
-
e.setPartMuted(
|
|
4523
|
-
}, w = (
|
|
4524
|
-
e.setPartSolo(
|
|
4525
|
-
}, Ql = (
|
|
4526
|
-
e.playLeadIn(
|
|
4595
|
+
}, i = (b) => {
|
|
4596
|
+
e.setTime(b);
|
|
4597
|
+
}, z = (b, o = 0) => {
|
|
4598
|
+
e.setBar(b, o);
|
|
4599
|
+
}, P = (b) => {
|
|
4600
|
+
e.goToPracticeMark(b);
|
|
4601
|
+
}, B = (b) => {
|
|
4602
|
+
e.setPlaybackSpeed(b);
|
|
4603
|
+
}, S = (b) => {
|
|
4604
|
+
e.setMasterVolume(b);
|
|
4605
|
+
}, T = (b, o) => {
|
|
4606
|
+
e.setPartVolume(b, o);
|
|
4607
|
+
}, I = (b, o) => {
|
|
4608
|
+
e.setPartMuted(b, o);
|
|
4609
|
+
}, w = (b, o) => {
|
|
4610
|
+
e.setPartSolo(b, o);
|
|
4611
|
+
}, Ql = (b = 1) => {
|
|
4612
|
+
e.playLeadIn(b);
|
|
4527
4613
|
}, Bl = () => {
|
|
4528
4614
|
e.playStartingNotes();
|
|
4529
|
-
}, Yl = (
|
|
4530
|
-
o && U.leadInEnabled ? (z(
|
|
4531
|
-
}, _l = (
|
|
4532
|
-
const q = l.getBarForMark(
|
|
4615
|
+
}, Yl = (b, o = !0, q = 0) => {
|
|
4616
|
+
o && U.leadInEnabled ? (z(b, q), Ql(U.leadInBars)) : (z(b, q), A());
|
|
4617
|
+
}, _l = (b, o = !0) => {
|
|
4618
|
+
const q = l.getBarForMark(b);
|
|
4533
4619
|
q && Yl(q, o);
|
|
4534
4620
|
}, $l = () => {
|
|
4535
|
-
const
|
|
4536
|
-
return
|
|
4621
|
+
const b = !Z.metronomeEnabled;
|
|
4622
|
+
return Z.setMetronomeEnabled(b), e.setMetronomeEnabled(b), b;
|
|
4537
4623
|
}, lU = () => {
|
|
4538
|
-
const
|
|
4539
|
-
return
|
|
4624
|
+
const b = !Z.leadInEnabled;
|
|
4625
|
+
return Z.setLeadInEnabled(b), e.updateToggleStates(Z.metronomeEnabled, b), b;
|
|
4540
4626
|
};
|
|
4541
4627
|
return cl(() => {
|
|
4542
4628
|
k();
|
|
@@ -4558,21 +4644,21 @@ function Rl() {
|
|
|
4558
4644
|
setPartVolume: T,
|
|
4559
4645
|
setPartMuted: I,
|
|
4560
4646
|
setPartSolo: w,
|
|
4561
|
-
getPartLevel: (
|
|
4647
|
+
getPartLevel: (b) => e.getPartLevel(b),
|
|
4562
4648
|
// Special features
|
|
4563
4649
|
playLeadIn: Ql,
|
|
4564
4650
|
playStartingNotes: Bl,
|
|
4565
4651
|
// Feature toggles
|
|
4566
4652
|
toggleMetronome: $l,
|
|
4567
4653
|
toggleLeadIn: lU,
|
|
4568
|
-
setMetronomeEnabled: (
|
|
4569
|
-
|
|
4654
|
+
setMetronomeEnabled: (b) => {
|
|
4655
|
+
Z.setMetronomeEnabled(b), e.setMetronomeEnabled(b);
|
|
4570
4656
|
},
|
|
4571
4657
|
// Complex operations
|
|
4572
4658
|
playFromBar: Yl,
|
|
4573
4659
|
playFromMark: _l,
|
|
4574
4660
|
// Access to stores for components
|
|
4575
|
-
audioState:
|
|
4661
|
+
audioState: Z,
|
|
4576
4662
|
musicData: l,
|
|
4577
4663
|
playbackState: U,
|
|
4578
4664
|
// Direct access to engine for advanced use
|
|
@@ -4589,7 +4675,7 @@ const zU = {
|
|
|
4589
4675
|
level: {
|
|
4590
4676
|
type: Number,
|
|
4591
4677
|
default: 0,
|
|
4592
|
-
validator: (
|
|
4678
|
+
validator: (Z) => Z >= 0 && Z <= 1
|
|
4593
4679
|
}
|
|
4594
4680
|
}, {
|
|
4595
4681
|
volume: { default: 0.75 },
|
|
@@ -4600,61 +4686,61 @@ const zU = {
|
|
|
4600
4686
|
soloModifiers: {}
|
|
4601
4687
|
}),
|
|
4602
4688
|
emits: ["update:volume", "update:mute", "update:solo"],
|
|
4603
|
-
setup(
|
|
4689
|
+
setup(Z) {
|
|
4604
4690
|
$((c) => ({
|
|
4605
4691
|
"746d5fc3": a.value
|
|
4606
4692
|
}));
|
|
4607
|
-
const l =
|
|
4693
|
+
const l = Z;
|
|
4608
4694
|
Ul();
|
|
4609
|
-
const U = Rl(), F = _(
|
|
4695
|
+
const U = Rl(), F = _(Z, "volume"), d = _(Z, "mute"), Q = _(Z, "solo");
|
|
4610
4696
|
v(F, (c) => {
|
|
4611
4697
|
U.setPartVolume(l.name, c);
|
|
4612
|
-
}), v(
|
|
4698
|
+
}), v(d, (c) => {
|
|
4613
4699
|
U.setPartMuted(l.name, c);
|
|
4614
|
-
}), v(
|
|
4700
|
+
}), v(Q, (c) => {
|
|
4615
4701
|
U.setPartSolo(l.name, c);
|
|
4616
4702
|
});
|
|
4617
|
-
const
|
|
4703
|
+
const V = O("el"), { width: t, height: R } = ll(V), a = G(() => Math.min(t.value, R.value) + "px"), n = G(
|
|
4618
4704
|
() => t.value > R.value ? "mobile" : t.value < 60 ? "tablet" : "desktop"
|
|
4619
4705
|
);
|
|
4620
4706
|
let m = null;
|
|
4621
|
-
const
|
|
4707
|
+
const W = x(0);
|
|
4622
4708
|
return el(() => {
|
|
4623
4709
|
m = setInterval(() => {
|
|
4624
|
-
if (
|
|
4625
|
-
|
|
4710
|
+
if (d.value)
|
|
4711
|
+
W.value = 0;
|
|
4626
4712
|
else
|
|
4627
4713
|
try {
|
|
4628
|
-
|
|
4714
|
+
W.value = U.getPartLevel(l.name);
|
|
4629
4715
|
} catch {
|
|
4630
|
-
Ol("randomLevelIndicators") ?
|
|
4716
|
+
Ol("randomLevelIndicators") ? W.value = Math.random() * F.value : W.value = 0;
|
|
4631
4717
|
}
|
|
4632
4718
|
}, 16);
|
|
4633
4719
|
}), cl(() => {
|
|
4634
4720
|
m && (clearInterval(m), m = null);
|
|
4635
4721
|
}), (c, s) => (X(), Y("div", {
|
|
4636
4722
|
ref_key: "el",
|
|
4637
|
-
ref:
|
|
4723
|
+
ref: V,
|
|
4638
4724
|
class: L([n.value, "part"])
|
|
4639
4725
|
}, [
|
|
4640
4726
|
C(XU, {
|
|
4641
4727
|
class: "tri",
|
|
4642
|
-
mute:
|
|
4643
|
-
"onUpdate:mute": s[0] || (s[0] = (N) =>
|
|
4644
|
-
solo:
|
|
4645
|
-
"onUpdate:solo": s[1] || (s[1] = (N) =>
|
|
4728
|
+
mute: d.value,
|
|
4729
|
+
"onUpdate:mute": s[0] || (s[0] = (N) => d.value = N),
|
|
4730
|
+
solo: Q.value,
|
|
4731
|
+
"onUpdate:solo": s[1] || (s[1] = (N) => Q.value = N)
|
|
4646
4732
|
}, null, 8, ["mute", "solo"]),
|
|
4647
4733
|
C(wl, {
|
|
4648
4734
|
align: "left",
|
|
4649
4735
|
class: "name"
|
|
4650
4736
|
}, {
|
|
4651
4737
|
default: D(() => [
|
|
4652
|
-
ol(K(
|
|
4738
|
+
ol(K(Z.name), 1)
|
|
4653
4739
|
]),
|
|
4654
4740
|
_: 1
|
|
4655
4741
|
}),
|
|
4656
4742
|
C(bl, {
|
|
4657
|
-
level:
|
|
4743
|
+
level: W.value,
|
|
4658
4744
|
"show-level": !0,
|
|
4659
4745
|
class: "vol",
|
|
4660
4746
|
value: F.value,
|
|
@@ -4667,34 +4753,34 @@ const zU = {
|
|
|
4667
4753
|
class: "mark-grid-container"
|
|
4668
4754
|
}, jU = { class: "mark-grid" }, PU = ["onClick"], wU = {
|
|
4669
4755
|
__name: "BarInput",
|
|
4670
|
-
setup(
|
|
4756
|
+
setup(Z) {
|
|
4671
4757
|
$((B) => ({
|
|
4672
4758
|
b117cda6: p.value,
|
|
4673
4759
|
"7cd7b1c8": M.value
|
|
4674
4760
|
}));
|
|
4675
|
-
const l = O("el"), U = O("rpt"), { width: F, height:
|
|
4761
|
+
const l = O("el"), U = O("rpt"), { width: F, height: d } = 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);
|
|
4676
4762
|
let J = null;
|
|
4677
4763
|
v(() => {
|
|
4678
4764
|
var B;
|
|
4679
|
-
return ((B =
|
|
4765
|
+
return ((B = Q.beats) == null ? void 0 : B.length) > 0;
|
|
4680
4766
|
}, (B) => {
|
|
4681
|
-
console.log(B), B && !
|
|
4682
|
-
}), v(() =>
|
|
4683
|
-
m.value =
|
|
4767
|
+
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);
|
|
4768
|
+
}), v(() => V.currentBar, (B) => {
|
|
4769
|
+
m.value = Q.getRepeatCountForBar(B);
|
|
4684
4770
|
}), v(R, () => {
|
|
4685
4771
|
R.value = R.value.replace(/\D/g, ""), R.value.length > 3 && (R.value = R.value.slice(0, 3));
|
|
4686
|
-
}), v(() =>
|
|
4772
|
+
}), v(() => V.currentBar, (B) => {
|
|
4687
4773
|
R.value = B.toString(), k(B);
|
|
4688
|
-
}), v(() =>
|
|
4774
|
+
}), v(() => V.currentBeat, () => {
|
|
4689
4775
|
N.value = !0, setTimeout(() => {
|
|
4690
4776
|
N.value = !1;
|
|
4691
4777
|
}, 50);
|
|
4692
4778
|
}), v(c, () => {
|
|
4693
4779
|
c.value && P();
|
|
4694
4780
|
});
|
|
4695
|
-
const p =
|
|
4781
|
+
const p = G(() => Math.min(d.value / 2.25, F.value / 4.5) + "px"), M = G(() => Math.min(F.value / 15, d.value / 6.4) + "px"), y = G(() => Object.keys(Q.practiceMarks).sort()), u = G(() => y.value.length > 0);
|
|
4696
4782
|
function k(B) {
|
|
4697
|
-
const S = Object.keys(
|
|
4783
|
+
const S = Object.keys(Q.practiceMarks).filter((T) => Q.practiceMarks[T] <= B).sort((T, I) => Q.practiceMarks[I] - Q.practiceMarks[T]);
|
|
4698
4784
|
S.length > 0 && (a.value = S[0]);
|
|
4699
4785
|
}
|
|
4700
4786
|
function E() {
|
|
@@ -4708,13 +4794,13 @@ const zU = {
|
|
|
4708
4794
|
S && S.stopPropagation(), a.value = B, c.value = !1, t.goToPracticeMark(B);
|
|
4709
4795
|
}
|
|
4710
4796
|
function j() {
|
|
4711
|
-
m.value > 1 && (s.value = !0),
|
|
4797
|
+
m.value > 1 && (s.value = !0), V.currentRepeat < m.value && t.setBar(V.currentBar, V.currentRepeat + 1);
|
|
4712
4798
|
}
|
|
4713
4799
|
function Zl() {
|
|
4714
|
-
m.value > 1 && (s.value = !0),
|
|
4800
|
+
m.value > 1 && (s.value = !0), V.currentRepeat > 1 && t.setBar(V.currentBar, V.currentRepeat - 1);
|
|
4715
4801
|
}
|
|
4716
4802
|
function i(B) {
|
|
4717
|
-
|
|
4803
|
+
u.value && (B.stopPropagation(), s.value = !1, c.value = !c.value);
|
|
4718
4804
|
}
|
|
4719
4805
|
function z(B) {
|
|
4720
4806
|
var S, T;
|
|
@@ -4732,8 +4818,8 @@ const zU = {
|
|
|
4732
4818
|
}
|
|
4733
4819
|
return el(() => {
|
|
4734
4820
|
document.addEventListener("click", z), Ol("beatAnimation") && (J = setInterval(() => {
|
|
4735
|
-
const B =
|
|
4736
|
-
|
|
4821
|
+
const B = V.currentBeat % Q.timeSignature + 1;
|
|
4822
|
+
V.setCurrentBar(V.currentBar, B, V.currentRepeat);
|
|
4737
4823
|
}, 800));
|
|
4738
4824
|
}), cl(() => {
|
|
4739
4825
|
document.removeEventListener("click", z), J && (clearInterval(J), J = null);
|
|
@@ -4744,10 +4830,10 @@ const zU = {
|
|
|
4744
4830
|
}, [
|
|
4745
4831
|
S[6] || (S[6] = h("div", { class: "frame" }, null, -1)),
|
|
4746
4832
|
h("div", {
|
|
4747
|
-
class: L(["mark-input", { empty: !a.value, edit: c.value, disabled: !
|
|
4833
|
+
class: L(["mark-input", { empty: !a.value, edit: c.value, disabled: !u.value }]),
|
|
4748
4834
|
onClick: i
|
|
4749
4835
|
}, [
|
|
4750
|
-
h("div", vU, K(
|
|
4836
|
+
h("div", vU, K(u.value ? a.value : "-"), 1)
|
|
4751
4837
|
], 2),
|
|
4752
4838
|
S[7] || (S[7] = h("div", { class: "mark-title" }, "Mark", -1)),
|
|
4753
4839
|
c.value ? f("", !0) : (X(), Y(al, { key: 0 }, [
|
|
@@ -4768,16 +4854,16 @@ const zU = {
|
|
|
4768
4854
|
ref: U,
|
|
4769
4855
|
class: L(["rpt-input", { edit: s.value, available: m.value > 1 }])
|
|
4770
4856
|
}, [
|
|
4771
|
-
h("div", KU, K(r(
|
|
4857
|
+
h("div", KU, K(r(V).currentRepeat || "-"), 1),
|
|
4772
4858
|
(X(), Y("svg", {
|
|
4773
|
-
class: L(["inc", { disabled: r(
|
|
4859
|
+
class: L(["inc", { disabled: r(V).currentRepeat >= m.value }]),
|
|
4774
4860
|
viewBox: "0 -100 100 100",
|
|
4775
4861
|
onClick: kl(j, ["prevent"])
|
|
4776
4862
|
}, S[1] || (S[1] = [
|
|
4777
4863
|
h("path", { d: "m10-20 40-60 40 60H10Z" }, null, -1)
|
|
4778
4864
|
]), 2)),
|
|
4779
4865
|
(X(), Y("svg", {
|
|
4780
|
-
class: L(["dec", { disabled: r(
|
|
4866
|
+
class: L(["dec", { disabled: r(V).currentRepeat <= 1 }]),
|
|
4781
4867
|
viewBox: "0 -100 100 100",
|
|
4782
4868
|
onClick: kl(Zl, ["prevent"])
|
|
4783
4869
|
}, S[2] || (S[2] = [
|
|
@@ -4786,7 +4872,7 @@ const zU = {
|
|
|
4786
4872
|
], 2),
|
|
4787
4873
|
S[4] || (S[4] = h("div", { class: "rpt-title" }, "Rpt", -1)),
|
|
4788
4874
|
h("div", gU, [
|
|
4789
|
-
h("div", HU, K(r(
|
|
4875
|
+
h("div", HU, K(r(V).currentBeat), 1)
|
|
4790
4876
|
]),
|
|
4791
4877
|
S[5] || (S[5] = h("div", { class: "beat-title" }, "Beat", -1))
|
|
4792
4878
|
], 64)),
|
|
@@ -4838,23 +4924,23 @@ const zU = {
|
|
|
4838
4924
|
},
|
|
4839
4925
|
formatValue: {
|
|
4840
4926
|
type: Function,
|
|
4841
|
-
default: (
|
|
4927
|
+
default: (Z) => Z.toString()
|
|
4842
4928
|
},
|
|
4843
4929
|
parseValue: {
|
|
4844
4930
|
type: Function,
|
|
4845
|
-
default: (
|
|
4931
|
+
default: (Z) => parseFloat(Z)
|
|
4846
4932
|
},
|
|
4847
4933
|
validateInput: {
|
|
4848
4934
|
type: Function,
|
|
4849
|
-
default: (
|
|
4935
|
+
default: (Z) => Z.replace(/[^0-9.]/g, "")
|
|
4850
4936
|
},
|
|
4851
4937
|
transformSliderToDisplay: {
|
|
4852
4938
|
type: Function,
|
|
4853
|
-
default: (
|
|
4939
|
+
default: (Z) => Z
|
|
4854
4940
|
},
|
|
4855
4941
|
transformDisplayToSlider: {
|
|
4856
4942
|
type: Function,
|
|
4857
|
-
default: (
|
|
4943
|
+
default: (Z) => Z
|
|
4858
4944
|
},
|
|
4859
4945
|
maxChars: {
|
|
4860
4946
|
type: Number,
|
|
@@ -4865,26 +4951,26 @@ const zU = {
|
|
|
4865
4951
|
valueModifiers: {}
|
|
4866
4952
|
}),
|
|
4867
4953
|
emits: ["update:value"],
|
|
4868
|
-
setup(
|
|
4954
|
+
setup(Z) {
|
|
4869
4955
|
$((n) => ({
|
|
4870
|
-
"0d0963e0":
|
|
4871
|
-
"4ad34b2f":
|
|
4872
|
-
"02156786":
|
|
4956
|
+
"0d0963e0": Z.textColor,
|
|
4957
|
+
"4ad34b2f": Z.backgroundColor,
|
|
4958
|
+
"02156786": Z.color,
|
|
4873
4959
|
"715a9528": R.value,
|
|
4874
4960
|
"30d64f7d": t.value,
|
|
4875
|
-
b8fbe65e:
|
|
4961
|
+
b8fbe65e: Z.focusColor
|
|
4876
4962
|
}));
|
|
4877
|
-
const l =
|
|
4878
|
-
v(
|
|
4879
|
-
const n = l.transformSliderToDisplay(
|
|
4880
|
-
|
|
4881
|
-
}), v(
|
|
4882
|
-
|
|
4963
|
+
const l = Z, U = O("el"), { width: F, height: d } = ll(U), Q = _(Z, "value"), V = x(l.formatValue(l.transformSliderToDisplay(Q.value)));
|
|
4964
|
+
v(Q, () => {
|
|
4965
|
+
const n = l.transformSliderToDisplay(Q.value);
|
|
4966
|
+
V.value = l.formatValue(n);
|
|
4967
|
+
}), v(V, () => {
|
|
4968
|
+
V.value = l.validateInput(V.value), l.maxChars && V.value.length > l.maxChars && (V.value = V.value.slice(0, l.maxChars));
|
|
4883
4969
|
});
|
|
4884
|
-
const t =
|
|
4970
|
+
const t = G(() => Math.min(d.value / 2.25, F.value / 2.2) + "px"), R = G(() => Math.min(F.value / 3, d.value / 6.4) + "px");
|
|
4885
4971
|
function a() {
|
|
4886
|
-
const n = l.parseValue(
|
|
4887
|
-
|
|
4972
|
+
const n = l.parseValue(V.value), m = l.transformDisplayToSlider(n);
|
|
4973
|
+
Q.value = Math.min(Math.max(m, l.sliderMin), l.sliderMax);
|
|
4888
4974
|
}
|
|
4889
4975
|
return (n, m) => (X(), Y("div", {
|
|
4890
4976
|
class: "outer",
|
|
@@ -4895,34 +4981,34 @@ const zU = {
|
|
|
4895
4981
|
vl(h("input", {
|
|
4896
4982
|
type: "text",
|
|
4897
4983
|
class: "input",
|
|
4898
|
-
"onUpdate:modelValue": m[0] || (m[0] = (
|
|
4984
|
+
"onUpdate:modelValue": m[0] || (m[0] = (W) => V.value = W),
|
|
4899
4985
|
inputmode: "decimal",
|
|
4900
4986
|
pattern: "\\d*",
|
|
4901
4987
|
onChange: a
|
|
4902
4988
|
}, null, 544), [
|
|
4903
|
-
[Kl,
|
|
4989
|
+
[Kl, V.value]
|
|
4904
4990
|
]),
|
|
4905
|
-
h("div", fU, K(
|
|
4991
|
+
h("div", fU, K(Z.title), 1),
|
|
4906
4992
|
C(bl, {
|
|
4907
4993
|
class: "slider",
|
|
4908
|
-
value:
|
|
4909
|
-
"onUpdate:value": m[1] || (m[1] = (
|
|
4910
|
-
"thumb-length":
|
|
4911
|
-
max:
|
|
4912
|
-
min:
|
|
4994
|
+
value: Q.value,
|
|
4995
|
+
"onUpdate:value": m[1] || (m[1] = (W) => Q.value = W),
|
|
4996
|
+
"thumb-length": Z.thumbLength,
|
|
4997
|
+
max: Z.sliderMax,
|
|
4998
|
+
min: Z.sliderMin
|
|
4913
4999
|
}, null, 8, ["value", "thumb-length", "max", "min"])
|
|
4914
5000
|
], 512));
|
|
4915
5001
|
}
|
|
4916
5002
|
}, ql = /* @__PURE__ */ g(AU, [["__scopeId", "data-v-79c7a539"]]), qU = {
|
|
4917
5003
|
__name: "SpeedInput",
|
|
4918
|
-
setup(
|
|
4919
|
-
const l = Ul(), U = Rl(), F =
|
|
5004
|
+
setup(Z) {
|
|
5005
|
+
const l = Ul(), U = Rl(), F = G({
|
|
4920
5006
|
get: () => Math.log2(l.playbackSpeed) * 0.5 + 0.5,
|
|
4921
5007
|
set: (a) => {
|
|
4922
5008
|
const n = Math.pow(2, a * 2 - 1);
|
|
4923
5009
|
U.setPlaybackSpeed(n);
|
|
4924
5010
|
}
|
|
4925
|
-
}),
|
|
5011
|
+
}), d = (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) => {
|
|
4926
5012
|
const n = Math.log2(a / 100) * 0.5 + 0.5;
|
|
4927
5013
|
return Math.min(Math.max(n, 0), 1);
|
|
4928
5014
|
};
|
|
@@ -4932,9 +5018,9 @@ const zU = {
|
|
|
4932
5018
|
title: "Speed",
|
|
4933
5019
|
color: "#336",
|
|
4934
5020
|
"text-color": "#aad",
|
|
4935
|
-
"format-value":
|
|
4936
|
-
"parse-value":
|
|
4937
|
-
"validate-input":
|
|
5021
|
+
"format-value": d,
|
|
5022
|
+
"parse-value": Q,
|
|
5023
|
+
"validate-input": V,
|
|
4938
5024
|
"transform-slider-to-display": t,
|
|
4939
5025
|
"transform-display-to-slider": R,
|
|
4940
5026
|
"thumb-length": 2,
|
|
@@ -4943,8 +5029,8 @@ const zU = {
|
|
|
4943
5029
|
}
|
|
4944
5030
|
}, _U = {
|
|
4945
5031
|
__name: "TimeInput",
|
|
4946
|
-
setup(
|
|
4947
|
-
const l = Ul(), U = tl(), F = Rl(),
|
|
5032
|
+
setup(Z) {
|
|
5033
|
+
const l = Ul(), U = tl(), F = Rl(), d = (a) => a.toFixed(1), Q = (a) => parseFloat(a), V = (a) => a.replace(/[^0-9.]/g, ""), t = (a) => a, R = (a) => a;
|
|
4948
5034
|
return (a, n) => (X(), nl(ql, {
|
|
4949
5035
|
value: r(l).currentTime,
|
|
4950
5036
|
"onUpdate:value": [
|
|
@@ -4958,9 +5044,9 @@ const zU = {
|
|
|
4958
5044
|
"background-color": "#111117",
|
|
4959
5045
|
"slider-max": r(U).totalDuration,
|
|
4960
5046
|
"slider-min": 0,
|
|
4961
|
-
"format-value":
|
|
4962
|
-
"parse-value":
|
|
4963
|
-
"validate-input":
|
|
5047
|
+
"format-value": d,
|
|
5048
|
+
"parse-value": Q,
|
|
5049
|
+
"validate-input": V,
|
|
4964
5050
|
"transform-slider-to-display": t,
|
|
4965
5051
|
"transform-display-to-slider": R,
|
|
4966
5052
|
"thumb-length": 2
|
|
@@ -4968,16 +5054,16 @@ const zU = {
|
|
|
4968
5054
|
}
|
|
4969
5055
|
}, $U = { class: "inner" }, lF = {
|
|
4970
5056
|
__name: "AudioButton",
|
|
4971
|
-
setup(
|
|
5057
|
+
setup(Z) {
|
|
4972
5058
|
const l = x(!1), U = () => l.value = !0, F = () => l.value = !1;
|
|
4973
|
-
return (
|
|
5059
|
+
return (d, Q) => (X(), Y("div", {
|
|
4974
5060
|
class: L(["button-outer", { down: l.value }]),
|
|
4975
5061
|
onPointerdown: U,
|
|
4976
5062
|
onPointerup: F,
|
|
4977
5063
|
onPointerleave: F
|
|
4978
5064
|
}, [
|
|
4979
5065
|
h("div", $U, [
|
|
4980
|
-
Vl(
|
|
5066
|
+
Vl(d.$slots, "default", {}, void 0, !0)
|
|
4981
5067
|
])
|
|
4982
5068
|
], 34));
|
|
4983
5069
|
}
|
|
@@ -4986,27 +5072,27 @@ const zU = {
|
|
|
4986
5072
|
viewBox: "0 0 48 48"
|
|
4987
5073
|
}, QF = ["d"], VF = {
|
|
4988
5074
|
__name: "MixerControls",
|
|
4989
|
-
setup(
|
|
5075
|
+
setup(Z) {
|
|
4990
5076
|
const l = tl(), U = Ul(), F = Rl();
|
|
4991
|
-
function
|
|
5077
|
+
function d() {
|
|
4992
5078
|
U.isPlaying ? F.stop() : F.play();
|
|
4993
5079
|
}
|
|
4994
|
-
function
|
|
4995
|
-
const y = U.currentTime,
|
|
5080
|
+
function Q() {
|
|
5081
|
+
const y = U.currentTime, u = l.beats.filter((E) => E.beat === 1).sort((E, H) => E.time - H.time);
|
|
4996
5082
|
let k = null;
|
|
4997
|
-
for (let E =
|
|
4998
|
-
if (
|
|
4999
|
-
k =
|
|
5083
|
+
for (let E = u.length - 1; E >= 0; E--)
|
|
5084
|
+
if (u[E].time < y) {
|
|
5085
|
+
k = u[E];
|
|
5000
5086
|
break;
|
|
5001
5087
|
}
|
|
5002
5088
|
k && F.setBar(k.bar, k.repeat);
|
|
5003
5089
|
}
|
|
5004
|
-
function
|
|
5005
|
-
const y = U.currentTime,
|
|
5090
|
+
function V() {
|
|
5091
|
+
const y = U.currentTime, u = l.beats.filter((E) => E.beat === 1).sort((E, H) => E.time - H.time);
|
|
5006
5092
|
let k = null;
|
|
5007
|
-
for (let E = 0; E <
|
|
5008
|
-
if (
|
|
5009
|
-
k =
|
|
5093
|
+
for (let E = 0; E < u.length; E++)
|
|
5094
|
+
if (u[E].time > y) {
|
|
5095
|
+
k = u[E];
|
|
5010
5096
|
break;
|
|
5011
5097
|
}
|
|
5012
5098
|
k && F.setBar(k.bar, k.repeat);
|
|
@@ -5014,8 +5100,8 @@ const zU = {
|
|
|
5014
5100
|
function t() {
|
|
5015
5101
|
F.playStartingNotes();
|
|
5016
5102
|
}
|
|
5017
|
-
const R =
|
|
5018
|
-
function
|
|
5103
|
+
const R = G(() => U.metronomeEnabled), a = G(() => U.leadInEnabled), n = x(!1), m = x(null);
|
|
5104
|
+
function W() {
|
|
5019
5105
|
n.value = !n.value, n.value && F.audioEngine.initializeAudioSystem().catch((y) => {
|
|
5020
5106
|
console.warn("Audio system pre-initialization failed:", y);
|
|
5021
5107
|
});
|
|
@@ -5037,14 +5123,14 @@ const zU = {
|
|
|
5037
5123
|
function J() {
|
|
5038
5124
|
F.toggleLeadIn();
|
|
5039
5125
|
}
|
|
5040
|
-
const p =
|
|
5126
|
+
const p = G({
|
|
5041
5127
|
get: () => U.masterVolume,
|
|
5042
5128
|
set: (y) => U.setMasterVolume(y)
|
|
5043
|
-
}), M =
|
|
5129
|
+
}), M = G({
|
|
5044
5130
|
get: () => U.metronomeVolume,
|
|
5045
5131
|
set: (y) => U.setMetronomeVolume(y)
|
|
5046
5132
|
});
|
|
5047
|
-
return (y,
|
|
5133
|
+
return (y, u) => (X(), Y("div", UF, [
|
|
5048
5134
|
h("div", FF, [
|
|
5049
5135
|
C(wl, {
|
|
5050
5136
|
class: "text",
|
|
@@ -5063,8 +5149,8 @@ const zU = {
|
|
|
5063
5149
|
(X(), Y("svg", {
|
|
5064
5150
|
class: "menu",
|
|
5065
5151
|
viewBox: "0 -960 960 960",
|
|
5066
|
-
onClick:
|
|
5067
|
-
},
|
|
5152
|
+
onClick: W
|
|
5153
|
+
}, u[2] || (u[2] = [
|
|
5068
5154
|
h("path", { d: "M120-240v-80h720v80H120Zm0-200v-80h720v80H120Zm0-200v-80h720v80H120Z" }, null, -1)
|
|
5069
5155
|
]))),
|
|
5070
5156
|
n.value && y.$slots.menu ? (X(), Y("div", {
|
|
@@ -5080,25 +5166,25 @@ const zU = {
|
|
|
5080
5166
|
class: "main",
|
|
5081
5167
|
colour: "red",
|
|
5082
5168
|
value: p.value,
|
|
5083
|
-
"onUpdate:value":
|
|
5169
|
+
"onUpdate:value": u[0] || (u[0] = (k) => p.value = k)
|
|
5084
5170
|
}, null, 8, ["value"]),
|
|
5085
5171
|
C(bl, {
|
|
5086
5172
|
class: "tick",
|
|
5087
5173
|
colour: "blue",
|
|
5088
5174
|
value: M.value,
|
|
5089
|
-
"onUpdate:value":
|
|
5175
|
+
"onUpdate:value": u[1] || (u[1] = (k) => M.value = k)
|
|
5090
5176
|
}, null, 8, ["value"]),
|
|
5091
|
-
|
|
5092
|
-
|
|
5177
|
+
u[8] || (u[8] = h("div", { class: "main-t" }, "Main", -1)),
|
|
5178
|
+
u[9] || (u[9] = h("div", { class: "tick-t" }, "Tick", -1)),
|
|
5093
5179
|
C(OU, { class: "bar" }),
|
|
5094
5180
|
C(_U, { class: "time" }),
|
|
5095
5181
|
C(qU, { class: "speed" }),
|
|
5096
5182
|
h("div", dF, [
|
|
5097
5183
|
C(Fl, {
|
|
5098
5184
|
class: "button",
|
|
5099
|
-
onClick:
|
|
5185
|
+
onClick: Q
|
|
5100
5186
|
}, {
|
|
5101
|
-
default: D(() =>
|
|
5187
|
+
default: D(() => u[3] || (u[3] = [
|
|
5102
5188
|
h("svg", {
|
|
5103
5189
|
class: "icon",
|
|
5104
5190
|
viewBox: "0 0 48 48"
|
|
@@ -5111,7 +5197,7 @@ const zU = {
|
|
|
5111
5197
|
}),
|
|
5112
5198
|
C(Fl, {
|
|
5113
5199
|
class: "button",
|
|
5114
|
-
onClick:
|
|
5200
|
+
onClick: d
|
|
5115
5201
|
}, {
|
|
5116
5202
|
default: D(() => [
|
|
5117
5203
|
(X(), Y("svg", ZF, [
|
|
@@ -5124,9 +5210,9 @@ const zU = {
|
|
|
5124
5210
|
}),
|
|
5125
5211
|
C(Fl, {
|
|
5126
5212
|
class: "button",
|
|
5127
|
-
onClick:
|
|
5213
|
+
onClick: V
|
|
5128
5214
|
}, {
|
|
5129
|
-
default: D(() =>
|
|
5215
|
+
default: D(() => u[4] || (u[4] = [
|
|
5130
5216
|
h("svg", {
|
|
5131
5217
|
class: "icon",
|
|
5132
5218
|
viewBox: "0 0 48 48"
|
|
@@ -5145,7 +5231,7 @@ const zU = {
|
|
|
5145
5231
|
(X(), Y("svg", {
|
|
5146
5232
|
class: L(["icon", R.value ? "on" : "off"]),
|
|
5147
5233
|
viewBox: "-128 -128 768 768"
|
|
5148
|
-
},
|
|
5234
|
+
}, u[5] || (u[5] = [
|
|
5149
5235
|
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)
|
|
5150
5236
|
]), 2))
|
|
5151
5237
|
]),
|
|
@@ -5159,7 +5245,7 @@ const zU = {
|
|
|
5159
5245
|
(X(), Y("svg", {
|
|
5160
5246
|
class: L(["icon", a.value ? "on" : "off"]),
|
|
5161
5247
|
viewBox: "-2 -2 28 28"
|
|
5162
|
-
},
|
|
5248
|
+
}, u[6] || (u[6] = [
|
|
5163
5249
|
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)
|
|
5164
5250
|
]), 2))
|
|
5165
5251
|
]),
|
|
@@ -5169,7 +5255,7 @@ const zU = {
|
|
|
5169
5255
|
class: "button",
|
|
5170
5256
|
onClick: t
|
|
5171
5257
|
}, {
|
|
5172
|
-
default: D(() =>
|
|
5258
|
+
default: D(() => u[7] || (u[7] = [
|
|
5173
5259
|
h("svg", {
|
|
5174
5260
|
class: "icon",
|
|
5175
5261
|
viewBox: "0 -960 960 960"
|
|
@@ -5216,9 +5302,9 @@ const zU = {
|
|
|
5216
5302
|
default: null
|
|
5217
5303
|
}
|
|
5218
5304
|
},
|
|
5219
|
-
setup(
|
|
5220
|
-
const l =
|
|
5221
|
-
return (
|
|
5305
|
+
setup(Z) {
|
|
5306
|
+
const l = Z, U = G(() => l.progress !== null), F = G(() => l.progress === null ? 0 : Math.max(0, Math.min(100, l.progress * 100))), d = G(() => l.hasError ? l.errorMessage : l.message);
|
|
5307
|
+
return (Q, V) => (X(), Y("div", RF, [
|
|
5222
5308
|
U.value ? (X(), Y("div", aF, [
|
|
5223
5309
|
h("div", {
|
|
5224
5310
|
class: "progress-fill",
|
|
@@ -5227,8 +5313,8 @@ const zU = {
|
|
|
5227
5313
|
])) : f("", !0),
|
|
5228
5314
|
h("div", nF, [
|
|
5229
5315
|
h("div", {
|
|
5230
|
-
class: L(["message", { error:
|
|
5231
|
-
}, K(
|
|
5316
|
+
class: L(["message", { error: Z.hasError }])
|
|
5317
|
+
}, K(d.value), 3)
|
|
5232
5318
|
])
|
|
5233
5319
|
]));
|
|
5234
5320
|
}
|
|
@@ -5256,15 +5342,15 @@ const zU = {
|
|
|
5256
5342
|
* @param {string} event.message - Human-readable message
|
|
5257
5343
|
* @param {number} [event.progress] - Optional progress (0-1)
|
|
5258
5344
|
*/
|
|
5259
|
-
updateProgress(
|
|
5260
|
-
this.currentStage =
|
|
5345
|
+
updateProgress(Z) {
|
|
5346
|
+
this.currentStage = Z.stage, this.message = Z.message, this.progress = Z.progress ?? null, Z.stage === "ready" ? (this.isInitializing = !1, this.isReady = !0) : (this.isInitializing = !0, this.isReady = !1), this.hasError = !1, this.errorMessage = null;
|
|
5261
5347
|
},
|
|
5262
5348
|
/**
|
|
5263
5349
|
* Set error state
|
|
5264
5350
|
* @param {string} message - Error message
|
|
5265
5351
|
*/
|
|
5266
|
-
setError(
|
|
5267
|
-
this.hasError = !0, this.errorMessage =
|
|
5352
|
+
setError(Z) {
|
|
5353
|
+
this.hasError = !0, this.errorMessage = Z, this.isInitializing = !1, this.isReady = !1;
|
|
5268
5354
|
},
|
|
5269
5355
|
/**
|
|
5270
5356
|
* Reset initialization state
|
|
@@ -5277,8 +5363,8 @@ const zU = {
|
|
|
5277
5363
|
* Should be called once during app startup
|
|
5278
5364
|
*/
|
|
5279
5365
|
initializeListeners() {
|
|
5280
|
-
e.on("initProgress", (
|
|
5281
|
-
this.updateProgress(
|
|
5366
|
+
e.on("initProgress", (Z) => {
|
|
5367
|
+
this.updateProgress(Z);
|
|
5282
5368
|
});
|
|
5283
5369
|
}
|
|
5284
5370
|
},
|
|
@@ -5286,17 +5372,17 @@ const zU = {
|
|
|
5286
5372
|
/**
|
|
5287
5373
|
* Whether to show the progress indicator
|
|
5288
5374
|
*/
|
|
5289
|
-
shouldShowProgress: (
|
|
5375
|
+
shouldShowProgress: (Z) => Z.isInitializing || Z.hasError,
|
|
5290
5376
|
/**
|
|
5291
5377
|
* Whether the progress bar should be visible
|
|
5292
5378
|
* Only show for stages that have progress data
|
|
5293
5379
|
*/
|
|
5294
|
-
hasProgressBar: (
|
|
5380
|
+
hasProgressBar: (Z) => Z.progress !== null
|
|
5295
5381
|
}
|
|
5296
5382
|
}), cF = { class: "container" }, eF = { class: "panel" }, sF = {
|
|
5297
5383
|
key: 0,
|
|
5298
5384
|
class: "blur"
|
|
5299
|
-
}, rl = 40, Ll = 40, Cl = 100, hF = 50, xl = 400, Ml = 570, zl = 570, BF = 350, JF = 330,
|
|
5385
|
+
}, rl = 40, Ll = 40, Cl = 100, hF = 50, xl = 400, Ml = 570, zl = 570, BF = 350, JF = 330, uF = 360, GF = 360, iF = {
|
|
5300
5386
|
__name: "MixerLayout",
|
|
5301
5387
|
props: {
|
|
5302
5388
|
/** Whether to show initialization progress (default: true) */
|
|
@@ -5305,31 +5391,31 @@ const zU = {
|
|
|
5305
5391
|
default: !0
|
|
5306
5392
|
}
|
|
5307
5393
|
},
|
|
5308
|
-
setup(
|
|
5309
|
-
$((
|
|
5394
|
+
setup(Z) {
|
|
5395
|
+
$((W) => ({
|
|
5310
5396
|
"53ffcc08": a.value,
|
|
5311
5397
|
"53f8f922": n.value,
|
|
5312
5398
|
"2b0b3d37": m.value
|
|
5313
5399
|
}));
|
|
5314
|
-
const l =
|
|
5400
|
+
const l = Z, U = tl(), F = Ul(), d = bF();
|
|
5315
5401
|
el(() => {
|
|
5316
|
-
|
|
5402
|
+
d.initializeListeners();
|
|
5317
5403
|
});
|
|
5318
|
-
const
|
|
5319
|
-
const
|
|
5320
|
-
return
|
|
5321
|
-
}), a =
|
|
5404
|
+
const Q = O("container"), { width: V } = ll(Q), t = G(() => F.isLoaded), R = G(() => {
|
|
5405
|
+
const W = V.value, c = U.parts.length;
|
|
5406
|
+
return W < 640 || W < rl * c + xl ? 0 : W < Ll * c + Ml ? 1 : W < Cl * c + zl ? 2 : 3;
|
|
5407
|
+
}), a = G(() => {
|
|
5322
5408
|
switch (R.value) {
|
|
5323
5409
|
case 0:
|
|
5324
5410
|
return `${BF}px ` + `${hF}px `.repeat(U.parts.length);
|
|
5325
5411
|
case 1:
|
|
5326
5412
|
return `${JF}px`;
|
|
5327
5413
|
case 2:
|
|
5328
|
-
return `${GF}px`;
|
|
5329
|
-
default:
|
|
5330
5414
|
return `${uF}px`;
|
|
5415
|
+
default:
|
|
5416
|
+
return `${GF}px`;
|
|
5331
5417
|
}
|
|
5332
|
-
}), n =
|
|
5418
|
+
}), n = G(() => {
|
|
5333
5419
|
switch (R.value) {
|
|
5334
5420
|
case 0:
|
|
5335
5421
|
return "100vw";
|
|
@@ -5340,14 +5426,14 @@ const zU = {
|
|
|
5340
5426
|
default:
|
|
5341
5427
|
return `${Cl}px `.repeat(U.parts.length) + `${zl}px`;
|
|
5342
5428
|
}
|
|
5343
|
-
}), m =
|
|
5344
|
-
const
|
|
5345
|
-
return R.value > 0 ? '"' +
|
|
5429
|
+
}), m = G(() => {
|
|
5430
|
+
const W = [...U.parts.keys()];
|
|
5431
|
+
return R.value > 0 ? '"' + W.map((c) => "part" + c).join(" ") + ' controls"' : '"controls" ' + W.map((c) => '"part' + c + '"').join(" ");
|
|
5346
5432
|
});
|
|
5347
|
-
return (
|
|
5433
|
+
return (W, c) => (X(), Y("div", {
|
|
5348
5434
|
class: "outer",
|
|
5349
5435
|
ref_key: "container",
|
|
5350
|
-
ref:
|
|
5436
|
+
ref: Q
|
|
5351
5437
|
}, [
|
|
5352
5438
|
h("div", cF, [
|
|
5353
5439
|
h("div", eF, [
|
|
@@ -5369,18 +5455,18 @@ const zU = {
|
|
|
5369
5455
|
class: "controls"
|
|
5370
5456
|
}, {
|
|
5371
5457
|
menu: D(() => [
|
|
5372
|
-
Vl(
|
|
5458
|
+
Vl(W.$slots, "menu", {}, void 0, !0)
|
|
5373
5459
|
]),
|
|
5374
5460
|
_: 3
|
|
5375
5461
|
}, 8, ["title"]),
|
|
5376
5462
|
t.value ? f("", !0) : (X(), Y("div", sF)),
|
|
5377
|
-
l.showInitProgress && r(
|
|
5463
|
+
l.showInitProgress && r(d).shouldShowProgress ? (X(), nl(WF, {
|
|
5378
5464
|
key: 1,
|
|
5379
|
-
stage: r(
|
|
5380
|
-
message: r(
|
|
5381
|
-
progress: r(
|
|
5382
|
-
"has-error": r(
|
|
5383
|
-
"error-message": r(
|
|
5465
|
+
stage: r(d).currentStage,
|
|
5466
|
+
message: r(d).message,
|
|
5467
|
+
progress: r(d).progress,
|
|
5468
|
+
"has-error": r(d).hasError,
|
|
5469
|
+
"error-message": r(d).errorMessage
|
|
5384
5470
|
}, null, 8, ["stage", "message", "progress", "has-error", "error-message"])) : f("", !0)
|
|
5385
5471
|
])
|
|
5386
5472
|
])
|
|
@@ -5401,14 +5487,14 @@ const zU = {
|
|
|
5401
5487
|
default: ""
|
|
5402
5488
|
}
|
|
5403
5489
|
},
|
|
5404
|
-
setup(
|
|
5490
|
+
setup(Z) {
|
|
5405
5491
|
return $((l) => ({
|
|
5406
|
-
"66bea586":
|
|
5492
|
+
"66bea586": Z.colour
|
|
5407
5493
|
})), (l, U) => (X(), Y("div", SF, [
|
|
5408
5494
|
h("div", oF, [
|
|
5409
5495
|
h("div", XF, [
|
|
5410
|
-
|
|
5411
|
-
ol(K(
|
|
5496
|
+
Z.text || l.$slots.default ? (X(), Y("div", NF, [
|
|
5497
|
+
ol(K(Z.text) + " ", 1),
|
|
5412
5498
|
Vl(l.$slots, "default", {}, void 0, !0)
|
|
5413
5499
|
])) : f("", !0)
|
|
5414
5500
|
])
|
|
@@ -5424,7 +5510,7 @@ class YF {
|
|
|
5424
5510
|
initialize(l) {
|
|
5425
5511
|
if (this.musicData = l, this.beats = l.beats || [], this.practiceMarks = l.practiceMarks || {}, this.beats.length > 0) {
|
|
5426
5512
|
const U = this.beats[this.beats.length - 1], F = U.tempo > 0 ? 60 / U.tempo : 0.75;
|
|
5427
|
-
this.songDuration = U.time + F, this.maxBar = Math.max(...this.beats.map((
|
|
5513
|
+
this.songDuration = U.time + F, this.maxBar = Math.max(...this.beats.map((d) => d.bar));
|
|
5428
5514
|
} else
|
|
5429
5515
|
this.songDuration = 0, this.maxBar = 0;
|
|
5430
5516
|
l.parts && l.parts.forEach((U) => {
|
|
@@ -5522,8 +5608,8 @@ class YF {
|
|
|
5522
5608
|
return;
|
|
5523
5609
|
}
|
|
5524
5610
|
this.eventBus.emit("timeChanged", { currentTime: this.currentTime });
|
|
5525
|
-
const
|
|
5526
|
-
if (
|
|
5611
|
+
const d = this.getBarFromTime(this.currentTime);
|
|
5612
|
+
if (d && (this.eventBus.emit("barChanged", d), this.maxBar > 0 && d.bar > this.maxBar)) {
|
|
5527
5613
|
this.stop(), this.eventBus.emit("songEnded", { finalTime: this.currentTime });
|
|
5528
5614
|
return;
|
|
5529
5615
|
}
|
|
@@ -5552,10 +5638,10 @@ class YF {
|
|
|
5552
5638
|
getTimeFromBar(l, U = 0) {
|
|
5553
5639
|
if (!this.beats || this.beats.length === 0) return null;
|
|
5554
5640
|
let F = this.beats.find(
|
|
5555
|
-
(
|
|
5641
|
+
(d) => d.bar === l && d.beat === 1 && d.repeat === U
|
|
5556
5642
|
);
|
|
5557
5643
|
return F || (F = this.beats.find(
|
|
5558
|
-
(
|
|
5644
|
+
(d) => d.bar === l && d.beat === 1
|
|
5559
5645
|
)), F ? F.time : null;
|
|
5560
5646
|
}
|
|
5561
5647
|
destroy() {
|
|
@@ -5568,7 +5654,7 @@ export {
|
|
|
5568
5654
|
bl as AudioSlider,
|
|
5569
5655
|
OU as BarInput,
|
|
5570
5656
|
ql as BaseNumericInput,
|
|
5571
|
-
|
|
5657
|
+
Gl as DEV_MODE,
|
|
5572
5658
|
YF as DummyAudioEngine,
|
|
5573
5659
|
WF as InitializationProgress,
|
|
5574
5660
|
tF as MixerControls,
|