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/dist/index.js CHANGED
@@ -41,6 +41,14 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
41
41
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
42
42
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
43
43
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
44
+ var __privateWrapper = (obj, member, setter, getter) => ({
45
+ set _(value) {
46
+ __privateSet(obj, member, value, setter);
47
+ },
48
+ get _() {
49
+ return __privateGet(obj, member, getter);
50
+ }
51
+ });
44
52
  var __async = (__this, __arguments, generator) => {
45
53
  return new Promise((resolve, reject) => {
46
54
  var fulfilled = (value) => {
@@ -86,7 +94,7 @@ __export(index_exports, {
86
94
  Versilian: () => Versilian,
87
95
  audioBufferToWav: () => audioBufferToWav,
88
96
  audioBufferToWav16: () => audioBufferToWav16,
89
- drumMachineToSmplrJson: () => drumMachineToSmplrJson,
97
+ drumMachineToPreset: () => drumMachineToPreset,
90
98
  getDrumMachineNames: () => getDrumMachineNames,
91
99
  getElectricPianoNames: () => getElectricPianoNames,
92
100
  getMalletNames: () => getMalletNames,
@@ -96,12 +104,12 @@ __export(index_exports, {
96
104
  getSoundfontNames: () => getSoundfontNames,
97
105
  getVersilianInstruments: () => getVersilianInstruments,
98
106
  loadVersilianInstrument: () => loadVersilianInstrument,
99
- mellotronToSmplrJson: () => mellotronToSmplrJson,
100
- pianoToSmplrJson: () => pianoToSmplrJson,
107
+ mellotronToPreset: () => mellotronToPreset,
108
+ pianoToPreset: () => pianoToPreset,
101
109
  renderOffline: () => renderOffline,
102
- samplerToSmplrJson: () => samplerToSmplrJson,
103
- sf2InstrumentToSmplrJson: () => sf2InstrumentToSmplrJson,
104
- soundfontToSmplrJson: () => soundfontToSmplrJson,
110
+ samplerToPreset: () => samplerToPreset,
111
+ sf2InstrumentToPreset: () => sf2InstrumentToPreset,
112
+ soundfontToPreset: () => soundfontToPreset,
105
113
  trimSilence: () => trimSilence
106
114
  });
107
115
  module.exports = __toCommonJS(index_exports);
@@ -938,11 +946,12 @@ var EMPTY_JSON = {
938
946
  function isSmplrJson(x) {
939
947
  return typeof x === "object" && x !== null && "groups" in x && Array.isArray(x.groups);
940
948
  }
941
- var _loadProgress, _buffers, _reversedBuffers, _defaults, _defaultVelocity, _aliases, _matcher, _voices2, _channel, _onLoadProgress, _onStart, _onEnded, _ccState, _disposed, _SmplrImpl_instances, assertNotDisposed_fn, getBuffer_fn, playNote_fn, normalizeNoteEvent_fn;
949
+ var _loadProgress, _loadToken, _buffers, _reversedBuffers, _defaults, _defaultVelocity, _aliases, _matcher, _voices2, _channel, _onLoadProgress, _onStart, _onEnded, _ccState, _disposed, _SmplrImpl_instances, assertNotDisposed_fn, getBuffer_fn, playNote_fn, normalizeNoteEvent_fn;
942
950
  var SmplrImpl = class {
943
951
  constructor(context, jsonOrOptions, maybeOptions) {
944
952
  __privateAdd(this, _SmplrImpl_instances);
945
953
  __privateAdd(this, _loadProgress, { loaded: 0, total: 0 });
954
+ __privateAdd(this, _loadToken, 0);
946
955
  __privateAdd(this, _buffers, /* @__PURE__ */ new Map());
947
956
  __privateAdd(this, _reversedBuffers, /* @__PURE__ */ new Map());
948
957
  __privateAdd(this, _defaults);
@@ -1005,17 +1014,18 @@ var SmplrImpl = class {
1005
1014
  this.ready = p;
1006
1015
  }
1007
1016
  /**
1008
- * Load (or replace) the instrument descriptor. Creates a new RegionMatcher
1009
- * and fetches all sample buffers. Pre-loaded buffers (e.g. base64-decoded)
1010
- * can be passed via the `buffers` parameter — those skip the fetch step.
1017
+ * Load (or replace) the instrument descriptor. All state (matcher, defaults,
1018
+ * aliases, reversed-buffer cache, sample buffers) swaps atomically when the
1019
+ * load resolves. Concurrent calls are serialized: only the latest call's
1020
+ * result is committed; earlier in-flight calls resolve but do not mutate
1021
+ * state.
1011
1022
  *
1012
- * Returns a Promise that resolves when all samples are ready.
1023
+ * Pre-loaded buffers (e.g. base64-decoded) can be passed via the `buffers`
1024
+ * parameter — those skip the fetch step.
1013
1025
  */
1014
1026
  loadInstrument(json, buffers) {
1015
1027
  __privateMethod(this, _SmplrImpl_instances, assertNotDisposed_fn).call(this, "load an instrument");
1016
- __privateSet(this, _defaults, json.defaults);
1017
- __privateSet(this, _aliases, json.aliases ? new Map(Object.entries(json.aliases)) : void 0);
1018
- __privateSet(this, _matcher, new RegionMatcher(json));
1028
+ const token = ++__privateWrapper(this, _loadToken)._;
1019
1029
  return this.loader.load(json, {
1020
1030
  buffers,
1021
1031
  onProgress: (loaded, total) => {
@@ -1024,6 +1034,11 @@ var SmplrImpl = class {
1024
1034
  (_a = __privateGet(this, _onLoadProgress)) == null ? void 0 : _a.call(this, { loaded, total });
1025
1035
  }
1026
1036
  }).then((newBuffers) => {
1037
+ if (token !== __privateGet(this, _loadToken)) return;
1038
+ __privateSet(this, _defaults, json.defaults);
1039
+ __privateSet(this, _aliases, json.aliases ? new Map(Object.entries(json.aliases)) : void 0);
1040
+ __privateSet(this, _matcher, new RegionMatcher(json));
1041
+ __privateSet(this, _reversedBuffers, /* @__PURE__ */ new Map());
1027
1042
  __privateSet(this, _buffers, newBuffers);
1028
1043
  });
1029
1044
  }
@@ -1110,6 +1125,7 @@ var SmplrImpl = class {
1110
1125
  }
1111
1126
  };
1112
1127
  _loadProgress = new WeakMap();
1128
+ _loadToken = new WeakMap();
1113
1129
  _buffers = new WeakMap();
1114
1130
  _reversedBuffers = new WeakMap();
1115
1131
  _defaults = new WeakMap();
@@ -1371,12 +1387,12 @@ var DrumMachine = Instrument(
1371
1387
  const instrumentPromise = isDrumMachineInstrument(config.instrument) ? Promise.resolve(config.instrument) : fetchDrumMachineInstrument(config.url, config.storage);
1372
1388
  const ready = instrumentPromise.then((inst) => {
1373
1389
  instrument = inst;
1374
- return smplr.loadInstrument(drumMachineToSmplrJson(inst));
1390
+ return smplr.loadInstrument(drumMachineToPreset(inst));
1375
1391
  });
1376
1392
  return { extras, ready };
1377
1393
  }
1378
1394
  );
1379
- function drumMachineToSmplrJson(instrument) {
1395
+ function drumMachineToPreset(instrument) {
1380
1396
  const aliases = {};
1381
1397
  const regions = [];
1382
1398
  const BASE_MIDI = 36;
@@ -2248,7 +2264,7 @@ var Sequencer = class {
2248
2264
  };
2249
2265
 
2250
2266
  // src/smplr/sfz-convert.ts
2251
- function sfzToSmplrJson(sfzText, options) {
2267
+ function sfzToPreset(sfzText, options) {
2252
2268
  var _a;
2253
2269
  const formats = (_a = options.formats) != null ? _a : ["ogg", "m4a"];
2254
2270
  const tokens = tokenize(resolveDefines(sfzText));
@@ -2558,7 +2574,7 @@ var ElectricPiano = Instrument(
2558
2574
  (sfzText) => {
2559
2575
  var _a;
2560
2576
  return smplr.loadInstrument(
2561
- sfzToSmplrJson(sfzText, {
2577
+ sfzToPreset(sfzText, {
2562
2578
  baseUrl: config.baseUrl,
2563
2579
  pathFromSampleName: config.pathFromSampleName,
2564
2580
  formats: (_a = options.formats) != null ? _a : ["ogg", "m4a"]
@@ -2593,7 +2609,7 @@ function loadVersilianInstrument(smplr, options) {
2593
2609
  const sampleBaseUrl = `${VCSL_BASE_URL}/${base}`;
2594
2610
  return fetch(sfzUrl).then((r) => r.text()).then(
2595
2611
  (sfzText) => smplr.loadInstrument(
2596
- sfzToSmplrJson(sfzText, {
2612
+ sfzToPreset(sfzText, {
2597
2613
  baseUrl: sampleBaseUrl,
2598
2614
  pathFromSampleName: (name) => name.replace(/\.wav$/i, ""),
2599
2615
  formats: ["ogg", "m4a"]
@@ -2698,7 +2714,7 @@ var Mellotron = Instrument(
2698
2714
  const baseUrl = `https://smpldsnds.github.io/archiveorg-mellotron/${instrumentName}/`;
2699
2715
  return fetch(baseUrl + "files.json").then((r) => r.json()).then(
2700
2716
  (names) => smplr.loadInstrument(
2701
- mellotronToSmplrJson(names, {
2717
+ mellotronToPreset(names, {
2702
2718
  instrument: instrumentName,
2703
2719
  variation: variation == null ? void 0 : variation[1]
2704
2720
  })
@@ -2706,7 +2722,7 @@ var Mellotron = Instrument(
2706
2722
  );
2707
2723
  }
2708
2724
  );
2709
- function mellotronToSmplrJson(sampleNames, config) {
2725
+ function mellotronToPreset(sampleNames, config) {
2710
2726
  var _a;
2711
2727
  const entries = [];
2712
2728
  for (const sampleName of sampleNames) {
@@ -2818,11 +2834,24 @@ _ready = new WeakMap();
2818
2834
  _output = new WeakMap();
2819
2835
 
2820
2836
  // src/sampler.ts
2837
+ function isSmplrPreset(x) {
2838
+ return typeof x === "object" && x !== null && "groups" in x && Array.isArray(x.groups);
2839
+ }
2821
2840
  var Sampler = Instrument(
2822
2841
  (ctx, options = {}, smplr) => {
2823
2842
  var _a, _b;
2824
2843
  const storage = (_a = options.storage) != null ? _a : HttpStorage;
2825
- return getSource(ctx, (_b = options.buffers) != null ? _b : {}).then((source) => buildSamplerBuffers(source, ctx, storage, options)).then(({ json, buffers }) => smplr.loadInstrument(json, buffers));
2844
+ const loadFromInput = (input) => {
2845
+ if (isSmplrPreset(input)) {
2846
+ return smplr.loadInstrument(input);
2847
+ }
2848
+ return getSource(ctx, input).then((source) => buildSamplerBuffers(source, ctx, storage, options)).then(({ json, buffers }) => smplr.loadInstrument(json, buffers));
2849
+ };
2850
+ const initialInput = "preset" in options && options.preset ? options.preset : (_b = options.buffers) != null ? _b : {};
2851
+ return {
2852
+ extras: { reload: loadFromInput },
2853
+ ready: loadFromInput(initialInput)
2854
+ };
2826
2855
  }
2827
2856
  );
2828
2857
  function getSource(ctx, raw) {
@@ -2836,7 +2865,7 @@ function getSource(ctx, raw) {
2836
2865
  }
2837
2866
  function buildSamplerBuffers(source, context, storage, options) {
2838
2867
  return __async(this, null, function* () {
2839
- const { json, urlMap, preloaded } = samplerToSmplrJson(source, options);
2868
+ const { json, urlMap, preloaded } = samplerToPreset(source, options);
2840
2869
  yield Promise.all(
2841
2870
  Object.entries(urlMap).map((_0) => __async(null, [_0], function* ([name, url]) {
2842
2871
  const buffer = yield loadAudioBuffer(context, url, storage);
@@ -2846,7 +2875,7 @@ function buildSamplerBuffers(source, context, storage, options) {
2846
2875
  return { json, buffers: preloaded };
2847
2876
  });
2848
2877
  }
2849
- function samplerToSmplrJson(source, options = {}) {
2878
+ function samplerToPreset(source, options = {}) {
2850
2879
  const keys = Object.keys(source);
2851
2880
  const preloaded = /* @__PURE__ */ new Map();
2852
2881
  const urlMap = {};
@@ -2945,7 +2974,7 @@ var Smolken = Instrument(
2945
2974
  const sfzUrl = getSmolkenUrl((_a = options.instrument) != null ? _a : "Arco");
2946
2975
  return fetch(sfzUrl).then((r) => r.text()).then(
2947
2976
  (sfzText) => smplr.loadInstrument(
2948
- sfzToSmplrJson(sfzText, {
2977
+ sfzToPreset(sfzText, {
2949
2978
  baseUrl: SMOLKEN_BASE_URL,
2950
2979
  pathFromSampleName: (name) => name.replace(/\\/g, "/").replace(/\.wav$/i, ""),
2951
2980
  formats: ["ogg", "m4a"]
@@ -3136,10 +3165,7 @@ var Soundfont = Instrument(
3136
3165
  gain.gain.value = config.extraGain;
3137
3166
  smplr.output.addInsert(gain);
3138
3167
  return loadSoundfontData(ctx, config).then(
3139
- ({ buffers, noteNames, loopData }) => smplr.loadInstrument(
3140
- soundfontToSmplrJson(noteNames, loopData),
3141
- buffers
3142
- )
3168
+ ({ buffers, noteNames, loopData }) => smplr.loadInstrument(soundfontToPreset(noteNames, loopData), buffers)
3143
3169
  );
3144
3170
  }
3145
3171
  );
@@ -3179,7 +3205,7 @@ function decodeSoundfontFile(context, config) {
3179
3205
  return { buffers, noteNames: [...buffers.keys()] };
3180
3206
  });
3181
3207
  }
3182
- function soundfontToSmplrJson(noteNames, loopData) {
3208
+ function soundfontToPreset(noteNames, loopData) {
3183
3209
  const entries = [];
3184
3210
  for (const noteName of noteNames) {
3185
3211
  const midi = toMidi(noteName);
@@ -3272,7 +3298,7 @@ function base64ToArrayBuffer(base64) {
3272
3298
  }
3273
3299
 
3274
3300
  // src/soundfont2.ts
3275
- function sf2InstrumentToSmplrJson(sf2Instrument, context) {
3301
+ function sf2InstrumentToPreset(sf2Instrument, context) {
3276
3302
  const buffers = /* @__PURE__ */ new Map();
3277
3303
  const regions = [];
3278
3304
  for (const zone of sf2Instrument.zones) {
@@ -3320,7 +3346,7 @@ var Soundfont2Sampler = Instrument(
3320
3346
  (inst) => inst.header.name === instrumentName
3321
3347
  );
3322
3348
  if (!sf2inst) return void 0;
3323
- const { json, buffers } = sf2InstrumentToSmplrJson(sf2inst, ctx);
3349
+ const { json, buffers } = sf2InstrumentToPreset(sf2inst, ctx);
3324
3350
  return baseLoadInstrument(json, buffers);
3325
3351
  }
3326
3352
  };
@@ -3352,9 +3378,9 @@ var DEFAULTS = {
3352
3378
  decayTime: 0.5
3353
3379
  };
3354
3380
  var SplendidGrandPiano = Instrument(
3355
- (ctx, options = {}, smplr) => smplr.loadInstrument(pianoToSmplrJson(__spreadValues(__spreadValues({}, DEFAULTS), options)))
3381
+ (ctx, options = {}, smplr) => smplr.loadInstrument(pianoToPreset(__spreadValues(__spreadValues({}, DEFAULTS), options)))
3356
3382
  );
3357
- function pianoToSmplrJson(options) {
3383
+ function pianoToPreset(options) {
3358
3384
  var _a;
3359
3385
  const { notesToLoad } = options;
3360
3386
  const layers = notesToLoad ? LAYERS.filter(
@@ -3751,7 +3777,7 @@ var LAYERS = [
3751
3777
  Versilian,
3752
3778
  audioBufferToWav,
3753
3779
  audioBufferToWav16,
3754
- drumMachineToSmplrJson,
3780
+ drumMachineToPreset,
3755
3781
  getDrumMachineNames,
3756
3782
  getElectricPianoNames,
3757
3783
  getMalletNames,
@@ -3761,12 +3787,12 @@ var LAYERS = [
3761
3787
  getSoundfontNames,
3762
3788
  getVersilianInstruments,
3763
3789
  loadVersilianInstrument,
3764
- mellotronToSmplrJson,
3765
- pianoToSmplrJson,
3790
+ mellotronToPreset,
3791
+ pianoToPreset,
3766
3792
  renderOffline,
3767
- samplerToSmplrJson,
3768
- sf2InstrumentToSmplrJson,
3769
- soundfontToSmplrJson,
3793
+ samplerToPreset,
3794
+ sf2InstrumentToPreset,
3795
+ soundfontToPreset,
3770
3796
  trimSilence
3771
3797
  });
3772
3798
  //# sourceMappingURL=index.js.map