spessasynth_core 3.27.7 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/README.md +188 -116
  2. package/dist/index.d.ts +4057 -0
  3. package/dist/index.js +17188 -0
  4. package/dist/index.js.map +1 -0
  5. package/package.json +23 -6
  6. package/index.js +0 -132
  7. package/src/externals/README.md +0 -6
  8. package/src/externals/fflate/LICENSE +0 -21
  9. package/src/externals/fflate/fflate.min.js +0 -1
  10. package/src/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -12
  11. package/src/externals/stbvorbis_sync/LICENSE +0 -202
  12. package/src/externals/stbvorbis_sync/NOTICE +0 -6
  13. package/src/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -1
  14. package/src/midi/README.md +0 -32
  15. package/src/midi/basic_midi.js +0 -587
  16. package/src/midi/midi_builder.js +0 -203
  17. package/src/midi/midi_loader.js +0 -321
  18. package/src/midi/midi_message.js +0 -254
  19. package/src/midi/midi_sequence.js +0 -230
  20. package/src/midi/midi_tools/get_note_times.js +0 -154
  21. package/src/midi/midi_tools/midi_editor.js +0 -611
  22. package/src/midi/midi_tools/midi_writer.js +0 -105
  23. package/src/midi/midi_tools/rmidi_writer.js +0 -566
  24. package/src/midi/midi_tools/used_keys_loaded.js +0 -256
  25. package/src/midi/xmf_loader.js +0 -454
  26. package/src/sequencer/README.md +0 -9
  27. package/src/sequencer/events.js +0 -81
  28. package/src/sequencer/play.js +0 -362
  29. package/src/sequencer/process_event.js +0 -165
  30. package/src/sequencer/process_tick.js +0 -104
  31. package/src/sequencer/sequencer_engine.js +0 -372
  32. package/src/sequencer/song_control.js +0 -196
  33. package/src/soundfont/README.md +0 -11
  34. package/src/soundfont/basic_soundfont/basic_global_zone.js +0 -6
  35. package/src/soundfont/basic_soundfont/basic_instrument.js +0 -115
  36. package/src/soundfont/basic_soundfont/basic_instrument_zone.js +0 -45
  37. package/src/soundfont/basic_soundfont/basic_preset.js +0 -313
  38. package/src/soundfont/basic_soundfont/basic_preset_zone.js +0 -39
  39. package/src/soundfont/basic_soundfont/basic_sample.js +0 -477
  40. package/src/soundfont/basic_soundfont/basic_soundbank.js +0 -740
  41. package/src/soundfont/basic_soundfont/basic_zone.js +0 -145
  42. package/src/soundfont/basic_soundfont/generator.js +0 -76
  43. package/src/soundfont/basic_soundfont/generator_types.js +0 -151
  44. package/src/soundfont/basic_soundfont/modulator.js +0 -581
  45. package/src/soundfont/basic_soundfont/riff_chunk.js +0 -195
  46. package/src/soundfont/basic_soundfont/write_dls/art2.js +0 -174
  47. package/src/soundfont/basic_soundfont/write_dls/articulator.js +0 -49
  48. package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +0 -374
  49. package/src/soundfont/basic_soundfont/write_dls/ins.js +0 -85
  50. package/src/soundfont/basic_soundfont/write_dls/lins.js +0 -15
  51. package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +0 -330
  52. package/src/soundfont/basic_soundfont/write_dls/rgn2.js +0 -120
  53. package/src/soundfont/basic_soundfont/write_dls/wave.js +0 -71
  54. package/src/soundfont/basic_soundfont/write_dls/write_dls.js +0 -124
  55. package/src/soundfont/basic_soundfont/write_dls/wsmp.js +0 -78
  56. package/src/soundfont/basic_soundfont/write_dls/wvpl.js +0 -35
  57. package/src/soundfont/basic_soundfont/write_sf2/ibag.js +0 -60
  58. package/src/soundfont/basic_soundfont/write_sf2/igen.js +0 -91
  59. package/src/soundfont/basic_soundfont/write_sf2/imod.js +0 -62
  60. package/src/soundfont/basic_soundfont/write_sf2/inst.js +0 -42
  61. package/src/soundfont/basic_soundfont/write_sf2/pbag.js +0 -57
  62. package/src/soundfont/basic_soundfont/write_sf2/pgen.js +0 -92
  63. package/src/soundfont/basic_soundfont/write_sf2/phdr.js +0 -61
  64. package/src/soundfont/basic_soundfont/write_sf2/pmod.js +0 -62
  65. package/src/soundfont/basic_soundfont/write_sf2/sdta.js +0 -131
  66. package/src/soundfont/basic_soundfont/write_sf2/shdr.js +0 -77
  67. package/src/soundfont/basic_soundfont/write_sf2/write.js +0 -287
  68. package/src/soundfont/dls/articulator_converter.js +0 -402
  69. package/src/soundfont/dls/dls_destinations.js +0 -38
  70. package/src/soundfont/dls/dls_instrument.js +0 -20
  71. package/src/soundfont/dls/dls_preset.js +0 -43
  72. package/src/soundfont/dls/dls_sample.js +0 -238
  73. package/src/soundfont/dls/dls_soundfont.js +0 -183
  74. package/src/soundfont/dls/dls_sources.js +0 -63
  75. package/src/soundfont/dls/dls_zone.js +0 -89
  76. package/src/soundfont/dls/read_articulation.js +0 -300
  77. package/src/soundfont/dls/read_instrument.js +0 -118
  78. package/src/soundfont/dls/read_instrument_list.js +0 -17
  79. package/src/soundfont/dls/read_lart.js +0 -35
  80. package/src/soundfont/dls/read_region.js +0 -157
  81. package/src/soundfont/dls/read_samples.js +0 -154
  82. package/src/soundfont/load_soundfont.js +0 -21
  83. package/src/soundfont/read_sf2/generators.js +0 -43
  84. package/src/soundfont/read_sf2/instrument_zones.js +0 -75
  85. package/src/soundfont/read_sf2/instruments.js +0 -71
  86. package/src/soundfont/read_sf2/modulators.js +0 -25
  87. package/src/soundfont/read_sf2/preset_zones.js +0 -79
  88. package/src/soundfont/read_sf2/presets.js +0 -80
  89. package/src/soundfont/read_sf2/samples.js +0 -317
  90. package/src/soundfont/read_sf2/soundfont.js +0 -452
  91. package/src/soundfont/read_sf2/zones.js +0 -28
  92. package/src/synthetizer/README.md +0 -7
  93. package/src/synthetizer/audio_engine/README.md +0 -9
  94. package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +0 -289
  95. package/src/synthetizer/audio_engine/engine_components/controller_tables.js +0 -90
  96. package/src/synthetizer/audio_engine/engine_components/dynamic_modulator_system.js +0 -95
  97. package/src/synthetizer/audio_engine/engine_components/enums.js +0 -18
  98. package/src/synthetizer/audio_engine/engine_components/key_modifier_manager.js +0 -151
  99. package/src/synthetizer/audio_engine/engine_components/lfo.js +0 -26
  100. package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +0 -282
  101. package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +0 -551
  102. package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +0 -181
  103. package/src/synthetizer/audio_engine/engine_components/modulator_curves.js +0 -89
  104. package/src/synthetizer/audio_engine/engine_components/soundfont_manager.js +0 -265
  105. package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -124
  106. package/src/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
  107. package/src/synthetizer/audio_engine/engine_components/voice.js +0 -525
  108. package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -402
  109. package/src/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -274
  110. package/src/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -159
  111. package/src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -48
  112. package/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -254
  113. package/src/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -20
  114. package/src/synthetizer/audio_engine/engine_methods/data_entry/awe32.js +0 -198
  115. package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -281
  116. package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -109
  117. package/src/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
  118. package/src/synthetizer/audio_engine/engine_methods/note_on.js +0 -214
  119. package/src/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
  120. package/src/synthetizer/audio_engine/engine_methods/program_change.js +0 -35
  121. package/src/synthetizer/audio_engine/engine_methods/render_voice.js +0 -214
  122. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/embedded_sound_bank.js +0 -42
  123. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -0
  124. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/update_preset_list.js +0 -19
  125. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -23
  126. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -56
  127. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
  128. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
  129. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
  130. package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -1058
  131. package/src/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -23
  132. package/src/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -31
  133. package/src/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -29
  134. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
  135. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -27
  136. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
  137. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
  138. package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
  139. package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
  140. package/src/synthetizer/audio_engine/main_processor.js +0 -813
  141. package/src/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -16
  142. package/src/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
  143. package/src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -116
  144. package/src/synthetizer/audio_engine/synth_processor_options.js +0 -18
  145. package/src/synthetizer/synth_constants.js +0 -26
  146. package/src/utils/README.md +0 -8
  147. package/src/utils/buffer_to_wav.js +0 -197
  148. package/src/utils/byte_functions/big_endian.js +0 -32
  149. package/src/utils/byte_functions/little_endian.js +0 -77
  150. package/src/utils/byte_functions/string.js +0 -92
  151. package/src/utils/byte_functions/variable_length_quantity.js +0 -42
  152. package/src/utils/fill_with_defaults.js +0 -21
  153. package/src/utils/indexed_array.js +0 -34
  154. package/src/utils/loggin.js +0 -71
  155. package/src/utils/other.js +0 -92
  156. package/src/utils/sysex_detector.js +0 -58
  157. package/src/utils/xg_hacks.js +0 -193
