spessasynth_lib 4.2.1 → 4.2.3
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 +8 -2
- package/dist/index.d.ts +24 -11
- package/dist/index.js +52 -29
- package/dist/index.js.map +1 -1
- package/dist/spessasynth_processor.min.js +2 -2
- package/dist/spessasynth_processor.min.js.map +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
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 for the browsers, based on spessasynth_core.
|
|
6
|
+
_A powerful multipurpose SF2/DLS/MIDI TypeScript/JavaScript library for the browsers, based on spessasynth_core.
|
|
7
7
|
This is a WebAudioAPI wrapper for the [spessasynth_core](https://github.com/spessasus/spessasynth_core) library._
|
|
8
8
|
|
|
9
9
|
It allows you to:
|
|
@@ -91,9 +91,15 @@ document.getElementById("button").onclick = async () => {
|
|
|
91
91
|
};
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
## License
|
|
95
95
|
|
|
96
96
|
Copyright © 2026 Spessasus
|
|
97
97
|
Licensed under the Apache-2.0 License.
|
|
98
98
|
|
|
99
|
+
#### Legal
|
|
100
|
+
|
|
101
|
+
This project is in no way endorsed or otherwise affiliated with the MIDI Manufacturers Association,
|
|
102
|
+
Roland Corporation, Yamaha Corporation, Creative Technology Ltd. or E-mu Systems, Inc.,
|
|
103
|
+
or any other organization mentioned.
|
|
99
104
|
SoundFont® is a registered trademark of Creative Technology Ltd.
|
|
105
|
+
All other trademarks are the property of their respective owners.
|
package/dist/index.d.ts
CHANGED
|
@@ -436,7 +436,6 @@ interface BasicSynthesizerMessageData {
|
|
|
436
436
|
midiMessage: {
|
|
437
437
|
messageData: Uint8Array;
|
|
438
438
|
channelOffset: number;
|
|
439
|
-
force: boolean;
|
|
440
439
|
options: SynthMethodOptions;
|
|
441
440
|
};
|
|
442
441
|
ccReset: null;
|
|
@@ -706,12 +705,27 @@ declare abstract class BasicSynthesizer {
|
|
|
706
705
|
rate: number;
|
|
707
706
|
}): void;
|
|
708
707
|
/**
|
|
709
|
-
* Connects
|
|
708
|
+
* Connects a given channel output to the given audio node.
|
|
709
|
+
* Note that this output is only meant for visualization and may be silent when Insertion Effect for this channel is enabled.
|
|
710
|
+
* @param targetNode The node to connect to.
|
|
711
|
+
* @param channelNumber The channel number to connect to, will be rolled over if value is greater than 15.
|
|
712
|
+
* @returns The target node.
|
|
713
|
+
*/
|
|
714
|
+
connectChannel(targetNode: AudioNode, channelNumber: number): AudioNode;
|
|
715
|
+
/**
|
|
716
|
+
* Disconnects a given channel output to the given audio node.
|
|
717
|
+
* @param targetNode The node to disconnect from.
|
|
718
|
+
* @param channelNumber The channel number to connect to, will be rolled over if value is greater than 15.
|
|
719
|
+
*/
|
|
720
|
+
disconnectChannel(targetNode: AudioNode, channelNumber: number): void;
|
|
721
|
+
/**
|
|
722
|
+
* Connects the individual audio outputs to the given audio nodes.
|
|
723
|
+
* Note that these outputs is only meant for visualization and may be silent when Insertion Effect for this channel is enabled.
|
|
710
724
|
* @param audioNodes Exactly 16 outputs.
|
|
711
725
|
*/
|
|
712
726
|
connectIndividualOutputs(audioNodes: AudioNode[]): void;
|
|
713
727
|
/**
|
|
714
|
-
* Disconnects the individual audio outputs
|
|
728
|
+
* Disconnects the individual audio outputs from the given audio nodes.
|
|
715
729
|
* @param audioNodes Exactly 16 outputs.
|
|
716
730
|
*/
|
|
717
731
|
disconnectIndividualOutputs(audioNodes: AudioNode[]): void;
|
|
@@ -739,10 +753,9 @@ declare abstract class BasicSynthesizer {
|
|
|
739
753
|
* Stops playing a note.
|
|
740
754
|
* @param channel Usually 0-15: the channel of the note.
|
|
741
755
|
* @param midiNote {number} 0-127 the key number of the note.
|
|
742
|
-
* @param force Instantly kills the note if true.
|
|
743
756
|
* @param eventOptions Additional options for this command.
|
|
744
757
|
*/
|
|
745
|
-
noteOff(channel: number, midiNote: number,
|
|
758
|
+
noteOff(channel: number, midiNote: number, eventOptions?: SynthMethodOptions): void;
|
|
746
759
|
/**
|
|
747
760
|
* Stops all notes.
|
|
748
761
|
* @param force If the notes should immediately be stopped, defaults to false.
|
|
@@ -753,10 +766,9 @@ declare abstract class BasicSynthesizer {
|
|
|
753
766
|
* @param channel Usually 0-15: the channel to change the controller.
|
|
754
767
|
* @param controllerNumber 0-127 the MIDI CC number.
|
|
755
768
|
* @param controllerValue 0-127 the controller value.
|
|
756
|
-
* @param force Forces the controller-change message, even if it's locked or gm system is set and the cc is bank select.
|
|
757
769
|
* @param eventOptions Additional options for this command.
|
|
758
770
|
*/
|
|
759
|
-
controllerChange(channel: number, controllerNumber: MIDIController, controllerValue: number,
|
|
771
|
+
controllerChange(channel: number, controllerNumber: MIDIController, controllerValue: number, eventOptions?: SynthMethodOptions): void;
|
|
760
772
|
/**
|
|
761
773
|
* Resets all controllers (for every channel)
|
|
762
774
|
*/
|
|
@@ -796,15 +808,16 @@ declare abstract class BasicSynthesizer {
|
|
|
796
808
|
* Sets the channel's pitch wheel range, in semitones.
|
|
797
809
|
* @param channel Usually 0-15: the channel to change.
|
|
798
810
|
* @param range The bend range in semitones.
|
|
811
|
+
* @param eventOptions Additional options for this command.
|
|
799
812
|
*/
|
|
800
|
-
pitchWheelRange(channel: number, range: number): void;
|
|
813
|
+
pitchWheelRange(channel: number, range: number, eventOptions?: SynthMethodOptions): void;
|
|
801
814
|
/**
|
|
802
815
|
* Changes the program for a given channel
|
|
803
816
|
* @param channel Usually 0-15: the channel to change.
|
|
804
817
|
* @param programNumber 0-127 the MIDI patch number.
|
|
805
|
-
*
|
|
818
|
+
* @param eventOptions Additional options for this command.
|
|
806
819
|
*/
|
|
807
|
-
programChange(channel: number, programNumber: number): void;
|
|
820
|
+
programChange(channel: number, programNumber: number, eventOptions?: SynthMethodOptions): void;
|
|
808
821
|
/**
|
|
809
822
|
* Transposes the channel by given number of semitones.
|
|
810
823
|
* @param channel The channel number.
|
|
@@ -860,7 +873,7 @@ declare abstract class BasicSynthesizer {
|
|
|
860
873
|
assignNewSequencer(callback: (m: SequencerReturnMessage) => unknown): number;
|
|
861
874
|
protected assignProgressTracker<K extends keyof SynthesizerProgress>(type: K, progressFunction: (args: SynthesizerProgress[K]) => unknown): void;
|
|
862
875
|
protected revokeProgressTracker<K extends keyof SynthesizerProgress>(type: K): void;
|
|
863
|
-
protected _sendInternal(message: Iterable<number>, channelOffset: number,
|
|
876
|
+
protected _sendInternal(message: Iterable<number>, channelOffset: number, eventOptions: Partial<SynthMethodOptions>): void;
|
|
864
877
|
/**
|
|
865
878
|
* Handles the messages received from the worklet.
|
|
866
879
|
*/
|
package/dist/index.js
CHANGED
|
@@ -557,7 +557,27 @@ var BasicSynthesizer = class {
|
|
|
557
557
|
void value;
|
|
558
558
|
}
|
|
559
559
|
/**
|
|
560
|
-
* Connects
|
|
560
|
+
* Connects a given channel output to the given audio node.
|
|
561
|
+
* Note that this output is only meant for visualization and may be silent when Insertion Effect for this channel is enabled.
|
|
562
|
+
* @param targetNode The node to connect to.
|
|
563
|
+
* @param channelNumber The channel number to connect to, will be rolled over if value is greater than 15.
|
|
564
|
+
* @returns The target node.
|
|
565
|
+
*/
|
|
566
|
+
connectChannel(targetNode, channelNumber) {
|
|
567
|
+
this.worklet.connect(targetNode, channelNumber % 16 + 1);
|
|
568
|
+
return targetNode;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Disconnects a given channel output to the given audio node.
|
|
572
|
+
* @param targetNode The node to disconnect from.
|
|
573
|
+
* @param channelNumber The channel number to connect to, will be rolled over if value is greater than 15.
|
|
574
|
+
*/
|
|
575
|
+
disconnectChannel(targetNode, channelNumber) {
|
|
576
|
+
this.worklet.disconnect(targetNode, channelNumber % 16 + 1);
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Connects the individual audio outputs to the given audio nodes.
|
|
580
|
+
* Note that these outputs is only meant for visualization and may be silent when Insertion Effect for this channel is enabled.
|
|
561
581
|
* @param audioNodes Exactly 16 outputs.
|
|
562
582
|
*/
|
|
563
583
|
connectIndividualOutputs(audioNodes) {
|
|
@@ -565,12 +585,12 @@ var BasicSynthesizer = class {
|
|
|
565
585
|
throw new Error(`input nodes amount differs from the system's outputs amount!
|
|
566
586
|
Expected ${this._outputsAmount} got ${audioNodes.length}`);
|
|
567
587
|
}
|
|
568
|
-
for (let
|
|
569
|
-
this.
|
|
588
|
+
for (let channel = 0; channel < this._outputsAmount; channel++) {
|
|
589
|
+
this.connectChannel(audioNodes[channel], channel);
|
|
570
590
|
}
|
|
571
591
|
}
|
|
572
592
|
/**
|
|
573
|
-
* Disconnects the individual audio outputs
|
|
593
|
+
* Disconnects the individual audio outputs from the given audio nodes.
|
|
574
594
|
* @param audioNodes Exactly 16 outputs.
|
|
575
595
|
*/
|
|
576
596
|
disconnectIndividualOutputs(audioNodes) {
|
|
@@ -578,8 +598,8 @@ var BasicSynthesizer = class {
|
|
|
578
598
|
throw new Error(`input nodes amount differs from the system's outputs amount!
|
|
579
599
|
Expected ${this._outputsAmount} got ${audioNodes.length}`);
|
|
580
600
|
}
|
|
581
|
-
for (let
|
|
582
|
-
this.
|
|
601
|
+
for (let channel = 0; channel < this._outputsAmount; channel++) {
|
|
602
|
+
this.disconnectChannel(audioNodes[channel], channel);
|
|
583
603
|
}
|
|
584
604
|
}
|
|
585
605
|
// noinspection JSUnusedGlobalSymbols
|
|
@@ -597,7 +617,7 @@ var BasicSynthesizer = class {
|
|
|
597
617
|
* @param eventOptions additional options for this command.
|
|
598
618
|
*/
|
|
599
619
|
sendMessage(message, channelOffset = 0, eventOptions = DEFAULT_SYNTH_METHOD_OPTIONS) {
|
|
600
|
-
this._sendInternal(message, channelOffset,
|
|
620
|
+
this._sendInternal(message, channelOffset, eventOptions);
|
|
601
621
|
}
|
|
602
622
|
/**
|
|
603
623
|
* Starts playing a note
|
|
@@ -621,17 +641,15 @@ var BasicSynthesizer = class {
|
|
|
621
641
|
* Stops playing a note.
|
|
622
642
|
* @param channel Usually 0-15: the channel of the note.
|
|
623
643
|
* @param midiNote {number} 0-127 the key number of the note.
|
|
624
|
-
* @param force Instantly kills the note if true.
|
|
625
644
|
* @param eventOptions Additional options for this command.
|
|
626
645
|
*/
|
|
627
|
-
noteOff(channel, midiNote,
|
|
646
|
+
noteOff(channel, midiNote, eventOptions = DEFAULT_SYNTH_METHOD_OPTIONS) {
|
|
628
647
|
midiNote %= 128;
|
|
629
648
|
const ch = channel % 16;
|
|
630
649
|
const offset = channel - ch;
|
|
631
650
|
this._sendInternal(
|
|
632
651
|
[midiMessageTypes.noteOff | ch, midiNote],
|
|
633
652
|
offset,
|
|
634
|
-
force,
|
|
635
653
|
eventOptions
|
|
636
654
|
);
|
|
637
655
|
}
|
|
@@ -651,10 +669,9 @@ var BasicSynthesizer = class {
|
|
|
651
669
|
* @param channel Usually 0-15: the channel to change the controller.
|
|
652
670
|
* @param controllerNumber 0-127 the MIDI CC number.
|
|
653
671
|
* @param controllerValue 0-127 the controller value.
|
|
654
|
-
* @param force Forces the controller-change message, even if it's locked or gm system is set and the cc is bank select.
|
|
655
672
|
* @param eventOptions Additional options for this command.
|
|
656
673
|
*/
|
|
657
|
-
controllerChange(channel, controllerNumber, controllerValue,
|
|
674
|
+
controllerChange(channel, controllerNumber, controllerValue, eventOptions = DEFAULT_SYNTH_METHOD_OPTIONS) {
|
|
658
675
|
if (controllerNumber > 127 || controllerNumber < 0) {
|
|
659
676
|
throw new Error(`Invalid controller number: ${controllerNumber}`);
|
|
660
677
|
}
|
|
@@ -669,7 +686,6 @@ var BasicSynthesizer = class {
|
|
|
669
686
|
controllerValue
|
|
670
687
|
],
|
|
671
688
|
offset,
|
|
672
|
-
force,
|
|
673
689
|
eventOptions
|
|
674
690
|
);
|
|
675
691
|
}
|
|
@@ -756,44 +772,55 @@ var BasicSynthesizer = class {
|
|
|
756
772
|
* Sets the channel's pitch wheel range, in semitones.
|
|
757
773
|
* @param channel Usually 0-15: the channel to change.
|
|
758
774
|
* @param range The bend range in semitones.
|
|
775
|
+
* @param eventOptions Additional options for this command.
|
|
759
776
|
*/
|
|
760
|
-
pitchWheelRange(channel, range) {
|
|
777
|
+
pitchWheelRange(channel, range, eventOptions = DEFAULT_SYNTH_METHOD_OPTIONS) {
|
|
761
778
|
this.controllerChange(
|
|
762
779
|
channel,
|
|
763
780
|
midiControllers.registeredParameterMSB,
|
|
764
|
-
0
|
|
781
|
+
0,
|
|
782
|
+
eventOptions
|
|
765
783
|
);
|
|
766
784
|
this.controllerChange(
|
|
767
785
|
channel,
|
|
768
786
|
midiControllers.registeredParameterLSB,
|
|
769
|
-
0
|
|
787
|
+
0,
|
|
788
|
+
eventOptions
|
|
770
789
|
);
|
|
771
790
|
this.controllerChange(channel, midiControllers.dataEntryMSB, range);
|
|
772
791
|
this.controllerChange(
|
|
773
792
|
channel,
|
|
774
793
|
midiControllers.registeredParameterMSB,
|
|
775
|
-
127
|
|
794
|
+
127,
|
|
795
|
+
eventOptions
|
|
776
796
|
);
|
|
777
797
|
this.controllerChange(
|
|
778
798
|
channel,
|
|
779
799
|
midiControllers.registeredParameterLSB,
|
|
780
|
-
127
|
|
800
|
+
127,
|
|
801
|
+
eventOptions
|
|
802
|
+
);
|
|
803
|
+
this.controllerChange(
|
|
804
|
+
channel,
|
|
805
|
+
midiControllers.dataEntryMSB,
|
|
806
|
+
0,
|
|
807
|
+
eventOptions
|
|
781
808
|
);
|
|
782
|
-
this.controllerChange(channel, midiControllers.dataEntryMSB, 0);
|
|
783
809
|
}
|
|
784
810
|
/**
|
|
785
811
|
* Changes the program for a given channel
|
|
786
812
|
* @param channel Usually 0-15: the channel to change.
|
|
787
813
|
* @param programNumber 0-127 the MIDI patch number.
|
|
788
|
-
*
|
|
814
|
+
* @param eventOptions Additional options for this command.
|
|
789
815
|
*/
|
|
790
|
-
programChange(channel, programNumber) {
|
|
816
|
+
programChange(channel, programNumber, eventOptions = DEFAULT_SYNTH_METHOD_OPTIONS) {
|
|
791
817
|
const ch = channel % 16;
|
|
792
818
|
const offset = channel - ch;
|
|
793
819
|
programNumber %= 128;
|
|
794
820
|
this.sendMessage(
|
|
795
821
|
[midiMessageTypes.programChange | ch, programNumber],
|
|
796
|
-
offset
|
|
822
|
+
offset,
|
|
823
|
+
eventOptions
|
|
797
824
|
);
|
|
798
825
|
}
|
|
799
826
|
// noinspection JSUnusedGlobalSymbols
|
|
@@ -836,7 +863,6 @@ var BasicSynthesizer = class {
|
|
|
836
863
|
this._sendInternal(
|
|
837
864
|
[midiMessageTypes.systemExclusive, ...Array.from(messageData)],
|
|
838
865
|
channelOffset,
|
|
839
|
-
false,
|
|
840
866
|
eventOptions
|
|
841
867
|
);
|
|
842
868
|
}
|
|
@@ -943,7 +969,7 @@ var BasicSynthesizer = class {
|
|
|
943
969
|
revokeProgressTracker(type) {
|
|
944
970
|
this.renderingProgressTracker.delete(type);
|
|
945
971
|
}
|
|
946
|
-
_sendInternal(message, channelOffset,
|
|
972
|
+
_sendInternal(message, channelOffset, eventOptions) {
|
|
947
973
|
const options = fillWithDefaults(
|
|
948
974
|
eventOptions,
|
|
949
975
|
DEFAULT_SYNTH_METHOD_OPTIONS
|
|
@@ -954,10 +980,8 @@ var BasicSynthesizer = class {
|
|
|
954
980
|
data: {
|
|
955
981
|
messageData: new Uint8Array(message),
|
|
956
982
|
channelOffset,
|
|
957
|
-
force,
|
|
958
983
|
options
|
|
959
984
|
}
|
|
960
|
-
//[new Uint8Array(message), offset, force, opts]
|
|
961
985
|
});
|
|
962
986
|
}
|
|
963
987
|
/**
|
|
@@ -1223,8 +1247,6 @@ function renderAudioWorker(sampleRate, options) {
|
|
|
1223
1247
|
const rendererSynth = new SpessaSynthProcessor(sampleRate, {
|
|
1224
1248
|
enableEventSystem: false
|
|
1225
1249
|
});
|
|
1226
|
-
const rendererSeq = new SpessaSynthSequencer(rendererSynth);
|
|
1227
|
-
rendererSynth.setMasterParameter("autoAllocateVoices", true);
|
|
1228
1250
|
for (const entry of this.synthesizer.soundBankManager.soundBankList)
|
|
1229
1251
|
rendererSynth.soundBankManager.addSoundBank(
|
|
1230
1252
|
entry.soundBank,
|
|
@@ -1244,12 +1266,14 @@ function renderAudioWorker(sampleRate, options) {
|
|
|
1244
1266
|
const loopDuration = loopEndAbsolute - loopStartAbsolute;
|
|
1245
1267
|
const duration = parsedMid.duration / playbackRate + options.extraTime + loopDuration * options.loopCount;
|
|
1246
1268
|
const sampleDuration = sampleRate * duration;
|
|
1269
|
+
const rendererSeq = new SpessaSynthSequencer(rendererSynth);
|
|
1247
1270
|
rendererSeq.loopCount = options.loopCount;
|
|
1248
1271
|
if (options.preserveSynthParams) {
|
|
1249
1272
|
rendererSeq.playbackRate = seq.playbackRate;
|
|
1250
1273
|
const snapshot = this.synthesizer.getSnapshot();
|
|
1251
1274
|
rendererSynth.applySynthesizerSnapshot(snapshot);
|
|
1252
1275
|
}
|
|
1276
|
+
rendererSynth.setMasterParameter("autoAllocateVoices", true);
|
|
1253
1277
|
rendererSeq.loadNewSongList([parsedMid]);
|
|
1254
1278
|
rendererSeq.play();
|
|
1255
1279
|
const wetL = new Float32Array(sampleDuration);
|
|
@@ -1744,7 +1768,6 @@ var BasicSynthesizerCore = class {
|
|
|
1744
1768
|
this.synthesizer.processMessage(
|
|
1745
1769
|
m.data.messageData,
|
|
1746
1770
|
m.data.channelOffset,
|
|
1747
|
-
m.data.force,
|
|
1748
1771
|
m.data.options
|
|
1749
1772
|
);
|
|
1750
1773
|
break;
|