spessasynth_core 3.26.1 → 3.26.2

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
@@ -21,68 +21,6 @@ npm install --save spessasynth_core
21
21
 
22
22
  > Note: This is the new heart of the SpessaSynth library, after the repository has been split.
23
23
 
24
- ###
25
- ```js
26
- import * as fs from "node:fs";
27
- import { MIDI } from "../../src/midi/midi_loader.js";
28
- import { SpessaSynthProcessor } from "../../src/synthetizer/audio_engine/main_processor.js";
29
- import { SpessaSynthSequencer } from "../../src/sequencer/sequencer_engine.js";
30
- import { audioToWav } from "../../src/utils/buffer_to_wav.js";
31
-
32
- // process arguments
33
- const args = process.argv.slice(2);
34
- if (args.length !== 3)
35
- {
36
- console.log("Usage: node index.js <soundfont path> <midi path> <wav output path>");
37
- process.exit();
38
- }
39
- // load the files
40
- const sf = fs.readFileSync(args[0]);
41
- const mid = fs.readFileSync(args[1]);
42
-
43
- const midi = new MIDI(mid);
44
- const sampleRate = 44100;
45
- const sampleCount = 44100 * (midi.duration + 2);
46
-
47
- const synth = new SpessaSynthProcessor(
48
- sf,
49
- sampleRate,
50
- {},
51
- false,
52
- false
53
- );
54
- await synth.processorInitialized;
55
-
56
- const seq = new SpessaSynthSequencer(synth);
57
- seq.loadNewSongList([midi]);
58
- seq.loop = false;
59
-
60
- const outLeft = new Float32Array(sampleCount);
61
- const outRight = new Float32Array(sampleCount);
62
- const start = performance.now();
63
- let filledSamples = 0;
64
-
65
- const bufSize = 128;
66
- while (filledSamples + bufSize < sampleCount)
67
- {
68
- const bufLeft = new Float32Array(bufSize);
69
- const bufRight = new Float32Array(bufSize);
70
- seq.processTick();
71
- const arr = [bufLeft, bufRight];
72
- synth.renderAudio(arr, arr, arr);
73
- outLeft.set(bufLeft, filledSamples);
74
- outRight.set(bufRight, filledSamples);
75
- filledSamples += bufSize;
76
- }
77
- const wave = audioToWav({
78
- leftChannel: outLeft,
79
- rightChannel: outRight,
80
- sampleRate: sampleRate
81
- });
82
- fs.writeFileSync(args[2], new Buffer(wave));
83
- process.exit();
84
- ```
85
-
86
24
  ## Current Features
87
25
 
88
26
  ### Easy Integration
@@ -208,6 +146,69 @@ process.exit();
208
146
 
209
147
  **If you like this project, consider giving it a star. It really helps out!**
210
148
 
149
+ ### Short example: MIDI to wav converter
150
+ ```js
151
+ import * as fs from "node:fs";
152
+ import { MIDI, SpessaSynthProcessor, SpessaSynthSequencer, audioToWav, loadSoundFont } from "spessasynth_core";
153
+
154
+ // process arguments
155
+ const args = process.argv.slice(2);
156
+ if (args.length !== 3)
157
+ {
158
+ console.log("Usage: node index.js <soundfont path> <midi path> <wav output path>");
159
+ process.exit();
160
+ }
161
+ const sf = fs.readFileSync(args[0]);
162
+ const mid = fs.readFileSync(args[1]);
163
+ const midi = new MIDI(mid);
164
+ const sampleRate = 44100;
165
+ const sampleCount = 44100 * (midi.duration + 2);
166
+ const synth = new SpessaSynthProcessor(sampleRate, {
167
+ enableEventSystem: false,
168
+ effectsEnabled: false
169
+ });
170
+ synth.soundfontManager.reloadManager(loadSoundFont(sf));
171
+ await synth.processorInitialized;
172
+ const seq = new SpessaSynthSequencer(synth);
173
+ seq.loadNewSongList([midi]);
174
+ seq.loop = false;
175
+ const outLeft = new Float32Array(sampleCount);
176
+ const outRight = new Float32Array(sampleCount);
177
+ const start = performance.now();
178
+ let filledSamples = 0;
179
+ // note: buffer size is recommended to be very small, as this is the interval between modulator updates and LFO updates
180
+ const bufSize = 128;
181
+ let i = 0;
182
+ while (filledSamples + bufSize < sampleCount)
183
+ {
184
+ const bufLeft = new Float32Array(bufSize);
185
+ const bufRight = new Float32Array(bufSize);
186
+ // process sequencer
187
+ seq.processTick();
188
+ const arr = [bufLeft, bufRight];
189
+ // render
190
+ synth.renderAudio(arr, arr, arr);
191
+ // write out
192
+ outLeft.set(bufLeft, filledSamples);
193
+ outRight.set(bufRight, filledSamples);
194
+ filledSamples += bufSize;
195
+ i++;
196
+ // log progress
197
+ if (i % 100 === 0)
198
+ {
199
+ console.log("Rendered", seq.currentTime, "/", midi.duration);
200
+ }
201
+ }
202
+ console.log("Rendered in", Math.floor(performance.now() - start), "ms");
203
+ const wave = audioToWav({
204
+ leftChannel: outLeft,
205
+ rightChannel: outRight,
206
+ sampleRate: sampleRate
207
+ });
208
+ fs.writeFileSync(args[2], new Buffer(wave));
209
+ process.exit();
210
+ ```
211
+
211
212
  # License
