spessasynth_lib 4.0.19 → 4.1.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 +28 -35
- package/dist/index.d.ts +43 -13
- package/dist/index.js +247 -156
- package/dist/index.js.map +1 -1
- package/dist/spessasynth_processor.min.js +13 -12
- package/dist/spessasynth_processor.min.js.map +4 -4
- package/package.json +17 -4
package/README.md
CHANGED
|
@@ -3,38 +3,30 @@
|
|
|
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
|
-
|
|
7
|
-
This is a WebAudioAPI wrapper for the [spessasynth_core](https://github.com/spessasus/spessasynth_core) library
|
|
8
|
-
|
|
9
|
-
**v4.0.0 TypeScript Update is here! The NPM package now contains type declarations for easier developing!**
|
|
10
|
-
[**Read about breaking changes here**](https://spessasus.github.io/spessasynth_lib/extra/4-0-migration-guide)
|
|
11
|
-
|
|
6
|
+
_A powerful SF2/DLS/MIDI TypeScript/JavaScript library for the browsers, based on spessasynth_core.
|
|
7
|
+
This is a WebAudioAPI wrapper for the [spessasynth_core](https://github.com/spessasus/spessasynth_core) library._
|
|
12
8
|
|
|
13
9
|
It allows you to:
|
|
10
|
+
|
|
14
11
|
- Play MIDI files using SF2/SF3/DLS files!
|
|
15
12
|
- Read and write MIDI files!
|
|
16
13
|
- Write SF2/SF3 files!
|
|
17
14
|
- Convert DLS to SF2! (and back!)
|
|
18
15
|
- [and more!](#current-features)
|
|
19
16
|
|
|
20
|
-
|
|
21
17
|
> **TIP:**
|
|
22
|
-
>
|
|
18
|
+
>
|
|
23
19
|
> Looking for a bare JS version that works without WebAudioAPI? Try [spessasynth_core](https://github.com/spessasus/spessasynth_core)!
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
27
21
|
### [Project site (consider giving it a star!)](https://github.com/spessasus/spessasynth_lib)
|
|
28
22
|
|
|
29
23
|
### Made with spessasynth_lib
|
|
24
|
+
|
|
30
25
|
- [SpessaSynth - Online SF2/DLS MIDI Player](https://spessasus.github.io/SpessaSynth)
|
|
31
26
|
- [SpessaFont - Online SoundFont/DLS Editor](https://spessasus.github.io/SpessaFont)
|
|
32
27
|
|
|
33
|
-
|
|
34
28
|
### [Documentation](https://spessasus.github.io/spessasynth_lib)
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
|
|
38
30
|
**SpessaSynth Project index**
|
|
39
31
|
|
|
40
32
|
- [spessasynth_core](https://github.com/spessasus/spessasynth_core) - SF2/DLS/MIDI library
|
|
@@ -47,25 +39,27 @@ It allows you to:
|
|
|
47
39
|
### [All the features of spessasynth_core!](https://github.com/spessasus/spessasynth_core?#current-features)
|
|
48
40
|
|
|
49
41
|
### On top of that...
|
|
50
|
-
|
|
51
|
-
- **
|
|
52
|
-
- **
|
|
53
|
-
- **
|
|
54
|
-
- **
|
|
42
|
+
|
|
43
|
+
- **Fully typed:** _Faster development and IDE auto-completion!_
|
|
44
|
+
- **Modular design:** _Easy integration into other projects (load what you need)_
|
|
45
|
+
- **[Detailed documentation:](https://spessasus.github.io/spessasynth_lib/)** _With [examples!](https://spessasus.github.io/spessasynth_lib/getting-started/#examples)_
|
|
46
|
+
- **Easy to Use:** _Basic setup is just [two lines of code!](https://spessasus.github.io/spessasynth_lib/getting-started/#minimal-setup)_
|
|
47
|
+
- **No external dependencies:** _Just spessasynth_core!_
|
|
55
48
|
- **Reverb and chorus support:** [customizable](https://spessasus.github.io/spessasynth_lib/synthesizer/#effects-configuration-object) and can be used standalone!
|
|
56
49
|
- **Export audio files** using [OfflineAudioContext](https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext)!
|
|
57
|
-
- **AudioWorklet synthesizer:**
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
- **Web Worker synthesizer:**
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
- **High-performance mode:** Play Rush E!
|
|
50
|
+
- **AudioWorklet synthesizer:**
|
|
51
|
+
- Runs in a **separate thread** for maximum performance!
|
|
52
|
+
- Does not stop playing even when the main thread is frozen!
|
|
53
|
+
- Supported by all modern browsers!
|
|
54
|
+
- **Web Worker synthesizer:**
|
|
55
|
+
- Synthesize directly in the Web Worker!
|
|
56
|
+
- Direct audio engine access!
|
|
57
|
+
- Export audio automatically in the worker!
|
|
58
|
+
- Avoids [Chromium Audio Bugs](https://issues.chromium.org/issues/367304685)!
|
|
59
|
+
- **High-performance mode:** Play Rush E! _note: may kill your browser ;)_
|
|
67
60
|
|
|
68
61
|
### Special Thanks
|
|
62
|
+
|
|
69
63
|
- [FluidSynth](https://github.com/FluidSynth/fluidsynth) - for the source code that helped implement functionality and fixes
|
|
70
64
|
- [Polyphone](https://www.polyphone-soundfonts.com/) - for the sound bank testing and editing tool
|
|
71
65
|
- [Meltysynth](https://github.com/sinshu/meltysynth) - for the initial low-pass filter implementation
|
|
@@ -78,11 +72,10 @@ It allows you to:
|
|
|
78
72
|
- [Christian Collins](https://schristiancollins.com) - for various bug reports regarding the synthesizer
|
|
79
73
|
- **And You!** - for checking out this project. I hope you like it :)
|
|
80
74
|
|
|
81
|
-
|
|
82
75
|
### Basic example: play a single note
|
|
83
76
|
|
|
84
77
|
```js
|
|
85
|
-
import { WorkletSynthesizer } from "spessasynth_lib"
|
|
78
|
+
import { WorkletSynthesizer } from "spessasynth_lib";
|
|
86
79
|
|
|
87
80
|
// SF2, SF3, SFOGG and DLS files are all supported!
|
|
88
81
|
const sfont = await (await fetch("soundfont.sf3")).arrayBuffer();
|
|
@@ -92,16 +85,16 @@ await ctx.audioWorklet.addModule("./spessasynth_processor.min.js");
|
|
|
92
85
|
const synth = new WorkletSynthesizer(ctx);
|
|
93
86
|
await synth.soundBankManager.addSoundBank(sfont, "main");
|
|
94
87
|
await synth.isReady;
|
|
95
|
-
document.getElementById("button").onclick = async () =>
|
|
96
|
-
{
|
|
88
|
+
document.getElementById("button").onclick = async () => {
|
|
97
89
|
await ctx.resume();
|
|
98
90
|
synth.programChange(0, 48); // strings ensemble
|
|
99
91
|
synth.noteOn(0, 52, 127);
|
|
100
|
-
}
|
|
92
|
+
};
|
|
101
93
|
```
|
|
102
94
|
|
|
103
95
|
# License
|
|
104
|
-
|
|
96
|
+
|
|
97
|
+
Copyright © 2026 Spessasus
|
|
105
98
|
Licensed under the Apache-2.0 License.
|
|
106
99
|
|
|
107
|
-
SoundFont® is a registered trademark of Creative Technology Ltd.
|
|
100
|
+
SoundFont® is a registered trademark of Creative Technology Ltd.
|
package/dist/index.d.ts
CHANGED
|
@@ -100,6 +100,7 @@ declare class SynthEventHandler {
|
|
|
100
100
|
/**
|
|
101
101
|
* Calls the given event.
|
|
102
102
|
* INTERNAL USE ONLY!
|
|
103
|
+
* @internal
|
|
103
104
|
*/
|
|
104
105
|
callEventInternal<T extends keyof SynthProcessorEventData>(name: T, eventData: SynthProcessorEventData[T]): void;
|
|
105
106
|
}
|
|
@@ -150,6 +151,7 @@ type SequencerMessage = {
|
|
|
150
151
|
[K in keyof SequencerMessageData]: {
|
|
151
152
|
type: K;
|
|
152
153
|
data: SequencerMessageData[K];
|
|
154
|
+
id: number;
|
|
153
155
|
};
|
|
154
156
|
}[keyof SequencerMessageData];
|
|
155
157
|
interface SequencerMessageData {
|
|
@@ -167,12 +169,16 @@ interface SequencerMessageData {
|
|
|
167
169
|
getMIDI: null;
|
|
168
170
|
setSkipToFirstNote: boolean;
|
|
169
171
|
}
|
|
170
|
-
type SequencerReturnMessage = SequencerEvent
|
|
172
|
+
type SequencerReturnMessage = (SequencerEvent & {
|
|
173
|
+
id: number;
|
|
174
|
+
}) | {
|
|
171
175
|
type: "getMIDI";
|
|
172
176
|
data: BasicMIDI;
|
|
177
|
+
id: number;
|
|
173
178
|
} | {
|
|
174
179
|
type: "midiError";
|
|
175
180
|
data: Error;
|
|
181
|
+
id: number;
|
|
176
182
|
};
|
|
177
183
|
/**
|
|
178
184
|
* Sequencer.js
|
|
@@ -227,7 +233,7 @@ type PostMessageSynthCore = (data: BasicSynthesizerReturnMessage, transfer?: Tra
|
|
|
227
233
|
*/
|
|
228
234
|
declare abstract class BasicSynthesizerCore {
|
|
229
235
|
readonly synthesizer: SpessaSynthProcessor;
|
|
230
|
-
readonly
|
|
236
|
+
readonly sequencers: SpessaSynthSequencer[];
|
|
231
237
|
protected readonly post: PostMessageSynthCore;
|
|
232
238
|
/**
|
|
233
239
|
* Indicates if the processor is alive.
|
|
@@ -235,6 +241,7 @@ declare abstract class BasicSynthesizerCore {
|
|
|
235
241
|
*/
|
|
236
242
|
protected alive: boolean;
|
|
237
243
|
protected constructor(sampleRate: number, options: SynthProcessorOptions, postMessage: PostMessageSynthCore);
|
|
244
|
+
protected createNewSequencer(): void;
|
|
238
245
|
protected postReady<K extends keyof SynthesizerReturn>(type: K, data: SynthesizerReturn[K], transferable?: Transferable[]): void;
|
|
239
246
|
protected postProgress<K extends keyof SynthesizerProgress>(type: K, data: SynthesizerProgress[K]): void;
|
|
240
247
|
protected destroy(): void;
|
|
@@ -299,6 +306,10 @@ interface WorkerRenderAudioOptions {
|
|
|
299
306
|
* If the effects should be enabled.
|
|
300
307
|
*/
|
|
301
308
|
enableEffects: boolean;
|
|
309
|
+
/**
|
|
310
|
+
* Which sequencer to render. Defaults to the first one (0).
|
|
311
|
+
*/
|
|
312
|
+
sequencerID: number;
|
|
302
313
|
}
|
|
303
314
|
|
|
304
315
|
interface PassedProcessorParameters {
|
|
@@ -369,6 +380,10 @@ interface WorkerBankWriteOptions {
|
|
|
369
380
|
* Trim the sound bank to only include samples used in the current MIDI file.
|
|
370
381
|
*/
|
|
371
382
|
trim: boolean;
|
|
383
|
+
/**
|
|
384
|
+
* Which sequencer to grab the MIDI from if trimming. Defaults to the first one (0).
|
|
385
|
+
*/
|
|
386
|
+
sequencerID: number;
|
|
372
387
|
/**
|
|
373
388
|
* The sound bank ID in the sound bank manager to write.
|
|
374
389
|
*/
|
|
@@ -417,7 +432,6 @@ interface BasicSynthesizerMessageData {
|
|
|
417
432
|
delay: number;
|
|
418
433
|
};
|
|
419
434
|
stopAll: number;
|
|
420
|
-
killNotes: number;
|
|
421
435
|
muteChannel: boolean;
|
|
422
436
|
addNewChannel: null;
|
|
423
437
|
customCcChange: {
|
|
@@ -435,6 +449,7 @@ interface BasicSynthesizerMessageData {
|
|
|
435
449
|
};
|
|
436
450
|
sequencerSpecific: SequencerMessage;
|
|
437
451
|
requestSynthesizerSnapshot: null;
|
|
452
|
+
requestNewSequencer: null;
|
|
438
453
|
setLogLevel: {
|
|
439
454
|
enableInfo: boolean;
|
|
440
455
|
enableWarning: boolean;
|
|
@@ -710,8 +725,10 @@ declare abstract class BasicSynthesizer {
|
|
|
710
725
|
presetList: PresetList;
|
|
711
726
|
/**
|
|
712
727
|
* INTERNAL USE ONLY!
|
|
728
|
+
* @internal
|
|
729
|
+
* All sequencer callbacks
|
|
713
730
|
*/
|
|
714
|
-
|
|
731
|
+
sequencers: ((m: SequencerReturnMessage) => unknown)[];
|
|
715
732
|
/**
|
|
716
733
|
* Resolves when the synthesizer is ready.
|
|
717
734
|
*/
|
|
@@ -728,6 +745,7 @@ declare abstract class BasicSynthesizer {
|
|
|
728
745
|
readonly chorusProcessor?: ChorusProcessor;
|
|
729
746
|
/**
|
|
730
747
|
* INTERNAL USE ONLY!
|
|
748
|
+
* @internal
|
|
731
749
|
*/
|
|
732
750
|
readonly post: (data: BasicSynthesizerMessage, transfer?: Transferable[]) => unknown;
|
|
733
751
|
protected readonly worklet: AudioWorkletNode;
|
|
@@ -957,8 +975,15 @@ declare abstract class BasicSynthesizer {
|
|
|
957
975
|
* INTERNAL USE ONLY!
|
|
958
976
|
* @param type INTERNAL USE ONLY!
|
|
959
977
|
* @param resolve INTERNAL USE ONLY!
|
|
978
|
+
* @internal
|
|
960
979
|
*/
|
|
961
980
|
awaitWorkerResponse<K extends keyof SynthesizerReturn>(type: K, resolve: (data: SynthesizerReturn[K]) => unknown): void;
|
|
981
|
+
/**
|
|
982
|
+
* INTERNAL USE ONLY!
|
|
983
|
+
* @param callback the sequencer callback
|
|
984
|
+
* @internal
|
|
985
|
+
*/
|
|
986
|
+
assignNewSequencer(callback: (m: SequencerReturnMessage) => unknown): number;
|
|
962
987
|
protected assignProgressTracker<K extends keyof SynthesizerProgress>(type: K, progressFunction: (args: SynthesizerProgress[K]) => unknown): void;
|
|
963
988
|
protected revokeProgressTracker<K extends keyof SynthesizerProgress>(type: K): void;
|
|
964
989
|
protected _sendInternal(message: Iterable<number>, channelOffset: number, force: boolean | undefined, eventOptions: Partial<SynthMethodOptions>): void;
|
|
@@ -1079,6 +1104,7 @@ declare class SeqEventHandler {
|
|
|
1079
1104
|
/**
|
|
1080
1105
|
* Calls the given event.
|
|
1081
1106
|
* Internal use only.
|
|
1107
|
+
* @internal
|
|
1082
1108
|
*/
|
|
1083
1109
|
callEventInternal<T extends keyof WorkletSequencerEventType>(name: T, eventData: WorkletSequencerEventType[T]): void;
|
|
1084
1110
|
}
|
|
@@ -1120,6 +1146,10 @@ declare class Sequencer {
|
|
|
1120
1146
|
* Absolute playback startTime, bases on the synth's time.
|
|
1121
1147
|
*/
|
|
1122
1148
|
private absoluteStartTime;
|
|
1149
|
+
/**
|
|
1150
|
+
* For sending the messages to the correct SpessaSynthSequencer in core
|
|
1151
|
+
*/
|
|
1152
|
+
private readonly sequencerID;
|
|
1123
1153
|
/**
|
|
1124
1154
|
* Creates a new MIDI sequencer for playing back MIDI files.
|
|
1125
1155
|
* @param synth synth to send events to.
|
|
@@ -1135,7 +1165,7 @@ declare class Sequencer {
|
|
|
1135
1165
|
* The current song number in the playlist.
|
|
1136
1166
|
*/
|
|
1137
1167
|
set songIndex(value: number);
|
|
1138
|
-
|
|
1168
|
+
private _currentTempo;
|
|
1139
1169
|
/**
|
|
1140
1170
|
* Current song's tempo in BPM.
|
|
1141
1171
|
*/
|
|
@@ -1144,9 +1174,9 @@ declare class Sequencer {
|
|
|
1144
1174
|
* The current sequence's length, in seconds.
|
|
1145
1175
|
*/
|
|
1146
1176
|
get duration(): number;
|
|
1147
|
-
|
|
1177
|
+
private _songsAmount;
|
|
1148
1178
|
get songsAmount(): number;
|
|
1149
|
-
|
|
1179
|
+
private _skipToFirstNoteOn;
|
|
1150
1180
|
/**
|
|
1151
1181
|
* Indicates if the sequencer should skip to first note on.
|
|
1152
1182
|
*/
|
|
@@ -1158,7 +1188,7 @@ declare class Sequencer {
|
|
|
1158
1188
|
/**
|
|
1159
1189
|
* Internal loop count marker (-1 is infinite).
|
|
1160
1190
|
*/
|
|
1161
|
-
|
|
1191
|
+
private _loopCount;
|
|
1162
1192
|
/**
|
|
1163
1193
|
* The current remaining number of loops. -1 means infinite looping.
|
|
1164
1194
|
*/
|
|
@@ -1170,7 +1200,7 @@ declare class Sequencer {
|
|
|
1170
1200
|
/**
|
|
1171
1201
|
* Controls the playback's rate.
|
|
1172
1202
|
*/
|
|
1173
|
-
|
|
1203
|
+
private _playbackRate;
|
|
1174
1204
|
/**
|
|
1175
1205
|
* Controls the playback's rate.
|
|
1176
1206
|
*/
|
|
@@ -1179,7 +1209,7 @@ declare class Sequencer {
|
|
|
1179
1209
|
* Controls the playback's rate.
|
|
1180
1210
|
*/
|
|
1181
1211
|
set playbackRate(value: number);
|
|
1182
|
-
|
|
1212
|
+
private _shuffleSongs;
|
|
1183
1213
|
/**
|
|
1184
1214
|
* Indicates if the song order is random.
|
|
1185
1215
|
*/
|
|
@@ -1229,9 +1259,9 @@ declare class Sequencer {
|
|
|
1229
1259
|
* Starts or resumes the playback.
|
|
1230
1260
|
*/
|
|
1231
1261
|
play(): void;
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1262
|
+
private handleMessage;
|
|
1263
|
+
private callEventInternal;
|
|
1264
|
+
private resetMIDIOutput;
|
|
1235
1265
|
private recalculateStartTime;
|
|
1236
1266
|
private sendMessage;
|
|
1237
1267
|
}
|