smplr 0.22.0 → 0.23.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/README.md CHANGED
@@ -254,7 +254,7 @@ Or stop the specified one. The argument is a `stopId` — by default the same va
254
254
 
255
255
  ```js
256
256
  piano.stop("C4"); // stop the note(s) started with `note: "C4"`
257
- piano.stop(60); // stop the note(s) started with `note: 60`
257
+ piano.stop(60); // stop the note(s) started with `note: 60`
258
258
  ```
259
259
 
260
260
  #### Schedule notes
@@ -308,8 +308,8 @@ Set and read MIDI Control Change values on the instrument:
308
308
 
309
309
  ```js
310
310
  piano.setCC(64, 127); // sustain pedal on
311
- piano.getCC(64); // => 127
312
- piano.setCC(64, 0); // sustain pedal off
311
+ piano.getCC(64); // => 127
312
+ piano.setCC(64, 0); // sustain pedal off
313
313
  ```
314
314
 
315
315
  Unset CCs default to `0` (matches MIDI's "undefined controller defaults to 0" convention).
@@ -677,15 +677,15 @@ This will download a WAV file you can attach to your issue or pull request.
677
677
 
678
678
  Each instrument family exposes a synchronous helper that returns the names you can pass to its factory:
679
679
 
680
- | Factory | Names helper |
681
- |---|---|
682
- | `Soundfont` | `getSoundfontNames(): string[]` |
683
- | `ElectricPiano` | `getElectricPianoNames(): string[]` |
684
- | `Mallet` | `getMalletNames(): string[]` |
685
- | `Mellotron` | `getMellotronNames(): string[]` |
686
- | `DrumMachine` | `getDrumMachineNames(): string[]` |
687
- | `Smolken` | `getSmolkenNames(): string[]` |
688
- | `Versilian` | `getVersilianInstruments(): Promise<string[]>` |
680
+ | Factory | Names helper |
681
+ | --------------- | ---------------------------------------------- |
682
+ | `Soundfont` | `getSoundfontNames(): string[]` |
683
+ | `ElectricPiano` | `getElectricPianoNames(): string[]` |
684
+ | `Mallet` | `getMalletNames(): string[]` |
685
+ | `Mellotron` | `getMellotronNames(): string[]` |
686
+ | `DrumMachine` | `getDrumMachineNames(): string[]` |
687
+ | `Smolken` | `getSmolkenNames(): string[]` |
688
+ | `Versilian` | `getVersilianInstruments(): Promise<string[]>` |
689
689
 
690
690
  `getVersilianInstruments` is async because the catalog is fetched from the network on first call (cached thereafter).
691
691
 
@@ -693,6 +693,8 @@ Each instrument family exposes a synchronous helper that returns the names you c
693
693
 
694
694
  An audio buffer sampler. Pass a `buffers` object with the files to be load:
695
695
 
696
+ #### Buffers mode
697
+
696
698
  ```js
697
699
  import { Sampler } from "smplr";
698
700
 
@@ -709,6 +711,37 @@ And then use the name of the buffer as note name:
709
711
  sampler.start({ note: "kick" });
710
712
  ```
711
713
 
714
+ #### Advanced mode
715
+
716
+ For advanced use cases (per-region pitch/velocity/round-robin, SFZ-like multi-sample instruments, runtime swaps), pass a `SmplrPreset` directly:
717
+
718
+ ```ts
719
+ import { Sampler, type SmplrPreset } from "smplr";
720
+
721
+ const kitA: SmplrPreset = {
722
+ samples: { baseUrl: "https://cdn.example.com/", formats: ["ogg"] },
723
+ groups: [
724
+ {
725
+ regions: [
726
+ { sample: "kick", keyRange: [60, 60], pitch: 60 },
727
+ { sample: "snare", keyRange: [62, 62], pitch: 62 },
728
+ ],
729
+ },
730
+ ],
731
+ };
732
+
733
+ const sampler = Sampler(new AudioContext(), { preset: kitA });
734
+ await sampler.ready;
735
+ sampler.start({ note: 60 });
736
+
737
+ // Swap content at runtime
738
+ await sampler.reload(kitB);
739
+ ```
740
+
741
+ The full `SmplrPreset` schema is documented in [SMPLR_PRESET.md](./SMPLR_PRESET.md). Note: `buffers` and `preset` are mutually exclusive on construction — pass exactly one.
742
+
743
+ `sampler.reload(input)` accepts either shape (flat buffers record or full `SmplrPreset`), regardless of which mode was used at construction.
744
+
712
745
  ### Soundfont
713
746
 
714
747
  A Soundfont player. By default it loads audio from Benjamin Gleitzman's package of
package/dist/index.d.mts CHANGED
@@ -114,7 +114,7 @@ type SmplrSamples = {
114
114
  /**
115
115
  * The top-level smplr.json descriptor. Passed to the Smplr constructor.
116
116
  */
117
- type SmplrJson = {
117
+ type SmplrPreset = {
118
118
  /** Schema version. Omit for the current format. Reserved for future migrations. */
119
119
  smplr?: "1.0";
120
120
  meta?: {
@@ -190,7 +190,7 @@ type VoiceParams = {
190
190
  };
191
191
 
192
192
  /**
193
- * Loads and caches AudioBuffers for all samples referenced in a SmplrJson.
193
+ * Loads and caches AudioBuffers for all samples referenced in a SmplrPreset.
194
194
  *
195
195
  * The cache is keyed by resolved URL, so the same audio file is never fetched
196
196
  * or decoded twice. Multiple Smplr instances can share one SampleLoader by
@@ -209,7 +209,7 @@ declare class SampleLoader {
209
209
  * - `buffers` in options: pre-loaded buffers — skips fetch for these names.
210
210
  * - All samples load in parallel. Failed samples are silently omitted.
211
211
  */
212
- load(json: SmplrJson, onProgressOrOptions?: ((loaded: number, total: number) => void) | {
212
+ load(json: SmplrPreset, onProgressOrOptions?: ((loaded: number, total: number) => void) | {
213
213
  buffers?: Map<string, AudioBuffer>;
214
214
  onProgress?: (loaded: number, total: number) => void;
215
215
  }): Promise<Map<string, AudioBuffer>>;
@@ -324,7 +324,7 @@ interface PluginSmplr extends Smplr {
324
324
  *
325
325
  * Resolves when all samples are ready.
326
326
  */
327
- loadInstrument(json: SmplrJson, buffers?: Map<string, AudioBuffer>): Promise<void>;
327
+ loadInstrument(json: SmplrPreset, buffers?: Map<string, AudioBuffer>): Promise<void>;
328
328
  }
329
329
  /**
330
330
  * Permitted return shapes for an {@link SmplrPlugin}:
@@ -429,13 +429,13 @@ declare const DrumMachine: InstrumentFactory<Partial<DrumMachineConfig & {
429
429
  /** Instance type returned by the {@link DrumMachine} factory. */
430
430
  type DrumMachine = ReturnType<typeof DrumMachine>;
431
431
  /**
432
- * Convert a DrumMachineInstrument to a SmplrJson descriptor.
432
+ * Convert a DrumMachineInstrument to a SmplrPreset descriptor.
433
433
  *
434
434
  * Each sample gets a sequential MIDI number starting at 36 (GM drum map base).
435
435
  * Aliases are created for both the full sample name ("kick/1") and the group
436
436
  * name ("kick") so both forms work with Smplr.start({ note: "kick" }).
437
437
  */
438
- declare function drumMachineToSmplrJson(instrument: DrumMachineInstrument): SmplrJson;
438
+ declare function drumMachineToPreset(instrument: DrumMachineInstrument): SmplrPreset;
439
439
 
440
440
  /**
441
441
  * The result of an offline render. Provides the raw AudioBuffer and
@@ -793,14 +793,14 @@ type MellotronJsonConfig = {
793
793
  variation?: string;
794
794
  };
795
795
  /**
796
- * Convert a Mellotron files.json sample list to SmplrJson.
796
+ * Convert a Mellotron files.json sample list to SmplrPreset.
797
797
  *
798
798
  * - Filters by variation string if provided.
799
799
  * - Extracts MIDI from the first word of each sample name.
800
800
  * - Uses spreadKeyRanges so nearby notes pitch-shift to the nearest sample.
801
801
  * - All regions get loopAuto to produce tape-loop playback.
802
802
  */
803
- declare function mellotronToSmplrJson(sampleNames: string[], config: MellotronJsonConfig): SmplrJson;
803
+ declare function mellotronToPreset(sampleNames: string[], config: MellotronJsonConfig): SmplrPreset;
804
804
 
805
805
  declare const PARAMS: readonly ["preDelay", "bandwidth", "inputDiffusion1", "inputDiffusion2", "decay", "decayDiffusion1", "decayDiffusion2", "damping", "excursionRate", "excursionDepth", "wet", "dry"];
806
806
  declare class Reverb {
@@ -820,26 +820,40 @@ type AudioBuffers = Record<string | number, AudioBuffer | undefined>;
820
820
  */
821
821
  type AudioBuffersLoader = (context: BaseAudioContext, buffers: AudioBuffers) => Promise<void>;
822
822
 
823
- type SamplerConfig = {
823
+ type SamplerBase = {
824
824
  storage?: Storage;
825
- detune: number;
826
- volume: number;
827
- velocity: number;
825
+ detune?: number;
826
+ volume?: number;
827
+ velocity?: number;
828
828
  decayTime?: number;
829
829
  lpfCutoffHz?: number;
830
- destination: AudioNode;
831
- buffers: Record<string | number, string | AudioBuffer | AudioBuffers> | AudioBuffersLoader;
832
- volumeToGain: (volume: number) => number;
830
+ destination?: AudioNode;
831
+ volumeToGain?: (volume: number) => number;
833
832
  onLoadProgress?: (progress: LoadProgress) => void;
834
833
  };
834
+ type SamplerBuffers = Record<string | number, string | AudioBuffer | AudioBuffers> | AudioBuffersLoader;
835
+ type SamplerBuffersInput = {
836
+ buffers?: SamplerBuffers;
837
+ preset?: never;
838
+ };
839
+ type SamplerPresetInput = {
840
+ preset: SmplrPreset;
841
+ buffers?: never;
842
+ };
843
+ type SamplerConfig = SamplerBase & (SamplerBuffersInput | SamplerPresetInput);
844
+ /** Input accepted by {@link Sampler.reload}: a `SmplrPreset` schema or a flat buffers record/loader. */
845
+ type SamplerReloadInput = SmplrPreset | SamplerBuffers;
846
+ type SamplerExtras = {
847
+ reload: (input: SamplerReloadInput) => Promise<void>;
848
+ };
835
849
  type SamplerJsonOptions = Pick<SamplerConfig, "decayTime" | "lpfCutoffHz" | "detune">;
836
850
  type InternalConvertResult = {
837
- json: SmplrJson;
851
+ json: SmplrPreset;
838
852
  urlMap: Record<string, string>;
839
853
  preloaded: Map<string, AudioBuffer>;
840
854
  };
841
855
  /**
842
- * Convert a flat source Record to SmplrJson + separated URL map + pre-loaded buffers.
856
+ * Convert a flat source Record to SmplrPreset + separated URL map + pre-loaded buffers.
843
857
  *
844
858
  * - Keys that are valid MIDI names/numbers → MIDI-mapped regions.
845
859
  * If ALL keys are MIDI-parseable, spread key ranges (pitch-shifting).
@@ -848,11 +862,18 @@ type InternalConvertResult = {
848
862
  * - AudioBuffer values → pre-loaded map (no fetch).
849
863
  * - String URL values → urlMap (fetched asynchronously by caller).
850
864
  */
851
- declare function samplerToSmplrJson(source: Record<string | number, string | AudioBuffer>, options?: Partial<SamplerJsonOptions>): InternalConvertResult;
865
+ declare function samplerToPreset(source: Record<string | number, string | AudioBuffer>, options?: Partial<SamplerJsonOptions>): InternalConvertResult;
852
866
  /**
853
- * A Sampler instrument.
867
+ * A Sampler instrument. Accepts either a flat record of samples
868
+ * (`{ buffers: { C4: "url" } }`) or a full `SmplrPreset`
869
+ * (`{ preset: { samples, groups, ... } }`) for advanced use cases including
870
+ * per-region pitch/velocity/round-robin control.
871
+ *
872
+ * Use `sampler.reload(input)` to swap content at runtime. `reload` accepts
873
+ * either shape (flat record or `SmplrPreset`), regardless of which mode was
874
+ * used at construction.
854
875
  */
855
- declare const Sampler: InstrumentFactory<Partial<SamplerConfig>, {}>;
876
+ declare const Sampler: InstrumentFactory<SamplerConfig, SamplerExtras>;
856
877
  /** Instance type returned by the {@link Sampler} factory. */
857
878
  type Sampler = ReturnType<typeof Sampler>;
858
879
 
@@ -904,10 +925,10 @@ declare const Soundfont: InstrumentFactory<Partial<SoundfontConfig & {
904
925
  /** Instance type returned by the {@link Soundfont} factory. */
905
926
  type Soundfont = ReturnType<typeof Soundfont>;
906
927
  /**
907
- * Convert a list of note names (with optional loop data) to SmplrJson.
928
+ * Convert a list of note names (with optional loop data) to SmplrPreset.
908
929
  * Uses spreadKeyRanges so notes between recorded pitches pitch-shift correctly.
909
930
  */
910
- declare function soundfontToSmplrJson(noteNames: string[], loopData?: LoopData): SmplrJson;
931
+ declare function soundfontToPreset(noteNames: string[], loopData?: LoopData): SmplrPreset;
911
932
 
912
933
  type Sf2 = {
913
934
  instruments: Sf2Instrument[];
@@ -945,8 +966,8 @@ type Soundfont2Options = {
945
966
  volume?: number;
946
967
  velocity?: number;
947
968
  };
948
- declare function sf2InstrumentToSmplrJson(sf2Instrument: Sf2Instrument, context: BaseAudioContext): {
949
- json: SmplrJson;
969
+ declare function sf2InstrumentToPreset(sf2Instrument: Sf2Instrument, context: BaseAudioContext): {
970
+ json: SmplrPreset;
950
971
  buffers: Map<string, AudioBuffer>;
951
972
  };
952
973
  type Soundfont2SamplerExtras = {
@@ -967,7 +988,7 @@ type SplendidGrandPianoConfig = {
967
988
  detune: number;
968
989
  /** Default velocity (0–127) when not specified per note. */
969
990
  velocity: number;
970
- /** Release time in seconds. Maps to SmplrJson defaults.ampRelease. */
991
+ /** Release time in seconds. Maps to SmplrPreset defaults.ampRelease. */
971
992
  decayTime: number;
972
993
  /** Destination audio node. Defaults to context.destination. */
973
994
  destination?: AudioNode;
@@ -988,7 +1009,7 @@ declare const SplendidGrandPiano: InstrumentFactory<Partial<SplendidGrandPianoCo
988
1009
  type SplendidGrandPiano = ReturnType<typeof SplendidGrandPiano>;
989
1010
  type PianoJsonOptions = Pick<SplendidGrandPianoConfig, "baseUrl" | "detune" | "decayTime" | "notesToLoad" | "formats">;
990
1011
  /**
991
- * Convert the LAYERS array and user options into a SmplrJson descriptor.
1012
+ * Convert the LAYERS array and user options into a SmplrPreset descriptor.
992
1013
  *
993
1014
  * Each layer becomes a SmplrGroup with its velRange. If `notesToLoad` is
994
1015
  * specified, layers and samples are filtered accordingly. The PPP layer
@@ -997,7 +1018,7 @@ type PianoJsonOptions = Pick<SplendidGrandPianoConfig, "baseUrl" | "detune" | "d
997
1018
  * `spreadKeyRanges` is used to pre-compute which key range each sample
998
1019
  * covers, replacing the old on-the-fly `findNearestMidiInLayer` logic.
999
1020
  */
1000
- declare function pianoToSmplrJson(options: PianoJsonOptions): SmplrJson;
1021
+ declare function pianoToPreset(options: PianoJsonOptions): SmplrPreset;
1001
1022
  declare const LAYERS: ({
1002
1023
  name: string;
1003
1024
  vel_range: number[];
@@ -1010,4 +1031,4 @@ declare const LAYERS: ({
1010
1031
  cutoff?: undefined;
1011
1032
  })[];
1012
1033
 
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 };
1034
+ 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, 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, 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, drumMachineToPreset, getDrumMachineNames, getElectricPianoNames, getMalletNames, getMellotronNames, getSmolkenNames, getSoundfontKits, getSoundfontNames, getVersilianInstruments, loadVersilianInstrument, mellotronToPreset, pianoToPreset, renderOffline, samplerToPreset, sf2InstrumentToPreset, soundfontToPreset, trimSilence };
package/dist/index.d.ts CHANGED
@@ -114,7 +114,7 @@ type SmplrSamples = {
114
114
  /**
115
115
  * The top-level smplr.json descriptor. Passed to the Smplr constructor.
116
116
  */
117
- type SmplrJson = {
117
+ type SmplrPreset = {
118
118
  /** Schema version. Omit for the current format. Reserved for future migrations. */
119
119
  smplr?: "1.0";
120
120
  meta?: {
@@ -190,7 +190,7 @@ type VoiceParams = {
190
190
  };
191
191
 
192
192
  /**
193
- * Loads and caches AudioBuffers for all samples referenced in a SmplrJson.
193
+ * Loads and caches AudioBuffers for all samples referenced in a SmplrPreset.
194
194
  *
195
195
  * The cache is keyed by resolved URL, so the same audio file is never fetched
196
196
  * or decoded twice. Multiple Smplr instances can share one SampleLoader by
@@ -209,7 +209,7 @@ declare class SampleLoader {
209
209
  * - `buffers` in options: pre-loaded buffers — skips fetch for these names.
210
210
  * - All samples load in parallel. Failed samples are silently omitted.
211
211
  */
212
- load(json: SmplrJson, onProgressOrOptions?: ((loaded: number, total: number) => void) | {
212
+ load(json: SmplrPreset, onProgressOrOptions?: ((loaded: number, total: number) => void) | {
213
213
  buffers?: Map<string, AudioBuffer>;
214
214
  onProgress?: (loaded: number, total: number) => void;
215
215
  }): Promise<Map<string, AudioBuffer>>;
@@ -324,7 +324,7 @@ interface PluginSmplr extends Smplr {
324
324
  *
325
325
  * Resolves when all samples are ready.
326
326
  */
327
- loadInstrument(json: SmplrJson, buffers?: Map<string, AudioBuffer>): Promise<void>;
327
+ loadInstrument(json: SmplrPreset, buffers?: Map<string, AudioBuffer>): Promise<void>;
328
328
  }
329
329
  /**
330
330
  * Permitted return shapes for an {@link SmplrPlugin}:
@@ -429,13 +429,13 @@ declare const DrumMachine: InstrumentFactory<Partial<DrumMachineConfig & {
429
429
  /** Instance type returned by the {@link DrumMachine} factory. */
430
430
  type DrumMachine = ReturnType<typeof DrumMachine>;
431
431
  /**
432
- * Convert a DrumMachineInstrument to a SmplrJson descriptor.
432
+ * Convert a DrumMachineInstrument to a SmplrPreset descriptor.
433
433
  *
434
434
  * Each sample gets a sequential MIDI number starting at 36 (GM drum map base).
435
435
  * Aliases are created for both the full sample name ("kick/1") and the group
436
436
  * name ("kick") so both forms work with Smplr.start({ note: "kick" }).
437
437
  */
438
- declare function drumMachineToSmplrJson(instrument: DrumMachineInstrument): SmplrJson;
438
+ declare function drumMachineToPreset(instrument: DrumMachineInstrument): SmplrPreset;
439
439
 
440
440
  /**
441
441
  * The result of an offline render. Provides the raw AudioBuffer and
@@ -793,14 +793,14 @@ type MellotronJsonConfig = {
793
793
  variation?: string;
794
794
  };
795
795
  /**
796
- * Convert a Mellotron files.json sample list to SmplrJson.
796
+ * Convert a Mellotron files.json sample list to SmplrPreset.
797
797
  *
798
798
  * - Filters by variation string if provided.
799
799
  * - Extracts MIDI from the first word of each sample name.
800
800
  * - Uses spreadKeyRanges so nearby notes pitch-shift to the nearest sample.
801
801
  * - All regions get loopAuto to produce tape-loop playback.
802
802
  */
803
- declare function mellotronToSmplrJson(sampleNames: string[], config: MellotronJsonConfig): SmplrJson;
803
+ declare function mellotronToPreset(sampleNames: string[], config: MellotronJsonConfig): SmplrPreset;
804
804
 
805
805
  declare const PARAMS: readonly ["preDelay", "bandwidth", "inputDiffusion1", "inputDiffusion2", "decay", "decayDiffusion1", "decayDiffusion2", "damping", "excursionRate", "excursionDepth", "wet", "dry"];
806
806
  declare class Reverb {
@@ -820,26 +820,40 @@ type AudioBuffers = Record<string | number, AudioBuffer | undefined>;
820
820
  */
821
821
  type AudioBuffersLoader = (context: BaseAudioContext, buffers: AudioBuffers) => Promise<void>;
822
822
 
823
- type SamplerConfig = {
823
+ type SamplerBase = {
824
824
  storage?: Storage;
825
- detune: number;
826
- volume: number;
827
- velocity: number;
825
+ detune?: number;
826
+ volume?: number;
827
+ velocity?: number;
828
828
  decayTime?: number;
829
829
  lpfCutoffHz?: number;
830
- destination: AudioNode;
831
- buffers: Record<string | number, string | AudioBuffer | AudioBuffers> | AudioBuffersLoader;
832
- volumeToGain: (volume: number) => number;
830
+ destination?: AudioNode;
831
+ volumeToGain?: (volume: number) => number;
833
832
  onLoadProgress?: (progress: LoadProgress) => void;
834
833
  };
834
+ type SamplerBuffers = Record<string | number, string | AudioBuffer | AudioBuffers> | AudioBuffersLoader;
835
+ type SamplerBuffersInput = {
836
+ buffers?: SamplerBuffers;
837
+ preset?: never;
838
+ };
839
+ type SamplerPresetInput = {
840
+ preset: SmplrPreset;
841
+ buffers?: never;
842
+ };
843
+ type SamplerConfig = SamplerBase & (SamplerBuffersInput | SamplerPresetInput);
844
+ /** Input accepted by {@link Sampler.reload}: a `SmplrPreset` schema or a flat buffers record/loader. */
845
+ type SamplerReloadInput = SmplrPreset | SamplerBuffers;
846
+ type SamplerExtras = {
847
+ reload: (input: SamplerReloadInput) => Promise<void>;
848
+ };
835
849
  type SamplerJsonOptions = Pick<SamplerConfig, "decayTime" | "lpfCutoffHz" | "detune">;
836
850
  type InternalConvertResult = {
837
- json: SmplrJson;
851
+ json: SmplrPreset;
838
852
  urlMap: Record<string, string>;
839
853
  preloaded: Map<string, AudioBuffer>;
840
854
  };
841
855
  /**
842
- * Convert a flat source Record to SmplrJson + separated URL map + pre-loaded buffers.
856
+ * Convert a flat source Record to SmplrPreset + separated URL map + pre-loaded buffers.
843
857
  *
844
858
  * - Keys that are valid MIDI names/numbers → MIDI-mapped regions.
845
859
  * If ALL keys are MIDI-parseable, spread key ranges (pitch-shifting).
@@ -848,11 +862,18 @@ type InternalConvertResult = {
848
862
  * - AudioBuffer values → pre-loaded map (no fetch).
849
863
  * - String URL values → urlMap (fetched asynchronously by caller).
850
864
  */
851
- declare function samplerToSmplrJson(source: Record<string | number, string | AudioBuffer>, options?: Partial<SamplerJsonOptions>): InternalConvertResult;
865
+ declare function samplerToPreset(source: Record<string | number, string | AudioBuffer>, options?: Partial<SamplerJsonOptions>): InternalConvertResult;
852
866
  /**
853
- * A Sampler instrument.
867
+ * A Sampler instrument. Accepts either a flat record of samples
868
+ * (`{ buffers: { C4: "url" } }`) or a full `SmplrPreset`
869
+ * (`{ preset: { samples, groups, ... } }`) for advanced use cases including
870
+ * per-region pitch/velocity/round-robin control.
871
+ *
872
+ * Use `sampler.reload(input)` to swap content at runtime. `reload` accepts
873
+ * either shape (flat record or `SmplrPreset`), regardless of which mode was
874
+ * used at construction.
854
875
  */
855
- declare const Sampler: InstrumentFactory<Partial<SamplerConfig>, {}>;
876
+ declare const Sampler: InstrumentFactory<SamplerConfig, SamplerExtras>;
856
877
  /** Instance type returned by the {@link Sampler} factory. */
857
878
  type Sampler = ReturnType<typeof Sampler>;
858
879
 
@@ -904,10 +925,10 @@ declare const Soundfont: InstrumentFactory<Partial<SoundfontConfig & {
904
925
  /** Instance type returned by the {@link Soundfont} factory. */
905
926
  type Soundfont = ReturnType<typeof Soundfont>;
906
927
  /**
907
- * Convert a list of note names (with optional loop data) to SmplrJson.
928
+ * Convert a list of note names (with optional loop data) to SmplrPreset.
908
929
  * Uses spreadKeyRanges so notes between recorded pitches pitch-shift correctly.
909
930
  */
910
- declare function soundfontToSmplrJson(noteNames: string[], loopData?: LoopData): SmplrJson;
931
+ declare function soundfontToPreset(noteNames: string[], loopData?: LoopData): SmplrPreset;
911
932
 
912
933
  type Sf2 = {
913
934
  instruments: Sf2Instrument[];
@@ -945,8 +966,8 @@ type Soundfont2Options = {
945
966
  volume?: number;
946
967
  velocity?: number;
947
968
  };
948
- declare function sf2InstrumentToSmplrJson(sf2Instrument: Sf2Instrument, context: BaseAudioContext): {
949
- json: SmplrJson;
969
+ declare function sf2InstrumentToPreset(sf2Instrument: Sf2Instrument, context: BaseAudioContext): {
970
+ json: SmplrPreset;
950
971
  buffers: Map<string, AudioBuffer>;
951
972
  };
952
973
  type Soundfont2SamplerExtras = {
@@ -967,7 +988,7 @@ type SplendidGrandPianoConfig = {
967
988
  detune: number;
968
989
  /** Default velocity (0–127) when not specified per note. */
969
990
  velocity: number;
970
- /** Release time in seconds. Maps to SmplrJson defaults.ampRelease. */
991
+ /** Release time in seconds. Maps to SmplrPreset defaults.ampRelease. */
971
992
  decayTime: number;
972
993
  /** Destination audio node. Defaults to context.destination. */
973
994
  destination?: AudioNode;
@@ -988,7 +1009,7 @@ declare const SplendidGrandPiano: InstrumentFactory<Partial<SplendidGrandPianoCo
988
1009
  type SplendidGrandPiano = ReturnType<typeof SplendidGrandPiano>;
989
1010
  type PianoJsonOptions = Pick<SplendidGrandPianoConfig, "baseUrl" | "detune" | "decayTime" | "notesToLoad" | "formats">;
990
1011
  /**
991
- * Convert the LAYERS array and user options into a SmplrJson descriptor.
1012
+ * Convert the LAYERS array and user options into a SmplrPreset descriptor.
992
1013
  *
993
1014
  * Each layer becomes a SmplrGroup with its velRange. If `notesToLoad` is
994
1015
  * specified, layers and samples are filtered accordingly. The PPP layer
@@ -997,7 +1018,7 @@ type PianoJsonOptions = Pick<SplendidGrandPianoConfig, "baseUrl" | "detune" | "d
997
1018
  * `spreadKeyRanges` is used to pre-compute which key range each sample
998
1019
  * covers, replacing the old on-the-fly `findNearestMidiInLayer` logic.
999
1020
  */
1000
- declare function pianoToSmplrJson(options: PianoJsonOptions): SmplrJson;
1021
+ declare function pianoToPreset(options: PianoJsonOptions): SmplrPreset;
1001
1022
  declare const LAYERS: ({
1002
1023
  name: string;
1003
1024
  vel_range: number[];
@@ -1010,4 +1031,4 @@ declare const LAYERS: ({
1010
1031
  cutoff?: undefined;
1011
1032
  })[];
1012
1033
 
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 };
1034
+ 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, 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, 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, drumMachineToPreset, getDrumMachineNames, getElectricPianoNames, getMalletNames, getMellotronNames, getSmolkenNames, getSoundfontKits, getSoundfontNames, getVersilianInstruments, loadVersilianInstrument, mellotronToPreset, pianoToPreset, renderOffline, samplerToPreset, sf2InstrumentToPreset, soundfontToPreset, trimSilence };