212
213
  Copyright © 2025 Spessasus
213
214
  Licensed under the Apache-2.0 License.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spessasynth_core",
3
- "version": "3.26.1",
3
+ "version": "3.26.2",
4
4
  "description": "MIDI and SoundFont2/DLS library with no compromises",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -370,6 +370,7 @@ class MidiAudioChannel
370
370
  this.sendChannelProperty();
371
371
  }
372
372
 
373
+ // noinspection JSUnusedGlobalSymbols
373
374
  /**
374
375
  * Sets a custom vibrato
375
376
  * @param depth {number} cents
@@ -387,6 +388,10 @@ class MidiAudioChannel
387
388
  this.channelVibrato.depth = depth;
388
389
  }
389
390
 
391
+ // noinspection JSUnusedGlobalSymbols
392
+ /**
393
+ * Yes
394
+ */
390
395
  disableAndLockGSNRPN()
391
396
  {
392
397
  this.lockGSNRPNParams = true;
@@ -431,7 +436,7 @@ class MidiAudioChannel
431
436
  bank: this.sentBank,
432
437
  program: this.preset.program
433
438
  };
434
- this.synth?.callbacks?.channelPropertyChange?.(data, this.channelNumber);
439
+ this.synth?.onChannelPropertyChange?.(data, this.channelNumber);
435
440
  }
436
441
  }
437
442
 
@@ -1,5 +1,4 @@
1
1
  import { SpessaSynthWarn } from "../../../utils/loggin.js";
2
- import { loadSoundFont } from "../../../soundfont/load_soundfont.js";
3
2
  import { isXGDrums } from "../../../utils/xg_hacks.js";
4
3
 
5
4
  /**
@@ -12,12 +11,21 @@ import { isXGDrums } from "../../../utils/xg_hacks.js";
12
11
  export class SoundFontManager
13
12
  {
14
13
  /**
15
- * Creates a new instance of soundfont manager
16
- * @param initialSoundFontBuffer {ArrayBuffer} Array buffer of the soundfont. This soudfont always has the id "main"
14
+ * All the soundfonts, ordered from the most important to the least.
15
+ * @type {SoundFontType[]}
17
16
  */
18
- constructor(initialSoundFontBuffer)
17
+ soundfontList = [];
18
+ /**
19
+ * @type {{bank: number, presetName: string, program: number}[]}
20
+ */
21
+ presetList = [];
22
+
23
+ /**
24
+ * @param presetListChangeCallback {function} to call when stuff changes
25
+ */
26
+ constructor(presetListChangeCallback)
19
27
  {
20
- this.reloadManager(initialSoundFontBuffer);
28
+ this.presetListChangeCallback = presetListChangeCallback;
21
29
  }
22
30
 
23
31
  generatePresetList()
@@ -49,9 +57,6 @@ export class SoundFontManager
49
57
  }
50
58
  }
51
59
 
