@dawcore/transport 0.0.10 → 0.0.11
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 +10 -5
- package/dist/index.d.ts +10 -5
- package/dist/index.js +44 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +44 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -8
package/dist/index.mjs
CHANGED
|
@@ -224,15 +224,27 @@ function curveNormalizedAt(x, slope) {
|
|
|
224
224
|
const p = Math.max(CURVE_EPSILON, Math.min(1 - CURVE_EPSILON, slope));
|
|
225
225
|
return p * p / (1 - p * 2) * (Math.pow((1 - p) / p, 2 * x) - 1);
|
|
226
226
|
}
|
|
227
|
-
var TempoMap = class {
|
|
227
|
+
var TempoMap = class _TempoMap {
|
|
228
228
|
constructor(ppqn = 960, initialBpm = 120) {
|
|
229
|
+
_TempoMap._validateBpm(initialBpm);
|
|
229
230
|
this._ppqn = ppqn;
|
|
230
231
|
this._entries = [{ tick: 0, bpm: initialBpm, interpolation: "step", secondsAtTick: 0 }];
|
|
231
232
|
}
|
|
233
|
+
/** A non-finite or non-positive BPM silently corrupts the secondsAtTick
|
|
234
|
+
* cache (Infinity, or non-monotonic values that break the binary search
|
|
235
|
+
* in secondsToTicks) — reject it at the boundary instead. */
|
|
236
|
+
static _validateBpm(bpm) {
|
|
237
|
+
if (!Number.isFinite(bpm) || bpm <= 0) {
|
|
238
|
+
throw new Error(
|
|
239
|
+
"[waveform-playlist] TempoMap: bpm must be a finite positive number, got " + bpm
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
232
243
|
getTempo(atTick = 0) {
|
|
233
244
|
return this._getTempoAt(atTick);
|
|
234
245
|
}
|
|
235
246
|
setTempo(bpm, atTick = 0, options) {
|
|
247
|
+
_TempoMap._validateBpm(bpm);
|
|
236
248
|
const interpolation = options?.interpolation ?? "step";
|
|
237
249
|
if (typeof interpolation === "object" && interpolation.type === "curve") {
|
|
238
250
|
const s = interpolation.slope;
|
|
@@ -470,6 +482,7 @@ function isPowerOf2(n) {
|
|
|
470
482
|
var MeterMap = class {
|
|
471
483
|
constructor(ppqn, numerator = 4, denominator = 4) {
|
|
472
484
|
this._ppqn = ppqn;
|
|
485
|
+
this._validateMeter(numerator, denominator);
|
|
473
486
|
this._entries = [{ tick: 0, numerator, denominator, barAtTick: 0 }];
|
|
474
487
|
}
|
|
475
488
|
get ppqn() {
|
|
@@ -763,11 +776,19 @@ var ClipPlayer = class {
|
|
|
763
776
|
const clipTick = clip.startTick !== void 0 ? clip.startTick : this._sampleTimeline.samplesToTicks(clip.startSample);
|
|
764
777
|
if (clipTick < fromTick) continue;
|
|
765
778
|
if (clipTick >= toTick) continue;
|
|
766
|
-
const
|
|
767
|
-
const
|
|
779
|
+
const timelineRate = this._sampleTimeline.sampleRate;
|
|
780
|
+
const bufferRate = clip.audioBuffer.sampleRate;
|
|
781
|
+
const fadeInDurationSamples = clip.fadeIn ? Math.round((clip.fadeIn.duration ?? 0) * timelineRate) : 0;
|
|
782
|
+
const fadeOutDurationSamples = clip.fadeOut ? Math.round((clip.fadeOut.duration ?? 0) * timelineRate) : 0;
|
|
768
783
|
let durationSamples = clip.durationSamples;
|
|
769
|
-
if (this._loopEnabled
|
|
770
|
-
|
|
784
|
+
if (this._loopEnabled) {
|
|
785
|
+
const durationTimelineSamples = Math.round(
|
|
786
|
+
clip.durationSamples / bufferRate * timelineRate
|
|
787
|
+
);
|
|
788
|
+
const allowedTimelineSamples = this._loopEndSamples - clip.startSample;
|
|
789
|
+
if (durationTimelineSamples > allowedTimelineSamples) {
|
|
790
|
+
durationSamples = Math.round(allowedTimelineSamples / timelineRate * bufferRate);
|
|
791
|
+
}
|
|
771
792
|
}
|
|
772
793
|
events.push({
|
|
773
794
|
trackId,
|
|
@@ -793,9 +814,9 @@ var ClipPlayer = class {
|
|
|
793
814
|
);
|
|
794
815
|
return;
|
|
795
816
|
}
|
|
796
|
-
const
|
|
797
|
-
const offsetSeconds = event.offsetSamples /
|
|
798
|
-
const durationSeconds = event.durationSamples /
|
|
817
|
+
const bufferRate = event.audioBuffer.sampleRate;
|
|
818
|
+
const offsetSeconds = event.offsetSamples / bufferRate;
|
|
819
|
+
const durationSeconds = event.durationSamples / bufferRate;
|
|
799
820
|
if (offsetSeconds >= event.audioBuffer.duration) {
|
|
800
821
|
console.warn(
|
|
801
822
|
"[waveform-playlist] ClipPlayer.consume: offset (" + offsetSeconds + "s) exceeds audioBuffer.duration (" + event.audioBuffer.duration + 's) for clipId "' + event.clipId + '" \u2014 clip will not play'
|
|
@@ -808,8 +829,9 @@ var ClipPlayer = class {
|
|
|
808
829
|
const when = this._toAudioTime(transportSeconds);
|
|
809
830
|
const gainNode = this._audioContext.createGain();
|
|
810
831
|
gainNode.gain.value = event.gain;
|
|
811
|
-
|
|
812
|
-
let
|
|
832
|
+
const timelineRate = this._sampleTimeline.sampleRate;
|
|
833
|
+
let fadeIn = event.fadeInDurationSamples / timelineRate;
|
|
834
|
+
let fadeOut = event.fadeOutDurationSamples / timelineRate;
|
|
813
835
|
if (fadeIn + fadeOut > durationSeconds) {
|
|
814
836
|
const ratio = durationSeconds / (fadeIn + fadeOut);
|
|
815
837
|
fadeIn *= ratio;
|
|
@@ -849,16 +871,21 @@ var ClipPlayer = class {
|
|
|
849
871
|
if (!clip.audioBuffer) continue;
|
|
850
872
|
const clipTick = clip.startTick !== void 0 ? clip.startTick : this._sampleTimeline.samplesToTicks(clip.startSample);
|
|
851
873
|
if (clipTick >= newTick) continue;
|
|
852
|
-
const
|
|
874
|
+
const timelineRate = this._sampleTimeline.sampleRate;
|
|
875
|
+
const bufferRate = clip.audioBuffer.sampleRate;
|
|
876
|
+
const bufToTimeline = (n) => Math.round(n / bufferRate * timelineRate);
|
|
877
|
+
const timelineToBuf = (n) => Math.round(n / timelineRate * bufferRate);
|
|
878
|
+
const clipEndSample = clip.startSample + bufToTimeline(clip.durationSamples);
|
|
853
879
|
if (clipEndSample <= newSample) continue;
|
|
854
880
|
const offsetIntoClipSamples = newSample - clip.startSample;
|
|
855
|
-
const offsetSamples = clip.offsetSamples + offsetIntoClipSamples;
|
|
856
|
-
let
|
|
857
|
-
if (this._loopEnabled && newSample +
|
|
858
|
-
|
|
881
|
+
const offsetSamples = clip.offsetSamples + timelineToBuf(offsetIntoClipSamples);
|
|
882
|
+
let remainingTimelineSamples = clipEndSample - newSample;
|
|
883
|
+
if (this._loopEnabled && newSample + remainingTimelineSamples > this._loopEndSamples) {
|
|
884
|
+
remainingTimelineSamples = this._loopEndSamples - newSample;
|
|
859
885
|
}
|
|
860
|
-
if (
|
|
861
|
-
const
|
|
886
|
+
if (remainingTimelineSamples <= 0) continue;
|
|
887
|
+
const durationSamples = timelineToBuf(remainingTimelineSamples);
|
|
888
|
+
const fadeOutDurationSamples = clip.fadeOut ? Math.round((clip.fadeOut.duration ?? 0) * timelineRate) : 0;
|
|
862
889
|
this.consume({
|
|
863
890
|
trackId,
|
|
864
891
|
clipId: clip.id,
|