spessasynth_core 4.2.0 → 4.2.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
@@ -3,14 +3,14 @@
3
3
  <img src='https://raw.githubusercontent.com/spessasus/SpessaSynth/refs/heads/master/src/website/spessasynth_logo_rounded.png' width='300' alt='SpessaSynth logo'>
4
4
  </p>
5
5
 
6
- _A powerful SF2/DLS/MIDI TypeScript/JavaScript library. It works with any modern JS environment that supports
6
+ _A powerful multipurpose SF2/DLS/MIDI JavaScript library. It works with any modern JS environment that supports
7
7
  WebAssembly._
8
8
 
9
9
  It allows you to:
10
10
 
11
11
  - Play MIDI files using SF2/SF3/DLS files!
12
12
  - Read and write MIDI files!
13
- - Write SF2/SF3 files!
13
+ - Read and write SF2/SF3 files!
14
14
  - Convert DLS to SF2! (and back!)
15
15
  - [and more!](#current-features)
16
16
 
@@ -23,7 +23,7 @@ Featuring Reverb, Chorus, Delay, Insertion effects and more!
23
23
  > Looking for an easy-to-use WebAudioAPI browser wrapper?
24
24
  > Try [spessasynth_lib](https://github.com/spessasus/spessasynth_lib)!
25
25
 
26
- ### [Project site (consider giving it a star!)](https://github.com/spessasus/spessasynth_core)
26
+ **[Project site (consider giving it a star!)](https://github.com/spessasus/spessasynth_core)**
27
27
 
28
28
  ### Made with spessasynth_core
29
29
 
@@ -44,12 +44,12 @@ Featuring Reverb, Chorus, Delay, Insertion effects and more!
44
44
 
45
45
  ### Easy Integration
46
46
 
47
- - **Modular design:** _Easy integration into other projects (load what you need)_
47
+ - **Modular design:** _Easy integration into other projects (only load what you need)_
48
48
  - **Flexible:** _It's not just a MIDI player!_
49
49
  - **Easy to Use:** _Basic setup is
50
50
  just [two lines of code!](https://spessasus.github.io/spessasynth_core/getting-started#minimal-setup)_
51
51
  - **No dependencies:** _Batteries included!_
52
- - **TypeScript definitions:** _Autocompletion in IDEs!_
52
+ - **Full TypeScript definitions:** _Autocompletion in IDEs!_
53
53
 
54
54
  ### Powerful MIDI Synthesizer
55
55
 
@@ -57,13 +57,11 @@ Featuring Reverb, Chorus, Delay, Insertion effects and more!
57
57
  - **Excellent SoundFont support:**
58
58
  - **Full Generator Support**
59
59
  - **Full Modulator Support:** _First (to my knowledge) JavaScript SoundFont synth with that feature!_
60
- - **GeneralUserGS Compatible:**
60
+ - **GeneralUser-GS Compatible:**
61
61
  _[See more here!](https://github.com/mrbumpy409/GeneralUser-GS/blob/main/documentation/README.md)_
62
62
  - **SoundFont3 Support:** Play compressed SoundFonts!
63
63
  - **Experimental SF2Pack Support:** Play soundfonts compressed with BASSMIDI! (_Note: only works with vorbis
64
64
  compression_)
65
- - **Can load very large SoundFonts:** up to 4GB! _Note: Only Firefox handles this well; Chromium has a hard-coded
66
- memory limit_
67
65
  - **Great DLS Support:**
68
66
  - **DLS Level 1 Support**
69
67
  - **DLS Level 2 Support**
@@ -74,14 +72,15 @@ Featuring Reverb, Chorus, Delay, Insertion effects and more!
74
72
  - **A-Law encoding support**
75
73
  - **Both unsigned 8-bit and signed 16-bit sample support (24-bit theoretically supported as well!)**
76
74
  - **Detects special articulator combinations:** _Such as vibratoLfoToPitch_
77
- - **Soundfont manager:** Stack multiple soundfonts!
75
+ - **Sound bank manager:** Stack multiple sound banks!
78
76
  - **Unlimited channel count:** Your CPU is the limit!
79
77
  - **Built-in, configurable effects:**
80
78
  - **Reverb:** _Multiple characters including delay and panning delay!_
81
79
  - **Chorus:** _Modulated delay lines with multiple presets!_
82
80
  - **Delay:** _Three delay lines for all of your delay needs!_
83
81
  - **Insertion Effects:** _The ultimate effects, they can give your sounds a completely different character! (limited support)_
84
- - **Replaceable:** _Effects not to your taste? You can bring your own!_
82
+ - **GS Compatible:** _MIDI files can configure the effects accurately!_
83
+ - **Replaceable:** _Effects not to your liking? You can replace them with your own!_
85
84
  - **Excellent MIDI Standards Support:**
86
85
  - **MIDI Controller Support:** Default supported
87
86
  controllers [here](https://spessasus.github.io/spessasynth_core/extra/midi-implementation#default-supported-controllers)
@@ -89,14 +88,13 @@ Featuring Reverb, Chorus, Delay, Insertion effects and more!
89
88
  - **Sound Controllers:** _Real-time filter and envelope control!_
90
89
  - **MIDI Tuning Standard Support:**
91
90
  _[more info here](https://spessasus.github.io/spessasynth_core/extra/midi-implementation#midi-tuning-standard)_
92
- - [Full **RPN** and limited **NRPN**
91
+ - [Full **RPN** and extensive **NRPN**
93
92
  support](https://spessasus.github.io/spessasynth_core/extra/midi-implementation#supported-registered-parameters)
94
93
  - **SoundFont2 NRPN Support**
95
94
  - [**AWE32**
96
95
  NRPN Compatibility Layer](https://spessasus.github.io/spessasynth_core/extra/midi-implementation#awe32-nrpn-compatibility-layer)
97
96
  - [**Roland GS** and **Yamaha XG**
98
97
  support!](https://spessasus.github.io/spessasynth_core/extra/midi-implementation#supported-system-exclusives)
99
- - Built-in effects are GS-Compatible!
100
98
 
101
99
  ### Powerful and Fast MIDI Sequencer
102
100
 
@@ -181,7 +179,7 @@ Featuring Reverb, Chorus, Delay, Insertion effects and more!
181
179
 
182
180
  ### Limitations
183
181
 
184
- - Synth's performance may be questionable sometimes
182
+ - Audio engine is written in pure TypeScript, so it may not be as performant as native implementations
185
183
  - [SF2 to DLS Conversion limits](https://spessasus.github.io/spessasynth_core/extra/dls-conversion-problem)
186
184
 
187
185
  #### TODO
@@ -208,6 +206,8 @@ Featuring Reverb, Chorus, Delay, Insertion effects and more!
208
206
 
209
207
  ### Short example: MIDI to wav converter
210
208
 
209
+ For use with node.js
210
+
211
211
  ```ts
212
212
  import * as fs from "fs/promises";
213
213
  import {
@@ -226,24 +226,30 @@ if (args.length !== 3) {
226
226
  );
227
227
  process.exit();
228
228
  }
229
+ // Read MIDI and sound bank
229
230
  const sf = await fs.readFile(args[0]);
230
231
  const mid = await fs.readFile(args[1]);
232
+ // Parse the MIDI and sound bank
231
233
  const midi = BasicMIDI.fromArrayBuffer(mid.buffer);
232
- const sampleRate = 44100;
233
- const sampleCount = Math.ceil(44100 * (midi.duration + 2));
234
+ const soundBank = SoundBankLoader.fromArrayBuffer(sf.buffer);
235
+
236
+ // Initialize the synthesizer
237
+ const sampleRate = 48000;
234
238
  const synth = new SpessaSynthProcessor(sampleRate, {
235
- enableEventSystem: false,
236
- enableEffects: false
239
+ enableEventSystem: false
237
240
  });
238
- synth.soundBankManager.addSoundBank(
239
- SoundBankLoader.fromArrayBuffer(sf.buffer),
240
- "main"
241
- );
241
+ synth.soundBankManager.addSoundBank(soundBank, "main");
242
242
  await synth.processorInitialized;
243
+ // Enable uncapped voice count
244
+ synth.setMasterParameter("autoAllocateVoices", true);
245
+
246
+ // Initialize the sequencer
243
247
  const seq = new SpessaSynthSequencer(synth);
244
248
  seq.loadNewSongList([midi]);
245
249
  seq.play();
246
250
 
251
+ // Prepare the output buffers
252
+ const sampleCount = Math.ceil(sampleRate * (midi.duration + 2));
247
253
  const outLeft = new Float32Array(sampleCount);
248
254
  const outRight = new Float32Array(sampleCount);
249
255
  const start = performance.now();
@@ -252,13 +258,12 @@ let filledSamples = 0;
252
258
  const BUFFER_SIZE = 128;
253
259
  let i = 0;
254
260
  const durationRounded = Math.floor(seq.midiData!.duration * 100) / 100;
255
- const outputArray = [outLeft, outRight];
256
261
  while (filledSamples < sampleCount) {
257
262
  // Process sequencer
258
263
  seq.processTick();
259
264
  // Render
260
265
  const bufferSize = Math.min(BUFFER_SIZE, sampleCount - filledSamples);
261
- synth.renderAudio(outputArray, [], [], filledSamples, bufferSize);
266
+ synth.process(outLeft, outRight, filledSamples, bufferSize);
262
267
  filledSamples += bufferSize;
263
268
  i++;
264
269
  // Log progress
@@ -282,6 +287,8 @@ await fs.writeFile(args[2], new Uint8Array(wave));
282
287
  console.info(`File written to ${args[2]}`);
283
288
  ```
284
289
 
290
+ Read more in the [documentation](https://spessasus.github.io/spessasynth_core)
291
+
285
292
  ### Building
286
293
 
287
294
  To build the NPM package, do:
@@ -301,6 +308,7 @@ Licensed under the Apache-2.0 License.
301
308
  #### Legal
302
309
 
303
310
  This project is in no way endorsed or otherwise affiliated with the MIDI Manufacturers Association,
304
- Creative Technology Ltd. or E-mu Systems, Inc., or any other organization mentioned.
311
+ Roland Corporation, Yamaha Corporation, Creative Technology Ltd. or E-mu Systems, Inc.,
312
+ or any other organization mentioned.
305
313
  SoundFont® is a registered trademark of Creative Technology Ltd.
306
314
  All other trademarks are the property of their respective owners.
package/dist/index.d.ts CHANGED
@@ -1053,27 +1053,9 @@ interface InsertionProcessor {
1053
1053
  interface InsertionProcessorSnapshot {
1054
1054
  type: number;
1055
1055
  /**
1056
- * Parameters for the effect, 255 means "no change"
1056
+ * 20 parameters for the effect, 255 means "no change" + 3 effect sends (index 20, 21, 22)
1057
1057
  */
1058
1058
  params: Uint8Array;
1059
- /**
1060
- * 0-127
1061
- * This parameter sets the amount of insertion sound that will be sent to the reverb.
1062
- * Higher values result in more sound being sent.
1063
- */
1064
- sendLevelToReverb: number;
1065
- /**
1066
- * 0-127
1067
- * This parameter sets the amount of insertion sound that will be sent to the chorus.
1068
- * Higher values result in more sound being sent.
1069
- */
1070
- sendLevelToChorus: number;
1071
- /**
1072
- * 0-127
1073
- * This parameter sets the amount of insertion sound that will be sent to the delay.
1074
- * Higher values result in more sound being sent.
1075
- */
1076
- sendLevelToDelay: number;
1077
1059
  /**
1078
1060
  * A boolean list for channels that have the insertion effect enabled.
1079
1061
  */
@@ -2732,8 +2714,6 @@ declare function dataEntryFine(this: MIDIChannel, dataValue: number): void;
2732
2714
  * midiControllers table and handling special cases like bank select,
2733
2715
  * data entry, and sustain pedal. It also computes modulators for all voices
2734
2716
  * in the channel based on the controller change.
2735
- * If the controller number is greater than 127, it is treated as a channel
2736
- * configuration controller, and the `force` parameter must be set to true
2737
2717
  * to allow changes.
2738
2718
  */
2739
2719
  declare function controllerChange(this: MIDIChannel, controllerNumber: MIDIController, controllerValue: number, sendEvent?: boolean): void;
@@ -3040,6 +3020,8 @@ declare class SynthesizerCore {
3040
3020
  protected portSelectChannelOffset: number;
3041
3021
  /**
3042
3022
  * For insertion snapshot tracking
3023
+ * 20 parameters (0-19) + 3 sends
3024
+ * Index to gs is Addr3 - 3 (for example EFX PARAMETER 1 is 0x03 and here it's 0)
3043
3025
  * note: 255 means "no change"
3044
3026
  * @protected
3045
3027
  */
@@ -3079,10 +3061,9 @@ declare class SynthesizerCore {
3079
3061
  * Processes a raw MIDI message.
3080
3062
  * @param message The message to process.
3081
3063
  * @param channelOffset The channel offset for the message.
3082
- * @param force If true, forces the message to be processed.
3083
3064
  * @param options Additional options for scheduling the message.
3084
3065
  */
3085
- processMessage(message: Uint8Array | number[], channelOffset?: number, force?: boolean, options?: SynthMethodOptions): void;
3066
+ processMessage(message: Uint8Array | number[], channelOffset?: number, options?: SynthMethodOptions): void;
3086
3067
  destroySynthProcessor(): void;
3087
3068
  /**
3088
3069
  * @param channel channel to get voices for
@@ -3159,6 +3140,7 @@ declare class SynthesizerCore {
3159
3140
  * Copied callback so MIDI channels can call it.
3160
3141
  */
3161
3142
  callEvent<K extends keyof SynthProcessorEventData>(eventName: K, eventData: SynthProcessorEventData[K]): void;
3143
+ protected resetInsertionParams(): void;
3162
3144
  protected resetInsertion(): void;
3163
3145
  /**
3164
3146
  * @param volume {number} 0 to 1
@@ -3669,10 +3651,9 @@ declare class SpessaSynthProcessor {
3669
3651
  * Processes a raw MIDI message.
3670
3652
  * @param message The message to process.
3671
3653
  * @param channelOffset The channel offset for the message.
3672
- * @param force If true, forces the message to be processed.
3673
3654
  * @param options Additional options for scheduling the message.
3674
3655
  */
3675
- readonly processMessage: (message: Uint8Array | number[], channelOffset?: number, force?: boolean, options?: SynthMethodOptions) => void;
3656
+ readonly processMessage: (message: Uint8Array | number[], channelOffset?: number, options?: SynthMethodOptions) => void;
3676
3657
  /**
3677
3658
  * Core synthesis engine.
3678
3659
  */
@@ -4793,9 +4774,9 @@ declare class SpessaSynthSequencer {
4793
4774
  songs: BasicMIDI[];
4794
4775
  /**
4795
4776
  * The shuffled song indexes.
4796
- * This is used when shuffleMode is enabled.
4777
+ * This is used when shuffle mode is enabled.
4797
4778
  */
4798
- shuffledSongIndexes: number[];
4779
+ readonly shuffledSongIndexes: number[];
4799
4780
  /**
4800
4781
  * The synthesizer connected to the sequencer.
4801
4782
  */
@@ -4910,23 +4891,25 @@ declare class SpessaSynthSequencer {
4910
4891
  protected _songIndex: number;
4911
4892
  /**
4912
4893
  * The current song index in the song list.
4913
- * If shuffleMode is enabled, this is the index of the shuffled song list.
4894
+ * If shuffle mode is enabled, this is the index of the shuffled song list.
4914
4895
  */
4915
4896
  get songIndex(): number;
4916
4897
  /**
4917
4898
  * The current song index in the song list.
4918
- * If shuffleMode is enabled, this is the index of the shuffled song list.
4899
+ * If shuffle mode is enabled, this is the index of the shuffled song list.
4919
4900
  */
4920
4901
  set songIndex(value: number);
4921
4902
  protected _shuffleMode: boolean;
4922
4903
  /**
4923
4904
  * Controls if the sequencer should shuffle the songs in the song list.
4924
4905
  * If true, the sequencer will play the songs in a random order.
4906
+ * Songs are shuffled on a `loadNewSongList` call.
4925
4907
  */
4926
4908
  get shuffleMode(): boolean;
4927
4909
  /**
4928
4910
  * Controls if the sequencer should shuffle the songs in the song list.
4929
4911
  * If true, the sequencer will play the songs in a random order.
4912
+ * Songs are shuffled on a `loadNewSongList` call.
4930
4913
  */
4931
4914
  set shuffleMode(on: boolean);
4932
4915
  /**
@@ -5012,7 +4995,6 @@ declare class SpessaSynthSequencer {
5012
4995
  protected sendMIDINoteOn(channel: number, midiNote: number, velocity: number): void;
5013
4996
  protected sendMIDINoteOff(channel: number, midiNote: number): void;
5014
4997
  protected sendMIDICC(channel: number, type: MIDIController, value: number): void;
5015
- protected sendMIDIProgramChange(channel: number, program: number): void;
5016
4998
  /**
5017
4999
  * Sets the pitch of the given channel
5018
5000
  * @param channel usually 0-15: the channel to change pitch