52
- /**
53
- * @type {{bank: number, presetName: string, program: number}[]}
54
- */
55
60
  this.presetList = [];
56
61
  for (const [string, name] of Object.entries(presetList))
57
62
  {
@@ -62,6 +67,7 @@ export class SoundFontManager
62
67
  bank: parseInt(pb[0])
63
68
  });
64
69
  }
70
+ this.presetListChangeCallback();
65
71
  }
66
72
 
67
73
  /**
@@ -73,13 +79,13 @@ export class SoundFontManager
73
79
  return this.presetList.slice();
74
80
  }
75
81
 
82
+ // noinspection JSUnusedGlobalSymbols
76
83
  /**
77
- * Clears all soundfonts and adds a new one
78
- * @param soundFontArrayBuffer {ArrayBuffer}
84
+ * Clears all soundfonts and adds a new one with an ID "main"
85
+ * @param soundFont {BasicSoundBank}
79
86
  */
80
- reloadManager(soundFontArrayBuffer)
87
+ reloadManager(soundFont)
81
88
  {
82
- const font = loadSoundFont(soundFontArrayBuffer);
83
89
  /**
84
90
  * All the soundfonts, ordered from the most important to the least.
85
91
  * @type {SoundFontType[]}
@@ -88,11 +94,16 @@ export class SoundFontManager
88
94
  this.soundfontList.push({
89
95
  id: "main",
90
96
  bankOffset: 0,
91
- soundfont: font
97
+ soundfont: soundFont
92
98
  });
93
99
  this.generatePresetList();
94
100
  }
95
101
 
102
+ // noinspection JSUnusedGlobalSymbols
103
+ /**
104
+ * Deletes a given soundfont.
105
+ * @param id {string}
106
+ */
96
107
  deleteSoundFont(id)
97
108
  {
98
109
  if (this.soundfontList.length === 0)
@@ -113,13 +124,14 @@ export class SoundFontManager
113
124
  this.generatePresetList();
114
125
  }
115
126
 
127
+ // noinspection JSUnusedGlobalSymbols
116
128
  /**
117
- * Adds a new soundfont buffer with a given ID
118
- * @param buffer {ArrayBuffer}
129
+ * Adds a new soundfont with a given ID
130
+ * @param font {BasicSoundBank}
119
131
  * @param id {string}
120
132
  * @param bankOffset {number}
121
133
  */
122
- addNewSoundFont(buffer, id, bankOffset)
134
+ addNewSoundFont(font, id, bankOffset)
123
135
  {
124
136
  if (this.soundfontList.find(s => s.id === id) !== undefined)
125
137
  {
@@ -127,12 +139,13 @@ export class SoundFontManager
127
139
  }
128
140
  this.soundfontList.push({
129
141
  id: id,
130
- soundfont: loadSoundFont(buffer),
142
+ soundfont: font,
131
143
  bankOffset: bankOffset
132
144
  });
133
145
  this.generatePresetList();
134
146
  }
135
147
 
148
+ // noinspection JSUnusedGlobalSymbols
136
149
  /**
137
150
  * Rearranges the soundfonts
138
151
  * @param newList {string[]} the order of soundfonts, a list of strings, first overwrites second
@@ -156,7 +169,7 @@ export class SoundFontManager
156
169
  {
157
170
  if (this.soundfontList.length < 1)
158
171
  {
159
- throw new Error("No soundfonts! This should never happen.");
172
+ throw new Error("No soundfonts! Did you forget to add one?");
160
173
  }
161
174
  for (const sf of this.soundfontList)
162
175
  {
@@ -1,7 +1,5 @@
1
1
  import { MidiAudioChannel } from "../engine_components/midi_audio_channel.js";
2
2
 
3
- import { DEFAULT_PERCUSSION } from "../../synth_constants.js";
4
-
5
3
  /**
6
4
  * @param sendEvent {boolean}
7
5
  * @this {SpessaSynthProcessor}
@@ -13,15 +11,10 @@ export function createMidiChannel(sendEvent = false)
13
11
  */
14
12
  const channel = new MidiAudioChannel(this, this.defaultPreset, this.midiAudioChannels.length);
15
13
  this.midiAudioChannels.push(channel);
16
- channel.resetControllers();
17
- channel.sendChannelProperty();
18
14
  if (sendEvent)
19
15
  {
20
16
  this.callEvent("newchannel", undefined);
21
- }
22
-
23
- if (channel.channelNumber % 16 === DEFAULT_PERCUSSION)
24
- {
17
+ channel.sendChannelProperty();
25
18
  this.midiAudioChannels[this.midiAudioChannels.length - 1].setDrums(true);
26
19
  }
27
20
  }
