spessasynth_core 1.1.3 → 1.1.5
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/LICENSE +3 -26
- package/README.md +156 -474
- package/index.js +74 -8
- package/package.json +21 -8
- package/src/externals/fflate/LICENSE +21 -0
- package/src/externals/fflate/fflate.min.js +1 -0
- package/src/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +12 -0
- package/src/externals/stbvorbis_sync/LICENSE +202 -0
- package/src/externals/stbvorbis_sync/NOTICE +6 -0
- package/src/externals/stbvorbis_sync/stbvorbis_sync.min.js +1 -0
- package/src/midi/README.md +32 -0
- package/src/midi/basic_midi.js +567 -0
- package/src/midi/midi_builder.js +202 -0
- package/src/midi/midi_loader.js +324 -0
- package/{spessasynth_core/midi_parser → src/midi}/midi_message.js +58 -35
- package/src/midi/midi_sequence.js +224 -0
- package/src/midi/midi_tools/get_note_times.js +154 -0
- package/src/midi/midi_tools/midi_editor.js +611 -0
- package/src/midi/midi_tools/midi_writer.js +99 -0
- package/src/midi/midi_tools/rmidi_writer.js +567 -0
- package/src/midi/midi_tools/used_keys_loaded.js +238 -0
- package/src/midi/xmf_loader.js +454 -0
- package/src/sequencer/README.md +5 -0
- package/src/sequencer/events.js +81 -0
- package/src/sequencer/play.js +349 -0
- package/src/sequencer/process_event.js +165 -0
- package/{spessasynth_core/sequencer/worklet_sequencer → src/sequencer}/process_tick.js +103 -84
- package/src/sequencer/sequencer_engine.js +367 -0
- package/src/sequencer/song_control.js +201 -0
- package/src/soundfont/README.md +13 -0
- package/src/soundfont/basic_soundfont/basic_instrument.js +77 -0
- package/src/soundfont/basic_soundfont/basic_preset.js +336 -0
- package/src/soundfont/basic_soundfont/basic_sample.js +206 -0
- package/src/soundfont/basic_soundfont/basic_soundfont.js +565 -0
- package/src/soundfont/basic_soundfont/basic_zone.js +64 -0
- package/src/soundfont/basic_soundfont/basic_zones.js +43 -0
- package/src/soundfont/basic_soundfont/generator.js +220 -0
- package/src/soundfont/basic_soundfont/modulator.js +378 -0
- package/src/soundfont/basic_soundfont/riff_chunk.js +149 -0
- package/src/soundfont/basic_soundfont/write_dls/art2.js +173 -0
- package/src/soundfont/basic_soundfont/write_dls/articulator.js +49 -0
- package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +400 -0
- package/src/soundfont/basic_soundfont/write_dls/ins.js +103 -0
- package/src/soundfont/basic_soundfont/write_dls/lins.js +18 -0
- package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +330 -0
- package/src/soundfont/basic_soundfont/write_dls/rgn2.js +121 -0
- package/src/soundfont/basic_soundfont/write_dls/wave.js +94 -0
- package/src/soundfont/basic_soundfont/write_dls/write_dls.js +119 -0
- package/src/soundfont/basic_soundfont/write_dls/wsmp.js +78 -0
- package/src/soundfont/basic_soundfont/write_dls/wvpl.js +32 -0
- package/src/soundfont/basic_soundfont/write_sf2/ibag.js +39 -0
- package/src/soundfont/basic_soundfont/write_sf2/igen.js +80 -0
- package/src/soundfont/basic_soundfont/write_sf2/imod.js +46 -0
- package/src/soundfont/basic_soundfont/write_sf2/inst.js +34 -0
- package/src/soundfont/basic_soundfont/write_sf2/pbag.js +39 -0
- package/src/soundfont/basic_soundfont/write_sf2/pgen.js +82 -0
- package/src/soundfont/basic_soundfont/write_sf2/phdr.js +42 -0
- package/src/soundfont/basic_soundfont/write_sf2/pmod.js +46 -0
- package/src/soundfont/basic_soundfont/write_sf2/sdta.js +80 -0
- package/src/soundfont/basic_soundfont/write_sf2/shdr.js +55 -0
- package/src/soundfont/basic_soundfont/write_sf2/write.js +222 -0
- package/src/soundfont/dls/articulator_converter.js +396 -0
- package/src/soundfont/dls/dls_destinations.js +38 -0
- package/src/soundfont/dls/dls_preset.js +44 -0
- package/src/soundfont/dls/dls_sample.js +75 -0
- package/src/soundfont/dls/dls_soundfont.js +186 -0
- package/src/soundfont/dls/dls_sources.js +62 -0
- package/src/soundfont/dls/dls_zone.js +95 -0
- package/src/soundfont/dls/read_articulation.js +299 -0
- package/src/soundfont/dls/read_instrument.js +121 -0
- package/src/soundfont/dls/read_instrument_list.js +17 -0
- package/src/soundfont/dls/read_lart.js +35 -0
- package/src/soundfont/dls/read_region.js +152 -0
- package/src/soundfont/dls/read_samples.js +270 -0
- package/src/soundfont/load_soundfont.js +21 -0
- package/src/soundfont/read_sf2/generators.js +46 -0
- package/{spessasynth_core/soundfont/chunk → src/soundfont/read_sf2}/instruments.js +20 -14
- package/src/soundfont/read_sf2/modulators.js +36 -0
- package/src/soundfont/read_sf2/presets.js +80 -0
- package/src/soundfont/read_sf2/samples.js +304 -0
- package/src/soundfont/read_sf2/soundfont.js +305 -0
- package/{spessasynth_core/soundfont/chunk → src/soundfont/read_sf2}/zones.js +68 -69
- package/src/synthetizer/README.md +7 -0
- package/src/synthetizer/audio_engine/README.md +9 -0
- package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +266 -0
- package/src/synthetizer/audio_engine/engine_components/controller_tables.js +88 -0
- package/src/synthetizer/audio_engine/engine_components/key_modifier_manager.js +150 -0
- package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/lfo.js +9 -6
- package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +282 -0
- package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +467 -0
- package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +181 -0
- package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/modulator_curves.js +33 -30
- package/src/synthetizer/audio_engine/engine_components/soundfont_manager.js +221 -0
- package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +120 -0
- package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/unit_converter.js +11 -4
- package/src/synthetizer/audio_engine/engine_components/voice.js +519 -0
- package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +401 -0
- package/src/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +263 -0
- package/src/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +132 -0
- package/src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +48 -0
- package/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +241 -0
- package/src/synthetizer/audio_engine/engine_methods/create_midi_channel.js +27 -0
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +253 -0
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +66 -0
- package/src/synthetizer/audio_engine/engine_methods/mute_channel.js +17 -0
- package/src/synthetizer/audio_engine/engine_methods/note_on.js +175 -0
- package/src/synthetizer/audio_engine/engine_methods/portamento_time.js +92 -0
- package/src/synthetizer/audio_engine/engine_methods/program_change.js +61 -0
- package/src/synthetizer/audio_engine/engine_methods/render_voice.js +196 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js +30 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +22 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js +28 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js +31 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js +21 -0
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +20 -0
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +55 -0
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +16 -0
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +30 -0
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +63 -0
- package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +776 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +24 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +33 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +31 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +15 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +27 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +19 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +27 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +15 -0
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +34 -0
- package/src/synthetizer/audio_engine/main_processor.js +804 -0
- package/src/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +15 -0
- package/src/synthetizer/audio_engine/snapshot/channel_snapshot.js +175 -0
- package/src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +116 -0
- package/src/synthetizer/synth_constants.js +22 -0
- package/{spessasynth_core → src}/utils/README.md +1 -0
- package/src/utils/buffer_to_wav.js +185 -0
- package/src/utils/byte_functions/big_endian.js +32 -0
- package/src/utils/byte_functions/little_endian.js +77 -0
- package/src/utils/byte_functions/string.js +107 -0
- package/src/utils/byte_functions/variable_length_quantity.js +42 -0
- package/src/utils/fill_with_defaults.js +21 -0
- package/src/utils/indexed_array.js +52 -0
- package/{spessasynth_core → src}/utils/loggin.js +70 -78
- package/src/utils/other.js +92 -0
- package/src/utils/sysex_detector.js +58 -0
- package/src/utils/xg_hacks.js +193 -0
- package/.idea/inspectionProfiles/Project_Default.xml +0 -10
- package/.idea/jsLibraryMappings.xml +0 -6
- package/.idea/modules.xml +0 -8
- package/.idea/spessasynth_core.iml +0 -12
- package/.idea/vcs.xml +0 -6
- package/spessasynth_core/midi_parser/README.md +0 -3
- package/spessasynth_core/midi_parser/midi_loader.js +0 -386
- package/spessasynth_core/sequencer/sequencer.js +0 -202
- package/spessasynth_core/sequencer/worklet_sequencer/play.js +0 -209
- package/spessasynth_core/sequencer/worklet_sequencer/process_event.js +0 -120
- package/spessasynth_core/sequencer/worklet_sequencer/song_control.js +0 -112
- package/spessasynth_core/soundfont/README.md +0 -4
- package/spessasynth_core/soundfont/chunk/generators.js +0 -205
- package/spessasynth_core/soundfont/chunk/modulators.js +0 -232
- package/spessasynth_core/soundfont/chunk/presets.js +0 -264
- package/spessasynth_core/soundfont/chunk/riff_chunk.js +0 -46
- package/spessasynth_core/soundfont/chunk/samples.js +0 -250
- package/spessasynth_core/soundfont/soundfont_parser.js +0 -301
- package/spessasynth_core/synthetizer/README.md +0 -6
- package/spessasynth_core/synthetizer/synthesizer.js +0 -313
- package/spessasynth_core/synthetizer/worklet_system/README.md +0 -3
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/controller_control.js +0 -290
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/data_entry.js +0 -280
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/note_off.js +0 -102
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/note_on.js +0 -77
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/program_control.js +0 -140
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/system_exclusive.js +0 -266
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/tuning_control.js +0 -104
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/vibrato_control.js +0 -29
- package/spessasynth_core/synthetizer/worklet_system/worklet_methods/voice_control.js +0 -223
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/lowpass_filter.js +0 -133
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +0 -73
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +0 -76
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +0 -272
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +0 -83
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_modulator.js +0 -175
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +0 -106
- package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +0 -285
- package/spessasynth_core/utils/buffer_to_wav.js +0 -70
- package/spessasynth_core/utils/byte_functions.js +0 -141
- package/spessasynth_core/utils/other.js +0 -49
- package/spessasynth_core/utils/shiftable_array.js +0 -26
- package/spessasynth_core/utils/stbvorbis_sync.js +0 -1877
package/README.md
CHANGED
|
@@ -1,474 +1,156 @@
|
|
|
1
|
-
# spessasynth_core
|
|
2
|
-
|
|
3
|
-
A
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
```
|
|
158
|
-
## Synthesizer
|
|
159
|
-
The main synth module.
|
|
160
|
-
### Initialization
|
|
161
|
-
```js
|
|
162
|
-
const synth = new Synthesizer(soundFontBuffer, sampleRate, blockSize)
|
|
163
|
-
```
|
|
164
|
-
- soundFontBuffer - a `Buffer` or `ArrayBufferLike`, represents the soundfont file.
|
|
165
|
-
- sampleRate - number, the output sample rate in hertz.
|
|
166
|
-
- blockSize - optional, a number. Sets the interval of the synth updating parameters like the sequencer tick processing and modulation envelope.
|
|
167
|
-
Default value is 128, and it's recommended to leave it as the default.
|
|
168
|
-
|
|
169
|
-
### sf3supportReady
|
|
170
|
-
A promise that gets resolved when the vorbis decoder is ready. You must await it if you use sf3 soundfonts.
|
|
171
|
-
```js
|
|
172
|
-
await synth.sf3supportReady;
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### render
|
|
176
|
-
Synthesizes audio the output buffers
|
|
177
|
-
```js
|
|
178
|
-
synth.render(outputChannels, reverbOutputChannels, chorusOutputChannels);
|
|
179
|
-
```
|
|
180
|
-
- outputChannels - two `Float32Arrays` that get filled with the audio data. Left is the left channel and right is the right channel. Can be any length. (except zero)
|
|
181
|
-
- reverbOutputChannels - two `Float32Arrays` that get filled with the unprocessed audio data for reverb processing. Left is the left channel and right is the right channel. Can be undefined.
|
|
182
|
-
- reverbOutputChannels - two `Float32Arrays` that get filled with the unprocessed audio data for chorus processing. Left is the left channel and right is the right channel. Can be undefined.
|
|
183
|
-
|
|
184
|
-
**All arrays must be the same length.**
|
|
185
|
-
|
|
186
|
-
### noteOn
|
|
187
|
-
|
|
188
|
-
Plays the given note.
|
|
189
|
-
|
|
190
|
-
```js
|
|
191
|
-
synth.noteOn(channel, midiNote, velocity, enableDebugging);
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
- channel - the MIDI channel to use. Usually ranges from 0 to 15, but it depends on the channel count.
|
|
195
|
-
- midiNote - the note to play. Ranges from 0 to 127.
|
|
196
|
-
- velocity - controls how loud the note is. 127 is normal loudness and 1 is the quietest. Note that velocity of 0 has the same effect as using `noteOff`. Ranges from 0 to 127.
|
|
197
|
-
- enableDebugging - boolean, used only for debugging. When `true`, the console will print out tables of the soundfont generator data used to play the note.
|
|
198
|
-
|
|
199
|
-
### noteOff
|
|
200
|
-
|
|
201
|
-
Stops the given note.
|
|
202
|
-
|
|
203
|
-
```js
|
|
204
|
-
synth.noteOff(channel, midiNote);
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
- channel - the MIDI channel to use. Usually ranges from 0 to 15, but it depends on the channel count.
|
|
208
|
-
- midiNote - the note to play. Ranges from 0 to 127.
|
|
209
|
-
> To stop a note instantly, use `synth.killNote` (takes the same arguments)
|
|
210
|
-
|
|
211
|
-
### stopAllChannels
|
|
212
|
-
|
|
213
|
-
Stops all notes. Equivalent of MIDI "panic".
|
|
214
|
-
|
|
215
|
-
```js
|
|
216
|
-
synth.stopAllChannels(force);
|
|
217
|
-
```
|
|
218
|
-
- force - `boolean`, if true, ignores the release time and stops everything instantly. Defaults to false.
|
|
219
|
-
> To stop all notes on a specific channel, use `synth.stopAll(channel, force)`. channel is the channel number.
|
|
220
|
-
|
|
221
|
-
### programChange
|
|
222
|
-
|
|
223
|
-
Changes the preset for the given channel.
|
|
224
|
-
|
|
225
|
-
```js
|
|
226
|
-
synth.programChange(channel, programNumber);
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
- channel - the MIDI channel to change. Usually ranges from 0 to 15, but it depends on the channel count.
|
|
230
|
-
- programNumber - the MIDI program number to use. Ranges from 0 to 127. To use other banks, go to [controllerChange](#controllerchange).
|
|
231
|
-
> To lock the preset (prevent MIDI file from changing it) use `synth.workletProcessorChannels[channel].lockPreset = true;`
|
|
232
|
-
|
|
233
|
-
### pitchWheel
|
|
234
|
-
|
|
235
|
-
Changes the channel's pitch, including the currently playing notes.
|
|
236
|
-
|
|
237
|
-
```js
|
|
238
|
-
synth.pitchWheel(channel, MSB, LSB);
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
- channel - the MIDI channel to use. Usually ranges from 0 to 15, but it depends on the channel count.
|
|
242
|
-
- MSB and LSB. 7-bit numbers that form a 14-bit pitch bend value.
|
|
243
|
-
> [I highly recommend this article for more info.](https://www.recordingblogs.com/wiki/midi-pitch-wheel-message)
|
|
244
|
-
|
|
245
|
-
### systemExclusive
|
|
246
|
-
|
|
247
|
-
Handles a MIDI System Exclusive message.
|
|
248
|
-
|
|
249
|
-
```js
|
|
250
|
-
synth.systemExclusive(messageData);
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
- message data - Uint8Array, the message byte data **Excluding the 0xF0 byte!**
|
|
254
|
-
> Refer to [this table](https://github.com/spessasus/SpessaSynth/wiki/Synthetizer-Class#supported-system-exclusives) for the list of supported System Exclusives.
|
|
255
|
-
|
|
256
|
-
### setMainVolume
|
|
257
|
-
Sets the main volume of the synthesizer.
|
|
258
|
-
```js
|
|
259
|
-
synth.setMainVolume(volume);
|
|
260
|
-
```
|
|
261
|
-
- volume - the volume, ranges from 0 to 1.
|
|
262
|
-
|
|
263
|
-
### setMasterPan
|
|
264
|
-
Sets the master panning of the synthesizer.
|
|
265
|
-
```js
|
|
266
|
-
synth.setMasterPan(pan);
|
|
267
|
-
```
|
|
268
|
-
- pan - ranges from -1 to 1, -1 is left, 0 is middle, 1 is right.
|
|
269
|
-
|
|
270
|
-
### lockController
|
|
271
|
-
|
|
272
|
-
Causes the given midi channel to ignore controller messages for the given controller number.
|
|
273
|
-
|
|
274
|
-
```js
|
|
275
|
-
synth.lockController(channel, controllerNumber, isLocked);
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
- channel - the channel to lock. Usually ranges from 0 to 15, but it depends on the channel count.
|
|
279
|
-
- controllerNumber - the MIDI CC to lock. Ranges from 0 to 127.
|
|
280
|
-
- isLocked - boolean, if true then locked, if false then unlocked.
|
|
281
|
-
|
|
282
|
-
### muteChannel
|
|
283
|
-
|
|
284
|
-
Mutes or unmutes a given channel
|
|
285
|
-
|
|
286
|
-
```js
|
|
287
|
-
synth.muteChannel(channel, isMuted);
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
- channel - the channel to mute/unmute. Usually ranges from 0 to 15, but it depends on the channel count.
|
|
291
|
-
- isMuted - if the channel should be muted. boolean.
|
|
292
|
-
|
|
293
|
-
### transposeAllChannels
|
|
294
|
-
|
|
295
|
-
Transposes the synth up or down in semitones. Floating point values can be used for more precise tuning.
|
|
296
|
-
|
|
297
|
-
```js
|
|
298
|
-
synth.transposeAllChannels(semitones);
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
- semitones - the amount of semitones to transpose the synth by. Can be positive or negative or zero. Zero resets the pitch.
|
|
302
|
-
|
|
303
|
-
### controllerChange
|
|
304
|
-
|
|
305
|
-
Sets a given MIDI controller to a given value.
|
|
306
|
-
|
|
307
|
-
```js
|
|
308
|
-
synth.controllerChange(channel, controllerNumber, controllerValue);
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
- channel - the MIDI channel to use. Usually ranges from 0 to 15, but it depends on the channel count.
|
|
312
|
-
- controllerName - the MIDI CC number. Refer to [this table](https://github.com/spessasus/SpessaSynth/wiki/Synthetizer-Class#default-supported-controllers) for the list of controllers supported by default.
|
|
313
|
-
- controllerValue - the value to set the given controller to. Ranges from 0 to 127.
|
|
314
|
-
> Note that theoreticallly all controllers are supported as it depends on the SoundFont's modulators.
|
|
315
|
-
|
|
316
|
-
### resetAllControllers
|
|
317
|
-
Resets all controllers and programs to their default values. Also resets the system.
|
|
318
|
-
```js
|
|
319
|
-
synth.resetAllControllers();
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
### addNewChannel
|
|
323
|
-
|
|
324
|
-
Adds a new channel.
|
|
325
|
-
```js
|
|
326
|
-
synth.addNewChannel();
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
### reloadSoundfont
|
|
330
|
-
|
|
331
|
-
Changes the soundfont of a Synthesizer's instance.
|
|
332
|
-
|
|
333
|
-
```js
|
|
334
|
-
synth.reloadSoundFont(soundFontBuffer);
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
- soundFont - the soundfont to change to, an `ArrayBuffer` instance of the file.
|
|
338
|
-
|
|
339
|
-
### setDrums
|
|
340
|
-
Sets the given channel to a drum channel.
|
|
341
|
-
```js
|
|
342
|
-
synth.setDrums(channel, isDrum);
|
|
343
|
-
```
|
|
344
|
-
- channel - the channel to change. Usually ranges from 0 to 15, but it depends on the channel count.
|
|
345
|
-
- isDrum - `boolean` indicates if the channel should be a drum channel.
|
|
346
|
-
|
|
347
|
-
### Accesing controller values
|
|
348
|
-
use `synth.workletProcessorChannels` to get the current values. A single channel is defined as follows:
|
|
349
|
-
```js
|
|
350
|
-
/**
|
|
351
|
-
* @typedef {Object} WorkletProcessorChannel
|
|
352
|
-
* @property {Int16Array} midiControllers - array of MIDI controller values
|
|
353
|
-
* @property {boolean[]} lockedControllers - array indicating if a controller is locked
|
|
354
|
-
* @property {boolean} holdPedal - indicates whether the hold pedal is active
|
|
355
|
-
* @property {boolean} drumChannel - indicates whether the channel is a drum channel
|
|
356
|
-
*
|
|
357
|
-
* @property {Preset} preset - the channel's preset
|
|
358
|
-
* @property {boolean} lockPreset - indicates whether the program on the channel is locked
|
|
359
|
-
*
|
|
360
|
-
* @property {boolean} lockVibrato - indicates whether the custom vibrato is locked
|
|
361
|
-
* @property {Object} channelVibrato - vibrato settings for the channel
|
|
362
|
-
* @property {number} channelVibrato.depth - depth of the vibrato effect (cents)
|
|
363
|
-
* @property {number} channelVibrato.delay - delay before the vibrato effect starts (seconds)
|
|
364
|
-
* @property {number} channelVibrato.rate - rate of the vibrato oscillation (Hz)
|
|
365
|
-
|
|
366
|
-
* @property {boolean} isMuted - indicates whether the channel is muted
|
|
367
|
-
* @property {WorkletVoice[]} voices - array of voices currently active on the channel
|
|
368
|
-
* @property {WorkletVoice[]} sustainedVoices - array of voices that are sustained on the channel
|
|
369
|
-
*/
|
|
370
|
-
|
|
371
|
-
```
|
|
372
|
-
Note: this definition is stripped from internal values.
|
|
373
|
-
|
|
374
|
-
## Sequencer
|
|
375
|
-
### Initialization
|
|
376
|
-
```js
|
|
377
|
-
const sequencer = new Sequencer(synthesizer);
|
|
378
|
-
```
|
|
379
|
-
- synthesizer - a `Synthesizer` instance to play to.
|
|
380
|
-
|
|
381
|
-
### loadNewSongList
|
|
382
|
-
Loads a new song list.
|
|
383
|
-
```js
|
|
384
|
-
sequencer.loadNewSongList(parsedMidis);
|
|
385
|
-
```
|
|
386
|
-
- parsedMidis - an array of `MIDI` instances representing the songs to play. If there's only one, the loop will be enabled.
|
|
387
|
-
|
|
388
|
-
### play
|
|
389
|
-
Starts playing the sequence. If the sequence was paused, it won't change any controllers, but if it wasn't (ex. the time was changed) then it will go through all the controller changes from the start before playing. **This function does NOT modify the current playback time!**
|
|
390
|
-
```js
|
|
391
|
-
sequencer.play(resetTime);
|
|
392
|
-
```
|
|
393
|
-
- resetTime - boolean, if set to `true` then the playback will start from 0. Defaults to `false`;
|
|
394
|
-
|
|
395
|
-
### pause
|
|
396
|
-
Pauses the playback of the sequence.
|
|
397
|
-
```js
|
|
398
|
-
sequencer.pause();
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
### stop
|
|
402
|
-
Stops the playback of the sequence. Currently only used internally by the `pause` function.
|
|
403
|
-
```js
|
|
404
|
-
sequencer.stop();
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
### nextSong
|
|
408
|
-
Plays the next song in the list.
|
|
409
|
-
```js
|
|
410
|
-
sequencer.nextSong();
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
### previousSong
|
|
414
|
-
Plays the previous song in the list.
|
|
415
|
-
```js
|
|
416
|
-
sequencer.previousSong();
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
### paused
|
|
420
|
-
Read-only boolean, indicating that if the sequencer's playback is paused.
|
|
421
|
-
```js
|
|
422
|
-
if(sequencer.paused)
|
|
423
|
-
{
|
|
424
|
-
console.log("Sequencer paused!");
|
|
425
|
-
}
|
|
426
|
-
else
|
|
427
|
-
{
|
|
428
|
-
console.log("Sequencer playing or stopped!");
|
|
429
|
-
}
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
### loop
|
|
433
|
-
Boolean that controls if the sequencer loops.
|
|
434
|
-
```js
|
|
435
|
-
sequencer.loop = false; // the playback will stop after reaching the end
|
|
436
|
-
```
|
|
437
|
-
|
|
438
|
-
### currentTime
|
|
439
|
-
Property used for changing and reading the current playback time.
|
|
440
|
-
#### get
|
|
441
|
-
Returns the current playback time in seconds.
|
|
442
|
-
```js
|
|
443
|
-
console.log("The sequences is playing for"+sequencer.currentTime+" seconds.");
|
|
444
|
-
```
|
|
445
|
-
#### set
|
|
446
|
-
Sets the current playback time. Calls `stop` and then `play` internally.
|
|
447
|
-
```js
|
|
448
|
-
sequencer.currentTime = 0; // go to the start
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
### duration
|
|
452
|
-
Length of the track in seconds. Equivalent of `Audio.duration`;
|
|
453
|
-
```js
|
|
454
|
-
console.log(`The track lasts for ${sequencer.duration} seconds!`);
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
## MIDI
|
|
458
|
-
See [MIDI on SpessaSynth wiki](https://github.com/spessasus/SpessaSynth/wiki/MIDI-Class)
|
|
459
|
-
|
|
460
|
-
## SoundFont2
|
|
461
|
-
See [SoundFont2 on SpessaSynth wiki](https://github.com/spessasus/SpessaSynth/wiki/SoundFont2-Class)
|
|
462
|
-
|
|
463
|
-
## Logging
|
|
464
|
-
By default, SpessaSynth prints out a lot of stuff to console.
|
|
465
|
-
Here's how you can disable it:
|
|
466
|
-
```js
|
|
467
|
-
// import (or require) here
|
|
468
|
-
SpessaSynthLogging(enableInfo, enableWarning, enableGroup, enableTable);
|
|
469
|
-
```
|
|
470
|
-
All the input variables are booleans corresponding to the things SpessaSynth logs.
|
|
471
|
-
- Info - all general info such as parsing soundfonts, midi files, RPN changes, etc.
|
|
472
|
-
- Warnings - all messages unrecognized by the synthesizer, other warnings
|
|
473
|
-
- group - the groups for parsing the soundfont and midi files.
|
|
474
|
-
- table - the debug table `when enableDebugging` is set to `true` for `synth.noteOn`
|
|
1
|
+
# spessasynth_core
|
|
2
|
+
|
|
3
|
+
**A powerful SF2/DLS/MIDI JavaScript library. It works with any modern JS environment that supports WebAssembly.**
|
|
4
|
+
|
|
5
|
+
> **TIP:**
|
|
6
|
+
> Looking for an easy-to-use WebAudioAPI browser wrapper? Try [spessasynth_lib](https://github.com/spessasus/spessasynth_lib)!
|
|
7
|
+
|
|
8
|
+
```shell
|
|
9
|
+
npm install --save spessasynth_core
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### [Project site (consider giving it a star!)](https://github.com/spessasus/spessasynth_core)
|
|
13
|
+
|
|
14
|
+
### [Demo (using the spessasynth_lib wrapper)](https://spessasus.github.io/SpessaSynth)
|
|
15
|
+
|
|
16
|
+
### [Documentation (in progress!)](https://github.com/spessasus/spessasynth_core/wiki/Home)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
> Note: This is the new heart of the SpessaSynth library, after the repository has been split.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## Current Features
|
|
23
|
+
|
|
24
|
+
### Numerous Format Support
|
|
25
|
+
Supported formats list:
|
|
26
|
+
- `.mid` - Standard MIDI File
|
|
27
|
+
- `.kar` - Soft Karaoke MIDI File
|
|
28
|
+
- `.sf2` - SoundFont2 File
|
|
29
|
+
- `.sf3` - SoundFont2 Compressed File
|
|
30
|
+
- `.sfogg` - SF2Pack With Vorbis Compression
|
|
31
|
+
- `.dls` - Downloadable Sounds Levels 1 & 2 (as well as Mobile DLS)
|
|
32
|
+
- `.rmi` - RIFF MIDI File
|
|
33
|
+
- `.rmi` - RIFF MIDI File With Embedded DLS
|
|
34
|
+
- `.rmi` - [RIFF MIDI File With Embedded SF2](https://github.com/spessasus/sf2-rmidi-specification)
|
|
35
|
+
- `.xmf` - eXtensible Music Format
|
|
36
|
+
- `.mxmf` - Mobile eXtensible Music format
|
|
37
|
+
|
|
38
|
+
*With [an easy way of converting between them!](https://github.com/spessasus/spessasynth_core/wiki/Converting-Between-Formats)*
|
|
39
|
+
|
|
40
|
+
### Easy Integration
|
|
41
|
+
- **Modular design:** *Easy integration into other projects (load what you need)*
|
|
42
|
+
- **Flexible:** *It's not just a MIDI player!*
|
|
43
|
+
- **No dependencies:** *Batteries included!*
|
|
44
|
+
|
|
45
|
+
### Powerful MIDI Synthesizer
|
|
46
|
+
- Suitable for both **real-time** and **offline** synthesis
|
|
47
|
+
- **Excellent SoundFont support:**
|
|
48
|
+
- **Full Generator Support**
|
|
49
|
+
- **Full Modulator Support:** *First (to my knowledge) JavaScript SoundFont synth with that feature!*
|
|
50
|
+
- **GeneralUserGS Compatible:** *[See more here!](https://github.com/mrbumpy409/GeneralUser-GS/blob/main/documentation/README.md)*
|
|
51
|
+
- **SoundFont3 Support:** Play compressed SoundFonts!
|
|
52
|
+
- **Experimental SF2Pack Support:** Play soundfonts compressed with BASSMIDI! (*Note: only works with vorbis compression*)
|
|
53
|
+
- **Can load very large SoundFonts:** up to 4GB!
|
|
54
|
+
- **Great DLS Support:**
|
|
55
|
+
- **DLS Level 1 Support**
|
|
56
|
+
- **DLS Level 2 Support**
|
|
57
|
+
- **Mobile DLS Support**
|
|
58
|
+
- **Correct articulator support:** *Converts articulators to both modulators and generators!*
|
|
59
|
+
- **Tested and working with gm.dls!**
|
|
60
|
+
- **Correct volume:** *Properly translated to SoundFont volume!*
|
|
61
|
+
- **A-Law encoding support**
|
|
62
|
+
- **Both unsigned 8-bit and signed 16-bit sample support (24-bit theoretically supported as well!)**
|
|
63
|
+
- **Detects special articulator combinations:** *Such as vibratoLfoToPitch*
|
|
64
|
+
- **Soundfont manager:** Stack multiple soundfonts!
|
|
65
|
+
- **[Custom modulators for additional controllers](https://github.com/spessasus/spessasynth_core/wiki/Modulator-Class#default-modulators):** *Why not?*
|
|
66
|
+
- **Unlimited channel count:** Your CPU is the limit!
|
|
67
|
+
- **Excellent MIDI Standards Support:**
|
|
68
|
+
- **MIDI Controller Support:** Default supported controllers [here](https://github.com/spessasus/spessasynth_core/wiki/MIDI-Implementation#supported-controllers)
|
|
69
|
+
- **Portamento Support:** Glide the notes!
|
|
70
|
+
- **Sound Controllers:** Real-time filter and envelope control!
|
|
71
|
+
- **MIDI Tuning Standard Support:** [more info here](https://github.com/spessasus/spessasynth_core/wiki/MIDI-Implementation#midi-tuning-standard)
|
|
72
|
+
- [Full **RPN** and limited **NRPN** support](https://github.com/spessasus/spessasynth_core/wiki/MIDI-Implementation#supported-registered-parameters)
|
|
73
|
+
- Supports some [**Roland GS** and **Yamaha XG** system exclusives](https://github.com/spessasus/spessasynth_core/wiki/MIDI-Implementation#supported-system-exclusives)
|
|
74
|
+
|
|
75
|
+
### Powerful and Fast MIDI Sequencer
|
|
76
|
+
- **Supports MIDI formats 0, 1, and 2:** *note: format 2 support is experimental as it's very, very rare.*
|
|
77
|
+
- **[Multi-Port MIDI](https://github.com/spessasus/spessasynth_core/wiki/About-Multi-Port) support:** More than 16 channels!
|
|
78
|
+
- **Smart preloading:** Only preloads the samples used in the MIDI file for smooth playback *(down to key and velocity!)*
|
|
79
|
+
- **Lyrics support:** Add karaoke to your program!
|
|
80
|
+
- **Raw lyrics available:** Decode in any encoding! *(Kanji? No problem!)*
|
|
81
|
+
- **Loop points support:** Ensures seamless loops!
|
|
82
|
+
|
|
83
|
+
### Read and Write SoundFont and MIDI Files with Ease
|
|
84
|
+
#### Read and write MIDI files
|
|
85
|
+
- **Smart name detection:** Handles incorrectly formatted and non-standard track names
|
|
86
|
+
- **Raw name available:** Decode in any encoding! *(Kanji? No problem!)*
|
|
87
|
+
- **Port detection during load time:** Manage ports and channels easily!
|
|
88
|
+
- **Used channels on track:** Quickly determine which channels are used
|
|
89
|
+
- **Key range detection:** Detect the key range of the MIDI
|
|
90
|
+
- **Easy MIDI editing:** Use [helper functions](https://github.com/spessasus/spessasynth_core/wiki/Writing-MIDI-Files#modifymidi) to modify the song to your needs!
|
|
91
|
+
- **Loop detection:** Automatically detects loops in MIDIs (e.g., from *Touhou Project*)
|
|
92
|
+
- **First note detection:** Skip unnecessary silence at the start by jumping to the first note!
|
|
93
|
+
- **Lyrics support:** Both regular MIDI and .kar files!
|
|
94
|
+
- **[Write MIDI files from scratch](https://github.com/spessasus/spessasynth_core/wiki/Creating-MIDI-Files)**
|
|
95
|
+
- **Easy saving:** Save with just [one function!](https://github.com/spessasus/spessasynth_core/wiki/Writing-MIDI-Files#writemidi)
|
|
96
|
+
|
|
97
|
+
#### Read and write [RMID files with embedded SF2 soundfonts](https://github.com/spessasus/sf2-rmidi-specification#readme)
|
|
98
|
+
- **[Level 4](https://github.com/spessasus/sf2-rmidi-specification#level-4) compliance:** Reads and writes *everything!*
|
|
99
|
+
- **Compression and trimming support:** Reduce a MIDI file with a 1GB soundfont to **as small as 5MB**!
|
|
100
|
+
- **DLS Version support:** The original legacy format with bank offset detection!
|
|
101
|
+
- **Automatic bank shifting and validation:** Every soundfont *just works!*
|
|
102
|
+
- **Metadata support:** Add title, artist, album name and cover and more! And of course read them too! *(In any encoding!)*
|
|
103
|
+
- **Compatible with [Falcosoft Midi Player 6!](https://falcosoft.hu/softwares.html#midiplayer)**
|
|
104
|
+
- **Easy saving:** [As simple as saving a MIDI file!](https://github.com/spessasus/spessasynth_core/wiki/Writing-MIDI-Files#writermidi)
|
|
105
|
+
|
|
106
|
+
#### Read and write SoundFont2 files
|
|
107
|
+
- **Easy info access:** Just an [object of strings!](https://github.com/spessasus/spessasynth_core/wiki/SoundFont2-Class#soundfontinfo)
|
|
108
|
+
- **Smart trimming:** Trim the SoundFont to only include samples used in the MIDI *(down to key and velocity!)*
|
|
109
|
+
- **sf3 conversion:** Compress SoundFont2 files to SoundFont3 with variable quality!
|
|
110
|
+
- **Easy saving:** Also just [one function!](https://github.com/spessasus/spessasynth_core/wiki/SoundFont2-Class#write)
|
|
111
|
+
|
|
112
|
+
#### Read and write SoundFont3 files
|
|
113
|
+
- Same features as SoundFont2 but with now with **Ogg Vorbis compression!**
|
|
114
|
+
- **Variable compression quality:** You choose between file size and quality!
|
|
115
|
+
- **Compression preserving:** Avoid decompressing and recompressing uncompressed samples for minimal quality loss!
|
|
116
|
+
|
|
117
|
+
#### Read and write DLS Level One or Two files
|
|
118
|
+
- Read DLS (DownLoadable Sounds) files as SF2 files!
|
|
119
|
+
- **Works like a normal soundfont:** *Saving it as sf2 is still [just one function!](https://github.com/spessasus/spessasynth_core/wiki/SoundFont2-Class#write)*
|
|
120
|
+
- Converts articulators to both **modulators** and **generators**!
|
|
121
|
+
- Works with both unsigned 8-bit samples and signed 16-bit samples!
|
|
122
|
+
- A-Law encoding support
|
|
123
|
+
- **Covers special generator cases:** *such as modLfoToPitch*!
|
|
124
|
+
- **Correct volume:** *looking at you, Viena and gm.sf2!*
|
|
125
|
+
- Support built right into the synthesizer!
|
|
126
|
+
- **Convert SF2 to DLS:** [with limitations](https://github.com/spessasus/spessasynth_core/wiki/DLS-Conversion-Problem)
|
|
127
|
+
|
|
128
|
+
### Export MIDI as WAV
|
|
129
|
+
- Save the MIDI file as WAV audio!
|
|
130
|
+
- **Metadata support:** *Embed metadata such as title, artist, album and more!*
|
|
131
|
+
- **Cue points:** *Write MIDI loop points as cue points!*
|
|
132
|
+
- **Loop multiple times:** *Render two (or more) loops into the file for seamless transitions!*
|
|
133
|
+
|
|
134
|
+
### Special Thanks
|
|
135
|
+
- [FluidSynth](https://github.com/FluidSynth/fluidsynth) - for the source code that helped implement functionality and fixes
|
|
136
|
+
- [Polyphone](https://www.polyphone-soundfonts.com/) - for the soundfont testing and editing tool
|
|
137
|
+
- [Meltysynth](https://github.com/sinshu/meltysynth) - for the initial low-pass filter implementation
|
|
138
|
+
- [RecordingBlogs](https://www.recordingblogs.com/) - for detailed explanations on MIDI messages
|
|
139
|
+
- [stbvorbis.js](https://github.com/hajimehoshi/stbvorbis.js) - for the Vorbis decoder
|
|
140
|
+
- [fflate](https://github.com/101arrowz/fflate) - for the MIT DEFLATE implementation
|
|
141
|
+
- [foo_midi](https://github.com/stuerp/foo_midi) - for useful resources on XMF file format
|
|
142
|
+
- [Falcosoft](https://falcosoft.hu) - for help with the RMIDI format
|
|
143
|
+
- [Christian Collins](https://schristiancollins.com) - for various bug reports regarding the synthesizer
|
|
144
|
+
- **And You!** - for checking out this project. I hope you like it :)
|
|
145
|
+
|
|
146
|
+
**If you like this project, consider giving it a star. It really helps out!**
|
|
147
|
+
|
|
148
|
+
# License
|
|
149
|
+
Copyright © 2025 Spessasus
|
|
150
|
+
Licensed under the Apache-2.0 License.
|
|
151
|
+
|
|
152
|
+
#### Legal
|
|
153
|
+
This project is in no way endorsed or otherwise affiliated with the MIDI Manufacturers Association,
|
|
154
|
+
Creative Technology Ltd. or E-mu Systems, Inc., or any other organization mentioned.
|
|
155
|
+
SoundFont® is a registered trademark of Creative Technology Ltd.
|
|
156
|
+
All other trademarks are the property of their respective owners.
|