spessasynth_lib 3.25.23 → 3.26.1

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 (162) hide show
  1. package/README.md +29 -114
  2. package/external_midi/midi_handler.js +14 -14
  3. package/external_midi/web_midi_link.js +3 -3
  4. package/index.js +33 -33
  5. package/package.json +19 -6
  6. package/{midi → sequencer}/midi_data.js +1 -1
  7. package/sequencer/{worklet_wrapper/sequencer.js → sequencer.js} +13 -12
  8. package/sequencer/{worklet_wrapper/sequencer_message.js → sequencer_message.js} +1 -1
  9. package/synthetizer/README.md +29 -1
  10. package/synthetizer/audio_effects/reverb_as_binary.js +2 -2
  11. package/synthetizer/{worklet_wrapper/key_modifier_manager.js → key_modifier_manager.js} +11 -2
  12. package/synthetizer/{worklet_wrapper/synth_event_handler.js → synth_event_handler.js} +16 -13
  13. package/synthetizer/{worklet_wrapper/synth_soundfont_manager.js → synth_soundfont_manager.js} +8 -5
  14. package/synthetizer/{worklet_wrapper/synthetizer.js → synthetizer.js} +29 -23
  15. package/synthetizer/{audio_engine/message_protocol/worklet_message.js → worklet_message.js} +15 -2
  16. package/synthetizer/{worklet_wrapper/worklet_processor.js → worklet_processor.js} +214 -31
  17. package/synthetizer/worklet_processor.min.js +13 -12
  18. package/synthetizer/worklet_processor.min.js.map +7 -0
  19. package/synthetizer/{worklet_wrapper/worklet_url.js → worklet_url.js} +2 -0
  20. package/utils/buffer_to_wav.js +7 -165
  21. package/utils/other.js +3 -84
  22. package/externals/fflate/LICENSE +0 -21
  23. package/externals/fflate/fflate.min.js +0 -1
  24. package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -12
  25. package/externals/stbvorbis_sync/LICENSE +0 -202
  26. package/externals/stbvorbis_sync/NOTICE +0 -6
  27. package/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -1
  28. package/midi/README.md +0 -32
  29. package/midi/basic_midi.js +0 -565
  30. package/midi/midi_builder.js +0 -202
  31. package/midi/midi_loader.js +0 -324
  32. package/midi/midi_message.js +0 -254
  33. package/midi/midi_sequence.js +0 -225
  34. package/midi/midi_tools/get_note_times.js +0 -154
  35. package/midi/midi_tools/midi_editor.js +0 -611
  36. package/midi/midi_tools/midi_writer.js +0 -99
  37. package/midi/midi_tools/rmidi_writer.js +0 -567
  38. package/midi/midi_tools/used_keys_loaded.js +0 -238
  39. package/midi/xmf_loader.js +0 -454
  40. package/sequencer/sequencer_engine/events.js +0 -104
  41. package/sequencer/sequencer_engine/play.js +0 -353
  42. package/sequencer/sequencer_engine/process_event.js +0 -169
  43. package/sequencer/sequencer_engine/process_tick.js +0 -106
  44. package/sequencer/sequencer_engine/sequencer_engine.js +0 -335
  45. package/sequencer/sequencer_engine/song_control.js +0 -229
  46. package/soundfont/README.md +0 -13
  47. package/soundfont/basic_soundfont/basic_instrument.js +0 -77
  48. package/soundfont/basic_soundfont/basic_preset.js +0 -336
  49. package/soundfont/basic_soundfont/basic_sample.js +0 -197
  50. package/soundfont/basic_soundfont/basic_soundfont.js +0 -565
  51. package/soundfont/basic_soundfont/basic_zone.js +0 -64
  52. package/soundfont/basic_soundfont/basic_zones.js +0 -43
  53. package/soundfont/basic_soundfont/generator.js +0 -220
  54. package/soundfont/basic_soundfont/modulator.js +0 -378
  55. package/soundfont/basic_soundfont/riff_chunk.js +0 -149
  56. package/soundfont/basic_soundfont/write_dls/art2.js +0 -173
  57. package/soundfont/basic_soundfont/write_dls/articulator.js +0 -49
  58. package/soundfont/basic_soundfont/write_dls/combine_zones.js +0 -400
  59. package/soundfont/basic_soundfont/write_dls/ins.js +0 -103
  60. package/soundfont/basic_soundfont/write_dls/lins.js +0 -18
  61. package/soundfont/basic_soundfont/write_dls/modulator_converter.js +0 -330
  62. package/soundfont/basic_soundfont/write_dls/rgn2.js +0 -121
  63. package/soundfont/basic_soundfont/write_dls/wave.js +0 -94
  64. package/soundfont/basic_soundfont/write_dls/write_dls.js +0 -119
  65. package/soundfont/basic_soundfont/write_dls/wsmp.js +0 -78
  66. package/soundfont/basic_soundfont/write_dls/wvpl.js +0 -32
  67. package/soundfont/basic_soundfont/write_sf2/ibag.js +0 -39
  68. package/soundfont/basic_soundfont/write_sf2/igen.js +0 -80
  69. package/soundfont/basic_soundfont/write_sf2/imod.js +0 -46
  70. package/soundfont/basic_soundfont/write_sf2/inst.js +0 -34
  71. package/soundfont/basic_soundfont/write_sf2/pbag.js +0 -39
  72. package/soundfont/basic_soundfont/write_sf2/pgen.js +0 -82
  73. package/soundfont/basic_soundfont/write_sf2/phdr.js +0 -42
  74. package/soundfont/basic_soundfont/write_sf2/pmod.js +0 -46
  75. package/soundfont/basic_soundfont/write_sf2/sdta.js +0 -80
  76. package/soundfont/basic_soundfont/write_sf2/shdr.js +0 -55
  77. package/soundfont/basic_soundfont/write_sf2/write.js +0 -222
  78. package/soundfont/dls/articulator_converter.js +0 -396
  79. package/soundfont/dls/dls_destinations.js +0 -38
  80. package/soundfont/dls/dls_preset.js +0 -44
  81. package/soundfont/dls/dls_sample.js +0 -75
  82. package/soundfont/dls/dls_soundfont.js +0 -186
  83. package/soundfont/dls/dls_sources.js +0 -62
  84. package/soundfont/dls/dls_zone.js +0 -95
  85. package/soundfont/dls/read_articulation.js +0 -299
  86. package/soundfont/dls/read_instrument.js +0 -121
  87. package/soundfont/dls/read_instrument_list.js +0 -17
  88. package/soundfont/dls/read_lart.js +0 -35
  89. package/soundfont/dls/read_region.js +0 -152
  90. package/soundfont/dls/read_samples.js +0 -270
  91. package/soundfont/load_soundfont.js +0 -21
  92. package/soundfont/read_sf2/generators.js +0 -46
  93. package/soundfont/read_sf2/instruments.js +0 -66
  94. package/soundfont/read_sf2/modulators.js +0 -36
  95. package/soundfont/read_sf2/presets.js +0 -80
  96. package/soundfont/read_sf2/samples.js +0 -304
  97. package/soundfont/read_sf2/soundfont.js +0 -305
  98. package/soundfont/read_sf2/zones.js +0 -263
  99. package/synthetizer/audio_engine/README.md +0 -25
  100. package/synthetizer/audio_engine/engine_components/compute_modulator.js +0 -266
  101. package/synthetizer/audio_engine/engine_components/controller_tables.js +0 -88
  102. package/synthetizer/audio_engine/engine_components/key_modifier_manager.js +0 -149
  103. package/synthetizer/audio_engine/engine_components/lfo.js +0 -26
  104. package/synthetizer/audio_engine/engine_components/lowpass_filter.js +0 -282
  105. package/synthetizer/audio_engine/engine_components/midi_audio_channel.js +0 -471
  106. package/synthetizer/audio_engine/engine_components/modulation_envelope.js +0 -181
  107. package/synthetizer/audio_engine/engine_components/modulator_curves.js +0 -89
  108. package/synthetizer/audio_engine/engine_components/soundfont_manager.js +0 -228
  109. package/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -120
  110. package/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
  111. package/synthetizer/audio_engine/engine_components/voice.js +0 -519
  112. package/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -401
  113. package/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -263
  114. package/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -132
  115. package/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -48
  116. package/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -241
  117. package/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -27
  118. package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -253
  119. package/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -66
  120. package/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
  121. package/synthetizer/audio_engine/engine_methods/note_on.js +0 -175
  122. package/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
  123. package/synthetizer/audio_engine/engine_methods/program_change.js +0 -61
  124. package/synthetizer/audio_engine/engine_methods/render_voice.js +0 -196
  125. package/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js +0 -30
  126. package/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -22
  127. package/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js +0 -40
  128. package/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js +0 -34
  129. package/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js +0 -21
  130. package/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -20
  131. package/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -55
  132. package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
  133. package/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
  134. package/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
  135. package/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -776
  136. package/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -24
  137. package/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -33
  138. package/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -31
  139. package/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
  140. package/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -27
  141. package/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
  142. package/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
  143. package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
  144. package/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
  145. package/synthetizer/audio_engine/main_processor.js +0 -765
  146. package/synthetizer/audio_engine/message_protocol/README.md +0 -13
  147. package/synthetizer/audio_engine/message_protocol/message_sending.js +0 -22
  148. package/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -14
  149. package/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
  150. package/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -122
  151. package/synthetizer/synth_constants.js +0 -20
  152. package/utils/README.md +0 -5
  153. package/utils/byte_functions/big_endian.js +0 -32
  154. package/utils/byte_functions/little_endian.js +0 -77
  155. package/utils/byte_functions/string.js +0 -107
  156. package/utils/byte_functions/variable_length_quantity.js +0 -42
  157. package/utils/indexed_array.js +0 -52
  158. package/utils/loggin.js +0 -79
  159. package/utils/sysex_detector.js +0 -58
  160. package/utils/xg_hacks.js +0 -193
  161. /package/sequencer/{worklet_wrapper/default_sequencer_options.js → default_sequencer_options.js} +0 -0
  162. /package/synthetizer/{worklet_wrapper/sfman_message.js → sfman_message.js} +0 -0