@@ -14,6 +14,11 @@ export function clearSoundFont(sendPresets = true, clearOverride = true)
14
14
  this.getDefaultPresets();
15
15
  this.cachedVoices = [];
16
16
 
17
+ if (sendPresets)
18
+ {
19
+ this.updatePresetList();
20
+ }
21
+
17
22
  for (let i = 0; i < this.midiAudioChannels.length; i++)
18
23
  {
19
24
  const channelObject = this.midiAudioChannels[i];
@@ -23,8 +28,5 @@ export function clearSoundFont(sendPresets = true, clearOverride = true)
23
28
  }
24
29
  channelObject.programChange(channelObject.preset.program);
25
30
  }
26
- if (sendPresets)
27
- {
28
- this.sendPresetList();
29
- }
31
+
30
32
  }
@@ -1,3 +1,7 @@
1
+ import { loadSoundFont } from "../../../../soundfont/load_soundfont.js";
2
+ import { SpessaSynthInfo } from "../../../../utils/loggin.js";
3
+ import { consoleColors } from "../../../../utils/other.js";
4
+
1
5
  /**
2
6
  * Sets the embedded (RMI soundfont)
3
7
  * @param font {ArrayBuffer}
@@ -8,14 +12,22 @@ export function setEmbeddedSoundFont(font, offset)
8
12
  {
9
13
  // set offset
10
14
  this.soundfontBankOffset = offset;
11
- this.reloadSoundFont(font, true);
15
+ this.clearSoundFont(false, true);
16
+ this.overrideSoundfont = loadSoundFont(font);
17
+ this.updatePresetList();
18
+ this.getDefaultPresets();
19
+ this.midiAudioChannels.forEach(c =>
20
+ c.programChange(c.preset.program)
21
+ );
12
22
  // preload all samples
13
23
  this.overrideSoundfont.samples.forEach(s => s.getAudioData());
14
24
 
25
+
15
26
  // apply snapshot again if applicable
16
27
  if (this._snapshot !== undefined)
17
28
  {
18
29
  this.applySynthesizerSnapshot(this._snapshot);
19
30
  this.resetAllControllers();
20
31
  }
32
+ SpessaSynthInfo("%cSpessaSynth is ready!", consoleColors.recognized);
21
33
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @this {SpessaSynthProcessor}
3
3
  */
