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.
Files changed (189) hide show
  1. package/LICENSE +3 -26
  2. package/README.md +156 -474
  3. package/index.js +74 -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
@@ -1,290 +0,0 @@
1
- import { consoleColors } from '../../../utils/other.js'
2
- import { midiControllers } from '../../../midi_parser/midi_message.js'
3
- import { DEFAULT_PERCUSSION, DEFAULT_SYNTH_MODE } from '../../synthesizer.js'
4
- import {
5
- customControllers,
6
- customResetArray,
7
- dataEntryStates,
8
- resetArray,
9
- } from '../worklet_utilities/worklet_processor_channel.js'
10
- import { computeModulators } from '../worklet_utilities/worklet_modulator.js'
11
- import { SpessaSynthInfo } from '../../../utils/loggin.js'
12
- import { SYNTHESIZER_GAIN } from '../../synthesizer.js'
13
-
14
- /**
15
- * Changes a MIDI controller
16
- * @param channel {number} - The MIDI Channel to use
17
- * @param controllerNumber {number} - The MIDI controller number
18
- * @param controllerValue {number} - The new value
19
- * @this {Synthesizer}
20
- */
21
- export function controllerChange(channel, controllerNumber, controllerValue)
22
- {
23
- /**
24
- * @type {WorkletProcessorChannel}
25
- */
26
- const channelObject = this.workletProcessorChannels[channel];
27
- switch (controllerNumber) {
28
- case midiControllers.allNotesOff:
29
- this.stopAll(channel);
30
- break;
31
-
32
- case midiControllers.allSoundOff:
33
- this.stopAll(channel, true);
34
- break;
35
-
36
- case midiControllers.bankSelect:
37
- let bankNr = controllerValue;
38
- switch (this.system)
39
- {
40
- case "gm":
41
- // gm ignores bank select
42
- SpessaSynthInfo(`%cIgnoring the Bank Select (${controllerValue}), as the synth is in GM mode.`, consoleColors.info);
43
- return;
44
-
45
- case "xg":
46
- // for xg, if msb is 127, then it's drums
47
- if (bankNr === 127)
48
- {
49
- channelObject.drumChannel = true;
50
- }
51
- break;
52
-
53
- case "gm2":
54
- if(bankNr === 120)
55
- {
56
- channelObject.drumChannel = true;
57
- }
58
- }
59
-
60
- if(channelObject.drumChannel)
61
- {
62
- // 128 for percussion channel
63
- bankNr = 128;
64
- }
65
- if(bankNr === 128 && !channelObject.drumChannel)
66
- {
67
- // if channel is not for percussion, default to bank current
68
- bankNr = channelObject.midiControllers[midiControllers.bankSelect];
69
- }
70
-
71
- channelObject.midiControllers[midiControllers.bankSelect] = bankNr;
72
- break;
73
-
74
- case midiControllers.lsbForControl0BankSelect:
75
- if(this.system === 'xg')
76
- {
77
- if(channelObject.midiControllers[midiControllers.bankSelect] === 0)
78
- {
79
- if(controllerValue !== 127)
80
- channelObject.midiControllers[midiControllers.bankSelect] = controllerValue;
81
- }
82
- }
83
- else
84
- if(this.system === "gm2")
85
- {
86
- channelObject.midiControllers[midiControllers.bankSelect] = controllerValue;
87
- }
88
- break;
89
-
90
- case midiControllers.RPNLsb:
91
- channelObject.RPValue = channelObject.RPValue << 7 | controllerValue;
92
- channelObject.dataEntryState = dataEntryStates.RPFine;
93
- break;
94
-
95
- case midiControllers.RPNMsb:
96
- channelObject.RPValue = controllerValue;
97
- channelObject.dataEntryState = dataEntryStates.RPCoarse;
98
- break;
99
-
100
- case midiControllers.NRPNMsb:
101
- channelObject.NRPCoarse = controllerValue;
102
- channelObject.dataEntryState = dataEntryStates.NRPCoarse;
103
- break;
104
-
105
- case midiControllers.NRPNLsb:
106
- channelObject.NRPFine = controllerValue;
107
- channelObject.dataEntryState = dataEntryStates.NRPFine;
108
- break;
109
-
110
- case midiControllers.dataEntryMsb:
111
- this.dataEntryCoarse(channel, controllerValue);
112
- break;
113
-
114
- case midiControllers.lsbForControl6DataEntry:
115
- this.dataEntryFine(channel, controllerValue);
116
- break;
117
-
118
- default:
119
- if(channelObject.lockedControllers[controllerNumber])
120
- {
121
- return;
122
- }
123
- // special case: hold pedal
124
- if(controllerNumber === midiControllers.sustainPedal) {
125
- if (controllerValue >= 64)
126
- {
127
- channelObject.holdPedal = true;
128
- }
129
- else
130
- {
131
- channelObject.holdPedal = false;
132
- channelObject.sustainedVoices.forEach(v => {
133
- this.releaseVoice(v)
134
- });
135
- channelObject.sustainedVoices = [];
136
- }
137
- }
138
- channelObject.midiControllers[controllerNumber] = controllerValue << 7;
139
- channelObject.voices.forEach(v => computeModulators(v, channelObject.midiControllers));
140
- break;
141
- }
142
- }
143
-
144
- /**
145
- * Resets all controllers and programs
146
- * @this {Synthesizer}
147
- */
148
- export function resetAllControllers()
149
- {
150
- SpessaSynthInfo("%cResetting all controllers!", consoleColors.info);
151
- for (let channelNumber = 0; channelNumber < this.workletProcessorChannels.length; channelNumber++)
152
- {
153
- this.resetControllers(channelNumber);
154
-
155
- /**
156
- * @type {WorkletProcessorChannel}
157
- **/
158
- const ch = this.workletProcessorChannels[channelNumber];
159
-
160
- // if preset is unlocked, switch to non drums and call event
161
- if(!ch.lockPreset)
162
- {
163
- ch.midiControllers[midiControllers.bankSelect] = 0;
164
- if (channelNumber % 16 === DEFAULT_PERCUSSION)
165
- {
166
- this.setPreset(channelNumber, this.drumPreset);
167
- ch.drumChannel = true;
168
- }
169
- else
170
- {
171
- ch.drumChannel = false;
172
- this.setPreset(channelNumber, this.defaultPreset);
173
- }
174
- }
175
- }
176
- this.system = DEFAULT_SYNTH_MODE;
177
- }
178
-
179
- /**
180
- * Resets all controllers for channel
181
- * @param channel {number} - The MIDI Channel to use
182
- * @this {Synthesizer}
183
- */
184
- export function resetControllers(channel)
185
- {
186
- const channelObject = this.workletProcessorChannels[channel];
187
- /**
188
- * get excluded (locked) cc numbers as locked ccs are unaffected by reset
189
- * @type {number[]}
190
- */
191
- const excludedCCs = channelObject.lockedControllers.reduce((lockedCCs, cc, ccNum) => {
192
- if(cc)
193
- {
194
- lockedCCs.push(ccNum);
195
- }
196
- return lockedCCs;
197
- }, []);
198
- // save excluded controllers as reset doesn't affect them
199
- let excludedCCvalues = excludedCCs.map(ccNum => {
200
- return {
201
- ccNum: ccNum,
202
- ccVal: channelObject.midiControllers[ccNum]
203
- }
204
- });
205
-
206
- // reset the array
207
- channelObject.midiControllers.set(resetArray);
208
- channelObject.channelVibrato = {rate: 0, depth: 0, delay: 0};
209
- channelObject.holdPedal = false;
210
-
211
- excludedCCvalues.forEach((cc) => {
212
- channelObject.midiControllers[cc.ccNum] = cc.ccVal;
213
- });
214
-
215
- // reset custom controllers
216
- // special case: transpose does not get affected
217
- const transpose = channelObject.customControllers[customControllers.channelTranspose];
218
- channelObject.customControllers.set(customResetArray);
219
- channelObject.customControllers[customControllers.channelTranspose] = transpose;
220
-
221
- this.resetParameters(channel);
222
-
223
- }
224
-
225
- /**
226
- * @param channel {number}
227
- * @this {Synthesizer}
228
- */
229
- export function resetParameters(channel)
230
- {
231
- const channelObject = this.workletProcessorChannels[channel];
232
-
233
- // reset parameters
234
- /**
235
- * @type {number}
236
- */
237
- channelObject.NRPCoarse = 0;
238
- /**
239
- * @type {number}
240
- */
241
- channelObject.NRPFine = 0;
242
- /**
243
- * @type {number}
244
- */
245
- channelObject.RPValue = 0;
246
- /**
247
- * @type {string}
248
- */
249
- channelObject.dataEntryState = dataEntryStates.Idle;
250
- }
251
-
252
- /**
253
- * Sets the main volume of the synthesizer
254
- * @param volume {number} - 0-1 the volume
255
- * @this {Synthesizer}
256
- */
257
- export function setMainVolume(volume)
258
- {
259
- this.mainVolume = volume * SYNTHESIZER_GAIN;
260
- this.setMasterPan(this.pan);
261
- }
262
-
263
- /**
264
- * Sets the master stereo panning of the synthesizer
265
- * @param pan {number} - -1 to 1 the pan, -1 is left, 0 is the middle, 1 is right
266
- * @this {Synthesizer}
267
- */
268
- export function setMasterPan(pan)
269
- {
270
- this.pan = pan;
271
- // clamp to 0-1 (0 is left)
272
- pan = (pan / 2) + 0.5;
273
- this.panLeft = (1 - pan) * this.mainVolume;
274
- this.panRight = (pan) * this.mainVolume;
275
- }
276
-
277
- /**
278
- * Mutes/unmutes a channel
279
- * @param channel {number} - The MIDI channel to use
280
- * @param isMuted {boolean} - If the channel should be muted or not
281
- * @this {Synthesizer}
282
- */
283
- export function muteChannel(channel, isMuted)
284
- {
285
- if(isMuted)
286
- {
287
- this.stopAll(channel, true);
288
- }
289
- this.workletProcessorChannels[channel].isMuted = isMuted;
290
- }
@@ -1,280 +0,0 @@
1
- import { consoleColors } from '../../../utils/other.js'
2
- import { midiControllers } from '../../../midi_parser/midi_message.js'
3
- import {
4
- customControllers,
5
- dataEntryStates,
6
- NON_CC_INDEX_OFFSET,
7
- } from '../worklet_utilities/worklet_processor_channel.js'
8
- import { modulatorSources } from '../../../soundfont/chunk/modulators.js'
9
- import { SpessaSynthInfo, SpessaSynthWarn } from '../../../utils/loggin.js'
10
-
11
- /**
12
- * Executes a data entry for an NRP for a sc88pro NRP (because touhou yes) and RPN tuning
13
- * @param channel {number}
14
- * @param dataValue {number} dataEntryCoarse MSB
15
- * @this {Synthesizer}
16
- * @private
17
- */
18
- export function dataEntryCoarse(channel, dataValue)
19
- {
20
- const channelObject = this.workletProcessorChannels[channel];
21
- let addDefaultVibrato = () =>
22
- {
23
- if(channelObject.channelVibrato.delay === 0 && channelObject.channelVibrato.rate === 0 && channelObject.channelVibrato.depth === 0)
24
- {
25
- channelObject.channelVibrato.depth = 50;
26
- channelObject.channelVibrato.rate = 8;
27
- channelObject.channelVibrato.delay = 0.6;
28
- }
29
- }
30
- switch(channelObject.dataEntryState)
31
- {
32
- default:
33
- case dataEntryStates.Idle:
34
- break;
35
-
36
- // https://cdn.roland.com/assets/media/pdf/SC-88PRO_OM.pdf
37
- // http://hummer.stanford.edu/sig/doc/classes/MidiOutput/rpn.html
38
- case dataEntryStates.NRPFine:
39
- switch(channelObject.NRPCoarse)
40
- {
41
- default:
42
- if(dataValue === 64)
43
- {
44
- // default value
45
- return;
46
- }
47
- SpessaSynthWarn(
48
- `%cUnrecognized NRPN for %c${channel}%c: %c(0x${channelObject.NRPCoarse.toString(16).toUpperCase()} 0x${channelObject.NRPFine.toString(16).toUpperCase()})%c data value: %c${dataValue}`,
49
- consoleColors.warn,
50
- consoleColors.recognized,
51
- consoleColors.warn,
52
- consoleColors.unrecognized,
53
- consoleColors.warn,
54
- consoleColors.value);
55
- break;
56
-
57
- case 0x01:
58
- switch(channelObject.NRPFine)
59
- {
60
- default:
61
- if(dataValue === 64)
62
- {
63
- // default value
64
- return;
65
- }
66
- SpessaSynthWarn(
67
- `%cUnrecognized NRPN for %c${channel}%c: %c(0x${channelObject.NRPCoarse.toString(16)} 0x${channelObject.NRPFine.toString(16)})%c data value: %c${dataValue}`,
68
- consoleColors.warn,
69
- consoleColors.recognized,
70
- consoleColors.warn,
71
- consoleColors.unrecognized,
72
- consoleColors.warn,
73
- consoleColors.value);
74
- break;
75
-
76
- // vibrato rate
77
- case 0x08:
78
- if(channelObject.lockVibrato)
79
- {
80
- return;
81
- }
82
- if(dataValue === 64)
83
- {
84
- return;
85
- }
86
- addDefaultVibrato();
87
- channelObject.channelVibrato.rate = (dataValue / 64) * 8;
88
- SpessaSynthInfo(`%cVibrato rate for channel %c${channel}%c is now set to %c${channelObject.channelVibrato.rate}%cHz.`,
89
- consoleColors.info,
90
- consoleColors.recognized,
91
- consoleColors.info,
92
- consoleColors.value,
93
- consoleColors.info);
94
- break;
95
-
96
- // vibrato depth
97
- case 0x09:
98
- if(channelObject.lockVibrato)
99
- {
100
- return;
101
- }
102
- if(dataValue === 64)
103
- {
104
- return;
105
- }
106
- addDefaultVibrato();
107
- channelObject.channelVibrato.depth = dataValue / 2;
108
- SpessaSynthInfo(`%cVibrato depth for %c${channel}%c is now set to %c${channelObject.channelVibrato.depth}%c cents range of detune.`,
109
- consoleColors.info,
110
- consoleColors.recognized,
111
- consoleColors.info,
112
- consoleColors.value,
113
- consoleColors.info);
114
- break;
115
-
116
- // vibrato delay
117
- case 0x0A:
118
- if(channelObject.lockVibrato)
119
- {
120
- return;
121
- }
122
- if(dataValue === 64)
123
- {
124
- return;
125
- }
126
- addDefaultVibrato();
127
- channelObject.channelVibrato.delay = (dataValue / 64) / 3;
128
- SpessaSynthInfo(`%cVibrato delay for %c${channel}%c is now set to %c${channelObject.channelVibrato.delay}%c seconds.`,
129
- consoleColors.info,
130
- consoleColors.recognized,
131
- consoleColors.info,
132
- consoleColors.value,
133
- consoleColors.info);
134
- break;
135
-
136
- // filter cutoff
137
- case 0x20:
138
- // affect the "brightness" controller as we have a default modulator that controls it
139
- const ccValue = dataValue;
140
- this.controllerChange(channel, midiControllers.brightness, dataValue)
141
- SpessaSynthInfo(`%cFilter cutoff for %c${channel}%c is now set to %c${ccValue}`,
142
- consoleColors.info,
143
- consoleColors.recognized,
144
- consoleColors.info,
145
- consoleColors.value);
146
- }
147
- break;
148
-
149
- // drum reverb
150
- case 0x1D:
151
- if(!channelObject.percussionChannel)
152
- {
153
- return;
154
- }
155
- const reverb = dataValue;
156
- this.controllerChange(channel, midiControllers.effects1Depth, reverb);
157
- SpessaSynthInfo(
158
- `%cGS Drum reverb for %c${channel}%c: %c${reverb}`,
159
- consoleColors.info,
160
- consoleColors.recognized,
161
- consoleColors.info,
162
- consoleColors.value);
163
- break;
164
-
165
- // drum chorus
166
- case 0x1E:
167
- if(!channelObject.percussionChannel)
168
- {
169
- return;
170
- }
171
- const chorus = dataValue;
172
- this.controllerChange(channel, midiControllers.effects3Depth, chorus);
173
- SpessaSynthInfo(
174
- `%cGS Drum chorus for %c${channel}%c: %c${chorus}`,
175
- consoleColors.info,
176
- consoleColors.recognized,
177
- consoleColors.info,
178
- consoleColors.value);
179
- }
180
- break;
181
-
182
- case dataEntryStates.RPCoarse:
183
- case dataEntryStates.RPFine:
184
- switch(channelObject.RPValue)
185
- {
186
- default:
187
- SpessaSynthWarn(
188
- `%cUnrecognized RPN for %c${channel}%c: %c(0x${channelObject.RPValue.toString(16)})%c data value: %c${dataValue}`,
189
- consoleColors.warn,
190
- consoleColors.recognized,
191
- consoleColors.warn,
192
- consoleColors.unrecognized,
193
- consoleColors.warn,
194
- consoleColors.value);
195
- break;
196
-
197
- // pitch bend range
198
- case 0x0000:
199
- channelObject.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] = dataValue << 7;
200
- SpessaSynthInfo(`%cChannel ${channel} bend range. Semitones: %c${dataValue}`,
201
- consoleColors.info,
202
- consoleColors.value);
203
- break;
204
-
205
- // coarse tuning
206
- case 0x0002:
207
- // semitones
208
- this.setChannelTuning(channel, (dataValue - 64) * 100);
209
- break;
210
-
211
- // fine tuning
212
- case 0x0001:
213
- // note: this will not work properly unless the lsb is sent!
214
- // here we store the raw value to then adjust in fine
215
- this.setChannelTuning(channel, (dataValue - 64));
216
- break;
217
-
218
- // modulation depth
219
- case 0x0005:
220
- this.setModulationDepth(channel, dataValue * 100);
221
- break
222
-
223
- case 0x3FFF:
224
- this.resetParameters(channel);
225
- break;
226
-
227
- }
228
-
229
- }
230
- }
231
-
232
- /**
233
- * Executes a data entry for an RPN tuning
234
- * @param channel {number}
235
- * @param dataValue {number} dataEntry LSB
236
- * @this {Synthesizer}
237
- * @private
238
- */
239
- export function dataEntryFine(channel, dataValue)
240
- {
241
- const channelObject = this.workletProcessorChannels[channel];
242
- switch (channelObject.dataEntryState)
243
- {
244
- default:
245
- break;
246
-
247
- case dataEntryStates.RPCoarse:
248
- case dataEntryStates.RPFine:
249
- switch(channelObject.RPValue)
250
- {
251
- default:
252
- break;
253
-
254
- // pitch bend range fine tune is not supported in the SoundFont2 format. (pitchbend range is in semitones rather than cents)
255
- case 0x0000:
256
- break;
257
-
258
- // fine tuning
259
- case 0x0001:
260
- // grab the data and shift
261
- const coarse = channelObject.customControllers[customControllers.channelTuning];
262
- const finalTuning = (coarse << 7) | dataValue;
263
- this.setChannelTuning(channel, finalTuning * 0.0122); // multiply by 8192 / 100 (cent increment)
264
- break;
265
-
266
- // modulation depth
267
- case 0x0005:
268
- const currentModulationDepthCents = channelObject.customControllers[customControllers.modulationMultiplier] * 50;
269
- let cents = currentModulationDepthCents + (dataValue / 128) * 100;
270
- this.setModulationDepth(channel, cents);
271
- break
272
-
273
- case 0x3FFF:
274
- this.resetParameters(channel);
275
- break;
276
-
277
- }
278
-
279
- }
280
- }
@@ -1,102 +0,0 @@
1
- import { generatorTypes } from '../../../soundfont/chunk/generators.js'
2
- import { consoleColors } from '../../../utils/other.js'
3
- import { SpessaSynthInfo, SpessaSynthWarn } from '../../../utils/loggin.js'
4
-
5
- /**
6
- * Releases a note
7
- * @param channel {number} - The MIDI channel to use
8
- * @param midiNote {number} - The MIDI key number
9
- * @this {Synthesizer}
10
- */
11
- export function noteOff(channel, midiNote)
12
- {
13
- if(midiNote > 127 || midiNote < 0)
14
- {
15
- SpessaSynthWarn(`Received a noteOn for note`, midiNote, "Ignoring.");
16
- return;
17
- }
18
-
19
- // if high performance mode, kill notes instead of stopping them
20
- if(this.highPerformanceMode)
21
- {
22
- // if the channel is percussion channel, do not kill the notes
23
- if(!this.workletProcessorChannels[channel].drumChannel)
24
- {
25
- this.killNote(channel, midiNote);
26
- return;
27
- }
28
- }
29
-
30
- const channelVoices = this.workletProcessorChannels[channel].voices;
31
- channelVoices.forEach(v => {
32
- if(v.midiNote !== midiNote || v.isInRelease === true)
33
- {
34
- return;
35
- }
36
- // if hold pedal, move to sustain
37
- if(this.workletProcessorChannels[channel].holdPedal) {
38
- this.workletProcessorChannels[channel].sustainedVoices.push(v);
39
- }
40
- else
41
- {
42
- this.releaseVoice(v);
43
- }
44
- });
45
- }
46
-
47
- /**
48
- * Stops a note nearly instantly
49
- * @param channel {number} - The MIDI channel to use
50
- * @param midiNote {number} - The MIDI key number
51
- * @this {Synthesizer}
52
- */
53
- export function killNote(channel, midiNote)
54
- {
55
- this.workletProcessorChannels[channel].voices.forEach(v => {
56
- if(v.midiNote !== midiNote)
57
- {
58
- return;
59
- }
60
- v.modulatedGenerators[generatorTypes.releaseVolEnv] = -12000; // set release to be very short
61
- this.releaseVoice(v);
62
- });
63
- }
64
-
65
- /**
66
- * stops all notes
67
- * @param channel {number} - The MIDI channel to use
68
- * @param force {boolean} - If the notes should stop instantly or release normally
69
- * @this {Synthesizer}
70
- */
71
- export function stopAll(channel, force = false)
72
- {
73
- const channelVoices = this.workletProcessorChannels[channel].voices;
74
- if(force)
75
- {
76
- // force stop all
77
- channelVoices.length = 0;
78
- this.workletProcessorChannels[channel].sustainedVoices.length = 0;
79
- }
80
- else
81
- {
82
- channelVoices.forEach(v => {
83
- if(v.isInRelease) return;
84
- this.releaseVoice(v);
85
- });
86
- this.workletProcessorChannels[channel].sustainedVoices.forEach(v => {
87
- this.releaseVoice(v);
88
- })
89
- }
90
- }
91
-
92
- /**
93
- * @this {Synthesizer}
94
- * @param force {boolean} - If the notes should stop instantly or release normally
95
- */
96
- export function stopAllChannels(force = false)
97
- {
98
- SpessaSynthInfo("%cStop all received!", consoleColors.info);
99
- for (let i = 0; i < this.workletProcessorChannels.length; i++) {
100
- this.stopAll(i, force);
101
- }
102
- }