smplr 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -8
- package/dist/index.d.ts +73 -23
- package/dist/index.js +505 -63677
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +489 -63673
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ Samples are stored at https://github.com/danigb/samples and there is no need to
|
|
|
56
56
|
|
|
57
57
|
## Documentation
|
|
58
58
|
|
|
59
|
-
### Create an instrument
|
|
59
|
+
### Create and load an instrument
|
|
60
60
|
|
|
61
61
|
All instruments follows the same pattern: `new Instrument(context, options?)`. For example:
|
|
62
62
|
|
|
@@ -70,10 +70,10 @@ const marimba = new Soundfont(context, { instrument: "marimba" });
|
|
|
70
70
|
|
|
71
71
|
#### Wait for audio loading
|
|
72
72
|
|
|
73
|
-
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 `
|
|
73
|
+
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:
|
|
74
74
|
|
|
75
75
|
```js
|
|
76
|
-
piano.
|
|
76
|
+
piano.load.then(() => {
|
|
77
77
|
// now the piano is fully loaded
|
|
78
78
|
});
|
|
79
79
|
```
|
|
@@ -81,7 +81,7 @@ piano.loaded().then(() => {
|
|
|
81
81
|
Since the promise returns the instrument instance, you can create and wait in a single line:
|
|
82
82
|
|
|
83
83
|
```js
|
|
84
|
-
const piano = await new SplendidGrandPiano(context).
|
|
84
|
+
const piano = await new SplendidGrandPiano(context).load;
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
### Play
|
|
@@ -132,7 +132,7 @@ const now = context.currentTime;
|
|
|
132
132
|
});
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
#### Looping
|
|
136
136
|
|
|
137
137
|
You can loop a note by using `loop`, `loopStart` and `loopEnd`:
|
|
138
138
|
|
|
@@ -148,7 +148,7 @@ sampler.start({
|
|
|
148
148
|
|
|
149
149
|
If `loopStart` or `loopEnd` is not specified it will be use by default 0 and total duration respectively.
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
#### Change volume
|
|
152
152
|
|
|
153
153
|
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:
|
|
154
154
|
|
|
@@ -193,9 +193,9 @@ piano.start({
|
|
|
193
193
|
|
|
194
194
|
The callback will receive as parameter the same object you pass to the `start` function;
|
|
195
195
|
|
|
196
|
-
|
|
196
|
+
### Experimental features
|
|
197
197
|
|
|
198
|
-
|
|
198
|
+
#### Cache requests
|
|
199
199
|
|
|
200
200
|
If you use default samples, they are stored at github pages. Github rate limits the number of requests per second. That could be a problem, specially if you're using a development environment with hot reload (like most React frameworks).
|
|
201
201
|
|
|
@@ -330,6 +330,20 @@ const mallet = new Mallet(new AudioContext(), {
|
|
|
330
330
|
});
|
|
331
331
|
```
|
|
332
332
|
|
|
333
|
+
### Mellotron
|
|
334
|
+
|
|
335
|
+
Samples from [archive.org](https://archive.org/details/mellotron-archive-cd-rom-nki-wav.-7z)
|
|
336
|
+
|
|
337
|
+
```js
|
|
338
|
+
import { Mellotron, getMellotronNames } from "smplr";
|
|
339
|
+
|
|
340
|
+
const instruments = getMellotronNames();
|
|
341
|
+
|
|
342
|
+
const mallet = new Mellotron(new AudioContext(), {
|
|
343
|
+
instrument: instruments[0],
|
|
344
|
+
});
|
|
345
|
+
```
|
|
346
|
+
|
|
333
347
|
### Drum Machines
|
|
334
348
|
|
|
335
349
|
Sampled drum machines. Samples from different sources:
|
package/dist/index.d.ts
CHANGED
|
@@ -27,6 +27,28 @@ declare class Channel {
|
|
|
27
27
|
disconnect(): void;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
type StorageResponse = {
|
|
31
|
+
readonly status: number;
|
|
32
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
33
|
+
json(): Promise<any>;
|
|
34
|
+
text(): Promise<string>;
|
|
35
|
+
};
|
|
36
|
+
type Storage = {
|
|
37
|
+
fetch: (url: string) => Promise<StorageResponse>;
|
|
38
|
+
};
|
|
39
|
+
declare const HttpStorage: Storage;
|
|
40
|
+
declare class CacheStorage implements Storage {
|
|
41
|
+
#private;
|
|
42
|
+
constructor(name?: string);
|
|
43
|
+
fetch(url: string): Promise<StorageResponse>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type AudioBuffers = Record<string | number, AudioBuffer | undefined>;
|
|
47
|
+
/**
|
|
48
|
+
* A function that downloads audio into a AudioBuffers
|
|
49
|
+
*/
|
|
50
|
+
type AudioBuffersLoader = (context: BaseAudioContext, buffers: AudioBuffers) => Promise<void>;
|
|
51
|
+
|
|
30
52
|
/**
|
|
31
53
|
* A function to unsubscribe from an event or control
|
|
32
54
|
*/
|
|
@@ -40,6 +62,16 @@ type Listener<T> = (value: T) => void;
|
|
|
40
62
|
*/
|
|
41
63
|
type Subscribe<T> = (listener: Listener<T>) => Unsubscribe;
|
|
42
64
|
|
|
65
|
+
/**
|
|
66
|
+
* @private
|
|
67
|
+
*/
|
|
68
|
+
type InternalPlayer = {
|
|
69
|
+
readonly buffers: AudioBuffers;
|
|
70
|
+
readonly context: BaseAudioContext;
|
|
71
|
+
start(sample: SampleStart): (time?: number) => void;
|
|
72
|
+
stop(sample?: SampleStop): void;
|
|
73
|
+
disconnect(): void;
|
|
74
|
+
};
|
|
43
75
|
type SampleStop = {
|
|
44
76
|
stopId?: string | number;
|
|
45
77
|
time?: number;
|
|
@@ -55,28 +87,26 @@ type SampleOptions = {
|
|
|
55
87
|
loopEnd?: number;
|
|
56
88
|
};
|
|
57
89
|
type SampleStart = {
|
|
90
|
+
name?: string;
|
|
58
91
|
note: string | number;
|
|
59
92
|
onEnded?: (sample: SampleStart) => void;
|
|
60
93
|
stop?: Subscribe<number>;
|
|
61
94
|
stopId?: string | number;
|
|
62
95
|
time?: number;
|
|
63
96
|
} & SampleOptions;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
97
|
+
type SampleRegion = {
|
|
98
|
+
sampleName: string;
|
|
99
|
+
sampleCenter: number;
|
|
100
|
+
rangeMidi?: [number, number];
|
|
101
|
+
rangeVol?: [number, number];
|
|
102
|
+
offsetVol?: number;
|
|
103
|
+
offsetDetune?: number;
|
|
104
|
+
sample?: Partial<SampleOptions>;
|
|
70
105
|
};
|
|
71
|
-
type
|
|
72
|
-
|
|
106
|
+
type SampleLayer = {
|
|
107
|
+
regions: SampleRegion[];
|
|
108
|
+
sample: Partial<SampleOptions>;
|
|
73
109
|
};
|
|
74
|
-
declare const HttpStorage: Storage;
|
|
75
|
-
declare class CacheStorage implements Storage {
|
|
76
|
-
#private;
|
|
77
|
-
constructor(name?: string);
|
|
78
|
-
fetch(url: string): Promise<StorageResponse>;
|
|
79
|
-
}
|
|
80
110
|
|
|
81
111
|
declare function getDrumMachineNames(): string[];
|
|
82
112
|
type DrumMachineConfig = ChannelOptions & SampleOptions & {
|
|
@@ -86,6 +116,7 @@ type DrumMachineConfig = ChannelOptions & SampleOptions & {
|
|
|
86
116
|
declare class DrumMachine {
|
|
87
117
|
#private;
|
|
88
118
|
private readonly player;
|
|
119
|
+
readonly load: Promise<this>;
|
|
89
120
|
readonly output: OutputChannel;
|
|
90
121
|
constructor(context: AudioContext, options?: Partial<DrumMachineConfig>);
|
|
91
122
|
loaded(): Promise<this>;
|
|
@@ -182,6 +213,7 @@ declare class SfzSampler {
|
|
|
182
213
|
readonly context: AudioContext;
|
|
183
214
|
readonly options: Readonly<Partial<SfzSamplerConfig>>;
|
|
184
215
|
private readonly player;
|
|
216
|
+
readonly load: Promise<this>;
|
|
185
217
|
constructor(context: AudioContext, options: Partial<SfzSamplerConfig> & Pick<SfzSamplerConfig, "instrument">);
|
|
186
218
|
get output(): OutputChannel;
|
|
187
219
|
loaded(): Promise<this>;
|
|
@@ -208,6 +240,26 @@ declare class Mallet extends SfzSampler {
|
|
|
208
240
|
}
|
|
209
241
|
declare const NAME_TO_PATH: Record<string, string | undefined>;
|
|
210
242
|
|
|
243
|
+
declare function getMellotronNames(): string[];
|
|
244
|
+
type MellotronConfig = {
|
|
245
|
+
instrument: string;
|
|
246
|
+
storage: Storage;
|
|
247
|
+
};
|
|
248
|
+
type MellotronOptions = Partial<SampleOptions & ChannelOptions & MellotronConfig>;
|
|
249
|
+
declare class Mellotron implements InternalPlayer {
|
|
250
|
+
readonly context: BaseAudioContext;
|
|
251
|
+
private readonly config;
|
|
252
|
+
private readonly player;
|
|
253
|
+
private readonly layer;
|
|
254
|
+
readonly load: Promise<this>;
|
|
255
|
+
constructor(context: BaseAudioContext, options: MellotronOptions);
|
|
256
|
+
get buffers(): AudioBuffers;
|
|
257
|
+
get output(): OutputChannel;
|
|
258
|
+
start(sample: SampleStart | string | number): (time?: number | undefined) => void;
|
|
259
|
+
stop(sample?: SampleStop | string | number): void;
|
|
260
|
+
disconnect(): void;
|
|
261
|
+
}
|
|
262
|
+
|
|
211
263
|
declare const PARAMS: readonly ["preDelay", "bandwidth", "inputDiffusion1", "inputDiffusion2", "decay", "decayDiffusion1", "decayDiffusion2", "damping", "excursionRate", "excursionDepth", "wet", "dry"];
|
|
212
264
|
declare class Reverb {
|
|
213
265
|
#private;
|
|
@@ -220,12 +272,6 @@ declare class Reverb {
|
|
|
220
272
|
connect(output: AudioNode): void;
|
|
221
273
|
}
|
|
222
274
|
|
|
223
|
-
type AudioBuffers = Record<string | number, AudioBuffer | undefined>;
|
|
224
|
-
/**
|
|
225
|
-
* A function that downloads audio into a AudioBuffers
|
|
226
|
-
*/
|
|
227
|
-
type AudioBuffersLoader = (context: BaseAudioContext, buffers: AudioBuffers) => Promise<void>;
|
|
228
|
-
|
|
229
275
|
type SamplerConfig = {
|
|
230
276
|
storage?: Storage;
|
|
231
277
|
detune: number;
|
|
@@ -246,6 +292,7 @@ declare class Sampler {
|
|
|
246
292
|
#private;
|
|
247
293
|
readonly context: AudioContext;
|
|
248
294
|
private readonly player;
|
|
295
|
+
readonly load: Promise<this>;
|
|
249
296
|
constructor(context: AudioContext, options?: Partial<SamplerConfig>);
|
|
250
297
|
loaded(): Promise<this>;
|
|
251
298
|
get output(): OutputChannel;
|
|
@@ -271,12 +318,14 @@ declare class Soundfont {
|
|
|
271
318
|
readonly context: AudioContext;
|
|
272
319
|
readonly config: Readonly<SoundfontConfig>;
|
|
273
320
|
private readonly player;
|
|
321
|
+
readonly load: Promise<this>;
|
|
322
|
+
readonly layer: SampleLayer;
|
|
274
323
|
constructor(context: AudioContext, options: SoundfontOptions);
|
|
275
324
|
get output(): OutputChannel;
|
|
276
|
-
loaded(): Promise<this>;
|
|
277
325
|
get hasLoops(): boolean;
|
|
326
|
+
loaded(): Promise<this>;
|
|
278
327
|
disconnect(): void;
|
|
279
|
-
start(sample: SampleStart): (time?: number | undefined) => void;
|
|
328
|
+
start(sample: SampleStart | string | number): (time?: number | undefined) => void;
|
|
280
329
|
stop(sample?: SampleStop | string | number): void;
|
|
281
330
|
}
|
|
282
331
|
|
|
@@ -298,6 +347,7 @@ declare class SplendidGrandPiano {
|
|
|
298
347
|
readonly context: AudioContext;
|
|
299
348
|
options: Readonly<SplendidGrandPianoConfig>;
|
|
300
349
|
private readonly player;
|
|
350
|
+
readonly load: Promise<this>;
|
|
301
351
|
constructor(context: AudioContext, options?: Partial<SplendidGrandPianoConfig>);
|
|
302
352
|
get output(): OutputChannel;
|
|
303
353
|
get buffers(): AudioBuffers;
|
|
@@ -317,4 +367,4 @@ declare const LAYERS: ({
|
|
|
317
367
|
cutoff?: undefined;
|
|
318
368
|
})[];
|
|
319
369
|
|
|
320
|
-
export { CacheStorage, DrumMachine, DrumMachineConfig, ElectricPiano, HttpStorage, LAYERS, Mallet, NAME_TO_PATH, Reverb, Sampler, SamplerConfig, Soundfont, SoundfontOptions, SplendidGrandPiano, SplendidGrandPianoConfig, Storage, StorageResponse, getDrumMachineNames, getElectricPianoNames, getMalletNames, getSoundfontKits, getSoundfontNames };
|
|
370
|
+
export { CacheStorage, DrumMachine, DrumMachineConfig, ElectricPiano, HttpStorage, LAYERS, Mallet, Mellotron, MellotronConfig, MellotronOptions, NAME_TO_PATH, Reverb, Sampler, SamplerConfig, Soundfont, SoundfontOptions, SplendidGrandPiano, SplendidGrandPianoConfig, Storage, StorageResponse, getDrumMachineNames, getElectricPianoNames, getMalletNames, getMellotronNames, getSoundfontKits, getSoundfontNames };
|