spessasynth_core 1.1.3 → 1.1.4

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.
Files changed (189) hide show
  1. package/LICENSE +3 -26
  2. package/README.md +156 -474
  3. package/index.js +73 -8
  4. package/package.json +21 -8
  5. package/src/externals/fflate/LICENSE +21 -0
  6. package/src/externals/fflate/fflate.min.js +1 -0
  7. package/src/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +12 -0
  8. package/src/externals/stbvorbis_sync/LICENSE +202 -0
  9. package/src/externals/stbvorbis_sync/NOTICE +6 -0
  10. package/src/externals/stbvorbis_sync/stbvorbis_sync.min.js +1 -0
  11. package/src/midi/README.md +32 -0
  12. package/src/midi/basic_midi.js +567 -0
  13. package/src/midi/midi_builder.js +202 -0
  14. package/src/midi/midi_loader.js +324 -0
  15. package/{spessasynth_core/midi_parser → src/midi}/midi_message.js +58 -35
  16. package/src/midi/midi_sequence.js +224 -0
  17. package/src/midi/midi_tools/get_note_times.js +154 -0
  18. package/src/midi/midi_tools/midi_editor.js +611 -0
  19. package/src/midi/midi_tools/midi_writer.js +99 -0
  20. package/src/midi/midi_tools/rmidi_writer.js +567 -0
  21. package/src/midi/midi_tools/used_keys_loaded.js +238 -0
  22. package/src/midi/xmf_loader.js +454 -0
  23. package/src/sequencer/README.md +5 -0
  24. package/src/sequencer/events.js +81 -0
  25. package/src/sequencer/play.js +349 -0
  26. package/src/sequencer/process_event.js +165 -0
  27. package/{spessasynth_core/sequencer/worklet_sequencer → src/sequencer}/process_tick.js +103 -84
  28. package/src/sequencer/sequencer_engine.js +367 -0
  29. package/src/sequencer/song_control.js +201 -0
  30. package/src/soundfont/README.md +13 -0
  31. package/src/soundfont/basic_soundfont/basic_instrument.js +77 -0
  32. package/src/soundfont/basic_soundfont/basic_preset.js +336 -0
  33. package/src/soundfont/basic_soundfont/basic_sample.js +206 -0
  34. package/src/soundfont/basic_soundfont/basic_soundfont.js +565 -0
  35. package/src/soundfont/basic_soundfont/basic_zone.js +64 -0
  36. package/src/soundfont/basic_soundfont/basic_zones.js +43 -0
  37. package/src/soundfont/basic_soundfont/generator.js +220 -0
  38. package/src/soundfont/basic_soundfont/modulator.js +378 -0
  39. package/src/soundfont/basic_soundfont/riff_chunk.js +149 -0
  40. package/src/soundfont/basic_soundfont/write_dls/art2.js +173 -0
  41. package/src/soundfont/basic_soundfont/write_dls/articulator.js +49 -0
  42. package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +400 -0
  43. package/src/soundfont/basic_soundfont/write_dls/ins.js +103 -0
  44. package/src/soundfont/basic_soundfont/write_dls/lins.js +18 -0
  45. package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +330 -0
  46. package/src/soundfont/basic_soundfont/write_dls/rgn2.js +121 -0
  47. package/src/soundfont/basic_soundfont/write_dls/wave.js +94 -0
  48. package/src/soundfont/basic_soundfont/write_dls/write_dls.js +119 -0
  49. package/src/soundfont/basic_soundfont/write_dls/wsmp.js +78 -0
  50. package/src/soundfont/basic_soundfont/write_dls/wvpl.js +32 -0
  51. package/src/soundfont/basic_soundfont/write_sf2/ibag.js +39 -0
  52. package/src/soundfont/basic_soundfont/write_sf2/igen.js +80 -0
  53. package/src/soundfont/basic_soundfont/write_sf2/imod.js +46 -0
  54. package/src/soundfont/basic_soundfont/write_sf2/inst.js +34 -0
  55. package/src/soundfont/basic_soundfont/write_sf2/pbag.js +39 -0
  56. package/src/soundfont/basic_soundfont/write_sf2/pgen.js +82 -0
  57. package/src/soundfont/basic_soundfont/write_sf2/phdr.js +42 -0
  58. package/src/soundfont/basic_soundfont/write_sf2/pmod.js +46 -0
  59. package/src/soundfont/basic_soundfont/write_sf2/sdta.js +80 -0
  60. package/src/soundfont/basic_soundfont/write_sf2/shdr.js +55 -0
  61. package/src/soundfont/basic_soundfont/write_sf2/write.js +222 -0
  62. package/src/soundfont/dls/articulator_converter.js +396 -0
  63. package/src/soundfont/dls/dls_destinations.js +38 -0
  64. package/src/soundfont/dls/dls_preset.js +44 -0
  65. package/src/soundfont/dls/dls_sample.js +75 -0
  66. package/src/soundfont/dls/dls_soundfont.js +186 -0
  67. package/src/soundfont/dls/dls_sources.js +62 -0
  68. package/src/soundfont/dls/dls_zone.js +95 -0
  69. package/src/soundfont/dls/read_articulation.js +299 -0
  70. package/src/soundfont/dls/read_instrument.js +121 -0
  71. package/src/soundfont/dls/read_instrument_list.js +17 -0
  72. package/src/soundfont/dls/read_lart.js +35 -0
  73. package/src/soundfont/dls/read_region.js +152 -0
  74. package/src/soundfont/dls/read_samples.js +270 -0
  75. package/src/soundfont/load_soundfont.js +21 -0
  76. package/src/soundfont/read_sf2/generators.js +46 -0
  77. package/{spessasynth_core/soundfont/chunk → src/soundfont/read_sf2}/instruments.js +20 -14
  78. package/src/soundfont/read_sf2/modulators.js +36 -0
  79. package/src/soundfont/read_sf2/presets.js +80 -0
  80. package/src/soundfont/read_sf2/samples.js +304 -0
  81. package/src/soundfont/read_sf2/soundfont.js +305 -0
  82. package/{spessasynth_core/soundfont/chunk → src/soundfont/read_sf2}/zones.js +68 -69
  83. package/src/synthetizer/README.md +7 -0
  84. package/src/synthetizer/audio_engine/README.md +9 -0
  85. package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +266 -0
  86. package/src/synthetizer/audio_engine/engine_components/controller_tables.js +88 -0
  87. package/src/synthetizer/audio_engine/engine_components/key_modifier_manager.js +150 -0
  88. package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/lfo.js +9 -6
  89. package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +282 -0
  90. package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +467 -0
  91. package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +181 -0
  92. package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/modulator_curves.js +33 -30
  93. package/src/synthetizer/audio_engine/engine_components/soundfont_manager.js +221 -0
  94. package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +120 -0
  95. package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/unit_converter.js +11 -4
  96. package/src/synthetizer/audio_engine/engine_components/voice.js +519 -0
  97. package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +401 -0
  98. package/src/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +263 -0
  99. package/src/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +132 -0
  100. package/src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +48 -0
  101. package/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +241 -0
  102. package/src/synthetizer/audio_engine/engine_methods/create_midi_channel.js +27 -0
  103. package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +253 -0
  104. package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +66 -0
  105. package/src/synthetizer/audio_engine/engine_methods/mute_channel.js +17 -0
  106. package/src/synthetizer/audio_engine/engine_methods/note_on.js +175 -0
  107. package/src/synthetizer/audio_engine/engine_methods/portamento_time.js +92 -0
  108. package/src/synthetizer/audio_engine/engine_methods/program_change.js +61 -0
  109. package/src/synthetizer/audio_engine/engine_methods/render_voice.js +196 -0
  110. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js +30 -0
  111. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +22 -0
  112. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js +28 -0
  113. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js +31 -0
  114. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js +21 -0
  115. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +20 -0
  116. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +55 -0
  117. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +16 -0
  118. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +30 -0
  119. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +63 -0
  120. package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +776 -0
  121. package/src/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +24 -0
  122. package/src/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +33 -0
  123. package/src/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +31 -0
  124. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +15 -0
  125. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +27 -0
  126. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +19 -0
  127. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +27 -0
  128. package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +15 -0
  129. package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +34 -0
  130. package/src/synthetizer/audio_engine/main_processor.js +804 -0
  131. package/src/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +15 -0
  132. package/src/synthetizer/audio_engine/snapshot/channel_snapshot.js +175 -0
  133. package/src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +116 -0
  134. package/src/synthetizer/synth_constants.js +22 -0
  135. package/{spessasynth_core → src}/utils/README.md +1 -0
  136. package/src/utils/buffer_to_wav.js +185 -0
  137. package/src/utils/byte_functions/big_endian.js +32 -0
  138. package/src/utils/byte_functions/little_endian.js +77 -0
  139. package/src/utils/byte_functions/string.js +107 -0
  140. package/src/utils/byte_functions/variable_length_quantity.js +42 -0
  141. package/src/utils/fill_with_defaults.js +21 -0
  142. package/src/utils/indexed_array.js +52 -0
  143. package/{spessasynth_core → src}/utils/loggin.js +70 -78
  144. package/src/utils/other.js +92 -0
  145. package/src/utils/sysex_detector.js +58 -0
  146. package/src/utils/xg_hacks.js +193 -0
  147. package/.idea/inspectionProfiles/Project_Default.xml +0 -10
  148. package/.idea/jsLibraryMappings.xml +0 -6
  149. package/.idea/modules.xml +0 -8
  150. package/.idea/spessasynth_core.iml +0 -12
  151. package/.idea/vcs.xml +0 -6
  152. package/spessasynth_core/midi_parser/README.md +0 -3
  153. package/spessasynth_core/midi_parser/midi_loader.js +0 -386
  154. package/spessasynth_core/sequencer/sequencer.js +0 -202
  155. package/spessasynth_core/sequencer/worklet_sequencer/play.js +0 -209
  156. package/spessasynth_core/sequencer/worklet_sequencer/process_event.js +0 -120
  157. package/spessasynth_core/sequencer/worklet_sequencer/song_control.js +0 -112
  158. package/spessasynth_core/soundfont/README.md +0 -4
  159. package/spessasynth_core/soundfont/chunk/generators.js +0 -205
  160. package/spessasynth_core/soundfont/chunk/modulators.js +0 -232
  161. package/spessasynth_core/soundfont/chunk/presets.js +0 -264
  162. package/spessasynth_core/soundfont/chunk/riff_chunk.js +0 -46
  163. package/spessasynth_core/soundfont/chunk/samples.js +0 -250
  164. package/spessasynth_core/soundfont/soundfont_parser.js +0 -301
  165. package/spessasynth_core/synthetizer/README.md +0 -6
  166. package/spessasynth_core/synthetizer/synthesizer.js +0 -313
  167. package/spessasynth_core/synthetizer/worklet_system/README.md +0 -3
  168. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/controller_control.js +0 -290
  169. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/data_entry.js +0 -280
  170. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/note_off.js +0 -102
  171. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/note_on.js +0 -77
  172. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/program_control.js +0 -140
  173. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/system_exclusive.js +0 -266
  174. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/tuning_control.js +0 -104
  175. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/vibrato_control.js +0 -29
  176. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/voice_control.js +0 -223
  177. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/lowpass_filter.js +0 -133
  178. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +0 -73
  179. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +0 -76
  180. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +0 -272
  181. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +0 -83
  182. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_modulator.js +0 -175
  183. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +0 -106
  184. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +0 -285
  185. package/spessasynth_core/utils/buffer_to_wav.js +0 -70
  186. package/spessasynth_core/utils/byte_functions.js +0 -141
  187. package/spessasynth_core/utils/other.js +0 -49
  188. package/spessasynth_core/utils/shiftable_array.js +0 -26
  189. package/spessasynth_core/utils/stbvorbis_sync.js +0 -1877