4
- export function sendPresetList()
4
+ export function updatePresetList()
5
5
  {
6
6
  /**
7
7
  * @type {{bank: number, presetName: string, program: number}[]}
@@ -28,4 +28,6 @@ export function sendPresetList()
28
28
  });
29
29
  }
30
30
  this.callEvent("presetlistchange", mainFont);
31
+ this.getDefaultPresets();
32
+ this.resetAllControllers(false);
31
33
  }
@@ -1,12 +1,7 @@
1
1
  import { SpessaSynthInfo } from "../../utils/loggin.js";
2
2
  import { consoleColors } from "../../utils/other.js";
3
3
  import { voiceKilling } from "./engine_methods/stopping_notes/voice_killing.js";
4
- import {
5
- ALL_CHANNELS_OR_DIFFERENT_ACTION,
6
- DEFAULT_PERCUSSION,
7
- DEFAULT_SYNTH_MODE,
8
- VOICE_CAP
9
- } from "../synth_constants.js";
4
+ import { ALL_CHANNELS_OR_DIFFERENT_ACTION, DEFAULT_SYNTH_MODE, VOICE_CAP } from "../synth_constants.js";
10
5
  import { stbvorbis } from "../../externals/stbvorbis_sync/stbvorbis_sync.min.js";
11
6
  import { VOLUME_ENVELOPE_SMOOTHING_FACTOR } from "./engine_components/volume_envelope.js";
12
7
  import { systemExclusive } from "./engine_methods/system_exclusive.js";
@@ -18,9 +13,8 @@ import { getVoices } from "./engine_components/voice.js";
18
13
  import { PAN_SMOOTHING_FACTOR } from "./engine_components/stereo_panner.js";
19
14
  import { stopAllChannels } from "./engine_methods/stopping_notes/stop_all_channels.js";
20
15
  import { setEmbeddedSoundFont } from "./engine_methods/soundfont_management/set_embedded_sound_font.js";
21
- import { reloadSoundFont } from "./engine_methods/soundfont_management/reload_sound_font.js";
22
16
  import { clearSoundFont } from "./engine_methods/soundfont_management/clear_sound_font.js";
23
- import { sendPresetList } from "./engine_methods/soundfont_management/send_preset_list.js";
17
+ import { updatePresetList } from "./engine_methods/soundfont_management/update_preset_list.js";
24
18
  import { getPreset } from "./engine_methods/soundfont_management/get_preset.js";
25
19
  import { transposeAllChannels } from "./engine_methods/tuning_control/transpose_all_channels.js";
26
20
  import { setMasterTuning } from "./engine_methods/tuning_control/set_master_tuning.js";
@@ -30,6 +24,8 @@ import { FILTER_SMOOTHING_FACTOR } from "./engine_components/lowpass_filter.js";
30
24
  import { getEvent, messageTypes } from "../../midi/midi_message.js";
31
25
  import { IndexedByteArray } from "../../utils/indexed_array.js";
32
26
  import { interpolationTypes } from "./engine_components/enums.js";
27
+ import { DEFAULT_SYNTH_OPTIONS } from "./synth_processor_options.js";
28
+ import { fillWithDefaults } from "../../utils/fill_with_defaults.js";
33
29
 
34
30
 
35
31
  /**
@@ -332,61 +328,73 @@ class SpessaSynthProcessor
332
328
  sampleRate;
333
329
 
334
330
  /**
335
- * @typedef {Object} CallbacksTypedef
336
- * @property {function?} ready
337
- * @property {function(EventTypes, EventCallbackData)?} eventCall
338
- * @property {function(ChannelProperty, number)?} channelPropertyChange
339
- * @property {function(masterParameterType, number|string)?} masterParameterChange
331
+ * Sample time in seconds
332
+ * @type {number}
333
+ */
334
+ sampleTime;
335
+
336
+ /**
337
+ * are the chorus and reverb effects enabled?
338
+ * @type {boolean}
339
+ */
340
+ effectsEnabled;
341
+
342
+ /**
343
+ * for applying the snapshot after an override sound bank too
344
+ * @type {SynthesizerSnapshot}
345
+ * @private
346
+ */
347
+ _snapshot;
348
+
349
+ /**
350
+ * Calls when an event occurs.
351
+ * @type {function}
352
+ * @param {EventTypes} eventType - the event type.
353
+ * @param {EventCallbackData} eventData - the event data.
354
+ */
355
+ onEventCall;
356
+
357
+ /**
358
+ * Calls when a channel property is changed.
359
+ * @type {function}
360
+ * @param {ChannelProperty} property - the updated property.
361
+ * @param {number} channelNumber - the channel number of the said property.
340
362
  */
363
+ onChannelPropertyChange;
364
+
365
+ /**
366
+ * Calls when a master parameter is changed.
367
+ * @type {function}
368
+ * @param {masterParameterType} parameter - the parameter type
369
+ * @param {number|string} value - the new value.
370
+ */
371
+ onMasterParameterChange;
372
+
341
373
 
342
374
  /**
343
375
  * Creates a new synthesizer engine.
344
- * @param midiChannels {number}
345
- * @param soundfont {ArrayBuffer}
346
- * @param enableEventSystem {boolean}
347
- * @param callbacks {CallbacksTypedef}
348
- * @param sampleRate {number}
349
- * @param initialTime {number}
350
- * @param effectsEnabled {boolean}
351
- * @param snapshot {SynthesizerSnapshot}
352
- */
353
- constructor(
354
- soundfont,
355
- sampleRate,
356
- callbacks,
357
- effectsEnabled = true,
358
- enableEventSystem = true,
359
- initialTime = 0,
360
- midiChannels = 16,
361
- snapshot = undefined)
376
+ * @param sampleRate {number} - sample rate, in Hertz.
377
+ * @param options {SynthProcessorOptions} - the processor's options.
378
+ */
379
+ constructor(sampleRate,
380
+ options = DEFAULT_SYNTH_OPTIONS)
362
381
  {
382
+ options = fillWithDefaults(options, DEFAULT_SYNTH_OPTIONS);
363
383
  /**
364
384
  * Midi output count
365
385
  * @type {number}
366
386
  */
367
- this.midiOutputsCount = midiChannels;
368
- /**
369
- * are the chorus and reverb effects enabled?
370
- * @type {boolean}
371
- */
372
- this.effectsEnabled = effectsEnabled;
373
- let initialChannelCount = this.midiOutputsCount;
374
-
375
- /**
376
- * @type {CallbacksTypedef}
377
- */
378
- this.callbacks = callbacks;
379
-
380
- this.currentSynthTime = initialTime;
381
- this.sampleRate = sampleRate;
382
-
383
- /**
384
- * Sample time in seconds
385
- * @type {number}
386
- */
387
+ this.midiOutputsCount = options.midiChannels;
388
+ this.effectsEnabled = options.effectsEnabled;
389
+ this.enableEventSystem = options.enableEventSystem;
390
+ this.currentSynthTime = options.midiChannels;
387
391
  this.sampleTime = 1 / sampleRate;
392
+ this.sampleRate = sampleRate;
388
393
 
389
- this.enableEventSystem = enableEventSystem;
394
+ // these smoothing factors were tested on 44,100 Hz, adjust them to target sample rate here
395
+ this.volumeEnvelopeSmoothingFactor = VOLUME_ENVELOPE_SMOOTHING_FACTOR * (44100 / sampleRate);
396
+ this.panSmoothingFactor = PAN_SMOOTHING_FACTOR * (44100 / sampleRate);
397
+ this.filterSmoothingFactor = FILTER_SMOOTHING_FACTOR * (44100 / sampleRate);
390
398
 
391
399
 
392
400
  for (let i = 0; i < 128; i++)
@@ -397,32 +405,16 @@ class SpessaSynthProcessor
397
405
  /**
398
406
  * @type {SoundFontManager}
399
407
  */
400
- this.soundfontManager = new SoundFontManager(
401
- soundfont
402
- );
403
- this.sendPresetList();
404
- this.getDefaultPresets();
405
-
408
+ this.soundfontManager = new SoundFontManager(this.updatePresetList.bind(this));
406
409
 
407
- for (let i = 0; i < initialChannelCount; i++)
410
+ for (let i = 0; i < this.midiOutputsCount; i++)
408
411
  {
409
412
  this.createMidiChannel(false);
410
413
  }
411
-
412
- this.midiAudioChannels[DEFAULT_PERCUSSION].preset = this.drumPreset;
413
- this.midiAudioChannels[DEFAULT_PERCUSSION].drumChannel = true;
414
-
415
- // these smoothing factors were tested on 44,100 Hz, adjust them to target sample rate here
416
- this.volumeEnvelopeSmoothingFactor = VOLUME_ENVELOPE_SMOOTHING_FACTOR * (44100 / sampleRate);
417
- this.panSmoothingFactor = PAN_SMOOTHING_FACTOR * (44100 / sampleRate);
418
- this.filterSmoothingFactor = FILTER_SMOOTHING_FACTOR * (44100 / sampleRate);
419
-
420
- this._snapshot = snapshot;
421
- if (this?._snapshot)
414
+ this.processorInitialized.then(() =>
422
415
  {
423
- this.applySynthesizerSnapshot(snapshot);
424
- }
425
- this.postReady();
416
+ SpessaSynthInfo("%cSpessaSynth is ready!", consoleColors.recognized);
417
+ });
426
418
  }
