@waveform-playlist/playout 11.3.0 → 11.3.1
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 +2 -4
- package/dist/index.d.ts +2 -4
- package/dist/index.js +33 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +20 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -20,6 +20,8 @@ interface ToneTrackOptions {
|
|
|
20
20
|
track: Track;
|
|
21
21
|
effects?: TrackEffectsFunction;
|
|
22
22
|
destination?: ToneAudioNode;
|
|
23
|
+
/** Max channel count across clips — sets Panner channelCount. Default: 1 */
|
|
24
|
+
channelCount?: number;
|
|
23
25
|
}
|
|
24
26
|
/** Per-clip scheduling info and audio nodes */
|
|
25
27
|
interface ScheduledClip {
|
|
@@ -98,7 +100,6 @@ declare class ToneTrack {
|
|
|
98
100
|
* Called on pause/stop to prevent stale fade envelopes.
|
|
99
101
|
*/
|
|
100
102
|
cancelFades(): void;
|
|
101
|
-
private gainToDb;
|
|
102
103
|
setVolume(gain: number): void;
|
|
103
104
|
setPan(pan: number): void;
|
|
104
105
|
setMute(muted: boolean): void;
|
|
@@ -169,7 +170,6 @@ declare class MidiToneTrack implements PlayableTrack {
|
|
|
169
170
|
* Routes per-note: channel 9 → percussion synths, others → melodic PolySynth.
|
|
170
171
|
*/
|
|
171
172
|
private triggerNote;
|
|
172
|
-
private gainToDb;
|
|
173
173
|
/**
|
|
174
174
|
* No-op for MIDI — schedule guard is for AudioBufferSourceNode ghost tick prevention.
|
|
175
175
|
* Tone.Part handles its own scheduling relative to Transport.
|
|
@@ -390,7 +390,6 @@ declare class SoundFontToneTrack implements PlayableTrack {
|
|
|
390
390
|
* Per-note routing: channel 9 → bank 128 (drums), others → bank 0 with programNumber.
|
|
391
391
|
*/
|
|
392
392
|
private triggerNote;
|
|
393
|
-
private gainToDb;
|
|
394
393
|
/**
|
|
395
394
|
* No-op — Tone.Part handles scheduling internally, no ghost tick guard needed.
|
|
396
395
|
*/
|
|
@@ -438,7 +437,6 @@ declare class TonePlayout {
|
|
|
438
437
|
private _loopStart;
|
|
439
438
|
private _loopEnd;
|
|
440
439
|
constructor(options?: TonePlayoutOptions);
|
|
441
|
-
private gainToDb;
|
|
442
440
|
private clearCompletionEvent;
|
|
443
441
|
init(): Promise<void>;
|
|
444
442
|
addTrack(trackOptions: ToneTrackOptions): ToneTrack;
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,8 @@ interface ToneTrackOptions {
|
|
|
20
20
|
track: Track;
|
|
21
21
|
effects?: TrackEffectsFunction;
|
|
22
22
|
destination?: ToneAudioNode;
|
|
23
|
+
/** Max channel count across clips — sets Panner channelCount. Default: 1 */
|
|
24
|
+
channelCount?: number;
|
|
23
25
|
}
|
|
24
26
|
/** Per-clip scheduling info and audio nodes */
|
|
25
27
|
interface ScheduledClip {
|
|
@@ -98,7 +100,6 @@ declare class ToneTrack {
|
|
|
98
100
|
* Called on pause/stop to prevent stale fade envelopes.
|
|
99
101
|
*/
|
|
100
102
|
cancelFades(): void;
|
|
101
|
-
private gainToDb;
|
|
102
103
|
setVolume(gain: number): void;
|
|
103
104
|
setPan(pan: number): void;
|
|
104
105
|
setMute(muted: boolean): void;
|
|
@@ -169,7 +170,6 @@ declare class MidiToneTrack implements PlayableTrack {
|
|
|
169
170
|
* Routes per-note: channel 9 → percussion synths, others → melodic PolySynth.
|
|
170
171
|
*/
|
|
171
172
|
private triggerNote;
|
|
172
|
-
private gainToDb;
|
|
173
173
|
/**
|
|
174
174
|
* No-op for MIDI — schedule guard is for AudioBufferSourceNode ghost tick prevention.
|
|
175
175
|
* Tone.Part handles its own scheduling relative to Transport.
|
|
@@ -390,7 +390,6 @@ declare class SoundFontToneTrack implements PlayableTrack {
|
|
|
390
390
|
* Per-note routing: channel 9 → bank 128 (drums), others → bank 0 with programNumber.
|
|
391
391
|
*/
|
|
392
392
|
private triggerNote;
|
|
393
|
-
private gainToDb;
|
|
394
393
|
/**
|
|
395
394
|
* No-op — Tone.Part handles scheduling internally, no ghost tick guard needed.
|
|
396
395
|
*/
|
|
@@ -438,7 +437,6 @@ declare class TonePlayout {
|
|
|
438
437
|
private _loopStart;
|
|
439
438
|
private _loopEnd;
|
|
440
439
|
constructor(options?: TonePlayoutOptions);
|
|
441
|
-
private gainToDb;
|
|
442
440
|
private clearCompletionEvent;
|
|
443
441
|
init(): Promise<void>;
|
|
444
442
|
addTrack(trackOptions: ToneTrackOptions): ToneTrack;
|
package/dist/index.js
CHANGED
|
@@ -49,9 +49,11 @@ module.exports = __toCommonJS(index_exports);
|
|
|
49
49
|
|
|
50
50
|
// src/TonePlayout.ts
|
|
51
51
|
var import_tone4 = require("tone");
|
|
52
|
+
var import_core5 = require("@waveform-playlist/core");
|
|
52
53
|
|
|
53
54
|
// src/ToneTrack.ts
|
|
54
55
|
var import_tone = require("tone");
|
|
56
|
+
var import_core2 = require("@waveform-playlist/core");
|
|
55
57
|
|
|
56
58
|
// src/fades.ts
|
|
57
59
|
var import_core = require("@waveform-playlist/core");
|
|
@@ -79,8 +81,11 @@ var ToneTrack = class {
|
|
|
79
81
|
// clips at/after this offset.
|
|
80
82
|
this._scheduleGuardOffset = 0;
|
|
81
83
|
this.track = options.track;
|
|
82
|
-
this.volumeNode = new import_tone.Volume(
|
|
83
|
-
this.panNode = new import_tone.Panner({
|
|
84
|
+
this.volumeNode = new import_tone.Volume((0, import_core2.gainToDb)(options.track.gain));
|
|
85
|
+
this.panNode = new import_tone.Panner({
|
|
86
|
+
pan: options.track.stereoPan,
|
|
87
|
+
channelCount: options.channelCount ?? 1
|
|
88
|
+
});
|
|
84
89
|
this.muteGain = new import_tone.Gain(options.track.muted ? 0 : 1);
|
|
85
90
|
this.volumeNode.chain(this.panNode, this.muteGain);
|
|
86
91
|
const destination = options.destination || (0, import_tone.getDestination)();
|
|
@@ -412,12 +417,9 @@ var ToneTrack = class {
|
|
|
412
417
|
audioParam.setValueAtTime(clipInfo.gain, 0);
|
|
413
418
|
});
|
|
414
419
|
}
|
|
415
|
-
gainToDb(gain) {
|
|
416
|
-
return 20 * Math.log10(gain);
|
|
417
|
-
}
|
|
418
420
|
setVolume(gain) {
|
|
419
421
|
this.track.gain = gain;
|
|
420
|
-
this.volumeNode.volume.value =
|
|
422
|
+
this.volumeNode.volume.value = (0, import_core2.gainToDb)(gain);
|
|
421
423
|
}
|
|
422
424
|
setPan(pan) {
|
|
423
425
|
this.track.stereoPan = pan;
|
|
@@ -498,6 +500,7 @@ var ToneTrack = class {
|
|
|
498
500
|
|
|
499
501
|
// src/MidiToneTrack.ts
|
|
500
502
|
var import_tone2 = require("tone");
|
|
503
|
+
var import_core3 = require("@waveform-playlist/core");
|
|
501
504
|
function getDrumCategory(midiNote) {
|
|
502
505
|
if (midiNote === 35 || midiNote === 36) return "kick";
|
|
503
506
|
if (midiNote >= 37 && midiNote <= 40) return "snare";
|
|
@@ -508,7 +511,7 @@ function getDrumCategory(midiNote) {
|
|
|
508
511
|
var MidiToneTrack = class {
|
|
509
512
|
constructor(options) {
|
|
510
513
|
this.track = options.track;
|
|
511
|
-
this.volumeNode = new import_tone2.Volume(
|
|
514
|
+
this.volumeNode = new import_tone2.Volume((0, import_core3.gainToDb)(options.track.gain));
|
|
512
515
|
this.panNode = new import_tone2.Panner(options.track.stereoPan);
|
|
513
516
|
this.muteGain = new import_tone2.Gain(options.track.muted ? 0 : 1);
|
|
514
517
|
this.volumeNode.chain(this.panNode, this.muteGain);
|
|
@@ -641,9 +644,6 @@ var MidiToneTrack = class {
|
|
|
641
644
|
this.synth.triggerAttackRelease(noteName, duration, time, velocity);
|
|
642
645
|
}
|
|
643
646
|
}
|
|
644
|
-
gainToDb(gain) {
|
|
645
|
-
return 20 * Math.log10(gain);
|
|
646
|
-
}
|
|
647
647
|
/**
|
|
648
648
|
* No-op for MIDI — schedule guard is for AudioBufferSourceNode ghost tick prevention.
|
|
649
649
|
* Tone.Part handles its own scheduling relative to Transport.
|
|
@@ -711,7 +711,7 @@ var MidiToneTrack = class {
|
|
|
711
711
|
}
|
|
712
712
|
setVolume(gain) {
|
|
713
713
|
this.track.gain = gain;
|
|
714
|
-
this.volumeNode.volume.value =
|
|
714
|
+
this.volumeNode.volume.value = (0, import_core3.gainToDb)(gain);
|
|
715
715
|
}
|
|
716
716
|
setPan(pan) {
|
|
717
717
|
this.track.stereoPan = pan;
|
|
@@ -800,6 +800,7 @@ var MidiToneTrack = class {
|
|
|
800
800
|
|
|
801
801
|
// src/SoundFontToneTrack.ts
|
|
802
802
|
var import_tone3 = require("tone");
|
|
803
|
+
var import_core4 = require("@waveform-playlist/core");
|
|
803
804
|
var _SoundFontToneTrack = class _SoundFontToneTrack {
|
|
804
805
|
constructor(options) {
|
|
805
806
|
this.activeSources = /* @__PURE__ */ new Set();
|
|
@@ -807,7 +808,7 @@ var _SoundFontToneTrack = class _SoundFontToneTrack {
|
|
|
807
808
|
this.soundFontCache = options.soundFontCache;
|
|
808
809
|
this.programNumber = options.programNumber ?? 0;
|
|
809
810
|
this.bankNumber = options.isPercussion ? 128 : 0;
|
|
810
|
-
this.volumeNode = new import_tone3.Volume(
|
|
811
|
+
this.volumeNode = new import_tone3.Volume((0, import_core4.gainToDb)(options.track.gain));
|
|
811
812
|
this.panNode = new import_tone3.Panner(options.track.stereoPan);
|
|
812
813
|
this.muteGain = new import_tone3.Gain(options.track.muted ? 0 : 1);
|
|
813
814
|
this.volumeNode.chain(this.panNode, this.muteGain);
|
|
@@ -907,9 +908,6 @@ var _SoundFontToneTrack = class _SoundFontToneTrack {
|
|
|
907
908
|
source.start(time);
|
|
908
909
|
source.stop(time + effectiveDuration + releaseVolEnv);
|
|
909
910
|
}
|
|
910
|
-
gainToDb(gain) {
|
|
911
|
-
return 20 * Math.log10(gain);
|
|
912
|
-
}
|
|
913
911
|
/**
|
|
914
912
|
* No-op — Tone.Part handles scheduling internally, no ghost tick guard needed.
|
|
915
913
|
*/
|
|
@@ -969,7 +967,7 @@ var _SoundFontToneTrack = class _SoundFontToneTrack {
|
|
|
969
967
|
}
|
|
970
968
|
setVolume(gain) {
|
|
971
969
|
this.track.gain = gain;
|
|
972
|
-
this.volumeNode.volume.value =
|
|
970
|
+
this.volumeNode.volume.value = (0, import_core4.gainToDb)(gain);
|
|
973
971
|
}
|
|
974
972
|
setPan(pan) {
|
|
975
973
|
this.track.stereoPan = pan;
|
|
@@ -1063,7 +1061,7 @@ var TonePlayout = class {
|
|
|
1063
1061
|
this._loopEnabled = false;
|
|
1064
1062
|
this._loopStart = 0;
|
|
1065
1063
|
this._loopEnd = 0;
|
|
1066
|
-
this.masterVolume = new import_tone4.Volume(
|
|
1064
|
+
this.masterVolume = new import_tone4.Volume((0, import_core5.gainToDb)(options.masterGain ?? 1));
|
|
1067
1065
|
if (options.effects) {
|
|
1068
1066
|
const cleanup = options.effects(this.masterVolume, (0, import_tone4.getDestination)(), false);
|
|
1069
1067
|
if (cleanup) {
|
|
@@ -1079,9 +1077,6 @@ var TonePlayout = class {
|
|
|
1079
1077
|
});
|
|
1080
1078
|
}
|
|
1081
1079
|
}
|
|
1082
|
-
gainToDb(gain) {
|
|
1083
|
-
return 20 * Math.log10(gain);
|
|
1084
|
-
}
|
|
1085
1080
|
clearCompletionEvent() {
|
|
1086
1081
|
if (this._completionEventId !== null) {
|
|
1087
1082
|
try {
|
|
@@ -1276,7 +1271,7 @@ var TonePlayout = class {
|
|
|
1276
1271
|
this.clearCompletionEvent();
|
|
1277
1272
|
}
|
|
1278
1273
|
setMasterGain(gain) {
|
|
1279
|
-
this.masterVolume.volume.value =
|
|
1274
|
+
this.masterVolume.volume.value = (0, import_core5.gainToDb)(gain);
|
|
1280
1275
|
}
|
|
1281
1276
|
setSolo(trackId, soloed) {
|
|
1282
1277
|
const track = this.tracks.get(trackId);
|
|
@@ -1630,7 +1625,7 @@ function hasMediaStreamSource(stream) {
|
|
|
1630
1625
|
}
|
|
1631
1626
|
|
|
1632
1627
|
// src/TonePlayoutAdapter.ts
|
|
1633
|
-
var
|
|
1628
|
+
var import_core6 = require("@waveform-playlist/core");
|
|
1634
1629
|
var import_tone7 = require("tone");
|
|
1635
1630
|
function createToneAdapter(options) {
|
|
1636
1631
|
let playout = null;
|
|
@@ -1645,8 +1640,8 @@ function createToneAdapter(options) {
|
|
|
1645
1640
|
const audioClips = track.clips.filter((c) => c.audioBuffer && !c.midiNotes);
|
|
1646
1641
|
const midiClips = track.clips.filter((c) => c.midiNotes && c.midiNotes.length > 0);
|
|
1647
1642
|
if (audioClips.length > 0) {
|
|
1648
|
-
const startTime = Math.min(...audioClips.map(
|
|
1649
|
-
const endTime = Math.max(...audioClips.map(
|
|
1643
|
+
const startTime = Math.min(...audioClips.map(import_core6.clipStartTime));
|
|
1644
|
+
const endTime = Math.max(...audioClips.map(import_core6.clipEndTime));
|
|
1650
1645
|
const trackObj = {
|
|
1651
1646
|
id: track.id,
|
|
1652
1647
|
name: track.name,
|
|
@@ -1659,9 +1654,9 @@ function createToneAdapter(options) {
|
|
|
1659
1654
|
};
|
|
1660
1655
|
const clipInfos = audioClips.map((clip) => ({
|
|
1661
1656
|
buffer: clip.audioBuffer,
|
|
1662
|
-
startTime: (0,
|
|
1663
|
-
duration: (0,
|
|
1664
|
-
offset: (0,
|
|
1657
|
+
startTime: (0, import_core6.clipStartTime)(clip) - startTime,
|
|
1658
|
+
duration: (0, import_core6.clipDurationTime)(clip),
|
|
1659
|
+
offset: (0, import_core6.clipOffsetTime)(clip),
|
|
1665
1660
|
fadeIn: clip.fadeIn,
|
|
1666
1661
|
fadeOut: clip.fadeOut,
|
|
1667
1662
|
gain: clip.gain
|
|
@@ -1669,12 +1664,13 @@ function createToneAdapter(options) {
|
|
|
1669
1664
|
p.addTrack({
|
|
1670
1665
|
clips: clipInfos,
|
|
1671
1666
|
track: trackObj,
|
|
1672
|
-
effects: track.effects
|
|
1667
|
+
effects: track.effects,
|
|
1668
|
+
channelCount: (0, import_core6.trackChannelCount)(track)
|
|
1673
1669
|
});
|
|
1674
1670
|
}
|
|
1675
1671
|
if (midiClips.length > 0) {
|
|
1676
|
-
const startTime = Math.min(...midiClips.map(
|
|
1677
|
-
const endTime = Math.max(...midiClips.map(
|
|
1672
|
+
const startTime = Math.min(...midiClips.map(import_core6.clipStartTime));
|
|
1673
|
+
const endTime = Math.max(...midiClips.map(import_core6.clipEndTime));
|
|
1678
1674
|
const trackId = audioClips.length > 0 ? `${track.id}:midi` : track.id;
|
|
1679
1675
|
const trackObj = {
|
|
1680
1676
|
id: trackId,
|
|
@@ -1688,9 +1684,9 @@ function createToneAdapter(options) {
|
|
|
1688
1684
|
};
|
|
1689
1685
|
const midiClipInfos = midiClips.map((clip) => ({
|
|
1690
1686
|
notes: clip.midiNotes,
|
|
1691
|
-
startTime: (0,
|
|
1692
|
-
duration: (0,
|
|
1693
|
-
offset: (0,
|
|
1687
|
+
startTime: (0, import_core6.clipStartTime)(clip) - startTime,
|
|
1688
|
+
duration: (0, import_core6.clipDurationTime)(clip),
|
|
1689
|
+
offset: (0, import_core6.clipOffsetTime)(clip)
|
|
1694
1690
|
}));
|
|
1695
1691
|
if (options?.soundFontCache?.isLoaded) {
|
|
1696
1692
|
const firstClip = midiClips[0];
|
|
@@ -1796,12 +1792,12 @@ function createToneAdapter(options) {
|
|
|
1796
1792
|
if (!playout) return;
|
|
1797
1793
|
const audioClips = track.clips.filter((c) => c.audioBuffer && !c.midiNotes);
|
|
1798
1794
|
if (audioClips.length > 0) {
|
|
1799
|
-
const startTime = Math.min(...audioClips.map(
|
|
1795
|
+
const startTime = Math.min(...audioClips.map(import_core6.clipStartTime));
|
|
1800
1796
|
const clipInfos = audioClips.map((clip) => ({
|
|
1801
1797
|
buffer: clip.audioBuffer,
|
|
1802
|
-
startTime: (0,
|
|
1803
|
-
duration: (0,
|
|
1804
|
-
offset: (0,
|
|
1798
|
+
startTime: (0, import_core6.clipStartTime)(clip) - startTime,
|
|
1799
|
+
duration: (0, import_core6.clipDurationTime)(clip),
|
|
1800
|
+
offset: (0, import_core6.clipOffsetTime)(clip),
|
|
1805
1801
|
fadeIn: clip.fadeIn,
|
|
1806
1802
|
fadeOut: clip.fadeOut,
|
|
1807
1803
|
gain: clip.gain
|