@@ -1,471 +0,0 @@
1
- import {
2
- CONTROLLER_TABLE_SIZE,
3
- CUSTOM_CONTROLLER_TABLE_SIZE,
4
- customControllers,
5
- dataEntryStates,
6
- NON_CC_INDEX_OFFSET
7
- } from "./controller_tables.js";
8
- import {
9
- resetControllers,
10
- resetControllersRP15Compliant,
11
- resetParameters
12
- } from "../engine_methods/controller_control/reset_controllers.js";
13
- import { renderVoice } from "../engine_methods/render_voice.js";
14
- import { panVoice } from "./stereo_panner.js";
15
- import { killNote } from "../engine_methods/stopping_notes/kill_note.js";
16
- import { setTuning } from "../engine_methods/tuning_control/set_tuning.js";
17
- import { setModulationDepth } from "../engine_methods/tuning_control/set_modulation_depth.js";
18
- import { dataEntryFine } from "../engine_methods/data_entry/data_entry_fine.js";
19
- import { controllerChange } from "../engine_methods/controller_control/controller_change.js";
20
- import { stopAllNotes } from "../engine_methods/stopping_notes/stop_all_notes.js";
21
- import { muteChannel } from "../engine_methods/mute_channel.js";
22
- import { transposeChannel } from "../engine_methods/tuning_control/transpose_channel.js";
23
- import { dataEntryCoarse } from "../engine_methods/data_entry/data_entry_coarse.js";
24
- import { noteOn } from "../engine_methods/note_on.js";
25
- import { noteOff } from "../engine_methods/stopping_notes/note_off.js";
26
- import { polyPressure } from "../engine_methods/tuning_control/poly_pressure.js";
27
- import { channelPressure } from "../engine_methods/tuning_control/channel_pressure.js";
28
- import { pitchWheel } from "../engine_methods/tuning_control/pitch_wheel.js";
29
- import { setOctaveTuning } from "../engine_methods/tuning_control/set_octave_tuning.js";
30
- import { programChange } from "../engine_methods/program_change.js";
31
- import { chooseBank, isSystemXG, parseBankSelect } from "../../../utils/xg_hacks.js";
32
- import { DEFAULT_PERCUSSION } from "../../synth_constants.js";
33
- import { modulatorSources } from "../../../soundfont/basic_soundfont/modulator.js";
34
- import { returnMessageType } from "../message_protocol/worklet_message.js";
35
-
36
- /**
37
- * This class represents a single MIDI Channel within the synthesizer.
38
- */
39
- class MidiAudioChannel
40
- {
41
- /**
42
- * An array of MIDI controller values and values used by modulators as the source (e.g., pitch bend, bend range, etc.).
43
- * These are stored as 14-bit values.
44
- * Refer to controller_tables.js for the index definitions.
45
- * @type {Int16Array}
46
- */
47
- midiControllers = new Int16Array(CONTROLLER_TABLE_SIZE);
48
-
49
- /**
50
- * An array indicating if a controller, at the equivalent index in the midiControllers array, is locked
51
- * (i.e., not allowed changing).
52
- * A locked controller cannot be modified.
53
- * @type {boolean[]}
54
- */
55
- lockedControllers = Array(CONTROLLER_TABLE_SIZE).fill(false);
56
-
57
- /**
58
- * An array of custom (non-SF2) control values such as RPN pitch tuning, transpose, modulation depth, etc.
59
- * Refer to controller_tables.js for the index definitions.
60
- * @type {Float32Array}
61
- */
62
- customControllers = new Float32Array(CUSTOM_CONTROLLER_TABLE_SIZE);
63
-
64
- /**
65
- * The key shift of the channel (in semitones).
66
- * @type {number}
67
- */
68
- channelTransposeKeyShift = 0;
69
-
70
- /**
71
- * An array of octave tuning values for each note on the channel.
72
- * Each index corresponds to a note (0 = C, 1 = C#, ..., 11 = B).
73
- * Note: Repeaded every 12 notes
74
- * @type {Int8Array}
75
- */
76
- channelOctaveTuning = new Int8Array(128);
77
-
78
- /**
79
- * Will be updated every time something tuning-related gets changed.
80
- * This is used to avoid a big addition for every voice rendering call.
81
- * @type {number}
82
- */
83
- channelTuningCents = 0;
84
-
85
- /**
86
- * Indicates whether the sustain (hold) pedal is active.
87
- * @type {boolean}
88
- */
89
- holdPedal = false;
90
-
91
- /**
92
- * Indicates whether this channel is a drum channel.
93
- * @type {boolean}
94
- */
95
- drumChannel = false;
96
-
97
- /**
98
- * If greater than 0, overrides the velocity value for the channel, otherwise it's disabled.
99
- * @type {number}
100
- */
101
- velocityOverride = 0;
102
-
103
- /**
104
- * Enables random panning for every note played on this channel.
105
- * @type {boolean}
106
- */
107
- randomPan = false;
108
-
109
- /**
110
- * The current state of the data entry for the channel.
111
- * @type {dataEntryStates}
112
- */
113
- dataEntryState = dataEntryStates.Idle;
114
-
115
- /**
116
- * The bank number of the channel (used for patch changes).
117
- * @type {number}
118
- */
119
- bank = 0;
120
-
121
- /**
122
- * The bank number sent as channel properties.
123
- * @type {number}
124
- */
125
- sentBank = 0;
126
-
127
- /**
128
- * The bank LSB number of the channel (used for patch changes in XG mode).
129
- * @type {number}
130
- */
131
- bankLSB = 0;
132
-
133
- /**
134
- * The preset currently assigned to the channel.
135
- * @type {BasicPreset}
136
- */
137
- preset = undefined;
138
-
139
- /**
140
- * Indicates whether the program on this channel is locked.
141
- * @type {boolean}
142
- */
143
- lockPreset = false;
144
-
145
- /**
146
- * Indicates the MIDI system when the preset was locked.
147
- * @type {SynthSystem}
148
- */
149
- lockedSystem = "gs";
150
-
151
- /**
152
- * Indicates whether the channel uses a preset from the override soundfont.
153
- * @type {boolean}
154
- */
155
- presetUsesOverride = false;
156
-
157
- /**
158
- * Indicates whether the GS NRPN parameters are enabled for this channel.
159
- * @type {boolean}
160
- */
161
- lockGSNRPNParams = false;
162
-
163
- /**
164
- * The vibrato settings for the channel.
165
- * @type {Object}
166
- * @property {number} depth - Depth of the vibrato effect in cents.
167
- * @property {number} delay - Delay before the vibrato effect starts (in seconds).
168
- * @property {number} rate - Rate of the vibrato oscillation (in Hz).
169
- */
170
- channelVibrato = { delay: 0, depth: 0, rate: 0 };
171
-
172
- /**
173
- * Indicates whether the channel is muted.
174
- * @type {boolean}
175
- */
176
- isMuted = false;
177
-
178
- /**
179
- * An array of voices currently active on the channel.
180
- * @type {Voice[]}
181
- */
182
- voices = [];
183
-
184
- /**
185
- * An array of voices that are sustained on the channel.
186
- * @type {Voice[]}
187
- */
188
- sustainedVoices = [];
189
-
190
- /**
191
- * The channel's number (0-based index)
192
- * @type {number}
193
- */
194
- channelNumber;
195
-
196
- /**
197
- * Parent processor instance.
198
- * @type {SpessaSynthProcessor}
199
- */
200
- synth;
201
-
202
- /**
203
- * Constructs a new MIDI channel
204
- * @param synth {SpessaSynthProcessor}
205
- * @param preset {BasicPreset}
206
- * @param channelNumber {number}
207
- */
208
- constructor(synth, preset, channelNumber)
209
- {
210
- this.synth = synth;
211
- this.preset = preset;
212
- this.channelNumber = channelNumber;
213
- }
214
-
215
- get isXGChannel()
216
- {
217
- return isSystemXG(this.synth.system) || (this.lockPreset && isSystemXG(this.lockedSystem));
218
- }
219
-
220
- /**
221
- * @param type {customControllers|number}
222
- * @param value {number}
223
- */
224
- setCustomController(type, value)
225
- {
226
- this.customControllers[type] = value;
227
- this.updateChannelTuning();
228
- }
229
-
230
- updateChannelTuning()
231
- {
232
- this.channelTuningCents =
233
- this.customControllers[customControllers.channelTuning] // RPN channel fine tuning
234
- + this.customControllers[customControllers.channelTransposeFine] // user tuning (transpose)
235
- + this.customControllers[customControllers.masterTuning] // master tuning, set by sysEx
236
- + (this.customControllers[customControllers.channelTuningSemitones] * 100); // RPN channel coarse tuning
237
- }
238
-
239
- /**
240
- * @param outputLeft {Float32Array} the left output buffer
241
- * @param outputRight {Float32Array} the right output buffer
242
- * @param reverbOutputLeft {Float32Array} left output for reverb
243
- * @param reverbOutputRight {Float32Array} right output for reverb
244
- * @param chorusOutputLeft {Float32Array} left output for chorus
245
- * @param chorusOutputRight {Float32Array} right output for chorus
246
- */
247
- renderAudio(
248
- outputLeft, outputRight,
249
- reverbOutputLeft, reverbOutputRight,
250
- chorusOutputLeft, chorusOutputRight
251
- )
252
- {
253
- this.voices = this.voices.filter(v => !this.renderVoice(
254
- v, this.synth.currentSynthTime,
255
- outputLeft, outputRight,
256
- reverbOutputLeft, reverbOutputRight,
257
- chorusOutputLeft, chorusOutputRight
258
- ));
259
- }
260
-
261
- /**
262
- * @param locked {boolean}
263
- */
264
- setPresetLock(locked)
265
- {
266
- this.lockPreset = locked;
267
- if (locked)
268
- {
269
- this.lockedSystem = this.synth.system;
270
- }
271
- }
272
-
273
- /**
274
- * @param bank {number}
275
- * @param isLSB {boolean}
276
- */
277
- setBankSelect(bank, isLSB = false)
278
- {
279
- if (this.lockPreset)
280
- {
281
- return;
282
- }
283
- if (isLSB)
284
- {
285
- this.bankLSB = bank;
286
- }
287
- else
288
- {
289
- this.bank = bank;
290
- const bankLogic = parseBankSelect(
291
- this.getBankSelect(),
292
- bank,
293
- this.synth.system,
294
- false,
295
- this.drumChannel,
296
- this.channelNumber
297
- );
298
- switch (bankLogic.drumsStatus)
299
- {
300
- default:
301
- case 0:
302
- break;
303
-
304
- case 1:
305
- if (this.channelNumber % 16 === DEFAULT_PERCUSSION)
306
- {
307
- // cannot disable drums on channel 9
308
- this.bank = 127;
309
- }
310
- break;
311
-
312
- case 2:
313
- this.setDrums(true);
314
- break;
315
- }
316
- }
317
- }
318
-
319
- /**
320
- * @returns {number}
321
- */
322
- getBankSelect()
323
- {
324
- return chooseBank(this.bank, this.bankLSB, this.drumChannel, this.isXGChannel);
325
- }
326
-
327
- /**
328
- * Changes a preset of this channel
329
- * @param preset {BasicPreset}
330
- */
331
- setPreset(preset)
332
- {
333
- if (this.lockPreset)
334
- {
335
- return;
336
- }
337
- delete this.preset;
338
- this.preset = preset;
339
- }
340
-
341
- /**
342
- * Sets drums on channel.
343
- * @param isDrum {boolean}
344
- */
345
- setDrums(isDrum)
346
- {
347
- if (this.lockPreset)
348
- {
349
- return;
350
- }
351
- if (this.drumChannel === isDrum)
352
- {
353
- return;
354
- }
355
- if (isDrum)
356
- {
357
- // clear transpose
358
- this.channelTransposeKeyShift = 0;
359
- this.drumChannel = true;
360
- }
361
- else
362
- {
363
- this.drumChannel = false;
364
- }
365
- this.presetUsesOverride = false;
366
- this.synth.callEvent("drumchange", {
367
- channel: this.channelNumber,
368
- isDrumChannel: this.drumChannel
369
- });
370
- this.programChange(this.preset.program);
371
- this.sendChannelProperty();
372
- }
373
-
374
- /**
375
- * Sets a custom vibrato
376
- * @param depth {number} cents
377
- * @param rate {number} Hz
378
- * @param delay {number} seconds
379
- */
380
- setVibrato(depth, rate, delay)
381
- {
382
- if (this.lockGSNRPNParams)
383
- {
384
- return;
385
- }
386
- this.channelVibrato.rate = rate;
387
- this.channelVibrato.delay = delay;
388
- this.channelVibrato.depth = depth;
389
- }
390
-
391
- disableAndLockGSNRPN()
392
- {
393
- this.lockGSNRPNParams = true;
394
- this.channelVibrato.rate = 0;
395
- this.channelVibrato.delay = 0;
396
- this.channelVibrato.depth = 0;
397
- }
398
-
399
-
400
- /**
401
- * @typedef {Object} ChannelProperty
402
- * @property {number} voicesAmount - the channel's current voice amount
403
- * @property {number} pitchBend - the channel's current pitch bend from -8192 do 8192
404
- * @property {number} pitchBendRangeSemitones - the pitch bend's range, in semitones
405
- * @property {boolean} isMuted - indicates whether the channel is muted
406
- * @property {boolean} isDrum - indicates whether the channel is a drum channel
407
- * @property {number} transposition - the channel's transposition, in semitones
408
- * @property {number} bank - the bank number of the current preset
409
- * @property {number} program - the MIDI program number of the current preset
410
- */
411
-
412
-
413
- /**
414
- * Sends this channel's property
415
- */
416
- sendChannelProperty()
417
- {
418
- if (!this.synth.enableEventSystem)
419
- {
420
- return;
421
- }
422
- /**
423
- * @type {ChannelProperty}
424
- */
425
- const data = {
426
- voicesAmount: this.voices.length,
427
- pitchBend: this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel],
428
- pitchBendRangeSemitones: this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] / 128,
429
- isMuted: this.isMuted,
430
- isDrum: this.drumChannel,
431
- transposition: this.channelTransposeKeyShift + this.customControllers[customControllers.channelTransposeFine] / 100,
432
- bank: this.sentBank,
433
- program: this.preset.program
434
- };
435
- this.synth.post({
436
- messageType: returnMessageType.channelPropertyChange,
437
- messageData: [this.channelNumber, data]
438
- });
439
- }
440
- }
441
-
442
- // voice
443
- MidiAudioChannel.prototype.renderVoice = renderVoice;
444
- MidiAudioChannel.prototype.panVoice = panVoice;
445
- MidiAudioChannel.prototype.killNote = killNote;
446
- MidiAudioChannel.prototype.stopAllNotes = stopAllNotes;
447
- MidiAudioChannel.prototype.muteChannel = muteChannel;
448
-
449
- // MIDI messages
450
- MidiAudioChannel.prototype.noteOn = noteOn;
451
- MidiAudioChannel.prototype.noteOff = noteOff;
452
- MidiAudioChannel.prototype.polyPressure = polyPressure;
453
- MidiAudioChannel.prototype.channelPressure = channelPressure;
454
- MidiAudioChannel.prototype.pitchWheel = pitchWheel;
455
- MidiAudioChannel.prototype.programChange = programChange;
456
-
457
- // Tuning
458
- MidiAudioChannel.prototype.setTuning = setTuning;
459
- MidiAudioChannel.prototype.setOctaveTuning = setOctaveTuning;
460
- MidiAudioChannel.prototype.setModulationDepth = setModulationDepth;
461
- MidiAudioChannel.prototype.transposeChannel = transposeChannel;
462
-
463
- // CC
464
- MidiAudioChannel.prototype.controllerChange = controllerChange;
465
- MidiAudioChannel.prototype.resetControllers = resetControllers;
466
- MidiAudioChannel.prototype.resetControllersRP15Compliant = resetControllersRP15Compliant;
467
- MidiAudioChannel.prototype.resetParameters = resetParameters;
468
- MidiAudioChannel.prototype.dataEntryFine = dataEntryFine;
469
- MidiAudioChannel.prototype.dataEntryCoarse = dataEntryCoarse;
470
-
471
- export { MidiAudioChannel };
@@ -1,181 +0,0 @@
1
- import { timecentsToSeconds } from "./unit_converter.js";
2
- import { getModulatorCurveValue } from "./modulator_curves.js";
3
- import { generatorTypes } from "../../../soundfont/basic_soundfont/generator.js";
4
- import { modulatorCurveTypes } from "../../../soundfont/basic_soundfont/modulator.js";
5
-
6
- /**
7
- * modulation_envelope.js
8
- * purpose: calculates the modulation envelope for the given voice
9
- */
10
- const MODENV_PEAK = 1;
11
-
12
- // 1000 should be precise enough
13
- const CONVEX_ATTACK = new Float32Array(1000);
14
- for (let i = 0; i < CONVEX_ATTACK.length; i++)
15
- {
16
- // this makes the db linear (I think)
17
- CONVEX_ATTACK[i] = getModulatorCurveValue(0, modulatorCurveTypes.convex, i / 1000, 0);
18
- }
19
-
20
- export class ModulationEnvelope
21
- {
22
- /**
23
- * The attack duration, in seconds
24
- * @type {number}
25
- */
26
- attackDuration = 0;
27
- /**
28
- * The decay duration, in seconds
29
- * @type {number}
30
- */
31
- decayDuration = 0;
32
-
33
- /**
34
- * The hold duration, in seconds
35
- * @type {number}
36
- */
37
- holdDuration = 0;
38
-
39
- /**
40
- * Release duration, in seconds
41
- * @type {number}
42
- */
43
- releaseDuration = 0;
44
-
45
- /**
46
- * The sustain level 0-1
47
- * @type {number}
48
- */
49
- sustainLevel = 0;
50
-
51
- /**
52
- * Delay phase end time in seconds, absolute (audio context time)
53
- * @type {number}
54
- */
55
- delayEnd = 0;
56
- /**
57
- * Attack phase end time in seconds, absolute (audio context time)
58
- * @type {number}
59
- */
60
- attackEnd = 0;
61
- /**
62
- * Hold phase end time in seconds, absolute (audio context time)
63
- * @type {number}
64
- */
65
- holdEnd = 0;
66
- /**
67
- * Decay phase end time in seconds, absolute (audio context time)
68
- * @type {number}
69
- */
70
- decayEnd = 0;
71
-
72
- /**
73
- * The level of the envelope when the release phase starts
74
- * @type {number}
75
- */
76
- releaseStartLevel = 0;
77
-
78
- /**
79
- * The current modulation envelope value
80
- * @type {number}
81
- */
82
- currentValue = 0;
83
-
84
- /**
85
- * Starts the release phase in the envelope
86
- * @param voice {Voice} the voice this envelope belongs to
87
- */
88
- static startRelease(voice)
89
- {
90
- ModulationEnvelope.recalculate(voice);
91
- }
92
-
93
- /**
94
- * @param voice {Voice} the voice to recalculate
95
- */
96
- static recalculate(voice)
97
- {
98
- const env = voice.modulationEnvelope;
99
-
100
- // in release? Might need to recalculate the value as it can be modulated
101
- if (voice.isInRelease)
102
- {
103
- env.releaseStartLevel = ModulationEnvelope.getValue(voice, voice.releaseStartTime, true);
104
- }
105
-
106
- env.sustainLevel = 1 - (voice.modulatedGenerators[generatorTypes.sustainModEnv] / 1000);
107
-
108
- env.attackDuration = timecentsToSeconds(voice.modulatedGenerators[generatorTypes.attackModEnv]);
109
-
110
- const decayKeyExcursionCents = ((60 - voice.midiNote) * voice.modulatedGenerators[generatorTypes.keyNumToModEnvDecay]);
111
- const decayTime = timecentsToSeconds(voice.modulatedGenerators[generatorTypes.decayModEnv] + decayKeyExcursionCents);
112
- // according to the specification, the decay time is the time it takes to reach 0% from 100%.
113
- // calculate the time to reach actual sustain level,
114
- // for example, sustain 0.6 will be 0.4 of the decay time
115
- env.decayDuration = decayTime * (1 - env.sustainLevel);
116
-
117
- const holdKeyExcursionCents = ((60 - voice.midiNote) * voice.modulatedGenerators[generatorTypes.keyNumToModEnvHold]);
118
- env.holdDuration = timecentsToSeconds(holdKeyExcursionCents + voice.modulatedGenerators[generatorTypes.holdModEnv]);
119
-
120
- const releaseTime = timecentsToSeconds(voice.modulatedGenerators[generatorTypes.releaseModEnv]);
121
- // release time is from the full level to 0%
122
- // to get the actual time, multiply by the release start level
123
- env.releaseDuration = releaseTime * env.releaseStartLevel;
124
-
125
- env.delayEnd = voice.startTime + timecentsToSeconds(voice.modulatedGenerators[generatorTypes.delayModEnv]);
126
- env.attackEnd = env.delayEnd + env.attackDuration;
127
- env.holdEnd = env.attackEnd + env.holdDuration;
128
- env.decayEnd = env.holdEnd + env.decayDuration;
129
- }
130
-
131
- /**
132
- * Calculates the current modulation envelope value for the given time and voice
133
- * @param voice {Voice} the voice we are working on
134
- * @param currentTime {number} in seconds
135
- * @param ignoreRelease {boolean} if true, it will compute the value as if the voice was not released
136
- * @returns {number} modenv value, from 0 to 1
137
- */
138
- static getValue(voice, currentTime, ignoreRelease = false)
139
- {
140
- const env = voice.modulationEnvelope;
141
- if (voice.isInRelease && !ignoreRelease)
142
- {
143
- // if the voice is still in the delay phase,
144
- // start level will be 0 that will result in divide by zero
145
- if (env.releaseStartLevel === 0)
146
- {
147
- return 0;
148
- }
149
- return Math.max(
150
- 0,
151
- (1 - (currentTime - voice.releaseStartTime) / env.releaseDuration) * env.releaseStartLevel
152
- );
153
- }
154
-
155
- if (currentTime < env.delayEnd)
156
- {
157
- env.currentValue = 0; // delay
158
- }
159
- else if (currentTime < env.attackEnd)
160
- {
161
- // modulation envelope uses convex curve for attack
162
- env.currentValue = CONVEX_ATTACK[~~((1 - (env.attackEnd - currentTime) / env.attackDuration) * 1000)];
163
- }
164
- else if (currentTime < env.holdEnd)
165
- {
166
- // hold: stay at 1
167
- env.currentValue = MODENV_PEAK;
168
- }
169
- else if (currentTime < env.decayEnd)
170
- {
171
- // decay: linear ramp from 1 to sustain level
172
- env.currentValue = (1 - (env.decayEnd - currentTime) / env.decayDuration) * (env.sustainLevel - MODENV_PEAK) + MODENV_PEAK;
173
- }
174
- else
175
- {
176
- // sustain: stay at sustain level
177
- env.currentValue = env.sustainLevel;
178
- }
179
- return env.currentValue;
180
- }
181
- }