@dawcore/transport 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -5
- package/dist/index.d.mts +68 -21
- package/dist/index.d.ts +68 -21
- package/dist/index.js +246 -57
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +245 -56
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -172,34 +172,6 @@ var SampleTimeline = class {
|
|
|
172
172
|
}
|
|
173
173
|
};
|
|
174
174
|
|
|
175
|
-
// src/timeline/tick-timeline.ts
|
|
176
|
-
var TickTimeline = class {
|
|
177
|
-
constructor(ppqn = 960) {
|
|
178
|
-
this._ppqn = ppqn;
|
|
179
|
-
}
|
|
180
|
-
get ppqn() {
|
|
181
|
-
return this._ppqn;
|
|
182
|
-
}
|
|
183
|
-
ticksPerBeat() {
|
|
184
|
-
return this._ppqn;
|
|
185
|
-
}
|
|
186
|
-
ticksPerBar(beatsPerBar) {
|
|
187
|
-
return this._ppqn * beatsPerBar;
|
|
188
|
-
}
|
|
189
|
-
toPosition(ticks, beatsPerBar) {
|
|
190
|
-
const ticksPerBar = this.ticksPerBar(beatsPerBar);
|
|
191
|
-
const bar = Math.floor(ticks / ticksPerBar) + 1;
|
|
192
|
-
const remaining = ticks % ticksPerBar;
|
|
193
|
-
const beat = Math.floor(remaining / this._ppqn) + 1;
|
|
194
|
-
const tick = remaining % this._ppqn;
|
|
195
|
-
return { bar, beat, tick };
|
|
196
|
-
}
|
|
197
|
-
fromPosition(bar, beat, tick, beatsPerBar) {
|
|
198
|
-
const ticksPerBar = this.ticksPerBar(beatsPerBar);
|
|
199
|
-
return (bar - 1) * ticksPerBar + (beat - 1) * this._ppqn + tick;
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
|
|
203
175
|
// src/timeline/tempo-map.ts
|
|
204
176
|
var TempoMap = class {
|
|
205
177
|
constructor(ppqn = 960, initialBpm = 120) {
|
|
@@ -252,6 +224,10 @@ var TempoMap = class {
|
|
|
252
224
|
secondsToBeats(seconds) {
|
|
253
225
|
return this.secondsToTicks(seconds) / this._ppqn;
|
|
254
226
|
}
|
|
227
|
+
clearTempos() {
|
|
228
|
+
const first = this._entries[0];
|
|
229
|
+
this._entries = [{ tick: 0, bpm: first.bpm, secondsAtTick: 0 }];
|
|
230
|
+
}
|
|
255
231
|
_ticksToSecondsInternal(ticks) {
|
|
256
232
|
const entry = this._entryAt(ticks);
|
|
257
233
|
const ticksIntoSegment = ticks - entry.tick;
|
|
@@ -284,6 +260,179 @@ var TempoMap = class {
|
|
|
284
260
|
}
|
|
285
261
|
};
|
|
286
262
|
|
|
263
|
+
// src/timeline/meter-map.ts
|
|
264
|
+
function isPowerOf2(n) {
|
|
265
|
+
return n > 0 && (n & n - 1) === 0;
|
|
266
|
+
}
|
|
267
|
+
var MeterMap = class {
|
|
268
|
+
constructor(ppqn, numerator = 4, denominator = 4) {
|
|
269
|
+
this._ppqn = ppqn;
|
|
270
|
+
this._entries = [{ tick: 0, numerator, denominator, barAtTick: 0 }];
|
|
271
|
+
}
|
|
272
|
+
get ppqn() {
|
|
273
|
+
return this._ppqn;
|
|
274
|
+
}
|
|
275
|
+
getMeter(atTick = 0) {
|
|
276
|
+
const entry = this._entryAt(atTick);
|
|
277
|
+
return { numerator: entry.numerator, denominator: entry.denominator };
|
|
278
|
+
}
|
|
279
|
+
setMeter(numerator, denominator, atTick = 0) {
|
|
280
|
+
this._validateMeter(numerator, denominator);
|
|
281
|
+
if (atTick < 0) {
|
|
282
|
+
throw new Error("[waveform-playlist] MeterMap: atTick must be non-negative, got " + atTick);
|
|
283
|
+
}
|
|
284
|
+
if (atTick === 0) {
|
|
285
|
+
this._entries[0] = { ...this._entries[0], numerator, denominator };
|
|
286
|
+
this._resnapDownstreamEntries(0);
|
|
287
|
+
this._recomputeCache(0);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
const snapped = this._snapToBarBoundary(atTick);
|
|
291
|
+
if (snapped !== atTick) {
|
|
292
|
+
console.warn(
|
|
293
|
+
"[waveform-playlist] MeterMap.setMeter: tick " + atTick + " is not on a bar boundary, snapped to " + snapped
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
let i = this._entries.length - 1;
|
|
297
|
+
while (i > 0 && this._entries[i].tick > snapped) i--;
|
|
298
|
+
if (this._entries[i].tick === snapped) {
|
|
299
|
+
this._entries[i] = { ...this._entries[i], numerator, denominator };
|
|
300
|
+
} else {
|
|
301
|
+
const barAtTick = this._computeBarAtTick(snapped);
|
|
302
|
+
this._entries.splice(i + 1, 0, { tick: snapped, numerator, denominator, barAtTick });
|
|
303
|
+
i = i + 1;
|
|
304
|
+
}
|
|
305
|
+
this._resnapDownstreamEntries(i);
|
|
306
|
+
this._recomputeCache(i);
|
|
307
|
+
}
|
|
308
|
+
removeMeter(atTick) {
|
|
309
|
+
if (atTick === 0) {
|
|
310
|
+
throw new Error("[waveform-playlist] MeterMap: cannot remove meter at tick 0");
|
|
311
|
+
}
|
|
312
|
+
const idx = this._entries.findIndex((e) => e.tick === atTick);
|
|
313
|
+
if (idx > 0) {
|
|
314
|
+
this._entries.splice(idx, 1);
|
|
315
|
+
this._recomputeCache(idx);
|
|
316
|
+
} else if (idx === -1) {
|
|
317
|
+
console.warn("[waveform-playlist] MeterMap.removeMeter: no entry at tick " + atTick);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
clearMeters() {
|
|
321
|
+
const first = this._entries[0];
|
|
322
|
+
this._entries = [{ ...first, barAtTick: 0 }];
|
|
323
|
+
}
|
|
324
|
+
ticksPerBeat(atTick = 0) {
|
|
325
|
+
const entry = this._entryAt(atTick);
|
|
326
|
+
return this._ppqn * (4 / entry.denominator);
|
|
327
|
+
}
|
|
328
|
+
ticksPerBar(atTick = 0) {
|
|
329
|
+
const entry = this._entryAt(atTick);
|
|
330
|
+
return entry.numerator * this._ppqn * (4 / entry.denominator);
|
|
331
|
+
}
|
|
332
|
+
barToTick(bar) {
|
|
333
|
+
if (bar < 1) {
|
|
334
|
+
throw new Error("[waveform-playlist] MeterMap: bar must be >= 1, got " + bar);
|
|
335
|
+
}
|
|
336
|
+
const targetBar = bar - 1;
|
|
337
|
+
for (let i = 0; i < this._entries.length; i++) {
|
|
338
|
+
const nextBar = i < this._entries.length - 1 ? this._entries[i + 1].barAtTick : Infinity;
|
|
339
|
+
if (targetBar < nextBar) {
|
|
340
|
+
const barsInto = targetBar - this._entries[i].barAtTick;
|
|
341
|
+
const tpb = this._ticksPerBarForEntry(this._entries[i]);
|
|
342
|
+
return this._entries[i].tick + barsInto * tpb;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return 0;
|
|
346
|
+
}
|
|
347
|
+
tickToBar(tick) {
|
|
348
|
+
const entry = this._entryAt(tick);
|
|
349
|
+
const ticksInto = tick - entry.tick;
|
|
350
|
+
const tpb = this._ticksPerBarForEntry(entry);
|
|
351
|
+
return entry.barAtTick + Math.floor(ticksInto / tpb) + 1;
|
|
352
|
+
}
|
|
353
|
+
isBarBoundary(tick) {
|
|
354
|
+
const entry = this._entryAt(tick);
|
|
355
|
+
const ticksInto = tick - entry.tick;
|
|
356
|
+
const tpb = this._ticksPerBarForEntry(entry);
|
|
357
|
+
return ticksInto % tpb === 0;
|
|
358
|
+
}
|
|
359
|
+
/** Internal: get the full entry at a tick (for MetronomePlayer beat grid anchoring) */
|
|
360
|
+
getEntryAt(tick) {
|
|
361
|
+
return this._entryAt(tick);
|
|
362
|
+
}
|
|
363
|
+
_entryAt(tick) {
|
|
364
|
+
let lo = 0;
|
|
365
|
+
let hi = this._entries.length - 1;
|
|
366
|
+
while (lo < hi) {
|
|
367
|
+
const mid = lo + hi + 1 >> 1;
|
|
368
|
+
if (this._entries[mid].tick <= tick) {
|
|
369
|
+
lo = mid;
|
|
370
|
+
} else {
|
|
371
|
+
hi = mid - 1;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return this._entries[lo];
|
|
375
|
+
}
|
|
376
|
+
_ticksPerBarForEntry(entry) {
|
|
377
|
+
return entry.numerator * this._ppqn * (4 / entry.denominator);
|
|
378
|
+
}
|
|
379
|
+
_snapToBarBoundary(atTick) {
|
|
380
|
+
const entry = this._entryAt(atTick);
|
|
381
|
+
const tpb = this._ticksPerBarForEntry(entry);
|
|
382
|
+
const ticksInto = atTick - entry.tick;
|
|
383
|
+
if (ticksInto % tpb === 0) return atTick;
|
|
384
|
+
return entry.tick + Math.ceil(ticksInto / tpb) * tpb;
|
|
385
|
+
}
|
|
386
|
+
_computeBarAtTick(tick) {
|
|
387
|
+
const entry = this._entryAt(tick);
|
|
388
|
+
const ticksInto = tick - entry.tick;
|
|
389
|
+
const tpb = this._ticksPerBarForEntry(entry);
|
|
390
|
+
return entry.barAtTick + ticksInto / tpb;
|
|
391
|
+
}
|
|
392
|
+
_recomputeCache(fromIndex) {
|
|
393
|
+
for (let i = Math.max(1, fromIndex); i < this._entries.length; i++) {
|
|
394
|
+
const prev = this._entries[i - 1];
|
|
395
|
+
const tickDelta = this._entries[i].tick - prev.tick;
|
|
396
|
+
const tpb = this._ticksPerBarForEntry(prev);
|
|
397
|
+
this._entries[i] = {
|
|
398
|
+
...this._entries[i],
|
|
399
|
+
barAtTick: prev.barAtTick + tickDelta / tpb
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* After changing a meter entry, re-snap downstream entries to bar boundaries
|
|
405
|
+
* of their preceding meter so barAtTick stays integer.
|
|
406
|
+
*/
|
|
407
|
+
_resnapDownstreamEntries(fromIndex) {
|
|
408
|
+
for (let i = Math.max(1, fromIndex + 1); i < this._entries.length; i++) {
|
|
409
|
+
const prev = this._entries[i - 1];
|
|
410
|
+
const tpb = this._ticksPerBarForEntry(prev);
|
|
411
|
+
const tick = this._entries[i].tick;
|
|
412
|
+
const ticksIntoPrev = tick - prev.tick;
|
|
413
|
+
if (ticksIntoPrev % tpb !== 0) {
|
|
414
|
+
const snapped = prev.tick + Math.ceil(ticksIntoPrev / tpb) * tpb;
|
|
415
|
+
console.warn(
|
|
416
|
+
"[waveform-playlist] MeterMap: meter change moved entry from tick " + tick + " to " + snapped + " (bar boundary alignment)"
|
|
417
|
+
);
|
|
418
|
+
this._entries[i] = { ...this._entries[i], tick: snapped };
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
_validateMeter(numerator, denominator) {
|
|
423
|
+
if (!Number.isInteger(numerator) || numerator < 1 || numerator > 32) {
|
|
424
|
+
throw new Error(
|
|
425
|
+
"[waveform-playlist] MeterMap: numerator must be an integer 1-32, got " + numerator
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
if (!isPowerOf2(denominator) || denominator > 32) {
|
|
429
|
+
throw new Error(
|
|
430
|
+
"[waveform-playlist] MeterMap: denominator must be a power of 2 (1-32), got " + denominator
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
|
|
287
436
|
// src/audio/master-node.ts
|
|
288
437
|
var MasterNode = class {
|
|
289
438
|
constructor(audioContext) {
|
|
@@ -550,15 +699,14 @@ var ClipPlayer = class {
|
|
|
550
699
|
|
|
551
700
|
// src/audio/metronome-player.ts
|
|
552
701
|
var MetronomePlayer = class {
|
|
553
|
-
constructor(audioContext, tempoMap,
|
|
702
|
+
constructor(audioContext, tempoMap, meterMap, destination, toAudioTime) {
|
|
554
703
|
this._enabled = false;
|
|
555
|
-
this._beatsPerBar = 4;
|
|
556
704
|
this._accentBuffer = null;
|
|
557
705
|
this._normalBuffer = null;
|
|
558
706
|
this._activeSources = /* @__PURE__ */ new Set();
|
|
559
707
|
this._audioContext = audioContext;
|
|
560
708
|
this._tempoMap = tempoMap;
|
|
561
|
-
this.
|
|
709
|
+
this._meterMap = meterMap;
|
|
562
710
|
this._destination = destination;
|
|
563
711
|
this._toAudioTime = toAudioTime;
|
|
564
712
|
}
|
|
@@ -568,9 +716,6 @@ var MetronomePlayer = class {
|
|
|
568
716
|
this.silence();
|
|
569
717
|
}
|
|
570
718
|
}
|
|
571
|
-
setBeatsPerBar(beats) {
|
|
572
|
-
this._beatsPerBar = beats;
|
|
573
|
-
}
|
|
574
719
|
setClickSounds(accent, normal) {
|
|
575
720
|
this._accentBuffer = accent;
|
|
576
721
|
this._normalBuffer = normal;
|
|
@@ -580,19 +725,27 @@ var MetronomePlayer = class {
|
|
|
580
725
|
return [];
|
|
581
726
|
}
|
|
582
727
|
const events = [];
|
|
583
|
-
const ppqn = this._tickTimeline.ppqn;
|
|
584
728
|
const fromTicks = this._tempoMap.secondsToTicks(fromTime);
|
|
585
729
|
const toTicks = this._tempoMap.secondsToTicks(toTime);
|
|
586
|
-
|
|
587
|
-
|
|
730
|
+
let entry = this._meterMap.getEntryAt(fromTicks);
|
|
731
|
+
let beatSize = this._meterMap.ticksPerBeat(fromTicks);
|
|
732
|
+
const tickIntoSection = fromTicks - entry.tick;
|
|
733
|
+
let tick = entry.tick + Math.ceil(tickIntoSection / beatSize) * beatSize;
|
|
734
|
+
while (tick < toTicks) {
|
|
735
|
+
const currentEntry = this._meterMap.getEntryAt(tick);
|
|
736
|
+
if (currentEntry.tick !== entry.tick) {
|
|
737
|
+
entry = currentEntry;
|
|
738
|
+
beatSize = this._meterMap.ticksPerBeat(tick);
|
|
739
|
+
}
|
|
740
|
+
const isAccent = this._meterMap.isBarBoundary(tick);
|
|
588
741
|
const transportTime = this._tempoMap.ticksToSeconds(tick);
|
|
589
|
-
const ticksPerBar = this._tickTimeline.ticksPerBar(this._beatsPerBar);
|
|
590
|
-
const isAccent = tick % ticksPerBar === 0;
|
|
591
742
|
events.push({
|
|
592
743
|
transportTime,
|
|
593
744
|
isAccent,
|
|
594
745
|
buffer: isAccent ? this._accentBuffer : this._normalBuffer
|
|
595
746
|
});
|
|
747
|
+
beatSize = this._meterMap.ticksPerBeat(tick);
|
|
748
|
+
tick += beatSize;
|
|
596
749
|
}
|
|
597
750
|
return events;
|
|
598
751
|
}
|
|
@@ -653,9 +806,10 @@ var Transport = class _Transport {
|
|
|
653
806
|
const sampleRate = options.sampleRate ?? audioContext.sampleRate;
|
|
654
807
|
const ppqn = options.ppqn ?? 960;
|
|
655
808
|
const tempo = options.tempo ?? 120;
|
|
656
|
-
const
|
|
809
|
+
const numerator = options.numerator ?? 4;
|
|
810
|
+
const denominator = options.denominator ?? 4;
|
|
657
811
|
const lookahead = options.schedulerLookahead ?? 0.2;
|
|
658
|
-
_Transport._validateOptions(sampleRate, ppqn, tempo,
|
|
812
|
+
_Transport._validateOptions(sampleRate, ppqn, tempo, numerator, denominator, lookahead);
|
|
659
813
|
this._clock = new Clock(audioContext);
|
|
660
814
|
this._scheduler = new Scheduler({
|
|
661
815
|
lookahead,
|
|
@@ -664,9 +818,9 @@ var Transport = class _Transport {
|
|
|
664
818
|
}
|
|
665
819
|
});
|
|
666
820
|
this._sampleTimeline = new SampleTimeline(sampleRate);
|
|
667
|
-
this.
|
|
821
|
+
this._meterMap = new MeterMap(ppqn, numerator, denominator);
|
|
668
822
|
this._tempoMap = new TempoMap(ppqn, tempo);
|
|
669
|
-
this._initAudioGraph(audioContext
|
|
823
|
+
this._initAudioGraph(audioContext);
|
|
670
824
|
this._timer = new Timer(() => {
|
|
671
825
|
const time = this._clock.getTime();
|
|
672
826
|
if (this._endTime !== void 0 && time >= this._endTime) {
|
|
@@ -858,15 +1012,46 @@ var Transport = class _Transport {
|
|
|
858
1012
|
this._emit("loop");
|
|
859
1013
|
}
|
|
860
1014
|
// --- Tempo ---
|
|
861
|
-
setTempo(bpm) {
|
|
862
|
-
this._tempoMap.setTempo(bpm);
|
|
1015
|
+
setTempo(bpm, atTick) {
|
|
1016
|
+
this._tempoMap.setTempo(bpm, atTick);
|
|
863
1017
|
this._emit("tempochange");
|
|
864
1018
|
}
|
|
865
|
-
getTempo() {
|
|
866
|
-
return this._tempoMap.getTempo();
|
|
1019
|
+
getTempo(atTick) {
|
|
1020
|
+
return this._tempoMap.getTempo(atTick);
|
|
1021
|
+
}
|
|
1022
|
+
// --- Meter ---
|
|
1023
|
+
setMeter(numerator, denominator, atTick) {
|
|
1024
|
+
this._meterMap.setMeter(numerator, denominator, atTick);
|
|
1025
|
+
this._emit("meterchange");
|
|
1026
|
+
}
|
|
1027
|
+
getMeter(atTick) {
|
|
1028
|
+
return this._meterMap.getMeter(atTick);
|
|
1029
|
+
}
|
|
1030
|
+
removeMeter(atTick) {
|
|
1031
|
+
this._meterMap.removeMeter(atTick);
|
|
1032
|
+
this._emit("meterchange");
|
|
1033
|
+
}
|
|
1034
|
+
clearMeters() {
|
|
1035
|
+
this._meterMap.clearMeters();
|
|
1036
|
+
this._emit("meterchange");
|
|
1037
|
+
}
|
|
1038
|
+
clearTempos() {
|
|
1039
|
+
this._tempoMap.clearTempos();
|
|
1040
|
+
this._emit("tempochange");
|
|
867
1041
|
}
|
|
868
|
-
|
|
869
|
-
this.
|
|
1042
|
+
barToTick(bar) {
|
|
1043
|
+
return this._meterMap.barToTick(bar);
|
|
1044
|
+
}
|
|
1045
|
+
tickToBar(tick) {
|
|
1046
|
+
return this._meterMap.tickToBar(tick);
|
|
1047
|
+
}
|
|
1048
|
+
/** Convert transport time (seconds) to tick position, using the tempo map. */
|
|
1049
|
+
timeToTick(seconds) {
|
|
1050
|
+
return this._tempoMap.secondsToTicks(seconds);
|
|
1051
|
+
}
|
|
1052
|
+
/** Convert tick position to transport time (seconds), using the tempo map. */
|
|
1053
|
+
tickToTime(tick) {
|
|
1054
|
+
return this._tempoMap.ticksToSeconds(tick);
|
|
870
1055
|
}
|
|
871
1056
|
// --- Metronome ---
|
|
872
1057
|
setMetronomeEnabled(enabled) {
|
|
@@ -913,7 +1098,7 @@ var Transport = class _Transport {
|
|
|
913
1098
|
this._listeners.clear();
|
|
914
1099
|
}
|
|
915
1100
|
// --- Private ---
|
|
916
|
-
static _validateOptions(sampleRate, ppqn, tempo,
|
|
1101
|
+
static _validateOptions(sampleRate, ppqn, tempo, numerator, denominator, lookahead) {
|
|
917
1102
|
if (sampleRate <= 0) {
|
|
918
1103
|
throw new Error(
|
|
919
1104
|
"[waveform-playlist] Transport: sampleRate must be positive, got " + sampleRate
|
|
@@ -927,9 +1112,14 @@ var Transport = class _Transport {
|
|
|
927
1112
|
if (tempo <= 0) {
|
|
928
1113
|
throw new Error("[waveform-playlist] Transport: tempo must be positive, got " + tempo);
|
|
929
1114
|
}
|
|
930
|
-
if (
|
|
1115
|
+
if (!Number.isInteger(numerator) || numerator < 1 || numerator > 32) {
|
|
1116
|
+
throw new Error(
|
|
1117
|
+
"[waveform-playlist] Transport: numerator must be an integer 1-32, got " + numerator
|
|
1118
|
+
);
|
|
1119
|
+
}
|
|
1120
|
+
if (denominator <= 0 || (denominator & denominator - 1) !== 0 || denominator > 32) {
|
|
931
1121
|
throw new Error(
|
|
932
|
-
"[waveform-playlist] Transport:
|
|
1122
|
+
"[waveform-playlist] Transport: denominator must be a power of 2 (1-32), got " + denominator
|
|
933
1123
|
);
|
|
934
1124
|
}
|
|
935
1125
|
if (lookahead <= 0) {
|
|
@@ -938,7 +1128,7 @@ var Transport = class _Transport {
|
|
|
938
1128
|
);
|
|
939
1129
|
}
|
|
940
1130
|
}
|
|
941
|
-
_initAudioGraph(audioContext
|
|
1131
|
+
_initAudioGraph(audioContext) {
|
|
942
1132
|
this._masterNode = new MasterNode(audioContext);
|
|
943
1133
|
this._masterNode.output.connect(audioContext.destination);
|
|
944
1134
|
const toAudioTime = (transportTime) => this._clock.toAudioTime(transportTime);
|
|
@@ -946,11 +1136,10 @@ var Transport = class _Transport {
|
|
|
946
1136
|
this._metronomePlayer = new MetronomePlayer(
|
|
947
1137
|
audioContext,
|
|
948
1138
|
this._tempoMap,
|
|
949
|
-
this.
|
|
1139
|
+
this._meterMap,
|
|
950
1140
|
this._masterNode.input,
|
|
951
1141
|
toAudioTime
|
|
952
1142
|
);
|
|
953
|
-
this._metronomePlayer.setBeatsPerBar(beatsPerBar);
|
|
954
1143
|
this._scheduler.addListener(this._clipPlayer);
|
|
955
1144
|
this._scheduler.addListener(this._metronomePlayer);
|
|
956
1145
|
}
|
|
@@ -1056,12 +1245,12 @@ export {
|
|
|
1056
1245
|
ClipPlayer,
|
|
1057
1246
|
Clock,
|
|
1058
1247
|
MasterNode,
|
|
1248
|
+
MeterMap,
|
|
1059
1249
|
MetronomePlayer,
|
|
1060
1250
|
NativePlayoutAdapter,
|
|
1061
1251
|
SampleTimeline,
|
|
1062
1252
|
Scheduler,
|
|
1063
1253
|
TempoMap,
|
|
1064
|
-
TickTimeline,
|
|
1065
1254
|
Timer,
|
|
1066
1255
|
TrackNode,
|
|
1067
1256
|
Transport
|