427
419
 
428
420
  /**
@@ -451,7 +443,7 @@ class SpessaSynthProcessor
451
443
  setSystem(value)
452
444
  {
453
445
  this.system = value;
454
- this?.callbacks?.masterParameterChange?.(masterParameterType.midiSystem, this.system);
446
+ this?.onMasterParameterChange?.(masterParameterType.midiSystem, this.system);
455
447
  }
456
448
 
457
449
  /**
@@ -497,16 +489,6 @@ class SpessaSynthProcessor
497
489
  this.cachedVoices[bank][program][midiNote][velocity] = voices;
498
490
  }
499
491
 
500
- postReady()
501
- {
502
- // ensure stbvorbis is fully initialized
503
- this.processorInitialized.then(() =>
504
- {
505
- SpessaSynthInfo("%cSpessaSynth is ready!", consoleColors.recognized);
506
- this?.callbacks?.ready?.();
507
- });
508
- }
509
-
510
492
  // noinspection JSUnusedGlobalSymbols
511
493
  /**
512
494
  * Renders float32 audio data to stereo outputs; buffer size of 128 is recommended
@@ -765,7 +747,7 @@ class SpessaSynthProcessor
765
747
  */
766
748
  callEvent(eventName, eventData)
767
749
  {
768
- this?.callbacks?.eventCall?.(eventName, eventData);
750
+ this?.onEventCall?.(eventName, eventData);
769
751
  }
