smplr 0.24.0 → 0.25.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
@@ -4,7 +4,7 @@
4
4
 
5
5
  > `smplr` is a collection of sampled instruments for Web Audio API ready to be used with no setup required.
6
6
 
7
- Examples:
7
+ ## Quick start
8
8
 
9
9
  **Play a note from a General MIDI soundfont:**
10
10
 
@@ -57,17 +57,13 @@ 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.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
-
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
-
64
60
  #### Library goals
65
61
 
66
62
  - No setup: specifically, all samples are online, so no need for a server.
67
63
  - Easy to use: everything should be intuitive for non-experienced developers
68
64
  - Decent sounding: uses high quality open source samples. For better or worse, it is sample based 🤷
69
65
 
70
- ## Setup
66
+ ## Installation
71
67
 
72
68
  You can install the library with a package manager or use it directly by importing from the browser.
73
69
 
@@ -105,17 +101,35 @@ You can import directly from the browser. For example:
105
101
 
106
102
  The package needs to be served as a URL from a service like [unpkg](https://unpkg.com) or similar.
107
103
 
108
- > To author your own instrument or publish a third-party package, see the [Defining an instrument](./AUTHORING.md) guide.
104
+ ## Available instruments
109
105
 
110
- ## Documentation
106
+ `smplr` ships eleven instruments out of the box. Pick one and jump to its section in the [Instrument reference](#instrument-reference) for setup details.
111
107
 
112
- ### Defining an instrument
108
+ | Instrument | Description | Names helper |
109
+ | ------------------------------------------- | ----------------------------------------- | ----------------------------- |
110
+ | [`Sampler`](#sampler) | Your own buffers or SFZ-style preset | — |
111
+ | [`Soundfont`](#soundfont) | General MIDI soundfonts | `getSoundfontNames()` |
112
+ | [`SplendidGrandPiano`](#splendidgrandpiano) | Sampled Steinway grand, 4 velocity layers | — |
113
+ | [`ElectricPiano`](#electric-piano) | CP80, PianetT, Wurlitzer, TX81Z | `getElectricPianoNames()` |
114
+ | [`DrumMachine`](#drum-machines) | Classic drum machines (TR-808, …) | `getDrumMachineNames()` |
115
+ | [`DrumAbuse`](#drumabuse) | ~210 machines (Synthabuse collection) | `getDrumAbuseMachineNames()` |
116
+ | [`Mallet`](#mallets) | VCSL mallets | `getMalletNames()` |
117
+ | [`Mellotron`](#mellotron) | Mellotron archive samples | `getMellotronNames()` |
118
+ | [`Smolken`](#smolken-double-bass) | Smolken double bass (Arco/Pizz/Switched) | `getSmolkenNames()` |
119
+ | [`Versilian`](#versilian) | VCSL multi-instrument (partial support) | `getVersilianInstruments()` * |
120
+ | [`Soundfont2`](#soundfont2) | Reads .sf2 files directly | — |
113
121
 
114
- `smplr` ships ten instruments out of the box `SplendidGrandPiano`, `Soundfont`, `DrumMachine`, `ElectricPiano`, `Mallet`, `Mellotron`, `Smolken`, `Versilian`, `Sampler`, `Soundfont2`. If none of them fit your use case, you can author your own with the `Instrument` builder and the `Smplr` interface.
122
+ `*` `getVersilianInstruments` is async because the catalog is fetched from the network on first call (cached thereafter).
115
123
 
116
- See **[Defining an instrument](./AUTHORING.md)** for the full authoring guide sync and async examples, third-party package layout, and how to use `Smplr` as a TypeScript type for generic helpers.
124
+ Each names helper returns the strings you can pass to the corresponding factory's `instrument` option.
125
+
126
+ If none of the bundled instruments fits your use case, you can author your own — see [Defining your own instrument](#defining-your-own-instrument).
127
+
128
+ ## Using an instrument
129
+
130
+ Every smplr instrument follows the same usage pattern. This section covers what's shared across all of them; for instrument-specific options, see the [Instrument reference](#instrument-reference).
117
131
 
118
- ### Create and load an instrument
132
+ ### Create and load
119
133
 
120
134
  Every smplr instrument is a factory function: call it with an `AudioContext` and an options object to get back an instance.
121
135
 
@@ -127,29 +141,18 @@ const piano = SplendidGrandPiano(context, { decayTime: 0.5 });
127
141
  const marimba = Soundfont(context, { instrument: "marimba" });
128
142
  ```
129
143
 
130
- > **Compatibility note:** All factories also support the `new` keyword — `new SplendidGrandPiano(context)` produces the same instance as `SplendidGrandPiano(context)`. Code from earlier `smplr` versions keeps working unchanged. Editors will mark the `new` form as `@deprecated` to nudge new code toward the call form; both remain supported throughout the 1.x line.
131
-
132
144
  #### Wait for audio loading
133
145
 
134
- You can start playing notes as soon as one audio is loaded. But if you want to wait for all of them, you can use the `load` property that returns a promise:
135
-
136
- ```js
137
- piano.load.then(() => {
138
- // now the piano is fully loaded
139
- });
140
- ```
146
+ You can start playing notes as soon as one sample is loaded. To wait for all of them, await either:
141
147
 
142
- Since the promise returns the instrument instance, you can create and wait in a single line:
148
+ - `piano.ready` resolves to `void` (preferred for new code).
149
+ - `piano.load` — resolves to the instrument itself, so you can create and await in one line:
143
150
 
144
151
  ```js
145
152
  const piano = await SplendidGrandPiano(context).load;
146
153
  ```
147
154
 
148
- The pre-1.0 `new`-prefixed form continues to work — `const piano = await new SplendidGrandPiano(context).load` resolves to the same instrument. This is the documented backward-compat path for code from earlier `smplr` versions.
149
-
150
- > **New in 1.0:** prefer `await piano.ready` for new code. It resolves to `void` (not the instrument) and won't be removed — `.load` is kept as a deprecated alias for compatibility.
151
-
152
- ⚠️ In versions lower than 0.8.0 a `loaded()` function was exposed instead.
155
+ > Upgrading from older versions? See [MIGRATE.md](./MIGRATE.md).
153
156
 
154
157
  #### Load progress
155
158
 
@@ -168,7 +171,7 @@ console.log(piano.loadProgress); // { loaded: 12, total: 48 }
168
171
 
169
172
  `total` is known before loading starts, so you can display a determinate progress bar.
170
173
 
171
- #### Shared configuration options
174
+ ### Shared configuration options
172
175
 
173
176
  All instruments share some configuration options, passed as the second argument to the factory. Every field is optional:
174
177
 
@@ -177,52 +180,14 @@ All instruments share some configuration options, passed as the second argument
177
180
  - `pan`: stereo pan, -1 (full left) to +1 (full right). 0 by default.
178
181
  - `destination`: the `AudioNode` the instrument writes to. `AudioContext.destination` by default.
179
182
  - `volumeToGain`: a function to map MIDI volume to a linear gain. Uses the MIDI standard curve by default.
180
- - `storage`: a [storage backend](#cache-requests) used to fetch sample buffers. `HttpStorage` by default.
183
+ - `storage`: a [storage backend](#caching-samples) used to fetch sample buffers. `HttpStorage` by default.
181
184
  - `loader`: a shared `SampleLoader` instance. Pass the same loader to multiple instruments to cache buffers across them (see [Buffer reuse](#buffer-reuse)).
182
185
  - `scheduler`: a shared `Scheduler` instance. Construct your own to tune scheduling — for example, `Scheduler(context, { lookaheadMs: 100, intervalMs: 25 })` — or omit to get a per-instrument default.
183
186
  - `onLoadProgress`: a function called after each sample buffer is decoded. Receives `{ loaded, total }` where `total` is the full count known before loading starts.
184
187
  - `onStart`: called when a note is dispatched to the audio engine. Receives the started note. See ⚠️ note under [Events](#events) on timing precision.
185
188
  - `onEnded`: called when each voice's audio node ends. Receives the started note.
186
189
 
187
- #### Usage with standardized-audio-context
188
-
189
- This package should be compatible with [standardized-audio-context](https://github.com/chrisguttandin/standardized-audio-context):
190
-
191
- ```js
192
- import { AudioContext } from "standardized-audio-context";
193
-
194
- const context = new AudioContext();
195
- const piano = SplendidGrandPiano(context);
196
- ```
197
-
198
- However, if you are using Typescript, you might need to "force cast" the types:
199
-
200
- ```ts
201
- import { Soundfont } from "smplr";
202
- import { AudioContext as StandardizedAudioContext } from "standardized-audio-context";
203
-
204
- const context = new StandardizedAudioContext() as unknown as AudioContext;
205
- const marimba = Soundfont(context, { instrument: "marimba" });
206
- ```
207
-
208
- In case you need to use the `Reverb` module (or any other module that needs `AudioWorkletNode`) you need to enforce to use the one from `standardized-audio-context` package. Here is how:
209
-
210
- ```ts
211
- import {
212
- AudioWorkletNode,
213
- IAudioContext,
214
- AudioContext as StandardizedAudioContext,
215
- } from "standardized-audio-context";
216
-
217
- window.AudioWorkletNode = AudioWorkletNode as any;
218
- const context = new StandardizedAudioContext() as unknown as AudioContext;
219
-
220
- // ... rest of the code
221
- ```
222
-
223
- See [standardized-audio-context issue #897](https://github.com/chrisguttandin/standardized-audio-context/issues/897) for background on why the cast is required.
224
-
225
- ### Play
190
+ ### Play notes
226
191
 
227
192
  #### Start and stop notes
228
193
 
@@ -289,7 +254,9 @@ sampler.start({
289
254
 
290
255
  If `loop` is true but `loopStart` or `loopEnd` are not specified, 0 and total duration will be used by default, respectively.
291
256
 
292
- #### Change volume
257
+ ### Output
258
+
259
+ #### Volume
293
260
 
294
261
  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
262
 
@@ -298,8 +265,6 @@ piano.output.volume = 80;
298
265
  piano.output.volume; // => 80
299
266
  ```
300
267
 
301
- `output.setVolume(n)` is kept as a deprecated alias and continues to work.
302
-
303
268
  ⚠️ `volume` is global to the instrument, but `velocity` is specific for each note.
304
269
 
305
270
  #### Pan, detune, and reverse
@@ -330,20 +295,28 @@ piano.setCC(64, 0); // sustain pedal off
330
295
 
331
296
  Unset CCs default to `0` (matches MIDI's "undefined controller defaults to 0" convention).
332
297
 
333
- #### Disposing
298
+ ### Effects
334
299
 
335
- 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.
300
+ #### Reverb
301
+
302
+ A packaged version of the [DattorroReverbNode](https://github.com/khoin/DattorroReverbNode) algorithmic reverb is included.
303
+
304
+ Use `output.addEffect(name, effect, mix)` to connect an effect using a send bus:
336
305
 
337
306
  ```js
338
- useEffect(() => {
339
- const piano = SplendidGrandPiano(context);
340
- return () => piano.dispose();
341
- }, []);
307
+ import { Reverb, SplendidGrandPiano } from "smplr";
308
+ const reverb = Reverb(context);
309
+ const piano = SplendidGrandPiano(context, { volume });
310
+ piano.output.addEffect("reverb", reverb, 0.2);
342
311
  ```
343
312
 
344
- `disconnect()` is kept as a deprecated alias and continues to work.
313
+ To change the mix level, use `output.setEffectMix(name, mix)`:
345
314
 
346
- #### Events
315
+ ```js
316
+ piano.output.setEffectMix("reverb", 0.5);
317
+ ```
318
+
319
+ ### Events
347
320
 
348
321
  Two events are supported `onStart` and `onEnded`. Both callbacks will receive as parameter started note.
349
322
 
@@ -374,30 +347,18 @@ Global callbacks will be invoked regardless of whether local events are defined.
374
347
 
375
348
  ⚠️ The invocation time of `onStart` is not exact: it fires slightly before the audio actually starts, by up to the scheduler's lookahead window (200ms by default; configurable via the `scheduler` option — see [Shared configuration options](#shared-configuration-options)).
376
349
 
377
- ### Effects
350
+ ### Dispose
378
351
 
379
- #### Reverb
380
-
381
- A packaged version of the [DattorroReverbNode](https://github.com/khoin/DattorroReverbNode) algorithmic reverb is included.
382
-
383
- Use `output.addEffect(name, effect, mix)` to connect an effect using a send bus:
384
-
385
- ```js
386
- import { Reverb, SplendidGrandPiano } from "smplr";
387
- const reverb = Reverb(context);
388
- const piano = SplendidGrandPiano(context, { volume });
389
- piano.output.addEffect("reverb", reverb, 0.2);
390
- ```
391
-
392
- To change the mix level, use `output.setEffectMix(name, mix)`:
352
+ 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.
393
353
 
394
354
  ```js
395
- piano.output.setEffectMix("reverb", 0.5);
355
+ useEffect(() => {
356
+ const piano = SplendidGrandPiano(context);
357
+ return () => piano.dispose();
358
+ }, []);
396
359
  ```
397
360
 
398
- `output.sendEffect(name, mix)` is kept as a deprecated alias and continues to work.
399
-
400
- ### Cache requests
361
+ ### Caching samples
401
362
 
402
363
  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).
403
364
 
@@ -414,9 +375,47 @@ const piano = SplendidGrandPiano(context, { storage });
414
375
 
415
376
  ⚠️ `CacheStorage` is based on the [Cache API](https://developer.mozilla.org/en-US/docs/Web/API/Cache) and only works in secure environments that run over `https`. Check your framework's documentation for local-HTTPS setup — for example [next-dev-https](https://www.npmjs.com/package/next-dev-https) for Next.js or [vite-plugin-mkcert](https://github.com/liuweiGL/vite-plugin-mkcert) for Vite.
416
377
 
378
+ ### Using with standardized-audio-context
379
+
380
+ This package should be compatible with [standardized-audio-context](https://github.com/chrisguttandin/standardized-audio-context):
381
+
382
+ ```js
383
+ import { AudioContext } from "standardized-audio-context";
384
+
385
+ const context = new AudioContext();
386
+ const piano = SplendidGrandPiano(context);
387
+ ```
388
+
389
+ However, if you are using Typescript, you might need to "force cast" the types:
390
+
391
+ ```ts
392
+ import { Soundfont } from "smplr";
393
+ import { AudioContext as StandardizedAudioContext } from "standardized-audio-context";
394
+
395
+ const context = new StandardizedAudioContext() as unknown as AudioContext;
396
+ const marimba = Soundfont(context, { instrument: "marimba" });
397
+ ```
398
+
399
+ In case you need to use the `Reverb` module (or any other module that needs `AudioWorkletNode`) you need to enforce to use the one from `standardized-audio-context` package. Here is how:
400
+
401
+ ```ts
402
+ import {
403
+ AudioWorkletNode,
404
+ IAudioContext,
405
+ AudioContext as StandardizedAudioContext,
406
+ } from "standardized-audio-context";
407
+
408
+ window.AudioWorkletNode = AudioWorkletNode as any;
409
+ const context = new StandardizedAudioContext() as unknown as AudioContext;
410
+
411
+ // ... rest of the code
412
+ ```
413
+
414
+ See [standardized-audio-context issue #897](https://github.com/chrisguttandin/standardized-audio-context/issues/897) for background on why the cast is required.
415
+
417
416
  ## Sequencer
418
417
 
419
- `Sequencer` schedules notes from one or more tracks against any smplr instrument with sample-accurate timing. Constructed as `Sequencer(context, opts)` (the `new Sequencer(...)` form also still works as a deprecated alias).
418
+ `Sequencer` schedules notes from one or more tracks against any smplr instrument with sample-accurate timing.
420
419
 
421
420
  ```js
422
421
  import { Sequencer, SplendidGrandPiano, DrumMachine } from "smplr";
@@ -712,7 +711,7 @@ seq.on("patternChange", (idx) => ui.highlightPattern(idx));
712
711
 
713
712
  ---
714
713
 
715
- ## Export Audio
714
+ ## Offline rendering
716
715
 
717
716
  Render audio offline (faster than real-time) and export it as a WAV file. Uses `OfflineAudioContext` under the hood.
718
717
 
@@ -791,23 +790,9 @@ This will download a WAV file you can attach to your issue or pull request.
791
790
 
792
791
  ---
793
792
 
794
- ## Instruments
795
-
796
- ### Available instruments
793
+ ## Instrument reference
797
794
 
798
- Each instrument family exposes a synchronous helper that returns the names you can pass to its factory:
799
-
800
- | Factory | Names helper |
801
- | --------------- | ---------------------------------------------- |
802
- | `Soundfont` | `getSoundfontNames(): string[]` |
803
- | `ElectricPiano` | `getElectricPianoNames(): string[]` |
804
- | `Mallet` | `getMalletNames(): string[]` |
805
- | `Mellotron` | `getMellotronNames(): string[]` |
806
- | `DrumMachine` | `getDrumMachineNames(): string[]` |
807
- | `Smolken` | `getSmolkenNames(): string[]` |
808
- | `Versilian` | `getVersilianInstruments(): Promise<string[]>` |
809
-
810
- `getVersilianInstruments` is async because the catalog is fetched from the network on first call (cached thereafter).
795
+ Detailed configuration for each bundled instrument. For the shared API (load, play, output, effects, events), see [Using an instrument](#using-an-instrument).
811
796
 
812
797
  ### Sampler
813
798
 
@@ -1025,6 +1010,61 @@ drums.start("kick"); // Play the first sample of the group
1025
1010
  drums.start("kick-1"); // Play this specific sample
1026
1011
  ```
1027
1012
 
1013
+ ### DrumAbuse
1014
+
1015
+ Sampled instrument for the [Synthabuse](https://www.youtube.com/watch?v=Ay-U9eYKmGA) drum-machine collection — 5 packs covering ~210 classic drum machines and synths. Samples hosted at `smpldsnds.github.io/drum-abuse-{pack}/`.
1016
+
1017
+ Two source modes: load a single machine's full kit, or load a cross-machine instrument list from a pack.
1018
+
1019
+ #### Machine mode
1020
+
1021
+ ```js
1022
+ import { DrumAbuse, getDrumAbuseMachineNames } from "smplr";
1023
+
1024
+ const machines = getDrumAbuseMachineNames(); // ~210 machine ids
1025
+
1026
+ const context = new AudioContext();
1027
+ const drums = DrumAbuse(context, {
1028
+ source: { kind: "machine", machine: "roland-tr-808" },
1029
+ });
1030
+ await drums.load;
1031
+
1032
+ drums.start({ note: "kick" });
1033
+
1034
+ // Samples are grouped by instrument name, like DrumMachine:
1035
+ drums.getGroupNames(); // => ["kick", "snare", "hi-hat", ...]
1036
+ drums.getSampleNamesForGroup("kick"); // => ["kick/1", "kick/2", ...]
1037
+ drums.start({ note: "kick" }); // first sample in the group
1038
+ drums.start({ note: "kick/1" }); // a specific sample
1039
+ ```
1040
+
1041
+ If a machine has more than one sample set, pass `set` to pick a specific one. Omit to load the first set.
1042
+
1043
+ ```js
1044
+ const drums = DrumAbuse(context, {
1045
+ source: { kind: "machine", machine: "roland-tr-808", set: "kit-a" },
1046
+ });
1047
+ ```
1048
+
1049
+ #### Pack mode
1050
+
1051
+ A pack is a cross-machine catalog of named instruments (e.g. all the kicks across `vol1`). Pass `source: { kind: "pack", pack, instrument }`:
1052
+
1053
+ ```js
1054
+ import {
1055
+ DrumAbuse,
1056
+ getDrumAbusePackNames,
1057
+ getDrumAbuseMachinesForPack,
1058
+ } from "smplr";
1059
+
1060
+ getDrumAbusePackNames(); // => ["vol1", "vol2", "vol3", "vol4", "vol5"]
1061
+ getDrumAbuseMachinesForPack("vol1"); // => machine ids in vol1
1062
+
1063
+ const drums = DrumAbuse(new AudioContext(), {
1064
+ source: { kind: "pack", pack: "vol1", instrument: "bass-drum" },
1065
+ });
1066
+ ```
1067
+
1028
1068
  ### Smolken double bass
1029
1069
 
1030
1070
  ```js
@@ -1055,7 +1095,7 @@ const versilian = Versilian(context, { instrument: instrumentNames[0] });
1055
1095
 
1056
1096
  ### Soundfont2
1057
1097
 
1058
- Sampler capable of reading .sf2 files directly. Previously named `Soundfont2Sampler`; the old name remains as a deprecated alias.
1098
+ Sampler capable of reading .sf2 files directly.
1059
1099
 
1060
1100
  ```ts
1061
1101
  import { Soundfont2 } from "smplr";
@@ -1078,6 +1118,16 @@ sampler.load.then(() => {
1078
1118
 
1079
1119
  Still limited support. API may vary.
1080
1120
 
1121
+ ## Defining your own instrument
1122
+
1123
+ If none of the bundled instruments fits your use case, you can author your own with the `Instrument` builder and the `Smplr` interface.
1124
+
1125
+ See **[Defining an instrument](./AUTHORING.md)** for the full authoring guide — sync and async examples, third-party package layout, and how to use `Smplr` as a TypeScript type for generic helpers.
1126
+
1127
+ ## Upgrading
1128
+
1129
+ `smplr` is approaching 1.0; pre-1.0 APIs keep working as deprecated aliases. See [MIGRATE.md](./MIGRATE.md) for the full compatibility table and [CHANGELOG](https://github.com/danigb/smplr/blob/main/CHANGELOG.md) for per-release detail.
1130
+
1081
1131
  ## License
1082
1132
 
1083
1133
  MIT License
package/dist/index.d.mts CHANGED
@@ -478,6 +478,55 @@ type DrumMachine = ReturnType<typeof DrumMachine>;
478
478
  */
479
479
  declare function drumMachineToPreset(instrument: DrumMachineInstrument): SmplrPreset;
480
480
 
481
+ declare const DRUM_ABUSE_PACKS: readonly ["vol1", "vol2", "vol3", "vol4", "vol5"];
482
+ type DrumAbusePackId = (typeof DRUM_ABUSE_PACKS)[number];
483
+ declare function getDrumAbuseMachineNames(): string[];
484
+ declare function getDrumAbuseMachinesForPack(pack: DrumAbusePackId): readonly string[];
485
+ declare function getDrumAbusePackNames(): readonly DrumAbusePackId[];
486
+ declare function getDrumAbuseMachinePack(id: string): DrumAbusePackId | undefined;
487
+ /** Build a full sample URL. Exported so external row-level Sampler use
488
+ * (e.g. the sequencer engine) can share the same URL convention. */
489
+ declare function drumAbuseSampleUrl(pack: DrumAbusePackId, urlPath: string, fileNoExt: string, format?: string, baseUrl?: string): string;
490
+ type DrumAbuseSource = {
491
+ kind: "machine";
492
+ machine: string;
493
+ set?: string;
494
+ } | {
495
+ kind: "pack";
496
+ pack: DrumAbusePackId;
497
+ instrument: string;
498
+ };
499
+ type DrumAbuseConfig = {
500
+ source: DrumAbuseSource;
501
+ baseUrl: string;
502
+ storage: Storage;
503
+ };
504
+ type DrumAbuseOptions = Partial<DrumAbuseConfig & {
505
+ destination?: AudioNode;
506
+ volume?: number;
507
+ pan?: number;
508
+ velocity?: number;
509
+ onLoadProgress?: (progress: LoadProgress) => void;
510
+ }>;
511
+ type DrumAbuseExtras = {
512
+ readonly mode: "machine" | "pack";
513
+ getSampleNames(): string[];
514
+ getGroupNames(): string[];
515
+ getSampleNamesForGroup(groupName: string): string[];
516
+ getMachineId(): string | null;
517
+ getSetPath(): string | null;
518
+ getPackId(): DrumAbusePackId;
519
+ start(event: NoteEvent): StopFn;
520
+ };
521
+ declare const DrumAbuse: InstrumentFactory<Partial<DrumAbuseConfig & {
522
+ destination?: AudioNode;
523
+ volume?: number;
524
+ pan?: number;
525
+ velocity?: number;
526
+ onLoadProgress?: (progress: LoadProgress) => void;
527
+ }>, DrumAbuseExtras>;
528
+ type DrumAbuse = ReturnType<typeof DrumAbuse>;
529
+
481
530
  /**
482
531
  * The result of an offline render. Provides the raw AudioBuffer and
483
532
  * lazy WAV encoding / download convenience methods.
@@ -1224,4 +1273,4 @@ declare const LAYERS: ({
1224
1273
  cutoff?: undefined;
1225
1274
  })[];
1226
1275
 
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 };
1276
+ export { type AddTrackOptions, CacheStorage, DRUM_ABUSE_PACKS, DrumAbuse, type DrumAbuseConfig, type DrumAbuseExtras, type DrumAbuseOptions, type DrumAbusePackId, type DrumAbuseSource, 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, drumAbuseSampleUrl, drumMachineToPreset, getDrumAbuseMachineNames, getDrumAbuseMachinePack, getDrumAbuseMachinesForPack, getDrumAbusePackNames, getDrumMachineNames, getElectricPianoNames, getMalletNames, getMellotronNames, getSmolkenNames, getSoundfontKits, getSoundfontNames, getVersilianInstruments, loadVersilianInstrument, mellotronToPreset, pianoToPreset, renderOffline, samplerToPreset, sf2InstrumentToPreset, soundfontToPreset, trimSilence };
package/dist/index.d.ts CHANGED
@@ -478,6 +478,55 @@ type DrumMachine = ReturnType<typeof DrumMachine>;
478
478
  */
479
479
  declare function drumMachineToPreset(instrument: DrumMachineInstrument): SmplrPreset;
480
480
 
481
+ declare const DRUM_ABUSE_PACKS: readonly ["vol1", "vol2", "vol3", "vol4", "vol5"];
482
+ type DrumAbusePackId = (typeof DRUM_ABUSE_PACKS)[number];
483
+ declare function getDrumAbuseMachineNames(): string[];
484
+ declare function getDrumAbuseMachinesForPack(pack: DrumAbusePackId): readonly string[];
485
+ declare function getDrumAbusePackNames(): readonly DrumAbusePackId[];
486
+ declare function getDrumAbuseMachinePack(id: string): DrumAbusePackId | undefined;
487
+ /** Build a full sample URL. Exported so external row-level Sampler use
488
+ * (e.g. the sequencer engine) can share the same URL convention. */
489
+ declare function drumAbuseSampleUrl(pack: DrumAbusePackId, urlPath: string, fileNoExt: string, format?: string, baseUrl?: string): string;
490
+ type DrumAbuseSource = {
491
+ kind: "machine";
492
+ machine: string;
493
+ set?: string;
494
+ } | {
495
+ kind: "pack";
496
+ pack: DrumAbusePackId;
497
+ instrument: string;
498
+ };
499
+ type DrumAbuseConfig = {
500
+ source: DrumAbuseSource;
501
+ baseUrl: string;
502
+ storage: Storage;
503
+ };
504
+ type DrumAbuseOptions = Partial<DrumAbuseConfig & {
505
+ destination?: AudioNode;
506
+ volume?: number;
507
+ pan?: number;
508
+ velocity?: number;
509
+ onLoadProgress?: (progress: LoadProgress) => void;
510
+ }>;
511
+ type DrumAbuseExtras = {
512
+ readonly mode: "machine" | "pack";
513
+ getSampleNames(): string[];
514
+ getGroupNames(): string[];
515
+ getSampleNamesForGroup(groupName: string): string[];
516
+ getMachineId(): string | null;
517
+ getSetPath(): string | null;
518
+ getPackId(): DrumAbusePackId;
519
+ start(event: NoteEvent): StopFn;
520
+ };
521
+ declare const DrumAbuse: InstrumentFactory<Partial<DrumAbuseConfig & {
522
+ destination?: AudioNode;
523
+ volume?: number;
524
+ pan?: number;
525
+ velocity?: number;
526
+ onLoadProgress?: (progress: LoadProgress) => void;
527
+ }>, DrumAbuseExtras>;
528
+ type DrumAbuse = ReturnType<typeof DrumAbuse>;
529
+
481
530
  /**
482
531
  * The result of an offline render. Provides the raw AudioBuffer and
483
532
  * lazy WAV encoding / download convenience methods.
@@ -1224,4 +1273,4 @@ declare const LAYERS: ({
1224
1273
  cutoff?: undefined;
1225
1274
  })[];
1226
1275
 
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 };
1276
+ export { type AddTrackOptions, CacheStorage, DRUM_ABUSE_PACKS, DrumAbuse, type DrumAbuseConfig, type DrumAbuseExtras, type DrumAbuseOptions, type DrumAbusePackId, type DrumAbuseSource, 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, drumAbuseSampleUrl, drumMachineToPreset, getDrumAbuseMachineNames, getDrumAbuseMachinePack, getDrumAbuseMachinesForPack, getDrumAbusePackNames, getDrumMachineNames, getElectricPianoNames, getMalletNames, getMellotronNames, getSmolkenNames, getSoundfontKits, getSoundfontNames, getVersilianInstruments, loadVersilianInstrument, mellotronToPreset, pianoToPreset, renderOffline, samplerToPreset, sf2InstrumentToPreset, soundfontToPreset, trimSilence };