@dawcore/transport 0.0.10 → 0.0.12
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/index.d.mts +29 -7
- package/dist/index.d.ts +29 -7
- package/dist/index.js +89 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +89 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -8
package/dist/index.d.mts
CHANGED
|
@@ -142,13 +142,26 @@ declare class TempoMap {
|
|
|
142
142
|
private _ppqn;
|
|
143
143
|
private _entries;
|
|
144
144
|
constructor(ppqn?: number, initialBpm?: number);
|
|
145
|
+
/** A non-finite or non-positive BPM silently corrupts the secondsAtTick
|
|
146
|
+
* cache (Infinity, or non-monotonic values that break the binary search
|
|
147
|
+
* in secondsToTicks) — reject it at the boundary instead. */
|
|
148
|
+
private static _validateBpm;
|
|
145
149
|
getTempo(atTick?: Tick): number;
|
|
150
|
+
/** Number of tempo entries in the map. Always >= 1 — the tick-0 entry is
|
|
151
|
+
* permanent. Used by Transport.setTempo to detect multi-entry maps. */
|
|
152
|
+
get entryCount(): number;
|
|
146
153
|
setTempo(bpm: number, atTick?: Tick, options?: SetTempoOptions): void;
|
|
147
154
|
ticksToSeconds(ticks: Tick): number;
|
|
148
155
|
secondsToTicks(seconds: number): Tick;
|
|
149
156
|
beatsToSeconds(beats: number): number;
|
|
150
157
|
secondsToBeats(seconds: number): number;
|
|
151
158
|
clearTempos(): void;
|
|
159
|
+
/** Remove the tempo entry at exactly `atTick`, if one exists. The tick-0
|
|
160
|
+
* entry is permanent (a map must always have a tempo) — removing it is a
|
|
161
|
+
* no-op, matching removeMeter's treatment of the initial meter. The
|
|
162
|
+
* seconds cache is recomputed from the removal point, the same partial
|
|
163
|
+
* update setTempo uses. */
|
|
164
|
+
removeTempo(atTick: Tick): void;
|
|
152
165
|
/** Get the interpolated BPM at a tick position */
|
|
153
166
|
private _getTempoAt;
|
|
154
167
|
private _ticksToSecondsInternal;
|
|
@@ -299,17 +312,18 @@ interface ClipEvent extends SchedulerEvent {
|
|
|
299
312
|
trackId: string;
|
|
300
313
|
clipId: string;
|
|
301
314
|
audioBuffer: AudioBuffer;
|
|
302
|
-
/** Clip position on timeline (integer samples) */
|
|
315
|
+
/** Clip position on timeline (integer samples, at the TIMELINE sample rate) */
|
|
303
316
|
startSample: Sample;
|
|
304
|
-
/** Offset into audioBuffer (integer samples
|
|
317
|
+
/** Offset into audioBuffer (integer samples, at the BUFFER's own sample
|
|
318
|
+
* rate — they index the buffer, not the timeline) */
|
|
305
319
|
offsetSamples: Sample;
|
|
306
|
-
/** Duration to play (integer samples) */
|
|
320
|
+
/** Duration to play (integer samples, at the BUFFER's own sample rate) */
|
|
307
321
|
durationSamples: Sample;
|
|
308
322
|
/** Clip gain multiplier */
|
|
309
323
|
gain: number;
|
|
310
|
-
/** Fade in duration (integer samples) */
|
|
324
|
+
/** Fade in duration (integer samples, at the TIMELINE sample rate) */
|
|
311
325
|
fadeInDurationSamples: Sample;
|
|
312
|
-
/** Fade out duration (integer samples) */
|
|
326
|
+
/** Fade out duration (integer samples, at the TIMELINE sample rate) */
|
|
313
327
|
fadeOutDurationSamples: Sample;
|
|
314
328
|
}
|
|
315
329
|
declare class ClipPlayer implements SchedulerListener<ClipEvent> {
|
|
@@ -443,13 +457,21 @@ declare class Transport {
|
|
|
443
457
|
setLoopSeconds(enabled: boolean, startSec: number, endSec: number): void;
|
|
444
458
|
/** Convenience — sets loop in samples */
|
|
445
459
|
setLoopSamples(enabled: boolean, startSample: Sample, endSample: Sample): void;
|
|
446
|
-
|
|
460
|
+
/** Returns true when the tempo was applied, false when a defaulted (no
|
|
461
|
+
* atTick) write was refused because the tempo map has multiple entries —
|
|
462
|
+
* pass an explicit atTick to modify a multi-entry map (#407). */
|
|
463
|
+
setTempo(bpm: number, atTick?: Tick, options?: SetTempoOptions): boolean;
|
|
447
464
|
getTempo(atTick?: Tick): number;
|
|
448
465
|
setMeter(numerator: number, denominator: number, atTick?: Tick): void;
|
|
449
466
|
getMeter(atTick?: Tick): MeterSignature;
|
|
450
467
|
removeMeter(atTick: Tick): void;
|
|
451
468
|
clearMeters(): void;
|
|
452
469
|
clearTempos(): void;
|
|
470
|
+
/** Remove the tempo entry at exactly `atTick` (tick 0 is permanent — a
|
|
471
|
+
* no-op, like removeMeter's initial entry). Mirrors setTempo's loop-cache
|
|
472
|
+
* invalidation and event; the emitted bpm is the tempo now in force at
|
|
473
|
+
* the removed position. */
|
|
474
|
+
removeTempo(atTick: Tick): void;
|
|
453
475
|
barToTick(bar: number): Tick;
|
|
454
476
|
tickToBar(tick: Tick): number;
|
|
455
477
|
/** Convert transport time (seconds) to tick position, using the tempo map. */
|
|
@@ -514,7 +536,7 @@ declare class NativePlayoutAdapter implements PlayoutAdapter {
|
|
|
514
536
|
setCountInMode(mode: CountInMode): void;
|
|
515
537
|
setRecording(recording: boolean): void;
|
|
516
538
|
isCountingIn(): boolean;
|
|
517
|
-
setTempo(bpm: number, atTick?: number):
|
|
539
|
+
setTempo(bpm: number, atTick?: number): boolean;
|
|
518
540
|
setMeter(numerator: number, denominator: number, atTick?: number): void;
|
|
519
541
|
ticksToSeconds(tick: number): number;
|
|
520
542
|
secondsToTicks(seconds: number): number;
|
package/dist/index.d.ts
CHANGED
|
@@ -142,13 +142,26 @@ declare class TempoMap {
|
|
|
142
142
|
private _ppqn;
|
|
143
143
|
private _entries;
|
|
144
144
|
constructor(ppqn?: number, initialBpm?: number);
|
|
145
|
+
/** A non-finite or non-positive BPM silently corrupts the secondsAtTick
|
|
146
|
+
* cache (Infinity, or non-monotonic values that break the binary search
|
|
147
|
+
* in secondsToTicks) — reject it at the boundary instead. */
|
|
148
|
+
private static _validateBpm;
|
|
145
149
|
getTempo(atTick?: Tick): number;
|
|
150
|
+
/** Number of tempo entries in the map. Always >= 1 — the tick-0 entry is
|
|
151
|
+
* permanent. Used by Transport.setTempo to detect multi-entry maps. */
|
|
152
|
+
get entryCount(): number;
|
|
146
153
|
setTempo(bpm: number, atTick?: Tick, options?: SetTempoOptions): void;
|
|
147
154
|
ticksToSeconds(ticks: Tick): number;
|
|
148
155
|
secondsToTicks(seconds: number): Tick;
|
|
149
156
|
beatsToSeconds(beats: number): number;
|
|
150
157
|
secondsToBeats(seconds: number): number;
|
|
151
158
|
clearTempos(): void;
|
|
159
|
+
/** Remove the tempo entry at exactly `atTick`, if one exists. The tick-0
|
|
160
|
+
* entry is permanent (a map must always have a tempo) — removing it is a
|
|
161
|
+
* no-op, matching removeMeter's treatment of the initial meter. The
|
|
162
|
+
* seconds cache is recomputed from the removal point, the same partial
|
|
163
|
+
* update setTempo uses. */
|
|
164
|
+
removeTempo(atTick: Tick): void;
|
|
152
165
|
/** Get the interpolated BPM at a tick position */
|
|
153
166
|
private _getTempoAt;
|
|
154
167
|
private _ticksToSecondsInternal;
|
|
@@ -299,17 +312,18 @@ interface ClipEvent extends SchedulerEvent {
|
|
|
299
312
|
trackId: string;
|
|
300
313
|
clipId: string;
|
|
301
314
|
audioBuffer: AudioBuffer;
|
|
302
|
-
/** Clip position on timeline (integer samples) */
|
|
315
|
+
/** Clip position on timeline (integer samples, at the TIMELINE sample rate) */
|
|
303
316
|
startSample: Sample;
|
|
304
|
-
/** Offset into audioBuffer (integer samples
|
|
317
|
+
/** Offset into audioBuffer (integer samples, at the BUFFER's own sample
|
|
318
|
+
* rate — they index the buffer, not the timeline) */
|
|
305
319
|
offsetSamples: Sample;
|
|
306
|
-
/** Duration to play (integer samples) */
|
|
320
|
+
/** Duration to play (integer samples, at the BUFFER's own sample rate) */
|
|
307
321
|
durationSamples: Sample;
|
|
308
322
|
/** Clip gain multiplier */
|
|
309
323
|
gain: number;
|
|
310
|
-
/** Fade in duration (integer samples) */
|
|
324
|
+
/** Fade in duration (integer samples, at the TIMELINE sample rate) */
|
|
311
325
|
fadeInDurationSamples: Sample;
|
|
312
|
-
/** Fade out duration (integer samples) */
|
|
326
|
+
/** Fade out duration (integer samples, at the TIMELINE sample rate) */
|
|
313
327
|
fadeOutDurationSamples: Sample;
|
|
314
328
|
}
|
|
315
329
|
declare class ClipPlayer implements SchedulerListener<ClipEvent> {
|
|
@@ -443,13 +457,21 @@ declare class Transport {
|
|
|
443
457
|
setLoopSeconds(enabled: boolean, startSec: number, endSec: number): void;
|
|
444
458
|
/** Convenience — sets loop in samples */
|
|
445
459
|
setLoopSamples(enabled: boolean, startSample: Sample, endSample: Sample): void;
|
|
446
|
-
|
|
460
|
+
/** Returns true when the tempo was applied, false when a defaulted (no
|
|
461
|
+
* atTick) write was refused because the tempo map has multiple entries —
|
|
462
|
+
* pass an explicit atTick to modify a multi-entry map (#407). */
|
|
463
|
+
setTempo(bpm: number, atTick?: Tick, options?: SetTempoOptions): boolean;
|
|
447
464
|
getTempo(atTick?: Tick): number;
|
|
448
465
|
setMeter(numerator: number, denominator: number, atTick?: Tick): void;
|
|
449
466
|
getMeter(atTick?: Tick): MeterSignature;
|
|
450
467
|
removeMeter(atTick: Tick): void;
|
|
451
468
|
clearMeters(): void;
|
|
452
469
|
clearTempos(): void;
|
|
470
|
+
/** Remove the tempo entry at exactly `atTick` (tick 0 is permanent — a
|
|
471
|
+
* no-op, like removeMeter's initial entry). Mirrors setTempo's loop-cache
|
|
472
|
+
* invalidation and event; the emitted bpm is the tempo now in force at
|
|
473
|
+
* the removed position. */
|
|
474
|
+
removeTempo(atTick: Tick): void;
|
|
453
475
|
barToTick(bar: number): Tick;
|
|
454
476
|
tickToBar(tick: Tick): number;
|
|
455
477
|
/** Convert transport time (seconds) to tick position, using the tempo map. */
|
|
@@ -514,7 +536,7 @@ declare class NativePlayoutAdapter implements PlayoutAdapter {
|
|
|
514
536
|
setCountInMode(mode: CountInMode): void;
|
|
515
537
|
setRecording(recording: boolean): void;
|
|
516
538
|
isCountingIn(): boolean;
|
|
517
|
-
setTempo(bpm: number, atTick?: number):
|
|
539
|
+
setTempo(bpm: number, atTick?: number): boolean;
|
|
518
540
|
setMeter(numerator: number, denominator: number, atTick?: number): void;
|
|
519
541
|
ticksToSeconds(tick: number): number;
|
|
520
542
|
secondsToTicks(seconds: number): number;
|
package/dist/index.js
CHANGED
|
@@ -249,7 +249,7 @@ var SampleTimeline = class {
|
|
|
249
249
|
"[waveform-playlist] SampleTimeline: tempoMap not set \u2014 call setTempoMap() first"
|
|
250
250
|
);
|
|
251
251
|
}
|
|
252
|
-
return this._tempoMap.secondsToTicks(samples / this._sampleRate);
|
|
252
|
+
return Math.round(this._tempoMap.secondsToTicks(samples / this._sampleRate));
|
|
253
253
|
}
|
|
254
254
|
};
|
|
255
255
|
|
|
@@ -261,15 +261,32 @@ function curveNormalizedAt(x, slope) {
|
|
|
261
261
|
const p = Math.max(CURVE_EPSILON, Math.min(1 - CURVE_EPSILON, slope));
|
|
262
262
|
return p * p / (1 - p * 2) * (Math.pow((1 - p) / p, 2 * x) - 1);
|
|
263
263
|
}
|
|
264
|
-
var TempoMap = class {
|
|
264
|
+
var TempoMap = class _TempoMap {
|
|
265
265
|
constructor(ppqn = 960, initialBpm = 120) {
|
|
266
|
+
_TempoMap._validateBpm(initialBpm);
|
|
266
267
|
this._ppqn = ppqn;
|
|
267
268
|
this._entries = [{ tick: 0, bpm: initialBpm, interpolation: "step", secondsAtTick: 0 }];
|
|
268
269
|
}
|
|
270
|
+
/** A non-finite or non-positive BPM silently corrupts the secondsAtTick
|
|
271
|
+
* cache (Infinity, or non-monotonic values that break the binary search
|
|
272
|
+
* in secondsToTicks) — reject it at the boundary instead. */
|
|
273
|
+
static _validateBpm(bpm) {
|
|
274
|
+
if (!Number.isFinite(bpm) || bpm <= 0) {
|
|
275
|
+
throw new Error(
|
|
276
|
+
"[waveform-playlist] TempoMap: bpm must be a finite positive number, got " + bpm
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
269
280
|
getTempo(atTick = 0) {
|
|
270
281
|
return this._getTempoAt(atTick);
|
|
271
282
|
}
|
|
283
|
+
/** Number of tempo entries in the map. Always >= 1 — the tick-0 entry is
|
|
284
|
+
* permanent. Used by Transport.setTempo to detect multi-entry maps. */
|
|
285
|
+
get entryCount() {
|
|
286
|
+
return this._entries.length;
|
|
287
|
+
}
|
|
272
288
|
setTempo(bpm, atTick = 0, options) {
|
|
289
|
+
_TempoMap._validateBpm(bpm);
|
|
273
290
|
const interpolation = options?.interpolation ?? "step";
|
|
274
291
|
if (typeof interpolation === "object" && interpolation.type === "curve") {
|
|
275
292
|
const s = interpolation.slope;
|
|
@@ -346,6 +363,18 @@ var TempoMap = class {
|
|
|
346
363
|
const first = this._entries[0];
|
|
347
364
|
this._entries = [{ tick: 0, bpm: first.bpm, interpolation: "step", secondsAtTick: 0 }];
|
|
348
365
|
}
|
|
366
|
+
/** Remove the tempo entry at exactly `atTick`, if one exists. The tick-0
|
|
367
|
+
* entry is permanent (a map must always have a tempo) — removing it is a
|
|
368
|
+
* no-op, matching removeMeter's treatment of the initial meter. The
|
|
369
|
+
* seconds cache is recomputed from the removal point, the same partial
|
|
370
|
+
* update setTempo uses. */
|
|
371
|
+
removeTempo(atTick) {
|
|
372
|
+
if (atTick === 0) return;
|
|
373
|
+
const i = this._entries.findIndex((e) => e.tick === atTick);
|
|
374
|
+
if (i === -1) return;
|
|
375
|
+
this._entries = [...this._entries.slice(0, i), ...this._entries.slice(i + 1)];
|
|
376
|
+
this._recomputeCache(i);
|
|
377
|
+
}
|
|
349
378
|
/** Get the interpolated BPM at a tick position */
|
|
350
379
|
_getTempoAt(atTick) {
|
|
351
380
|
const entryIndex = this._entryIndexAt(atTick);
|
|
@@ -507,6 +536,7 @@ function isPowerOf2(n) {
|
|
|
507
536
|
var MeterMap = class {
|
|
508
537
|
constructor(ppqn, numerator = 4, denominator = 4) {
|
|
509
538
|
this._ppqn = ppqn;
|
|
539
|
+
this._validateMeter(numerator, denominator);
|
|
510
540
|
this._entries = [{ tick: 0, numerator, denominator, barAtTick: 0 }];
|
|
511
541
|
}
|
|
512
542
|
get ppqn() {
|
|
@@ -670,6 +700,11 @@ var MeterMap = class {
|
|
|
670
700
|
"[waveform-playlist] MeterMap: denominator must be a power of 2 (1-32), got " + denominator
|
|
671
701
|
);
|
|
672
702
|
}
|
|
703
|
+
if (!Number.isInteger(this._ppqn * 4 / denominator)) {
|
|
704
|
+
throw new Error(
|
|
705
|
+
"[waveform-playlist] MeterMap: ppqn (" + this._ppqn + ") * 4 is not divisible by denominator (" + denominator + ") \u2014 bar boundaries would fall on fractional ticks"
|
|
706
|
+
);
|
|
707
|
+
}
|
|
673
708
|
}
|
|
674
709
|
};
|
|
675
710
|
|
|
@@ -800,11 +835,19 @@ var ClipPlayer = class {
|
|
|
800
835
|
const clipTick = clip.startTick !== void 0 ? clip.startTick : this._sampleTimeline.samplesToTicks(clip.startSample);
|
|
801
836
|
if (clipTick < fromTick) continue;
|
|
802
837
|
if (clipTick >= toTick) continue;
|
|
803
|
-
const
|
|
804
|
-
const
|
|
838
|
+
const timelineRate = this._sampleTimeline.sampleRate;
|
|
839
|
+
const bufferRate = clip.audioBuffer.sampleRate;
|
|
840
|
+
const fadeInDurationSamples = clip.fadeIn ? Math.round((clip.fadeIn.duration ?? 0) * timelineRate) : 0;
|
|
841
|
+
const fadeOutDurationSamples = clip.fadeOut ? Math.round((clip.fadeOut.duration ?? 0) * timelineRate) : 0;
|
|
805
842
|
let durationSamples = clip.durationSamples;
|
|
806
|
-
if (this._loopEnabled
|
|
807
|
-
|
|
843
|
+
if (this._loopEnabled) {
|
|
844
|
+
const durationTimelineSamples = Math.round(
|
|
845
|
+
clip.durationSamples / bufferRate * timelineRate
|
|
846
|
+
);
|
|
847
|
+
const allowedTimelineSamples = this._loopEndSamples - clip.startSample;
|
|
848
|
+
if (durationTimelineSamples > allowedTimelineSamples) {
|
|
849
|
+
durationSamples = Math.round(allowedTimelineSamples / timelineRate * bufferRate);
|
|
850
|
+
}
|
|
808
851
|
}
|
|
809
852
|
events.push({
|
|
810
853
|
trackId,
|
|
@@ -830,9 +873,9 @@ var ClipPlayer = class {
|
|
|
830
873
|
);
|
|
831
874
|
return;
|
|
832
875
|
}
|
|
833
|
-
const
|
|
834
|
-
const offsetSeconds = event.offsetSamples /
|
|
835
|
-
const durationSeconds = event.durationSamples /
|
|
876
|
+
const bufferRate = event.audioBuffer.sampleRate;
|
|
877
|
+
const offsetSeconds = event.offsetSamples / bufferRate;
|
|
878
|
+
const durationSeconds = event.durationSamples / bufferRate;
|
|
836
879
|
if (offsetSeconds >= event.audioBuffer.duration) {
|
|
837
880
|
console.warn(
|
|
838
881
|
"[waveform-playlist] ClipPlayer.consume: offset (" + offsetSeconds + "s) exceeds audioBuffer.duration (" + event.audioBuffer.duration + 's) for clipId "' + event.clipId + '" \u2014 clip will not play'
|
|
@@ -845,8 +888,9 @@ var ClipPlayer = class {
|
|
|
845
888
|
const when = this._toAudioTime(transportSeconds);
|
|
846
889
|
const gainNode = this._audioContext.createGain();
|
|
847
890
|
gainNode.gain.value = event.gain;
|
|
848
|
-
|
|
849
|
-
let
|
|
891
|
+
const timelineRate = this._sampleTimeline.sampleRate;
|
|
892
|
+
let fadeIn = event.fadeInDurationSamples / timelineRate;
|
|
893
|
+
let fadeOut = event.fadeOutDurationSamples / timelineRate;
|
|
850
894
|
if (fadeIn + fadeOut > durationSeconds) {
|
|
851
895
|
const ratio = durationSeconds / (fadeIn + fadeOut);
|
|
852
896
|
fadeIn *= ratio;
|
|
@@ -886,16 +930,21 @@ var ClipPlayer = class {
|
|
|
886
930
|
if (!clip.audioBuffer) continue;
|
|
887
931
|
const clipTick = clip.startTick !== void 0 ? clip.startTick : this._sampleTimeline.samplesToTicks(clip.startSample);
|
|
888
932
|
if (clipTick >= newTick) continue;
|
|
889
|
-
const
|
|
933
|
+
const timelineRate = this._sampleTimeline.sampleRate;
|
|
934
|
+
const bufferRate = clip.audioBuffer.sampleRate;
|
|
935
|
+
const bufToTimeline = (n) => Math.round(n / bufferRate * timelineRate);
|
|
936
|
+
const timelineToBuf = (n) => Math.round(n / timelineRate * bufferRate);
|
|
937
|
+
const clipEndSample = clip.startSample + bufToTimeline(clip.durationSamples);
|
|
890
938
|
if (clipEndSample <= newSample) continue;
|
|
891
939
|
const offsetIntoClipSamples = newSample - clip.startSample;
|
|
892
|
-
const offsetSamples = clip.offsetSamples + offsetIntoClipSamples;
|
|
893
|
-
let
|
|
894
|
-
if (this._loopEnabled && newSample +
|
|
895
|
-
|
|
940
|
+
const offsetSamples = clip.offsetSamples + timelineToBuf(offsetIntoClipSamples);
|
|
941
|
+
let remainingTimelineSamples = clipEndSample - newSample;
|
|
942
|
+
if (this._loopEnabled && newSample + remainingTimelineSamples > this._loopEndSamples) {
|
|
943
|
+
remainingTimelineSamples = this._loopEndSamples - newSample;
|
|
896
944
|
}
|
|
897
|
-
if (
|
|
898
|
-
const
|
|
945
|
+
if (remainingTimelineSamples <= 0) continue;
|
|
946
|
+
const durationSamples = timelineToBuf(remainingTimelineSamples);
|
|
947
|
+
const fadeOutDurationSamples = clip.fadeOut ? Math.round((clip.fadeOut.duration ?? 0) * timelineRate) : 0;
|
|
899
948
|
this.consume({
|
|
900
949
|
trackId,
|
|
901
950
|
clipId: clip.id,
|
|
@@ -1499,12 +1548,22 @@ var _Transport = class _Transport {
|
|
|
1499
1548
|
this._emit("loop");
|
|
1500
1549
|
}
|
|
1501
1550
|
// --- Tempo ---
|
|
1551
|
+
/** Returns true when the tempo was applied, false when a defaulted (no
|
|
1552
|
+
* atTick) write was refused because the tempo map has multiple entries —
|
|
1553
|
+
* pass an explicit atTick to modify a multi-entry map (#407). */
|
|
1502
1554
|
setTempo(bpm, atTick, options) {
|
|
1555
|
+
if (atTick === void 0 && this._tempoMap.entryCount > 1) {
|
|
1556
|
+
console.warn(
|
|
1557
|
+
"[waveform-playlist] Transport.setTempo: refusing defaulted tick-0 write of " + bpm + " BPM \u2014 the tempo map has " + this._tempoMap.entryCount + " entries. Pass an explicit atTick to modify a multi-entry tempo map."
|
|
1558
|
+
);
|
|
1559
|
+
return false;
|
|
1560
|
+
}
|
|
1503
1561
|
this._tempoMap.setTempo(bpm, atTick, options);
|
|
1504
1562
|
if (this._loopEnabled) {
|
|
1505
1563
|
this._loopStartSeconds = this._tempoMap.ticksToSeconds(this._loopStartTick);
|
|
1506
1564
|
}
|
|
1507
1565
|
this._emit("tempochange", { bpm, atTick: atTick ?? 0 });
|
|
1566
|
+
return true;
|
|
1508
1567
|
}
|
|
1509
1568
|
getTempo(atTick) {
|
|
1510
1569
|
return this._tempoMap.getTempo(atTick);
|
|
@@ -1542,6 +1601,17 @@ var _Transport = class _Transport {
|
|
|
1542
1601
|
}
|
|
1543
1602
|
this._emit("tempochange", { bpm: this._tempoMap.getTempo(), atTick: 0 });
|
|
1544
1603
|
}
|
|
1604
|
+
/** Remove the tempo entry at exactly `atTick` (tick 0 is permanent — a
|
|
1605
|
+
* no-op, like removeMeter's initial entry). Mirrors setTempo's loop-cache
|
|
1606
|
+
* invalidation and event; the emitted bpm is the tempo now in force at
|
|
1607
|
+
* the removed position. */
|
|
1608
|
+
removeTempo(atTick) {
|
|
1609
|
+
this._tempoMap.removeTempo(atTick);
|
|
1610
|
+
if (this._loopEnabled) {
|
|
1611
|
+
this._loopStartSeconds = this._tempoMap.ticksToSeconds(this._loopStartTick);
|
|
1612
|
+
}
|
|
1613
|
+
this._emit("tempochange", { bpm: this._tempoMap.getTempo(atTick), atTick });
|
|
1614
|
+
}
|
|
1545
1615
|
barToTick(bar) {
|
|
1546
1616
|
return this._meterMap.barToTick(bar);
|
|
1547
1617
|
}
|
|
@@ -1914,7 +1984,7 @@ var NativePlayoutAdapter = class {
|
|
|
1914
1984
|
return this._transport.isCountingIn();
|
|
1915
1985
|
}
|
|
1916
1986
|
setTempo(bpm, atTick) {
|
|
1917
|
-
this._transport.setTempo(bpm, atTick !== void 0 ? atTick : void 0);
|
|
1987
|
+
return this._transport.setTempo(bpm, atTick !== void 0 ? atTick : void 0);
|
|
1918
1988
|
}
|
|
1919
1989
|
setMeter(numerator, denominator, atTick) {
|
|
1920
1990
|
this._transport.setMeter(
|