770
752
  }
771
753
 
@@ -791,10 +773,9 @@ SpessaSynthProcessor.prototype.setMasterTuning = setMasterTuning;
791
773
 
792
774
  // program related
793
775
  SpessaSynthProcessor.prototype.getPreset = getPreset;
794
- SpessaSynthProcessor.prototype.reloadSoundFont = reloadSoundFont;
795
776
  SpessaSynthProcessor.prototype.clearSoundFont = clearSoundFont;
796
777
  SpessaSynthProcessor.prototype.setEmbeddedSoundFont = setEmbeddedSoundFont;
797
- SpessaSynthProcessor.prototype.sendPresetList = sendPresetList;
778
+ SpessaSynthProcessor.prototype.updatePresetList = updatePresetList;
798
779
 
799
780
  // snapshot related
800
781
  SpessaSynthProcessor.prototype.applySynthesizerSnapshot = applySynthesizerSnapshot;
@@ -9,6 +9,7 @@ import { SynthesizerSnapshot } from "./synthesizer_snapshot.js";
9
9
  */
10
10
  export function applySynthesizerSnapshot(snapshot)
11
11
  {
12
+ this._snapshot = snapshot;
12
13
  SynthesizerSnapshot.applySnapshot(this, snapshot);
13
14
  SpessaSynthInfo("%cFinished applying snapshot!", consoleColors.info);
14
15
  this.resetAllControllers();
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @typedef {Object} SynthProcessorOptions
3
+ * @property {boolean?} enableEventSystem - if the event system is enabled.
4
+ * @property {number?} initialTime - initial synth time, in seconds.
5
+ * @property {boolean?} effectsEnabled - if the processor should route audio to the effect channels.
6
+ * @property {number?} midiChannels - the default MIDI channel count.
7
+ */
8
+
9
+
10
+ /**
11
+ * @type {SynthProcessorOptions}
12
+ */
13
+ export const DEFAULT_SYNTH_OPTIONS = {
14
+ enableEventSystem: true,
15
+ initialTime: 0,
16
+ effectsEnabled: true,
17
+ midiChannels: 16
18
+ };
@@ -1,28 +0,0 @@
1
- import { loadSoundFont } from "../../../../soundfont/load_soundfont.js";
2
- import { SpessaSynthInfo } from "../../../../utils/loggin.js";
3
- import { consoleColors } from "../../../../utils/other.js";
4
-
5
- /**
6
- * @param buffer {ArrayBuffer}
7
- * @param isOverride {Boolean}
8
- * @this {SpessaSynthProcessor}
9
- */
10
- export function reloadSoundFont(buffer, isOverride = false)
11
- {
12
- this.clearSoundFont(false, isOverride);
13
- if (isOverride)
14
- {
15
- this.overrideSoundfont = loadSoundFont(buffer);
16
- }
17
- else
18
- {
19
- this.soundfontManager.reloadManager(buffer);
20
- }
21
- this.getDefaultPresets();
22
- this.midiAudioChannels.forEach(c =>
23
- c.programChange(c.preset.program)
24
- );
25
- this.postReady();
26
- this.sendPresetList();
27
- SpessaSynthInfo("%cSpessaSynth is ready!", consoleColors.recognized);
28
- }