@@ -1,281 +0,0 @@
1
- import { customControllers, dataEntryStates, NON_CC_INDEX_OFFSET } from "../../engine_components/controller_tables.js";
2
- import { SpessaSynthInfo, SpessaSynthWarn } from "../../../../utils/loggin.js";
3
- import { consoleColors } from "../../../../utils/other.js";
4
- import { midiControllers } from "../../../../midi/midi_message.js";
5
- import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulator.js";
6
-
7
-
8
- /**
9
- * @enum {number}
10
- */
11
- export const registeredParameterTypes = {
12
- pitchBendRange: 0x0000,
13
- fineTuning: 0x0001,
14
- coarseTuning: 0x0002,
15
- modulationDepth: 0x0005,
16
- resetParameters: 0x3FFF
17
- };
18
-
19
- /**
20
- * @enum {number}
21
- */
22
- export const nonRegisteredMSB = {
23
- partParameter: 0x01,
24
- awe32: 0x7F,
25
- SF2: 120
26
- };
27
-
28
- /**
29
- * https://cdn.roland.com/assets/media/pdf/SC-88PRO_OM.pdf
30
- * http://hummer.stanford.edu/sig/doc/classes/MidiOutput/rpn.html
31
- * @enum {number}
32
- */
33
- const nonRegisteredGSLSB = {
34
- vibratoRate: 0x08,
35
- vibratoDepth: 0x09,
36
- vibratoDelay: 0x0A,
37
-
38
- TVFFilterCutoff: 0x20,
39
- TVFFilterResonance: 0x21,
40
-
41
- EGAttackTime: 0x63,
42
- EGReleaseTime: 0x66
43
-
44
- };
45
-
46
-
47
- /**
48
- * Executes a data entry for an NRP for a sc88pro NRP (because touhou yes) and RPN tuning
49
- * @param dataValue {number} dataEntryCoarse MSB
50
- * @this {MidiAudioChannel}
51
- * @private
52
- */
53
- export function dataEntryCoarse(dataValue)
54
- {
55
- // store in cc table
56
- this.midiControllers[midiControllers.dataEntryMsb] = dataValue << 7;
57
- /*
58
- A note on this vibrato.
59
- This is a completely custom vibrato, with its own oscillator and parameters.
60
- It is disabled by default,
61
- only being enabled when one of the NPRN messages changing it is received
62
- and stays on until the next system-reset.
63
- */
64
- const addDefaultVibrato = () =>
65
- {
66
- if (this.channelVibrato.delay === 0 && this.channelVibrato.rate === 0 && this.channelVibrato.depth === 0)
67
- {
68
- this.channelVibrato.depth = 50;
69
- this.channelVibrato.rate = 8;
70
- this.channelVibrato.delay = 0.6;
71
- }
72
- };
73
-
74
- const coolInfo = (what, value, type) =>
75
- {
76
- if (type.length > 0)
77
- {
78
- type = " " + type;
79
- }
80
- SpessaSynthInfo(
81
- `%c${what} for %c${this.channelNumber}%c is now set to %c${value}%c${type}.`,
82
- consoleColors.info,
83
- consoleColors.recognized,
84
- consoleColors.info,
85
- consoleColors.value,
86
- consoleColors.info
87
- );
88
- };
89
- switch (this.dataEntryState)
90
- {
91
- default:
92
- case dataEntryStates.Idle:
93
- break;
94
-
95
- // process GS NRPNs
96
- case dataEntryStates.NRPFine:
97
- if (this.lockGSNRPNParams)
98
- {
99
- return;
100
- }
101
- /**
102
- * @type {number}
103
- */
104
- const NRPNCoarse = this.midiControllers[midiControllers.NRPNMsb] >> 7;
105
- /**
106
- * @type {number}
107
- */
108
- const NRPNFine = this.midiControllers[midiControllers.NRPNLsb] >> 7;
109
- const dataEntryFine = this.midiControllers[midiControllers.lsbForControl6DataEntry] >> 7;
110
- switch (NRPNCoarse)
111
- {
112
- default:
113
- if (dataValue === 64)
114
- {
115
- // default value
116
- return;
117
- }
118
- SpessaSynthWarn(
119
- `%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${NRPNFine.toString(16)
120
- .toUpperCase()} 0x${NRPNFine.toString(
121
- 16).toUpperCase()})%c data value: %c${dataValue}`,
122
- consoleColors.warn,
123
- consoleColors.recognized,
124
- consoleColors.warn,
125
- consoleColors.unrecognized,
126
- consoleColors.warn,
127
- consoleColors.value
128
- );
129
- break;
130
-
131
- // part parameters: vibrato, cutoff
132
- case nonRegisteredMSB.partParameter:
133
- switch (NRPNFine)
134
- {
135
- default:
136
- if (dataValue === 64)
137
- {
138
- // default value
139
- return;
140
- }
141
- SpessaSynthWarn(
142
- `%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${NRPNCoarse.toString(16)} 0x${NRPNFine.toString(
143
- 16)})%c data value: %c${dataValue}`,
144
- consoleColors.warn,
145
- consoleColors.recognized,
146
- consoleColors.warn,
147
- consoleColors.unrecognized,
148
- consoleColors.warn,
149
- consoleColors.value
150
- );
151
- break;
152
-
153
- // vibrato rate
154
- case nonRegisteredGSLSB.vibratoRate:
155
- if (dataValue === 64)
156
- {
157
- return;
158
- }
159
- addDefaultVibrato();
160
- this.channelVibrato.rate = (dataValue / 64) * 8;
161
- coolInfo("Vibrato rate", `${dataValue} = ${this.channelVibrato.rate}`, "Hz");
162
- break;
163
-
164
- // vibrato depth
165
- case nonRegisteredGSLSB.vibratoDepth:
166
- if (dataValue === 64)
167
- {
168
- return;
169
- }
170
- addDefaultVibrato();
171
- this.channelVibrato.depth = dataValue / 2;
172
- coolInfo("Vibrato depth", `${dataValue} = ${this.channelVibrato.depth}`, "cents of detune");
173
- break;
174
-
175
- // vibrato delay
176
- case nonRegisteredGSLSB.vibratoDelay:
177
- if (dataValue === 64)
178
- {
179
- return;
180
- }
181
- addDefaultVibrato();
182
- this.channelVibrato.delay = (dataValue / 64) / 3;
183
- coolInfo("Vibrato delay", `${dataValue} = ${this.channelVibrato.delay}`, "seconds");
184
- break;
185
-
186
- // filter cutoff
187
- case nonRegisteredGSLSB.TVFFilterCutoff:
188
- // affect the "brightness" controller as we have a default modulator that controls it
189
- this.controllerChange(midiControllers.brightness, dataValue);
190
- coolInfo("Filter cutoff", dataValue.toString(), "");
191
- break;
192
-
193
- // attack time
194
- case nonRegisteredGSLSB.EGAttackTime:
195
- // affect the "attack time" controller as we have a default modulator that controls it
196
- this.controllerChange(midiControllers.attackTime, dataValue);
197
- coolInfo("EG attack time", dataValue.toString(), "");
198
- break;
199
-
200
- // release time
201
- case nonRegisteredGSLSB.EGReleaseTime:
202
- // affect the "release time" controller as we have a default modulator that controls it
203
- this.controllerChange(midiControllers.releaseTime, dataValue);
204
- coolInfo("EG release time", dataValue.toString(), "");
205
- break;
206
- }
207
- break;
208
-
209
- case nonRegisteredMSB.awe32:
210
- break;
211
-
212
- // SF2 NRPN
213
- case nonRegisteredMSB.SF2:
214
- if (NRPNFine > 100)
215
- {
216
- // sfspec:
217
- // Note that NRPN Select LSB greater than 100 are for setup only, and should not be used on their own to select a
218
- // generator parameter.
219
- break;
220
- }
221
- const gen = this.customControllers[customControllers.sf2NPRNGeneratorLSB];
222
- const offset = (dataValue << 7 | dataEntryFine) - 8192;
223
- this.setGeneratorOffset(gen, offset);
224
- break;
225
- }
226
- break;
227
-
228
- case dataEntryStates.RPCoarse:
229
- case dataEntryStates.RPFine:
230
- /**
231
- * @type {number}
232
- */
233
- const rpnValue = this.midiControllers[midiControllers.RPNMsb] | (this.midiControllers[midiControllers.RPNLsb] >> 7);
234
- switch (rpnValue)
235
- {
236
- default:
237
- SpessaSynthWarn(
238
- `%cUnrecognized RPN for %c${this.channelNumber}%c: %c(0x${rpnValue.toString(16)})%c data value: %c${dataValue}`,
239
- consoleColors.warn,
240
- consoleColors.recognized,
241
- consoleColors.warn,
242
- consoleColors.unrecognized,
243
- consoleColors.warn,
244
- consoleColors.value
245
- );
246
- break;
247
-
248
- // pitch bend range
249
- case registeredParameterTypes.pitchBendRange:
250
- this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] = dataValue << 7;
251
- coolInfo("Pitch bend range", dataValue.toString(), "semitones");
252
- break;
253
-
254
- // coarse tuning
255
- case registeredParameterTypes.coarseTuning:
256
- // semitones
257
- const semitones = dataValue - 64;
258
- this.setCustomController(customControllers.channelTuningSemitones, semitones);
259
- coolInfo("Coarse tuning", semitones.toString(), "semitones");
260
- break;
261
-
262
- // fine-tuning
263
- case registeredParameterTypes.fineTuning:
264
- // note: this will not work properly unless the lsb is sent!
265
- // here we store the raw value to then adjust in fine
266
- this.setTuning(dataValue - 64, false);
267
- break;
268
-
269
- // modulation depth
270
- case registeredParameterTypes.modulationDepth:
271
- this.setModulationDepth(dataValue * 100);
272
- break;
273
-
274
- case registeredParameterTypes.resetParameters:
275
- this.resetParameters();
276
- break;
277
-
278
- }
279
-
280
- }
281
- }
@@ -1,109 +0,0 @@
1
- import { consoleColors } from "../../../../utils/other.js";
2
- import { SpessaSynthInfo, SpessaSynthWarn } from "../../../../utils/loggin.js";
3
- import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulator.js";
4
- import { customControllers, dataEntryStates, NON_CC_INDEX_OFFSET } from "../../engine_components/controller_tables.js";
5
- import { midiControllers } from "../../../../midi/midi_message.js";
6
- import { nonRegisteredMSB, registeredParameterTypes } from "./data_entry_coarse.js";
7
- import { handleAWE32NRPN } from "./awe32.js";
8
-
9
- /**
10
- * Executes a data entry for an RPN tuning
11
- * @param dataValue {number} dataEntry LSB
12
- * @this {MidiAudioChannel}
13
- * @private
14
- */
15
- export function dataEntryFine(dataValue)
16
- {
17
- // store in cc table
18
- this.midiControllers[midiControllers.lsbForControl6DataEntry] = dataValue << 7;
19
- switch (this.dataEntryState)
20
- {
21
- default:
22
- break;
23
-
24
- case dataEntryStates.RPCoarse:
25
- case dataEntryStates.RPFine:
26
- const rpnValue = this.midiControllers[midiControllers.RPNMsb] | (this.midiControllers[midiControllers.RPNLsb] >> 7);
27
- switch (rpnValue)
28
- {
29
- default:
30
- break;
31
-
32
- // pitch bend range fine tune
33
- case registeredParameterTypes.pitchBendRange:
34
- if (dataValue === 0)
35
- {
36
- break;
37
- }
38
- // 14-bit value, so upper 7 are coarse and lower 7 are fine!
39
- this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] |= dataValue;
40
- const actualTune = (this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] >> 7) + dataValue / 128;
41
- SpessaSynthInfo(
42
- `%cChannel ${this.channelNumber} bend range. Semitones: %c${actualTune}`,
43
- consoleColors.info,
44
- consoleColors.value
45
- );
46
- break;
47
-
48
- // fine-tuning
49
- case registeredParameterTypes.fineTuning:
50
- // grab the data and shift
51
- const coarse = this.customControllers[customControllers.channelTuning];
52
- const finalTuning = (coarse << 7) | dataValue;
53
- this.setTuning(finalTuning * 0.01220703125); // multiply by 8192 / 100 (cent increments)
54
- break;
55
-
56
- // modulation depth
57
- case registeredParameterTypes.modulationDepth:
58
- const currentModulationDepthCents = this.customControllers[customControllers.modulationMultiplier] * 50;
59
- let cents = currentModulationDepthCents + (dataValue / 128) * 100;
60
- this.setModulationDepth(cents);
61
- break;
62
-
63
- case 0x3FFF:
64
- this.resetParameters();
65
- break;
66
-
67
- }
68
- break;
69
-
70
- case dataEntryStates.NRPFine:
71
- /**
72
- * @type {number}
73
- */
74
- const NRPNCoarse = this.midiControllers[midiControllers.NRPNMsb] >> 7;
75
- /**
76
- * @type {number}
77
- */
78
- const NRPNFine = this.midiControllers[midiControllers.NRPNLsb] >> 7;
79
- if (NRPNCoarse === nonRegisteredMSB.SF2)
80
- {
81
- return;
82
- }
83
- switch (NRPNCoarse)
84
- {
85
- default:
86
- SpessaSynthWarn(
87
- `%cUnrecognized NRPN LSB for %c${this.channelNumber}%c: %c(0x${NRPNFine.toString(16)
88
- .toUpperCase()} 0x${NRPNFine.toString(
89
- 16).toUpperCase()})%c data value: %c${dataValue}`,
90
- consoleColors.warn,
91
- consoleColors.recognized,
92
- consoleColors.warn,
93
- consoleColors.unrecognized,
94
- consoleColors.warn,
95
- consoleColors.value
96
- );
97
- break;
98
-
99
- case nonRegisteredMSB.awe32:
100
- handleAWE32NRPN.call(
101
- this,
102
- NRPNFine,
103
- dataValue,
104
- this.midiControllers[midiControllers.dataEntryMsb] >> 7
105
- );
106
- break;
107
- }
108
- }
109
- }
@@ -1,17 +0,0 @@
1
- /**
2
- * @param isMuted {boolean}
3
- * @this {MidiAudioChannel}
4
- */
5
- export function muteChannel(isMuted)
6
- {
7
- if (isMuted)
8
- {
9
- this.stopAllNotes(true);
10
- }
11
- this.isMuted = isMuted;
12
- this.sendChannelProperty();
13
- this.synth.callEvent("mutechannel", {
14
- channel: this.channelNumber,
15
- isMuted: isMuted
16
- });
17
- }
@@ -1,214 +0,0 @@
1
- import { midiControllers } from "../../../midi/midi_message.js";
2
- import { portamentoTimeToSeconds } from "./portamento_time.js";
3
- import { customControllers } from "../engine_components/controller_tables.js";
4
- import { Modulator } from "../../../soundfont/basic_soundfont/modulator.js";
5
- import { GENERATOR_OVERRIDE_NO_CHANGE_VALUE } from "../../synth_constants.js";
6
- import { generatorTypes } from "../../../soundfont/basic_soundfont/generator_types.js";
7
- import { SpessaSynthWarn } from "../../../utils/loggin.js";
8
-
9
- /**
10
- * sends a "MIDI Note on message"
11
- * @param midiNote {number}
12
- * @param velocity {number}
13
- * @this {MidiAudioChannel}
14
- */
15
- export function noteOn(midiNote, velocity)
16
- {
17
- if (velocity < 1)
18
- {
19
- this.noteOff(midiNote);
20
- return;
21
- }
22
- velocity = Math.min(127, velocity);
23
-
24
- if (
25
- (this.synth.highPerformanceMode && this.synth.totalVoicesAmount > 200 && velocity < 40) ||
26
- (this.synth.highPerformanceMode && velocity < 10) ||
27
- (this.isMuted)
28
- )
29
- {
30
- return;
31
- }
32
-
33
- if (!this.preset)
34
- {
35
- SpessaSynthWarn(`No preset for channel ${this.channelNumber}!`);
36
- return;
37
- }
38
-
39
- const realKey = midiNote + this.channelTransposeKeyShift + this.customControllers[customControllers.channelKeyShift];
40
- let internalMidiNote = realKey;
41
-
42
- if (realKey > 127 || realKey < 0)
43
- {
44
- return;
45
- }
46
- const program = this.preset?.program;
47
- const tune = this.synth.tunings[program]?.[realKey]?.midiNote;
48
- if (tune >= 0)
49
- {
50
- internalMidiNote = tune;
51
- }
52
-
53
- // velocity override
54
- if (this.velocityOverride > 0)
55
- {
56
- velocity = this.velocityOverride;
57
- }
58
-
59
- // key velocity override
60
- const keyVel = this.synth.keyModifierManager.getVelocity(this.channelNumber, realKey);
61
- if (keyVel > -1)
62
- {
63
- velocity = keyVel;
64
- }
65
-
66
- // gain
67
- const voiceGain = this.synth.keyModifierManager.getGain(this.channelNumber, realKey);
68
-
69
- // portamento
70
- let portamentoFromKey = -1;
71
- let portamentoDuration = 0;
72
- // note: the 14-bit value needs to go down to 7-bit
73
- const portamentoTime = this.midiControllers[midiControllers.portamentoTime] >> 7;
74
- const control = this.midiControllers[midiControllers.portamentoControl];
75
- const currentFromKey = control >> 7;
76
- if (
77
- !this.drumChannel && // no portamento on drum channel
78
- currentFromKey !== internalMidiNote && // if the same note, there's no portamento
79
- this.midiControllers[midiControllers.portamentoOnOff] >= 8192 && // (64 << 7)
80
- portamentoTime > 0 // 0 duration is no portamento
81
- )
82
- {
83
- // a value of one means the initial portamento
84
- if (control !== 1)
85
- {
86
- const diff = Math.abs(internalMidiNote - currentFromKey);
87
- portamentoDuration = portamentoTimeToSeconds(portamentoTime, diff);
88
- portamentoFromKey = currentFromKey;
89
- }
90
- // set portamento control to previous value
91
- this.controllerChange(midiControllers.portamentoControl, internalMidiNote);
92
- }
93
- // get voices
94
- const voices = this.synth.getVoices(
95
- this.channelNumber,
96
- internalMidiNote,
97
- velocity,
98
- realKey
99
- );
100
-
101
- // zero means disabled
102
- let panOverride = 0;
103
- if (this.randomPan)
104
- {
105
- // the range is -500 to 500
106
- panOverride = Math.round(Math.random() * 1000 - 500);
107
- }
108
-
109
- // add voices
110
- const channelVoices = this.voices;
111
- voices.forEach(voice =>
112
- {
113
- // apply portamento
114
- voice.portamentoFromKey = portamentoFromKey;
115
- voice.portamentoDuration = portamentoDuration;
116
-
117
- // apply pan override
118
- voice.overridePan = panOverride;
119
-
120
- // apply gain override
121
- voice.gain = voiceGain;
122
-
123
- // dynamic modulators (if none, this won't iterate over anything)
124
- this.sysExModulators.modulatorList.forEach(m =>
125
- {
126
- const mod = m.mod;
127
- const existingModIndex = voice.modulators.findIndex(voiceMod => Modulator.isIdentical(voiceMod, mod));
128
-
129
- // replace or add
130
- if (existingModIndex !== -1)
131
- {
132
- voice.modulators[existingModIndex] = Modulator.copy(mod);
133
- }
134
- else
135
- {
136
- voice.modulators.push(Modulator.copy(mod));
137
- }
138
- });
139
-
140
- // apply generator override
141
- if (this.generatorOverridesEnabled)
142
- {
143
- this.generatorOverrides.forEach((overrideValue, generatorType) =>
144
- {
145
- if (overrideValue === GENERATOR_OVERRIDE_NO_CHANGE_VALUE)
146
- {
147
- return;
148
- }
149
- voice.generators[generatorType] = overrideValue;
150
- });
151
- }
152
-
153
-
154
- // apply exclusive class
155
- const exclusive = voice.exclusiveClass;
156
- if (exclusive !== 0)
157
- {
158
- // kill all voices with the same exclusive class
159
- channelVoices.forEach(v =>
160
- {
161
- if (v.exclusiveClass === exclusive)
162
- {
163
- v.exclusiveRelease(this.synth.currentSynthTime);
164
- }
165
- });
166
- }
167
- // compute all modulators
168
- this.computeModulators(voice);
169
- // modulate sample offsets (these are not real time)
170
- const cursorStartOffset = voice.modulatedGenerators[generatorTypes.startAddrsOffset] + voice.modulatedGenerators[generatorTypes.startAddrsCoarseOffset] * 32768;
171
- const endOffset = voice.modulatedGenerators[generatorTypes.endAddrOffset] + voice.modulatedGenerators[generatorTypes.endAddrsCoarseOffset] * 32768;
172
- const loopStartOffset = voice.modulatedGenerators[generatorTypes.startloopAddrsOffset] + voice.modulatedGenerators[generatorTypes.startloopAddrsCoarseOffset] * 32768;
173
- const loopEndOffset = voice.modulatedGenerators[generatorTypes.endloopAddrsOffset] + voice.modulatedGenerators[generatorTypes.endloopAddrsCoarseOffset] * 32768;
174
- const sm = voice.sample;
175
- // apply them
176
- const clamp = num => Math.max(0, Math.min(sm.sampleData.length - 1, num));
177
- sm.cursor = clamp(sm.cursor + cursorStartOffset);
178
- sm.end = clamp(sm.end + endOffset);
179
- sm.loopStart = clamp(sm.loopStart + loopStartOffset);
180
- sm.loopEnd = clamp(sm.loopEnd + loopEndOffset);
181
- // swap loops if needed
182
- if (sm.loopEnd < sm.loopStart)
183
- {
184
- const temp = sm.loopStart;
185
- sm.loopStart = sm.loopEnd;
186
- sm.loopEnd = temp;
187
- }
188
- if (sm.loopEnd - sm.loopStart < 1)
189
- {
190
- sm.loopingMode = 0;
191
- sm.isLooping = false;
192
- }
193
- // set the current attenuation to target,
194
- // as it's interpolated (we don't want 0 attenuation for even a split second)
195
- voice.volumeEnvelope.attenuation = voice.volumeEnvelope.attenuationTargetGain;
196
- // set initial pan to avoid split second changing from middle to the correct value
197
- voice.currentPan = Math.max(-500, Math.min(500, voice.modulatedGenerators[generatorTypes.pan])); // -500 to 500
198
- });
199
-
200
- this.synth.totalVoicesAmount += voices.length;
201
- // cap the voices
202
- if (this.synth.totalVoicesAmount > this.synth.voiceCap)
203
- {
204
- this.synth.voiceKilling(voices.length);
205
- }
206
- channelVoices.push(...voices);
207
- this.sendChannelProperty();
208
- this.synth.callEvent("noteon", {
209
- midiNote: midiNote,
210
- channel: this.channelNumber,
211
- velocity: velocity
212
- });
213
-
214
- }