package/README.md CHANGED
@@ -1,474 +1,156 @@
1
- # spessasynth_core
2
- A SoundFont2 synthesizer library, made for use with node.js.
3
- A fork of [SpessaSynth](https://github.com/spessasus/SpessaSynth).
4
-
5
- [Jump to the API reference](#api-reference)
6
-
7
- `npm install --save spessasynth_core`
8
-
9
- > Looking for a browser version? Try [SpessaSynth](https://github.com/spessasus/SpessaSynth).
10
-
11
- ## Features:
12
- - SoundFont2 support (both modulators and generators)
13
- - SoundFont3 support (vorbis compressed sf2)
14
- - GS, XG, GM2, GM1 system exclusive support
15
- - NRPN, RPN support
16
- - Integrated sequencer
17
- - Additional custom modulators
18
- - Multi-port MIDIs support (more than 16 channels)
19
- - No SoundFont size limit
20
- - No dependencies
21
-
22
- ### Example: Render a MIDI file to a .wav file
23
- ```js
24
- const fs = require('fs');
25
- // spessasynth_core is an es6 module
26
- import("spessasynth_core").then(core => {
27
- // usage: node test.js <sf path> <midi path> <output path>
28
- const [,, soundfontName, midiName, outputName] = process.argv;
29
- // read the input files
30
- const soundfont = fs.readFileSync(soundfontName);
31
- const mid = new core.MIDI(fs.readFileSync(midiName))
32
-
33
- // initialize synth and sequencer
34
- const synth = new core.Synthesizer(soundfont, 44100);
35
- const seq = new core.Sequencer(synth);
36
- // load new song and disable the loop
37
- seq.loadNewSongList([mid]);
38
- seq.loop = false;
39
-
40
- // calculate length and allocate buffers
41
- const lengthSamples = mid.duration * 44100;
42
- const outLeft = new Float32Array(lengthSamples);
43
- const outRight = new Float32Array(lengthSamples);
44
-
45
- // wait for sf3 support to load and render
46
- synth.sf3supportReady.then(() => {
47
- // note: this discards reverb and chorus outputs!
48
- synth.render([outLeft, outRight]);
49
- // write output data
50
- const wav = core.rawDataToWav(44100, outLeft, outRight);
51
- fs.writeFileSync(outputName, Buffer.from(wav));
52
- });
53
- });
54
- ```
55
-
56
- ### Example 2: play a MIDI file to speakers
57
- via npm package `speaker`
58
- ```js
59
- const fs = require('fs');
60
- const Speaker = require("speaker");
61
- const SAMPLE_RATE = 44100; // hertz
62
- const BLOCK_SIZE = 128; // samples
63
-
64
- // usage: node test.js <sf path> <midi path>
65
- import("spessasynth_core").then(core => {
66
- // Disable logging
67
- core.SpessaSynthLogging(false, false, false, false);
68
-
69
- // Read arguments and load the input files
70
- const [,, soundfontName, midiName] = process.argv;
71
- const soundfont = fs.readFileSync(soundfontName);
72
- const mid = new core.MIDI(fs.readFileSync(midiName)); // parse the midi
73
-
74
-
75
- // Initialize synth and sequencer
76
- const synth = new core.Synthesizer(soundfont, SAMPLE_RATE, BLOCK_SIZE);
77
- const seq = new core.Sequencer(synth);
78
-
79
- // Load new song and disable the loop
80
- seq.loadNewSongList([mid]);
81
- seq.loop = false;
82
-
83
- // make the program stop after the sequence is finished
84
- const time = seq.duration + 1
85
- let isPlaying = true;
86
- setTimeout(() => isPlaying = false, time * 1000);
87
- console.log(`Playing "${mid.midiName || "<unnamed song>"}"`);
88
-
89
- // Calculate length and allocate buffers
90
- const outLeft = new Float32Array(BLOCK_SIZE);
91
- const outRight = new Float32Array(BLOCK_SIZE);
92
-
93
- // Wait for sf3 support to load and render
94
- synth.sf3supportReady.then(() => {
95
- const speakerOut = new Speaker({
96
- channels: 2,
97
- bitDepth: 16,
98
- sampleRate: SAMPLE_RATE,
99
- });
100
-
101
- function render()
102
- {
103
- // Render audio samples from the synthesizer
104
- synth.render([outLeft, outRight]);
105
-
106
- // Prepare buffer for WAV output
107
- const wavData = new Int16Array(outLeft.length * 2); // 2 channels
108
-
109
- // Interleave audio data
110
- let offset = 0;
111
- for (let i = 0; i < outLeft.length; i++)
112
- {
113
- // Float ranges from -1 to 1, int16 ranges from -32768 to 32767, convert it here
114
- const sampleL = Math.max(-1, Math.min(1, outLeft[i])) * 32767;
115
- const sampleR = Math.max(-1, Math.min(1, outRight[i])) * 32767;
116
-
117
- // Interleave data: L, R, L, R, etc...
118
- wavData[offset++] = sampleL;
119
- wavData[offset++] = sampleR;
120
- }
121
- // Write WAV data to speaker
122
- speakerOut.write(wavData);
123
-
124
- if(isPlaying)
125
- {
126
- setImmediate(render);
127
- }
128
- else
129
- {
130
- process.exit(0);
131
- }
132
- }
133
-
134
- render();
135
- });
136
- });
137
- ```
138
-
139
- ## API reference
140
- ### Contents
141
- - [Importing the library](#importing-the-library)
142
- - [Synthesizer](#synthesizer)
143
- - [Sequencer](#sequencer)
144
- - [MIDI](#midi)
145
- - [SoundFont2](#soundfont2)
146
- - [How to disable console output](#logging)
147
-
148
- ### Importing the library
149
- spessasynth_core is an es6 package.
150
- ```js
151
- // es6
152
- import {Synthesizer} from "spessasynth_core"
153
- // commonjs
154
- import("spessasynth_core").then(core => {
155
- // use core.Synthesizer
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.