smplr 0.21.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
@@ -57,7 +57,7 @@ wav.downloadWav("arpeggio.wav");
57
57
 
58
58
  See demo: https://danigb.github.io/smplr/
59
59
 
60
- `smplr` is approaching 1.0. The 0.21.0 release is the **1.0 candidate** — the documented surface is intended to ship unchanged into 1.0; the formal stability commitment lands when a handful of coordinated sibling tickets are in (see the 0.21.0 [CHANGELOG](https://github.com/danigb/smplr/blob/main/CHANGELOG.md) entry).
60
+ `smplr` is approaching 1.0. The 0.22.0 release lands the final batch of pre-1.0 API work every documented `new X(ctx, opts)` keeps working, and the documented surface is intended to ship unchanged into 1.0. The formal stability commitment lands once the narrow `loader`/`scheduler` public interfaces sibling ticket is in (see [CHANGELOG](https://github.com/danigb/smplr/blob/main/CHANGELOG.md)).
61
61
 
62
62
  > **Upgrading from an earlier 0.x?** No code changes are required — every documented `new X(ctx, opts)` keeps working. New code should drop the `new` (`X(ctx, opts)`) and prefer `await x.ready` over `await x.load`.
63
63
 
@@ -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
@@ -291,14 +291,42 @@ If `loop` is true but `loopStart` or `loopEnd` are not specified, 0 and total du
291
291
 
292
292
  #### Change volume
293
293
 
294
- Instrument `output` attribute represents the main output of the instrument. `output.setVolume` method accepts a number where 0 means no volume, and 127 is max volume without amplification:
294
+ Instrument `output` attribute represents the main output of the instrument. The `output.volume` getter/setter accepts a number where 0 means no volume, and 127 is max volume without amplification:
295
295
 
296
296
  ```js
297
- piano.output.setVolume(80);
297
+ piano.output.volume = 80;
298
+ piano.output.volume; // => 80
298
299
  ```
299
300
 
301
+ `output.setVolume(n)` is kept as a deprecated alias and continues to work.
302
+
300
303
  ⚠️ `volume` is global to the instrument, but `velocity` is specific for each note.
301
304
 
305
+ #### MIDI CC
306
+
307
+ Set and read MIDI Control Change values on the instrument:
308
+
309
+ ```js
310
+ piano.setCC(64, 127); // sustain pedal on
311
+ piano.getCC(64); // => 127
312
+ piano.setCC(64, 0); // sustain pedal off
313
+ ```
314
+
315
+ Unset CCs default to `0` (matches MIDI's "undefined controller defaults to 0" convention).
316
+
317
+ #### Disposing
318
+
319
+ When you're done with an instrument, call `dispose()` to stop all voices, tear down the audio graph, and stop the scheduler. The instance must not be used after this call.
320
+
321
+ ```js
322
+ useEffect(() => {
323
+ const piano = SplendidGrandPiano(context);
324
+ return () => piano.dispose();
325
+ }, []);
326
+ ```
327
+
328
+ `disconnect()` is kept as a deprecated alias and continues to work.
329
+
302
330
  #### Events
303
331
 
304
332
  Two events are supported `onStart` and `onEnded`. Both callbacks will receive as parameter started note.
@@ -345,12 +373,14 @@ const piano = SplendidGrandPiano(context, { volume });
345
373
  piano.output.addEffect("reverb", reverb, 0.2);
346
374
  ```
347
375
 
348
- To change the mix level, use `output.sendEffect(name, mix)`:
376
+ To change the mix level, use `output.setEffectMix(name, mix)`:
349
377
 
350
378
  ```js
351
- piano.output.sendEffect("reverb", 0.5);
379
+ piano.output.setEffectMix("reverb", 0.5);
352
380
  ```
353
381
 
382
+ `output.sendEffect(name, mix)` is kept as a deprecated alias and continues to work.
383
+
354
384
  ### Cache requests
355
385
 
356
386
  The default sample sets are hosted on GitHub Pages, which rate-limits requests per second. That can be a problem, especially in a development environment with hot reload (most React frameworks).
@@ -643,10 +673,28 @@ This will download a WAV file you can attach to your issue or pull request.
643
673
 
644
674
  ## Instruments
645
675
 
676
+ ### Available instruments
677
+
678
+ Each instrument family exposes a synchronous helper that returns the names you can pass to its factory:
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[]>` |
689
+
690
+ `getVersilianInstruments` is async because the catalog is fetched from the network on first call (cached thereafter).
691
+
646
692
  ### Sampler
647
693
 
648
694
  An audio buffer sampler. Pass a `buffers` object with the files to be load:
649
695
 
696
+ #### Buffers mode
697
+
650
698
  ```js
651
699
  import { Sampler } from "smplr";
652
700
 
@@ -663,6 +711,37 @@ And then use the name of the buffer as note name:
663
711
  sampler.start({ note: "kick" });
664
712
  ```
665
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
+
666
745
  ### Soundfont
667
746
 
668
747
  A Soundfont player. By default it loads audio from Benjamin Gleitzman's package of
package/dist/index.d.mts CHANGED
@@ -17,15 +17,20 @@ type OutputChannel = Omit<Channel, "input">;
17
17
  declare class Channel {
18
18
  #private;
19
19
  readonly context: BaseAudioContext;
20
+ /** @deprecated Use `output.volume = n` instead. */
20
21
  readonly setVolume: (vol: number) => void;
21
22
  readonly input: AudioNode;
22
23
  constructor(context: BaseAudioContext, options?: Partial<ChannelConfig>);
24
+ get volume(): number;
25
+ set volume(value: number);
23
26
  get pan(): number;
24
27
  set pan(value: number);
25
28
  addInsert(effect: AudioNode | AudioInsert): void;
26
29
  addEffect(name: string, effect: AudioNode | {
27
30
  input: AudioNode;
28
31
  }, mixValue: number): void;
32
+ setEffectMix(name: string, mix: number): void;
33
+ /** @deprecated Use `setEffectMix(name, mix)` instead. */
29
34
  sendEffect(name: string, mix: number): void;
30
35
  disconnect(): void;
31
36
  }
@@ -109,7 +114,9 @@ type SmplrSamples = {
109
114
  /**
110
115
  * The top-level smplr.json descriptor. Passed to the Smplr constructor.
111
116
  */
112
- type SmplrJson = {
117
+ type SmplrPreset = {
118
+ /** Schema version. Omit for the current format. Reserved for future migrations. */
119
+ smplr?: "1.0";
113
120
  meta?: {
114
121
  name?: string;
115
122
  description?: string;
@@ -183,7 +190,7 @@ type VoiceParams = {
183
190
  };
184
191
 
185
192
  /**
186
- * Loads and caches AudioBuffers for all samples referenced in a SmplrJson.
193
+ * Loads and caches AudioBuffers for all samples referenced in a SmplrPreset.
187
194
  *
188
195
  * The cache is keyed by resolved URL, so the same audio file is never fetched
189
196
  * or decoded twice. Multiple Smplr instances can share one SampleLoader by
@@ -202,7 +209,7 @@ declare class SampleLoader {
202
209
  * - `buffers` in options: pre-loaded buffers — skips fetch for these names.
203
210
  * - All samples load in parallel. Failed samples are silently omitted.
204
211
  */
205
- load(json: SmplrJson, onProgressOrOptions?: ((loaded: number, total: number) => void) | {
212
+ load(json: SmplrPreset, onProgressOrOptions?: ((loaded: number, total: number) => void) | {
206
213
  buffers?: Map<string, AudioBuffer>;
207
214
  onProgress?: (loaded: number, total: number) => void;
208
215
  }): Promise<Map<string, AudioBuffer>>;
@@ -287,6 +294,19 @@ interface Smplr {
287
294
  start(event: NoteEvent): StopFn;
288
295
  stop(target?: StopTarget): void;
289
296
  setCC(cc: number, value: number): void;
297
+ /**
298
+ * Read the latest value set via `setCC`. Returns `0` for any CC that has
299
+ * not been set (matches MIDI's "undefined controller defaults to 0" convention).
300
+ */
301
+ getCC(cc: number): number;
302
+ /**
303
+ * Stop all voices, dispose the output channel, and stop the scheduler.
304
+ * The instance must not be used after this call — subsequent `start`/`stop`/
305
+ * `setCC`/`getCC`/`setControlValue`/`loadInstrument` calls throw. Subsequent
306
+ * `dispose()` calls are no-ops.
307
+ */
308
+ dispose(): void;
309
+ /** @deprecated Use `dispose()` instead. */
290
310
  disconnect(): void;
291
311
  }
292
312
  /**
@@ -304,7 +324,7 @@ interface PluginSmplr extends Smplr {
304
324
  *
305
325
  * Resolves when all samples are ready.
306
326
  */
307
- loadInstrument(json: SmplrJson, buffers?: Map<string, AudioBuffer>): Promise<void>;
327
+ loadInstrument(json: SmplrPreset, buffers?: Map<string, AudioBuffer>): Promise<void>;
308
328
  }
309
329
  /**
310
330
  * Permitted return shapes for an {@link SmplrPlugin}:
@@ -406,14 +426,16 @@ declare const DrumMachine: InstrumentFactory<Partial<DrumMachineConfig & {
406
426
  velocity?: number;
407
427
  onLoadProgress?: (progress: LoadProgress) => void;
408
428
  }>, DrumMachineExtras>;
429
+ /** Instance type returned by the {@link DrumMachine} factory. */
430
+ type DrumMachine = ReturnType<typeof DrumMachine>;
409
431
  /**
410
- * Convert a DrumMachineInstrument to a SmplrJson descriptor.
432
+ * Convert a DrumMachineInstrument to a SmplrPreset descriptor.
411
433
  *
412
434
  * Each sample gets a sequential MIDI number starting at 36 (GM drum map base).
413
435
  * Aliases are created for both the full sample name ("kick/1") and the group
414
436
  * name ("kick") so both forms work with Smplr.start({ note: "kick" }).
415
437
  */
416
- declare function drumMachineToSmplrJson(instrument: DrumMachineInstrument): SmplrJson;
438
+ declare function drumMachineToPreset(instrument: DrumMachineInstrument): SmplrPreset;
417
439
 
418
440
  /**
419
441
  * The result of an offline render. Provides the raw AudioBuffer and
@@ -482,22 +504,6 @@ declare function audioBufferToWav16(buffer: AudioBuffer): Blob;
482
504
  */
483
505
  declare function trimSilence(buffer: AudioBuffer): AudioBuffer;
484
506
 
485
- /**
486
- * Given a list of [midi, sampleName] pairs, return one entry per sample with
487
- * a keyRange that covers all MIDI notes closer to that sample than to any
488
- * neighbour. The first sample extends down to 0; the last extends up to 127.
489
- *
490
- * The boundary between two adjacent samples A and B (A < B) is placed at
491
- * `floor((A + B) / 2)`, matching the behaviour of the old `findNearestMidiInLayer`
492
- * which always resolved ties in favour of the lower sample.
493
- */
494
- type SpreadResult = {
495
- keyRange: [number, number];
496
- pitch: number;
497
- sample: string;
498
- };
499
- declare function spreadKeyRanges(samples: [number, string][]): SpreadResult[];
500
-
501
507
  /**
502
508
  * TransportClock
503
509
  *
@@ -715,6 +721,8 @@ declare const ElectricPiano: InstrumentFactory<Partial<{
715
721
  level: (value: number) => void;
716
722
  }>;
717
723
  }>;
724
+ /** Instance type returned by the {@link ElectricPiano} factory. */
725
+ type ElectricPiano = ReturnType<typeof ElectricPiano>;
718
726
 
719
727
  declare function getVersilianInstruments(): Promise<string[]>;
720
728
  type VersilianConfig = {
@@ -739,6 +747,8 @@ declare const Versilian: InstrumentFactory<Partial<VersilianConfig & {
739
747
  velocity?: number;
740
748
  onLoadProgress?: (progress: LoadProgress) => void;
741
749
  }>, {}>;
750
+ /** Instance type returned by the {@link Versilian} factory. */
751
+ type Versilian = ReturnType<typeof Versilian>;
742
752
  /**
743
753
  * Fetch the SFZ for a VCSL instrument and load it into `smplr`. Shared by
744
754
  * the {@link Versilian} and {@link Mallet} factories — not exported from the
@@ -746,14 +756,15 @@ declare const Versilian: InstrumentFactory<Partial<VersilianConfig & {
746
756
  */
747
757
  declare function loadVersilianInstrument(smplr: PluginSmplr, options: VersilianOptions): Promise<void>;
748
758
 
749
- declare function getMalletNames(): MalletName[];
759
+ declare function getMalletNames(): string[];
750
760
  declare const Mallet: InstrumentFactory<Partial<VersilianConfig & {
751
761
  destination?: AudioNode;
752
762
  volume?: number;
753
763
  velocity?: number;
754
764
  onLoadProgress?: (progress: LoadProgress) => void;
755
765
  }>, {}>;
756
- type MalletName = keyof typeof NAME_TO_PATH;
766
+ /** Instance type returned by the {@link Mallet} factory. */
767
+ type Mallet = ReturnType<typeof Mallet>;
757
768
  declare const NAME_TO_PATH: Record<string, string | undefined>;
758
769
 
759
770
  declare function getMellotronNames(): string[];
@@ -775,19 +786,21 @@ declare const Mellotron: InstrumentFactory<Partial<MellotronConfig & {
775
786
  decayTime?: number;
776
787
  onLoadProgress?: (progress: LoadProgress) => void;
777
788
  }>, {}>;
789
+ /** Instance type returned by the {@link Mellotron} factory. */
790
+ type Mellotron = ReturnType<typeof Mellotron>;
778
791
  type MellotronJsonConfig = {
779
792
  instrument: string;
780
793
  variation?: string;
781
794
  };
782
795
  /**
783
- * Convert a Mellotron files.json sample list to SmplrJson.
796
+ * Convert a Mellotron files.json sample list to SmplrPreset.
784
797
  *
785
798
  * - Filters by variation string if provided.
786
799
  * - Extracts MIDI from the first word of each sample name.
787
800
  * - Uses spreadKeyRanges so nearby notes pitch-shift to the nearest sample.
788
801
  * - All regions get loopAuto to produce tape-loop playback.
789
802
  */
790
- declare function mellotronToSmplrJson(sampleNames: string[], config: MellotronJsonConfig): SmplrJson;
803
+ declare function mellotronToPreset(sampleNames: string[], config: MellotronJsonConfig): SmplrPreset;
791
804
 
792
805
  declare const PARAMS: readonly ["preDelay", "bandwidth", "inputDiffusion1", "inputDiffusion2", "decay", "decayDiffusion1", "decayDiffusion2", "damping", "excursionRate", "excursionDepth", "wet", "dry"];
793
806
  declare class Reverb {
@@ -807,30 +820,40 @@ type AudioBuffers = Record<string | number, AudioBuffer | undefined>;
807
820
  */
808
821
  type AudioBuffersLoader = (context: BaseAudioContext, buffers: AudioBuffers) => Promise<void>;
809
822
 
810
- type SamplerConfig = {
823
+ type SamplerBase = {
811
824
  storage?: Storage;
812
- detune: number;
813
- volume: number;
814
- velocity: number;
825
+ detune?: number;
826
+ volume?: number;
827
+ velocity?: number;
815
828
  decayTime?: number;
816
829
  lpfCutoffHz?: number;
817
- destination: AudioNode;
818
- buffers: Record<string | number, string | AudioBuffer | AudioBuffers> | AudioBuffersLoader;
819
- volumeToGain: (volume: number) => number;
830
+ destination?: AudioNode;
831
+ volumeToGain?: (volume: number) => number;
820
832
  onLoadProgress?: (progress: LoadProgress) => void;
821
833
  };
822
- /**
823
- * A Sampler instrument.
824
- */
825
- declare const Sampler: InstrumentFactory<Partial<SamplerConfig>, {}>;
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
+ };
826
849
  type SamplerJsonOptions = Pick<SamplerConfig, "decayTime" | "lpfCutoffHz" | "detune">;
827
850
  type InternalConvertResult = {
828
- json: SmplrJson;
851
+ json: SmplrPreset;
829
852
  urlMap: Record<string, string>;
830
853
  preloaded: Map<string, AudioBuffer>;
831
854
  };
832
855
  /**
833
- * 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.
834
857
  *
835
858
  * - Keys that are valid MIDI names/numbers → MIDI-mapped regions.
836
859
  * If ALL keys are MIDI-parseable, spread key ranges (pitch-shifting).
@@ -839,7 +862,20 @@ type InternalConvertResult = {
839
862
  * - AudioBuffer values → pre-loaded map (no fetch).
840
863
  * - String URL values → urlMap (fetched asynchronously by caller).
841
864
  */
842
- 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;
866
+ /**
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.
875
+ */
876
+ declare const Sampler: InstrumentFactory<SamplerConfig, SamplerExtras>;
877
+ /** Instance type returned by the {@link Sampler} factory. */
878
+ type Sampler = ReturnType<typeof Sampler>;
843
879
 
844
880
  declare function getSmolkenNames(): string[];
845
881
  type SmolkenConfig = {
@@ -858,6 +894,8 @@ declare const Smolken: InstrumentFactory<Partial<SmolkenConfig & {
858
894
  velocity?: number;
859
895
  onLoadProgress?: (progress: LoadProgress) => void;
860
896
  }>, {}>;
897
+ /** Instance type returned by the {@link Smolken} factory. */
898
+ type Smolken = ReturnType<typeof Smolken>;
861
899
 
862
900
  type LoopData = Record<number, [number, number]>;
863
901
 
@@ -884,11 +922,13 @@ declare const Soundfont: InstrumentFactory<Partial<SoundfontConfig & {
884
922
  velocity?: number;
885
923
  onLoadProgress?: (progress: LoadProgress) => void;
886
924
  }>, {}>;
925
+ /** Instance type returned by the {@link Soundfont} factory. */
926
+ type Soundfont = ReturnType<typeof Soundfont>;
887
927
  /**
888
- * 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.
889
929
  * Uses spreadKeyRanges so notes between recorded pitches pitch-shift correctly.
890
930
  */
891
- declare function soundfontToSmplrJson(noteNames: string[], loopData?: LoopData): SmplrJson;
931
+ declare function soundfontToPreset(noteNames: string[], loopData?: LoopData): SmplrPreset;
892
932
 
893
933
  type Sf2 = {
894
934
  instruments: Sf2Instrument[];
@@ -926,8 +966,8 @@ type Soundfont2Options = {
926
966
  volume?: number;
927
967
  velocity?: number;
928
968
  };
929
- declare function sf2InstrumentToSmplrJson(sf2Instrument: Sf2Instrument, context: BaseAudioContext): {
930
- json: SmplrJson;
969
+ declare function sf2InstrumentToPreset(sf2Instrument: Sf2Instrument, context: BaseAudioContext): {
970
+ json: SmplrPreset;
931
971
  buffers: Map<string, AudioBuffer>;
932
972
  };
933
973
  type Soundfont2SamplerExtras = {
@@ -935,6 +975,8 @@ type Soundfont2SamplerExtras = {
935
975
  loadInstrument(instrumentName: string): Promise<void> | undefined;
936
976
  };
937
977
  declare const Soundfont2Sampler: InstrumentFactory<Soundfont2Options, Soundfont2SamplerExtras>;
978
+ /** Instance type returned by the {@link Soundfont2Sampler} factory. */
979
+ type Soundfont2Sampler = ReturnType<typeof Soundfont2Sampler>;
938
980
 
939
981
  /**
940
982
  * Configuration options for SplendidGrandPiano.
@@ -946,7 +988,7 @@ type SplendidGrandPianoConfig = {
946
988
  detune: number;
947
989
  /** Default velocity (0–127) when not specified per note. */
948
990
  velocity: number;
949
- /** Release time in seconds. Maps to SmplrJson defaults.ampRelease. */
991
+ /** Release time in seconds. Maps to SmplrPreset defaults.ampRelease. */
950
992
  decayTime: number;
951
993
  /** Destination audio node. Defaults to context.destination. */
952
994
  destination?: AudioNode;
@@ -963,9 +1005,11 @@ type SplendidGrandPianoConfig = {
963
1005
  };
964
1006
  };
965
1007
  declare const SplendidGrandPiano: InstrumentFactory<Partial<SplendidGrandPianoConfig>, {}>;
1008
+ /** Instance type returned by the {@link SplendidGrandPiano} factory. */
1009
+ type SplendidGrandPiano = ReturnType<typeof SplendidGrandPiano>;
966
1010
  type PianoJsonOptions = Pick<SplendidGrandPianoConfig, "baseUrl" | "detune" | "decayTime" | "notesToLoad" | "formats">;
967
1011
  /**
968
- * Convert the LAYERS array and user options into a SmplrJson descriptor.
1012
+ * Convert the LAYERS array and user options into a SmplrPreset descriptor.
969
1013
  *
970
1014
  * Each layer becomes a SmplrGroup with its velRange. If `notesToLoad` is
971
1015
  * specified, layers and samples are filtered accordingly. The PPP layer
@@ -974,8 +1018,7 @@ type PianoJsonOptions = Pick<SplendidGrandPianoConfig, "baseUrl" | "detune" | "d
974
1018
  * `spreadKeyRanges` is used to pre-compute which key range each sample
975
1019
  * covers, replacing the old on-the-fly `findNearestMidiInLayer` logic.
976
1020
  */
977
- declare function pianoToSmplrJson(options: PianoJsonOptions): SmplrJson;
978
-
1021
+ declare function pianoToPreset(options: PianoJsonOptions): SmplrPreset;
979
1022
  declare const LAYERS: ({
980
1023
  name: string;
981
1024
  vel_range: number[];
@@ -988,4 +1031,4 @@ declare const LAYERS: ({
988
1031
  cutoff?: undefined;
989
1032
  })[];
990
1033
 
991
- 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 SpreadResult, 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, spreadKeyRanges, 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 };