smplr 0.22.0 → 0.24.0

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 CHANGED
@@ -35,6 +35,23 @@ declare class Channel {
35
35
  disconnect(): void;
36
36
  }
37
37
 
38
+ /**
39
+ * Wrap a class so it is callable both as `X(...)` (preferred) and as
40
+ * `new X(...)` (kept for compatibility with pre-1.0 examples). Returns
41
+ * a value with both call and construct signatures.
42
+ *
43
+ * Used by the auxiliary exports (`Sequencer`, `Reverb`, `CacheStorage`,
44
+ * `Scheduler`, `SampleLoader`) to match the dual signature already shipped
45
+ * by `InstrumentFactory`. Instrument factories themselves use the richer
46
+ * `Instrument()` builder instead, which owns option-splitting and the
47
+ * ready-promise lifecycle.
48
+ */
49
+ type Constructable<A extends unknown[], R> = {
50
+ (...args: A): R;
51
+ /** @deprecated Call as a function: `X(...)` instead of `new X(...)`. */
52
+ new (...args: A): R;
53
+ };
54
+
38
55
  type StorageResponse = {
39
56
  readonly status: number;
40
57
  arrayBuffer(): Promise<ArrayBuffer>;
@@ -45,11 +62,13 @@ type Storage = {
45
62
  fetch: (url: string) => Promise<StorageResponse>;
46
63
  };
47
64
  declare const HttpStorage: Storage;
48
- declare class CacheStorage implements Storage {
65
+ declare class CacheStorageImpl implements Storage {
49
66
  #private;
50
67
  constructor(name?: string);
51
68
  fetch(url: string): Promise<StorageResponse>;
52
69
  }
70
+ declare const CacheStorage: Constructable<[name?: string | undefined], CacheStorageImpl>;
71
+ type CacheStorage = ReturnType<typeof CacheStorage>;
53
72
 
54
73
  /**
55
74
  * Inheritable playback parameters. Can appear at global defaults, group, or region level.
@@ -114,7 +133,7 @@ type SmplrSamples = {
114
133
  /**
115
134
  * The top-level smplr.json descriptor. Passed to the Smplr constructor.
116
135
  */
117
- type SmplrJson = {
136
+ type SmplrPreset = {
118
137
  /** Schema version. Omit for the current format. Reserved for future migrations. */
119
138
  smplr?: "1.0";
120
139
  meta?: {
@@ -190,13 +209,13 @@ type VoiceParams = {
190
209
  };
191
210
 
192
211
  /**
193
- * Loads and caches AudioBuffers for all samples referenced in a SmplrJson.
212
+ * Loads and caches AudioBuffers for all samples referenced in a SmplrPreset.
194
213
  *
195
214
  * The cache is keyed by resolved URL, so the same audio file is never fetched
196
215
  * or decoded twice. Multiple Smplr instances can share one SampleLoader by
197
216
  * passing it via SmplrOptions.loader.
198
217
  */
199
- declare class SampleLoader {
218
+ declare class SampleLoaderImpl {
200
219
  #private;
201
220
  constructor(context: BaseAudioContext, options?: {
202
221
  storage?: Storage;
@@ -209,11 +228,15 @@ declare class SampleLoader {
209
228
  * - `buffers` in options: pre-loaded buffers — skips fetch for these names.
210
229
  * - All samples load in parallel. Failed samples are silently omitted.
211
230
  */
212
- load(json: SmplrJson, onProgressOrOptions?: ((loaded: number, total: number) => void) | {
231
+ load(json: SmplrPreset, onProgressOrOptions?: ((loaded: number, total: number) => void) | {
213
232
  buffers?: Map<string, AudioBuffer>;
214
233
  onProgress?: (loaded: number, total: number) => void;
215
234
  }): Promise<Map<string, AudioBuffer>>;
216
235
  }
236
+ declare const SampleLoader: Constructable<[context: BaseAudioContext, options?: {
237
+ storage?: Storage;
238
+ } | undefined], SampleLoaderImpl>;
239
+ type SampleLoader = ReturnType<typeof SampleLoader>;
217
240
 
218
241
  /**
219
242
  * Standalone scheduler. Dispatches NoteEvents immediately when they fall within the
@@ -221,7 +244,7 @@ declare class SampleLoader {
221
244
  *
222
245
  * Multiple Smplr instances can share a single Scheduler for coordinated timing.
223
246
  */
224
- declare class Scheduler {
247
+ declare class SchedulerImpl {
225
248
  #private;
226
249
  constructor(context: BaseAudioContext, options?: {
227
250
  lookaheadMs?: number;
@@ -242,6 +265,11 @@ declare class Scheduler {
242
265
  */
243
266
  stop(): void;
244
267
  }
268
+ declare const Scheduler: Constructable<[context: BaseAudioContext, options?: {
269
+ lookaheadMs?: number;
270
+ intervalMs?: number;
271
+ } | undefined], SchedulerImpl>;
272
+ type Scheduler = ReturnType<typeof Scheduler>;
245
273
 
246
274
  type SmplrOptions = {
247
275
  /** Custom storage backend for sample fetching (e.g. CacheStorage). */
@@ -299,6 +327,19 @@ interface Smplr {
299
327
  * not been set (matches MIDI's "undefined controller defaults to 0" convention).
300
328
  */
301
329
  getCC(cc: number): number;
330
+ /**
331
+ * Set the cents detune applied to every future note. Mutates the instrument's
332
+ * playback defaults in place; takes effect on notes scheduled after the call.
333
+ * In-flight notes are unaffected.
334
+ */
335
+ setDetune(cents: number): void;
336
+ /**
337
+ * Set whether every future note plays its sample reversed. Mutates the
338
+ * instrument's playback defaults in place. The reversed-buffer cache is
339
+ * populated lazily on demand; no cache invalidation is needed in either
340
+ * direction.
341
+ */
342
+ setReverse(reverse: boolean): void;
302
343
  /**
303
344
  * Stop all voices, dispose the output channel, and stop the scheduler.
304
345
  * The instance must not be used after this call — subsequent `start`/`stop`/
@@ -324,7 +365,7 @@ interface PluginSmplr extends Smplr {
324
365
  *
325
366
  * Resolves when all samples are ready.
326
367
  */
327
- loadInstrument(json: SmplrJson, buffers?: Map<string, AudioBuffer>): Promise<void>;
368
+ loadInstrument(json: SmplrPreset, buffers?: Map<string, AudioBuffer>): Promise<void>;
328
369
  }
329
370
  /**
330
371
  * Permitted return shapes for an {@link SmplrPlugin}:
@@ -429,13 +470,13 @@ declare const DrumMachine: InstrumentFactory<Partial<DrumMachineConfig & {
429
470
  /** Instance type returned by the {@link DrumMachine} factory. */
430
471
  type DrumMachine = ReturnType<typeof DrumMachine>;
431
472
  /**
432
- * Convert a DrumMachineInstrument to a SmplrJson descriptor.
473
+ * Convert a DrumMachineInstrument to a SmplrPreset descriptor.
433
474
  *
434
475
  * Each sample gets a sequential MIDI number starting at 36 (GM drum map base).
435
476
  * Aliases are created for both the full sample name ("kick/1") and the group
436
477
  * name ("kick") so both forms work with Smplr.start({ note: "kick" }).
437
478
  */
438
- declare function drumMachineToSmplrJson(instrument: DrumMachineInstrument): SmplrJson;
479
+ declare function drumMachineToPreset(instrument: DrumMachineInstrument): SmplrPreset;
439
480
 
440
481
  /**
441
482
  * The result of an offline render. Provides the raw AudioBuffer and
@@ -534,6 +575,19 @@ type SequencerNote = {
534
575
  velocity?: number;
535
576
  /** Probability (0–100) that this note fires on each pass. Default 100 (always). */
536
577
  chance?: number;
578
+ /**
579
+ * Expand into N evenly-spaced sub-notes over `duration`. Requires `duration`;
580
+ * silently ignored if `duration` is omitted. Default 1 (no ratchet). When >1,
581
+ * each sub-note's `noteId` is suffixed with `#0`, `#1`, … so individual
582
+ * ratchet voices can be stopped via `stopNote("id#0")`.
583
+ */
584
+ ratchet?: number;
585
+ /**
586
+ * Multiplicative velocity decay per ratchet step: each step's velocity is
587
+ * scaled by `(1 - decay) ** step_index`. 0 = constant, 1 = silence by last
588
+ * step. Default 0.
589
+ */
590
+ ratchetVelocityDecay?: number;
537
591
  };
538
592
  /**
539
593
  * Any instrument the Sequencer can drive.
@@ -558,10 +612,20 @@ type SequencerNoteEvent = {
558
612
  noteIndex: number;
559
613
  note: SequencerNote;
560
614
  };
615
+ /**
616
+ * Time signature as a `{ numerator, denominator }` pair (e.g. `{ numerator: 7, denominator: 8 }`
617
+ * for 7/8). The numerator counts beats per bar; the denominator defines the
618
+ * note value of one beat (4 = quarter note, 8 = eighth note, …).
619
+ */
620
+ type TimeSignature = {
621
+ numerator: number;
622
+ denominator: number;
623
+ };
561
624
  type SequencerOptions = {
562
625
  bpm?: number;
563
626
  ppq?: number;
564
- timeSignature?: number;
627
+ /** Time signature. Accepts `4` (interpreted as 4/4) or `{ numerator, denominator }`. */
628
+ timeSignature?: number | TimeSignature;
565
629
  loop?: boolean;
566
630
  loopStart?: string | number;
567
631
  loopEnd?: string | number;
@@ -577,35 +641,128 @@ type SequencerOptions = {
577
641
  /** Emit a "step" event at this interval. Accepts musical notation or ticks: "16n", "8n", ticks, etc. */
578
642
  stepSize?: string | number;
579
643
  };
580
- declare class Sequencer {
644
+ /**
645
+ * Per-track options accepted by {@link Sequencer.addTrack} and
646
+ * {@link Sequencer.setPatterns}.
647
+ */
648
+ type AddTrackOptions = {
649
+ /**
650
+ * Stable track id. Required to address this track via
651
+ * {@link Sequencer.setTrackVolume}, {@link Sequencer.muteTrack},
652
+ * {@link Sequencer.soloTrack}, etc.
653
+ */
654
+ id?: string;
655
+ /** Per-track humanize. Overrides {@link SequencerOptions.humanize} when set. */
656
+ humanize?: {
657
+ timingMs?: number;
658
+ velocity?: number;
659
+ };
660
+ /** Multiplicative velocity scalar in [0, 1+]. Default 1. */
661
+ volume?: number;
662
+ /** When true, this track does not dispatch any notes. Default false. */
663
+ muted?: boolean;
664
+ /**
665
+ * When true, only soloed tracks dispatch notes. If any track in the pattern
666
+ * is soloed, every non-soloed track is silenced. Default false.
667
+ */
668
+ solo?: boolean;
669
+ };
670
+ /**
671
+ * Public shape for one pattern accepted by {@link Sequencer.setPatterns}.
672
+ */
673
+ type PatternInput = {
674
+ tracks: Array<{
675
+ instrument: SequencerInstrument;
676
+ notes: SequencerNote[];
677
+ } & AddTrackOptions>;
678
+ /**
679
+ * Pattern length override in ticks or musical time. Defaults to the longest
680
+ * track in this pattern.
681
+ */
682
+ loopEnd?: string | number;
683
+ };
684
+ declare class SequencerImpl {
581
685
  private readonly _context;
582
686
  private readonly _clock;
583
687
  private readonly _ppq;
584
688
  private _timeSignature;
585
689
  private _stepTicks;
586
- private _tracks;
690
+ /**
691
+ * Patterns. Always at least one (the implicit default pattern). Replaced
692
+ * atomically by {@link setPatterns}.
693
+ */
694
+ private _patterns;
695
+ /** Indices into {@link _patterns} defining playback order. */
696
+ private _chainOrder;
697
+ /** Current position within {@link _chainOrder}. */
698
+ private _chainIndex;
699
+ /**
700
+ * True once {@link setPatterns} has been called. After this point,
701
+ * `addTrack` / `removeTrack` / `clearTracks` throw because the chain shape
702
+ * is owned by the patterns array.
703
+ */
704
+ private _patternsExplicit;
587
705
  private _repeatEvents;
588
706
  private _listeners;
589
707
  private _loop;
590
708
  private _loopStartTick;
591
- /** null = default to _totalTicks */
592
- private _loopEndOverride;
593
709
  private _lookaheadSec;
594
710
  private _intervalMs;
595
711
  private _humanize;
596
712
  private _intervalId;
597
713
  /** AudioContext time high-water mark: notes up to here have been scheduled. */
598
714
  private _scheduledThrough;
599
- /** Computed from track notes; the tick where the last note ends. */
600
- private _totalTicks;
601
715
  /** Guards against scheduling the auto-stop setTimeout more than once. */
602
716
  private _endScheduled;
603
717
  /** Active voices keyed by noteId, so individual notes can be stopped. */
604
718
  private _activeVoices;
605
719
  constructor(context: BaseAudioContext, options?: SequencerOptions);
606
- addTrack(instrument: SequencerInstrument, notes: SequencerNote[]): this;
720
+ /**
721
+ * Add a track to the (implicit, default) pattern. Throws after
722
+ * {@link setPatterns} has been called — use {@link setPatterns} to mutate
723
+ * the chain.
724
+ */
725
+ addTrack(instrument: SequencerInstrument, notes: SequencerNote[], options?: AddTrackOptions): this;
607
726
  removeTrack(instrument: SequencerInstrument): this;
608
727
  clearTracks(): this;
728
+ /**
729
+ * Replace the sequencer's patterns. Each pattern owns its own tracks and
730
+ * optional `loopEnd`. After this call, `addTrack` / `removeTrack` /
731
+ * `clearTracks` throw — the chain is owned by the patterns array.
732
+ *
733
+ * `chainOrder` is reset to `[0, 1, …, patterns.length - 1]`.
734
+ */
735
+ setPatterns(patterns: PatternInput[]): this;
736
+ /** Current chain order: indices into the patterns array, in playback order. */
737
+ get chainOrder(): number[];
738
+ /**
739
+ * Set a new chain order. Each entry must be a valid pattern index.
740
+ * Throws if `order` is empty or contains an out-of-range index.
741
+ */
742
+ set chainOrder(order: number[]);
743
+ /**
744
+ * Set a track's multiplicative volume scalar. Affects every note dispatched
745
+ * by the track from the next flush onwards. No-op if no track has the
746
+ * given id. Search is scoped to the currently-playing pattern.
747
+ */
748
+ setTrackVolume(id: string, volume: number): this;
749
+ /** Mute a track by id. No-op if no track has the given id. */
750
+ muteTrack(id: string): this;
751
+ /** Unmute a track by id. No-op if no track has the given id. */
752
+ unmuteTrack(id: string): this;
753
+ /** Solo a track by id. While any track is soloed, non-soloed tracks are silenced. */
754
+ soloTrack(id: string): this;
755
+ /** Remove the solo flag from a track. */
756
+ unsoloTrack(id: string): this;
757
+ /**
758
+ * Locate a track by id, scoped to the currently-playing pattern.
759
+ */
760
+ private _findTrack;
761
+ private _setTrackFlag;
762
+ private _buildTrack;
763
+ private _currentPattern;
764
+ private _assertImplicitPattern;
765
+ private _computePatternTotalTicks;
609
766
  get state(): TransportState;
610
767
  /**
611
768
  * Start playback from `offsetTick`, or resume from pause if no offset given.
@@ -625,8 +782,8 @@ declare class Sequencer {
625
782
  togglePlayPause(): this;
626
783
  get bpm(): number;
627
784
  set bpm(value: number);
628
- get timeSignature(): number;
629
- set timeSignature(value: number);
785
+ get timeSignature(): TimeSignature;
786
+ set timeSignature(value: number | TimeSignature);
630
787
  /** Current transport position as "bar:beat:tick" (1-indexed). */
631
788
  get position(): string;
632
789
  /**
@@ -639,7 +796,10 @@ declare class Sequencer {
639
796
  /** Loop start in ticks. */
640
797
  get loopStart(): number;
641
798
  set loopStart(value: string | number);
642
- /** Loop end in ticks. Defaults to the end of the longest track. */
799
+ /**
800
+ * Loop end in ticks for the currently-playing pattern. Defaults to the end
801
+ * of the pattern's longest track.
802
+ */
643
803
  get loopEnd(): number;
644
804
  set loopEnd(value: string | number);
645
805
  /**
@@ -658,19 +818,20 @@ declare class Sequencer {
658
818
  /**
659
819
  * Listen to a sequencer event.
660
820
  *
661
- * | Event | Args |
662
- * |----------------|---------------------------------------------------|
663
- * | "statechange" | (state: "playing" \| "paused" \| "stopped") |
664
- * | "start" | |
665
- * | "stop" | |
666
- * | "pause" | |
667
- * | "end" | |
668
- * | "loop" | |
669
- * | "beat" | (beat: number, time: number) |
670
- * | "bar" | (bar: number, time: number) |
671
- * | "step" | (stepIndex: number, time: number) |
672
- * | "noteOn" | (event: SequencerNoteEvent) |
673
- * | "noteOff" | (event: SequencerNoteEvent) |
821
+ * | Event | Args |
822
+ * |-----------------|---------------------------------------------------|
823
+ * | "statechange" | (state: "playing" \| "paused" \| "stopped") |
824
+ * | "start" | |
825
+ * | "stop" | |
826
+ * | "pause" | |
827
+ * | "end" | |
828
+ * | "loop" | |
829
+ * | "patternChange" | (patternIndex: number, time: number) |
830
+ * | "beat" | (beat: number, time: number) |
831
+ * | "bar" | (bar: number, time: number) |
832
+ * | "step" | (stepIndex: number, time: number) |
833
+ * | "noteOn" | (event: SequencerNoteEvent) |
834
+ * | "noteOff" | (event: SequencerNoteEvent) |
674
835
  */
675
836
  on(event: string, callback: (...args: any[]) => void): this;
676
837
  off(event: string, callback: (...args: any[]) => void): this;
@@ -683,8 +844,6 @@ declare class Sequencer {
683
844
  private _emit;
684
845
  /** Emit both the specific state event ("start"/"pause"/"stop") and the unified "statechange" event. */
685
846
  private _emitStateChange;
686
- /** Recompute _totalTicks from all track notes (at + duration). */
687
- private _recomputeTotalTicks;
688
847
  /** Format a raw tick count as "bar:beat:tick" (all 1-indexed). */
689
848
  private _tickToPosition;
690
849
  /**
@@ -693,6 +852,8 @@ declare class Sequencer {
693
852
  */
694
853
  private _resetRepeatEvents;
695
854
  }
855
+ declare const Sequencer: Constructable<[context: BaseAudioContext, options?: SequencerOptions | undefined], SequencerImpl>;
856
+ type Sequencer = ReturnType<typeof Sequencer>;
696
857
 
697
858
  declare function getElectricPianoNames(): string[];
698
859
  type ElectricPianoOptions = Partial<{
@@ -700,6 +861,8 @@ type ElectricPianoOptions = Partial<{
700
861
  storage: Storage;
701
862
  destination: AudioNode;
702
863
  volume: number;
864
+ /** Stereo pan position (-1 = full left, 0 = centre, +1 = full right). */
865
+ pan: number;
703
866
  velocity: number;
704
867
  onLoadProgress: (progress: LoadProgress) => void;
705
868
  /** Audio formats to try, in order of preference. Defaults to ["ogg", "m4a"]. */
@@ -710,6 +873,8 @@ declare const ElectricPiano: InstrumentFactory<Partial<{
710
873
  storage: Storage;
711
874
  destination: AudioNode;
712
875
  volume: number;
876
+ /** Stereo pan position (-1 = full left, 0 = centre, +1 = full right). */
877
+ pan: number;
713
878
  velocity: number;
714
879
  onLoadProgress: (progress: LoadProgress) => void;
715
880
  /** Audio formats to try, in order of preference. Defaults to ["ogg", "m4a"]. */
@@ -732,6 +897,8 @@ type VersilianConfig = {
732
897
  type VersilianOptions = Partial<VersilianConfig & {
733
898
  destination?: AudioNode;
734
899
  volume?: number;
900
+ /** Stereo pan position (-1 = full left, 0 = centre, +1 = full right). */
901
+ pan?: number;
735
902
  velocity?: number;
736
903
  onLoadProgress?: (progress: LoadProgress) => void;
737
904
  }>;
@@ -744,6 +911,8 @@ type VersilianOptions = Partial<VersilianConfig & {
744
911
  declare const Versilian: InstrumentFactory<Partial<VersilianConfig & {
745
912
  destination?: AudioNode;
746
913
  volume?: number;
914
+ /** Stereo pan position (-1 = full left, 0 = centre, +1 = full right). */
915
+ pan?: number;
747
916
  velocity?: number;
748
917
  onLoadProgress?: (progress: LoadProgress) => void;
749
918
  }>, {}>;
@@ -760,6 +929,7 @@ declare function getMalletNames(): string[];
760
929
  declare const Mallet: InstrumentFactory<Partial<VersilianConfig & {
761
930
  destination?: AudioNode;
762
931
  volume?: number;
932
+ pan?: number;
763
933
  velocity?: number;
764
934
  onLoadProgress?: (progress: LoadProgress) => void;
765
935
  }>, {}>;
@@ -775,6 +945,8 @@ type MellotronConfig = {
775
945
  type MellotronOptions = Partial<MellotronConfig & {
776
946
  destination?: AudioNode;
777
947
  volume?: number;
948
+ /** Stereo pan position (-1 = full left, 0 = centre, +1 = full right). */
949
+ pan?: number;
778
950
  velocity?: number;
779
951
  decayTime?: number;
780
952
  onLoadProgress?: (progress: LoadProgress) => void;
@@ -782,6 +954,8 @@ type MellotronOptions = Partial<MellotronConfig & {
782
954
  declare const Mellotron: InstrumentFactory<Partial<MellotronConfig & {
783
955
  destination?: AudioNode;
784
956
  volume?: number;
957
+ /** Stereo pan position (-1 = full left, 0 = centre, +1 = full right). */
958
+ pan?: number;
785
959
  velocity?: number;
786
960
  decayTime?: number;
787
961
  onLoadProgress?: (progress: LoadProgress) => void;
@@ -793,17 +967,17 @@ type MellotronJsonConfig = {
793
967
  variation?: string;
794
968
  };
795
969
  /**
796
- * Convert a Mellotron files.json sample list to SmplrJson.
970
+ * Convert a Mellotron files.json sample list to SmplrPreset.
797
971
  *
798
972
  * - Filters by variation string if provided.
799
973
  * - Extracts MIDI from the first word of each sample name.
800
974
  * - Uses spreadKeyRanges so nearby notes pitch-shift to the nearest sample.
801
975
  * - All regions get loopAuto to produce tape-loop playback.
802
976
  */
803
- declare function mellotronToSmplrJson(sampleNames: string[], config: MellotronJsonConfig): SmplrJson;
977
+ declare function mellotronToPreset(sampleNames: string[], config: MellotronJsonConfig): SmplrPreset;
804
978
 
805
979
  declare const PARAMS: readonly ["preDelay", "bandwidth", "inputDiffusion1", "inputDiffusion2", "decay", "decayDiffusion1", "decayDiffusion2", "damping", "excursionRate", "excursionDepth", "wet", "dry"];
806
- declare class Reverb {
980
+ declare class ReverbImpl {
807
981
  #private;
808
982
  readonly input: AudioNode;
809
983
  constructor(context: AudioContext);
@@ -813,6 +987,8 @@ declare class Reverb {
813
987
  ready(): Promise<this>;
814
988
  connect(output: AudioNode): void;
815
989
  }
990
+ declare const Reverb: Constructable<[context: AudioContext], ReverbImpl>;
991
+ type Reverb = ReturnType<typeof Reverb>;
816
992
 
817
993
  type AudioBuffers = Record<string | number, AudioBuffer | undefined>;
818
994
  /**
@@ -820,26 +996,41 @@ type AudioBuffers = Record<string | number, AudioBuffer | undefined>;
820
996
  */
821
997
  type AudioBuffersLoader = (context: BaseAudioContext, buffers: AudioBuffers) => Promise<void>;
822
998
 
823
- type SamplerConfig = {
999
+ type SamplerBase = {
824
1000
  storage?: Storage;
825
- detune: number;
826
- volume: number;
827
- velocity: number;
1001
+ detune?: number;
1002
+ volume?: number;
1003
+ pan?: number;
1004
+ velocity?: number;
828
1005
  decayTime?: number;
829
1006
  lpfCutoffHz?: number;
830
- destination: AudioNode;
831
- buffers: Record<string | number, string | AudioBuffer | AudioBuffers> | AudioBuffersLoader;
832
- volumeToGain: (volume: number) => number;
1007
+ destination?: AudioNode;
1008
+ volumeToGain?: (volume: number) => number;
833
1009
  onLoadProgress?: (progress: LoadProgress) => void;
834
1010
  };
1011
+ type SamplerBuffers = Record<string | number, string | AudioBuffer | AudioBuffers> | AudioBuffersLoader;
1012
+ type SamplerBuffersInput = {
1013
+ buffers?: SamplerBuffers;
1014
+ preset?: never;
1015
+ };
1016
+ type SamplerPresetInput = {
1017
+ preset: SmplrPreset;
1018
+ buffers?: never;
1019
+ };
1020
+ type SamplerConfig = SamplerBase & (SamplerBuffersInput | SamplerPresetInput);
1021
+ /** Input accepted by {@link Sampler.reload}: a `SmplrPreset` schema or a flat buffers record/loader. */
1022
+ type SamplerReloadInput = SmplrPreset | SamplerBuffers;
1023
+ type SamplerExtras = {
1024
+ reload: (input: SamplerReloadInput) => Promise<void>;
1025
+ };
835
1026
  type SamplerJsonOptions = Pick<SamplerConfig, "decayTime" | "lpfCutoffHz" | "detune">;
836
1027
  type InternalConvertResult = {
837
- json: SmplrJson;
1028
+ json: SmplrPreset;
838
1029
  urlMap: Record<string, string>;
839
1030
  preloaded: Map<string, AudioBuffer>;
840
1031
  };
841
1032
  /**
842
- * Convert a flat source Record to SmplrJson + separated URL map + pre-loaded buffers.
1033
+ * Convert a flat source Record to SmplrPreset + separated URL map + pre-loaded buffers.
843
1034
  *
844
1035
  * - Keys that are valid MIDI names/numbers → MIDI-mapped regions.
845
1036
  * If ALL keys are MIDI-parseable, spread key ranges (pitch-shifting).
@@ -848,11 +1039,18 @@ type InternalConvertResult = {
848
1039
  * - AudioBuffer values → pre-loaded map (no fetch).
849
1040
  * - String URL values → urlMap (fetched asynchronously by caller).
850
1041
  */
851
- declare function samplerToSmplrJson(source: Record<string | number, string | AudioBuffer>, options?: Partial<SamplerJsonOptions>): InternalConvertResult;
1042
+ declare function samplerToPreset(source: Record<string | number, string | AudioBuffer>, options?: Partial<SamplerJsonOptions>): InternalConvertResult;
852
1043
  /**
853
- * A Sampler instrument.
1044
+ * A Sampler instrument. Accepts either a flat record of samples
1045
+ * (`{ buffers: { C4: "url" } }`) or a full `SmplrPreset`
1046
+ * (`{ preset: { samples, groups, ... } }`) for advanced use cases including
1047
+ * per-region pitch/velocity/round-robin control.
1048
+ *
1049
+ * Use `sampler.reload(input)` to swap content at runtime. `reload` accepts
1050
+ * either shape (flat record or `SmplrPreset`), regardless of which mode was
1051
+ * used at construction.
854
1052
  */
855
- declare const Sampler: InstrumentFactory<Partial<SamplerConfig>, {}>;
1053
+ declare const Sampler: InstrumentFactory<SamplerConfig, SamplerExtras>;
856
1054
  /** Instance type returned by the {@link Sampler} factory. */
857
1055
  type Sampler = ReturnType<typeof Sampler>;
858
1056
 
@@ -864,12 +1062,16 @@ type SmolkenConfig = {
864
1062
  type SmolkenOptions = Partial<SmolkenConfig & {
865
1063
  destination?: AudioNode;
866
1064
  volume?: number;
1065
+ /** Stereo pan position (-1 = full left, 0 = centre, +1 = full right). */
1066
+ pan?: number;
867
1067
  velocity?: number;
868
1068
  onLoadProgress?: (progress: LoadProgress) => void;
869
1069
  }>;
870
1070
  declare const Smolken: InstrumentFactory<Partial<SmolkenConfig & {
871
1071
  destination?: AudioNode;
872
1072
  volume?: number;
1073
+ /** Stereo pan position (-1 = full left, 0 = centre, +1 = full right). */
1074
+ pan?: number;
873
1075
  velocity?: number;
874
1076
  onLoadProgress?: (progress: LoadProgress) => void;
875
1077
  }>, {}>;
@@ -892,22 +1094,26 @@ type SoundfontConfig = {
892
1094
  type SoundfontOptions = Partial<SoundfontConfig & {
893
1095
  destination?: AudioNode;
894
1096
  volume?: number;
1097
+ /** Stereo pan position (-1 = full left, 0 = centre, +1 = full right). */
1098
+ pan?: number;
895
1099
  velocity?: number;
896
1100
  onLoadProgress?: (progress: LoadProgress) => void;
897
1101
  }>;
898
1102
  declare const Soundfont: InstrumentFactory<Partial<SoundfontConfig & {
899
1103
  destination?: AudioNode;
900
1104
  volume?: number;
1105
+ /** Stereo pan position (-1 = full left, 0 = centre, +1 = full right). */
1106
+ pan?: number;
901
1107
  velocity?: number;
902
1108
  onLoadProgress?: (progress: LoadProgress) => void;
903
1109
  }>, {}>;
904
1110
  /** Instance type returned by the {@link Soundfont} factory. */
905
1111
  type Soundfont = ReturnType<typeof Soundfont>;
906
1112
  /**
907
- * Convert a list of note names (with optional loop data) to SmplrJson.
1113
+ * Convert a list of note names (with optional loop data) to SmplrPreset.
908
1114
  * Uses spreadKeyRanges so notes between recorded pitches pitch-shift correctly.
909
1115
  */
910
- declare function soundfontToSmplrJson(noteNames: string[], loopData?: LoopData): SmplrJson;
1116
+ declare function soundfontToPreset(noteNames: string[], loopData?: LoopData): SmplrPreset;
911
1117
 
912
1118
  type Sf2 = {
913
1119
  instruments: Sf2Instrument[];
@@ -943,19 +1149,25 @@ type Soundfont2Options = {
943
1149
  createSoundfont: (data: Uint8Array) => Sf2;
944
1150
  destination?: AudioNode;
945
1151
  volume?: number;
1152
+ /** Stereo pan position (-1 = full left, 0 = centre, +1 = full right). */
1153
+ pan?: number;
946
1154
  velocity?: number;
947
1155
  };
948
- declare function sf2InstrumentToSmplrJson(sf2Instrument: Sf2Instrument, context: BaseAudioContext): {
949
- json: SmplrJson;
1156
+ declare function sf2InstrumentToPreset(sf2Instrument: Sf2Instrument, context: BaseAudioContext): {
1157
+ json: SmplrPreset;
950
1158
  buffers: Map<string, AudioBuffer>;
951
1159
  };
952
1160
  type Soundfont2SamplerExtras = {
953
1161
  readonly instrumentNames: string[];
954
1162
  loadInstrument(instrumentName: string): Promise<void> | undefined;
955
1163
  };
1164
+ declare const Soundfont2: InstrumentFactory<Soundfont2Options, Soundfont2SamplerExtras>;
1165
+ /** Instance type returned by the {@link Soundfont2} factory. */
1166
+ type Soundfont2 = ReturnType<typeof Soundfont2>;
1167
+ /** @deprecated Use `Soundfont2` instead. */
956
1168
  declare const Soundfont2Sampler: InstrumentFactory<Soundfont2Options, Soundfont2SamplerExtras>;
957
- /** Instance type returned by the {@link Soundfont2Sampler} factory. */
958
- type Soundfont2Sampler = ReturnType<typeof Soundfont2Sampler>;
1169
+ /** @deprecated Use `Soundfont2` instead. */
1170
+ type Soundfont2Sampler = Soundfont2;
959
1171
 
960
1172
  /**
961
1173
  * Configuration options for SplendidGrandPiano.
@@ -967,12 +1179,14 @@ type SplendidGrandPianoConfig = {
967
1179
  detune: number;
968
1180
  /** Default velocity (0–127) when not specified per note. */
969
1181
  velocity: number;
970
- /** Release time in seconds. Maps to SmplrJson defaults.ampRelease. */
1182
+ /** Release time in seconds. Maps to SmplrPreset defaults.ampRelease. */
971
1183
  decayTime: number;
972
1184
  /** Destination audio node. Defaults to context.destination. */
973
1185
  destination?: AudioNode;
974
1186
  /** Master volume (0–127 MIDI scale). */
975
1187
  volume?: number;
1188
+ /** Stereo pan position (-1 = full left, 0 = centre, +1 = full right). */
1189
+ pan?: number;
976
1190
  /** Called after each buffer is loaded or served from cache. */
977
1191
  onLoadProgress?: (progress: LoadProgress) => void;
978
1192
  /** Audio formats to try, in order of preference. Defaults to ["ogg", "m4a"]. */
@@ -988,7 +1202,7 @@ declare const SplendidGrandPiano: InstrumentFactory<Partial<SplendidGrandPianoCo
988
1202
  type SplendidGrandPiano = ReturnType<typeof SplendidGrandPiano>;
989
1203
  type PianoJsonOptions = Pick<SplendidGrandPianoConfig, "baseUrl" | "detune" | "decayTime" | "notesToLoad" | "formats">;
990
1204
  /**
991
- * Convert the LAYERS array and user options into a SmplrJson descriptor.
1205
+ * Convert the LAYERS array and user options into a SmplrPreset descriptor.
992
1206
  *
993
1207
  * Each layer becomes a SmplrGroup with its velRange. If `notesToLoad` is
994
1208
  * specified, layers and samples are filtered accordingly. The PPP layer
@@ -997,7 +1211,7 @@ type PianoJsonOptions = Pick<SplendidGrandPianoConfig, "baseUrl" | "detune" | "d
997
1211
  * `spreadKeyRanges` is used to pre-compute which key range each sample
998
1212
  * covers, replacing the old on-the-fly `findNearestMidiInLayer` logic.
999
1213
  */
1000
- declare function pianoToSmplrJson(options: PianoJsonOptions): SmplrJson;
1214
+ declare function pianoToPreset(options: PianoJsonOptions): SmplrPreset;
1001
1215
  declare const LAYERS: ({
1002
1216
  name: string;
1003
1217
  vel_range: number[];
@@ -1010,4 +1224,4 @@ declare const LAYERS: ({
1010
1224
  cutoff?: undefined;
1011
1225
  })[];
1012
1226
 
1013
- export { CacheStorage, DrumMachine, type DrumMachineOptions, ElectricPiano, type ElectricPianoOptions, HttpStorage, Instrument, LAYERS, type LoadProgress, Mallet, Mellotron, type MellotronConfig, type MellotronOptions, NAME_TO_PATH, type NoteEvent, type PlaybackParams, type RenderOfflineOptions, RenderResult, Reverb, SampleLoader, Sampler, type SamplerConfig, Scheduler, Sequencer, type SequencerInstrument, type SequencerNote, type SequencerNoteEvent, type SequencerOptions, Smolken, type SmolkenConfig, type SmolkenOptions, type Smplr, type SmplrGroup, type SmplrJson, type SmplrOptions, type SmplrPlugin, type SmplrRegion, type SmplrSamples, Soundfont, type Soundfont2Options, Soundfont2Sampler, type SoundfontOptions, SplendidGrandPiano, type SplendidGrandPianoConfig, type StopFn, type StopTarget, type Storage, type StorageResponse, Versilian, type VersilianConfig, type VersilianOptions, type VoiceParams, audioBufferToWav, audioBufferToWav16, drumMachineToSmplrJson, getDrumMachineNames, getElectricPianoNames, getMalletNames, getMellotronNames, getSmolkenNames, getSoundfontKits, getSoundfontNames, getVersilianInstruments, loadVersilianInstrument, mellotronToSmplrJson, pianoToSmplrJson, renderOffline, samplerToSmplrJson, sf2InstrumentToSmplrJson, soundfontToSmplrJson, trimSilence };
1227
+ export { type AddTrackOptions, CacheStorage, DrumMachine, type DrumMachineOptions, ElectricPiano, type ElectricPianoOptions, HttpStorage, Instrument, LAYERS, type LoadProgress, Mallet, Mellotron, type MellotronConfig, type MellotronOptions, NAME_TO_PATH, type NoteEvent, type PatternInput, type PlaybackParams, type RenderOfflineOptions, RenderResult, Reverb, SampleLoader, Sampler, type SamplerConfig, type SamplerReloadInput, Scheduler, Sequencer, type SequencerInstrument, type SequencerNote, type SequencerNoteEvent, type SequencerOptions, Smolken, type SmolkenConfig, type SmolkenOptions, type Smplr, type SmplrGroup, type SmplrOptions, type SmplrPlugin, type SmplrPreset, type SmplrRegion, type SmplrSamples, Soundfont, Soundfont2, type Soundfont2Options, Soundfont2Sampler, type SoundfontOptions, SplendidGrandPiano, type SplendidGrandPianoConfig, type StopFn, type StopTarget, type Storage, type StorageResponse, type TimeSignature, Versilian, type VersilianConfig, type VersilianOptions, type VoiceParams, audioBufferToWav, audioBufferToWav16, drumMachineToPreset, getDrumMachineNames, getElectricPianoNames, getMalletNames, getMellotronNames, getSmolkenNames, getSoundfontKits, getSoundfontNames, getVersilianInstruments, loadVersilianInstrument, mellotronToPreset, pianoToPreset, renderOffline, samplerToPreset, sf2InstrumentToPreset, soundfontToPreset, trimSilence };