spessasynth_lib 3.24.13 → 3.24.15

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 (61) hide show
  1. package/midi_parser/basic_midi.js +457 -68
  2. package/midi_parser/midi_loader.js +18 -503
  3. package/midi_parser/midi_message.js +18 -5
  4. package/midi_parser/midi_sequence.js +2 -2
  5. package/package.json +1 -1
  6. package/sequencer/worklet_sequencer/process_event.js +1 -6
  7. package/synthetizer/synthetizer.js +9 -6
  8. package/synthetizer/worklet_processor.min.js +12 -12
  9. package/synthetizer/worklet_system/README.md +2 -2
  10. package/synthetizer/worklet_system/main_processor.js +106 -95
  11. package/synthetizer/worklet_system/message_protocol/handle_message.js +22 -17
  12. package/synthetizer/worklet_system/message_protocol/worklet_message.js +2 -1
  13. package/synthetizer/worklet_system/snapshot/apply_synthesizer_snapshot.js +14 -0
  14. package/synthetizer/worklet_system/snapshot/channel_snapshot.js +166 -0
  15. package/synthetizer/worklet_system/snapshot/send_synthesizer_snapshot.js +14 -0
  16. package/synthetizer/worklet_system/snapshot/synthesizer_snapshot.js +121 -0
  17. package/synthetizer/worklet_system/worklet_methods/controller_control/controller_change.js +196 -0
  18. package/synthetizer/worklet_system/worklet_methods/controller_control/master_parameters.js +34 -0
  19. package/synthetizer/worklet_system/worklet_methods/{reset_controllers.js → controller_control/reset_controllers.js} +33 -39
  20. package/synthetizer/worklet_system/worklet_methods/create_worklet_channel.js +26 -0
  21. package/synthetizer/worklet_system/worklet_methods/{data_entry.js → data_entry/data_entry_coarse.js} +38 -105
  22. package/synthetizer/worklet_system/worklet_methods/data_entry/data_entry_fine.js +64 -0
  23. package/synthetizer/worklet_system/worklet_methods/mute_channel.js +17 -0
  24. package/synthetizer/worklet_system/worklet_methods/note_on.js +36 -34
  25. package/synthetizer/worklet_system/worklet_methods/program_change.js +49 -0
  26. package/synthetizer/worklet_system/worklet_methods/{voice_control.js → render_voice.js} +37 -120
  27. package/synthetizer/worklet_system/worklet_methods/soundfont_management/clear_sound_font.js +35 -0
  28. package/synthetizer/worklet_system/worklet_methods/soundfont_management/get_preset.js +20 -0
  29. package/synthetizer/worklet_system/worklet_methods/soundfont_management/reload_sound_font.js +43 -0
  30. package/synthetizer/worklet_system/worklet_methods/soundfont_management/send_preset_list.js +31 -0
  31. package/synthetizer/worklet_system/worklet_methods/soundfont_management/set_embedded_sound_font.js +21 -0
  32. package/synthetizer/worklet_system/worklet_methods/stopping_notes/kill_note.js +19 -0
  33. package/synthetizer/worklet_system/worklet_methods/stopping_notes/note_off.js +51 -0
  34. package/synthetizer/worklet_system/worklet_methods/stopping_notes/stop_all_channels.js +16 -0
  35. package/synthetizer/worklet_system/worklet_methods/stopping_notes/stop_all_notes.js +30 -0
  36. package/synthetizer/worklet_system/worklet_methods/stopping_notes/voice_killing.js +63 -0
  37. package/synthetizer/worklet_system/worklet_methods/system_exclusive.js +31 -30
  38. package/synthetizer/worklet_system/worklet_methods/tuning_control/channel_pressure.js +24 -0
  39. package/synthetizer/worklet_system/worklet_methods/tuning_control/pitch_wheel.js +33 -0
  40. package/synthetizer/worklet_system/worklet_methods/tuning_control/poly_pressure.js +31 -0
  41. package/synthetizer/worklet_system/worklet_methods/tuning_control/set_master_tuning.js +15 -0
  42. package/synthetizer/worklet_system/worklet_methods/tuning_control/set_modulation_depth.js +27 -0
  43. package/synthetizer/worklet_system/worklet_methods/tuning_control/set_octave_tuning.js +15 -0
  44. package/synthetizer/worklet_system/worklet_methods/tuning_control/set_tuning.js +24 -0
  45. package/synthetizer/worklet_system/worklet_methods/tuning_control/set_tuning_semitones.js +19 -0
  46. package/synthetizer/worklet_system/worklet_methods/tuning_control/transpose_all_channels.js +15 -0
  47. package/synthetizer/worklet_system/worklet_methods/tuning_control/transpose_channel.js +31 -0
  48. package/synthetizer/worklet_system/worklet_utilities/controller_tables.js +10 -1
  49. package/synthetizer/worklet_system/worklet_utilities/lfo.js +2 -1
  50. package/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +4 -4
  51. package/synthetizer/worklet_system/worklet_utilities/modulator_curves.js +4 -5
  52. package/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +18 -18
  53. package/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +210 -206
  54. package/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +354 -108
  55. package/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +22 -9
  56. package/synthetizer/worklet_system/snapshot/snapshot.js +0 -311
  57. package/synthetizer/worklet_system/worklet_methods/controller_control.js +0 -260
  58. package/synthetizer/worklet_system/worklet_methods/note_off.js +0 -119
  59. package/synthetizer/worklet_system/worklet_methods/program_control.js +0 -282
  60. package/synthetizer/worklet_system/worklet_methods/tuning_control.js +0 -233
  61. package/synthetizer/worklet_system/worklet_methods/vibrato_control.js +0 -29
@@ -0,0 +1,121 @@
1
+ import { SpessaSynthInfo } from "../../../utils/loggin.js";
2
+ import { consoleColors } from "../../../utils/other.js";
3
+ import { ChannelSnapshot } from "./channel_snapshot.js";
4
+
5
+ /**
6
+ * Represents a snapshot of the synthesizer's state.
7
+ */
8
+ export class SynthesizerSnapshot
9
+ {
10
+ /**
11
+ * The individual channel snapshots.
12
+ * @type {ChannelSnapshot[]}
13
+ */
14
+ channelSnapshots;
15
+
16
+ /**
17
+ * Key modifiers.
18
+ * @type {KeyModifier[][]}
19
+ */
20
+ keyMappings;
21
+
22
+ /**
23
+ * Main synth volume (set by MIDI), from 0 to 1.
24
+ * @type {number}
25
+ */
26
+ mainVolume;
27
+
28
+ /**
29
+ * Master stereo panning, from -1 to 1.
30
+ * @type {number}
31
+ */
32
+ pan;
33
+
34
+ /**
35
+ * The synth's interpolation type.
36
+ * @type {interpolationTypes}
37
+ */
38
+ interpolation;
39
+
40
+ /**
41
+ * The synth's system. Values can be "gs", "gm", "gm2" or "xg".
42
+ * @type {SynthSystem}
43
+ */
44
+ system;
45
+
46
+ /**
47
+ * The current synth transposition in semitones. Can be a float.
48
+ * @type {number}
49
+ */
50
+ transposition;
51
+
52
+ /**
53
+ * The effect configuration object.
54
+ * @type {SynthConfig}
55
+ */
56
+ effectsConfig;
57
+
58
+
59
+ /**
60
+ * Creates a snapshot of the synthesizer's state.
61
+ * @param workletProcessor {SpessaSynthProcessor}
62
+ * @returns {SynthesizerSnapshot}
63
+ */
64
+ static createSynthesizerSnapshot(workletProcessor)
65
+ {
66
+ const snapshot = new SynthesizerSnapshot();
67
+ // channel snapshots
68
+ snapshot.channelSnapshots =
69
+ workletProcessor.workletProcessorChannels.map((_, i) =>
70
+ ChannelSnapshot.getChannelSnapshot(workletProcessor, i));
71
+
72
+ // key mappings
73
+ snapshot.keyMappings = workletProcessor.keyModifierManager.getMappings();
74
+ // pan and volume
75
+ snapshot.mainVolume = workletProcessor.midiVolume;
76
+ snapshot.pan = workletProcessor.pan;
77
+
78
+ // others
79
+ snapshot.system = workletProcessor.system;
80
+ snapshot.interpolation = workletProcessor.interpolationType;
81
+ snapshot.transposition = workletProcessor.transposition;
82
+
83
+ // effect config is stored on the main thread, leave it empty
84
+ snapshot.effectsConfig = {};
85
+ return snapshot;
86
+
87
+ }
88
+
89
+ /**
90
+ * Applies the snapshot to the synthesizer.
91
+ * @param workletProcessor {SpessaSynthProcessor}
92
+ * @param snapshot {SynthesizerSnapshot}
93
+ */
94
+ static applySnapshot(workletProcessor, snapshot)
95
+ {
96
+ // restore system
97
+ workletProcessor.system = snapshot.system;
98
+
99
+ // restore pan and volume
100
+ workletProcessor.setMasterGain(snapshot.mainVolume);
101
+ workletProcessor.setMasterPan(snapshot.pan);
102
+ workletProcessor.transposeAllChannels(snapshot.transposition);
103
+ workletProcessor.interpolationType = snapshot.interpolation;
104
+ workletProcessor.keyModifierManager.setMappings(snapshot.keyMappings);
105
+
106
+ // add channels if more needed
107
+ while (workletProcessor.workletProcessorChannels.length < snapshot.channelSnapshots.length)
108
+ {
109
+ workletProcessor.createWorkletChannel();
110
+ }
111
+
112
+ // restore channels
113
+ snapshot.channelSnapshots.forEach((channelSnapshot, index) =>
114
+ {
115
+ ChannelSnapshot.applyChannelSnapshot(workletProcessor, index, channelSnapshot);
116
+ });
117
+
118
+ SpessaSynthInfo("%cFinished restoring controllers!", consoleColors.info);
119
+ }
120
+ }
121
+
@@ -0,0 +1,196 @@
1
+ import { SpessaSynthInfo } from "../../../../utils/loggin.js";
2
+ import { midiControllers } from "../../../../midi_parser/midi_message.js";
3
+ import { computeModulators } from "../../worklet_utilities/worklet_modulator.js";
4
+ import { consoleColors } from "../../../../utils/other.js";
5
+ import { DEFAULT_PERCUSSION } from "../../../synthetizer.js";
6
+ import { channelConfiguration, dataEntryStates } from "../../worklet_utilities/controller_tables.js";
7
+
8
+ /**
9
+ * @param controllerNumber {number}
10
+ * @param controllerValue {number}
11
+ * @param force {boolean}
12
+ * @this {WorkletProcessorChannel}
13
+ */
14
+ export function controllerChange(controllerNumber, controllerValue, force = false)
15
+ {
16
+ if (controllerNumber > 127)
17
+ {
18
+ // channel configuration. force must be set to true
19
+ if (!force)
20
+ {
21
+ return;
22
+ }
23
+ switch (controllerNumber)
24
+ {
25
+ default:
26
+ return;
27
+
28
+ case channelConfiguration.velocityOverride:
29
+ this.velocityOverride = controllerValue;
30
+ }
31
+ }
32
+
33
+ // lsb controller values: append them as the lower nibble of the 14-bit value
34
+ // excluding bank select and data entry as it's handled separately
35
+ if (
36
+ controllerNumber >= midiControllers.lsbForControl1ModulationWheel
37
+ && controllerNumber <= midiControllers.lsbForControl13EffectControl2
38
+ && controllerNumber !== midiControllers.lsbForControl6DataEntry
39
+ )
40
+ {
41
+ const actualCCNum = controllerNumber - 32;
42
+ if (this.lockedControllers[actualCCNum])
43
+ {
44
+ return;
45
+ }
46
+ // append the lower nibble to the main controller
47
+ this.midiControllers[actualCCNum] = (this.midiControllers[actualCCNum] & 0x3F80) | (controllerValue & 0x7F);
48
+ this.voices.forEach(v => computeModulators(v, this.midiControllers, 1, actualCCNum));
49
+ }
50
+ switch (controllerNumber)
51
+ {
52
+ case midiControllers.allNotesOff:
53
+ this.stopAllNotes();
54
+ break;
55
+
56
+ case midiControllers.allSoundOff:
57
+ this.stopAllNotes(true);
58
+ break;
59
+
60
+ // special case: bank select
61
+ case midiControllers.bankSelect:
62
+ let bankNr = controllerValue;
63
+ if (!force)
64
+ {
65
+ switch (this.synth.system)
66
+ {
67
+ case "gm":
68
+ // gm ignores bank select
69
+ SpessaSynthInfo(
70
+ `%cIgnoring the Bank Select (${controllerValue}), as the synth is in GM mode.`,
71
+ consoleColors.info
72
+ );
73
+ return;
74
+
75
+ case "xg":
76
+ // for xg, if msb is 120, 126 or 127, then it's drums
77
+ if (bankNr === 120 || bankNr === 126 || bankNr === 127)
78
+ {
79
+ this.setDrums(true);
80
+ }
81
+ else
82
+ {
83
+ // drums shall not be disabled on channel 9
84
+ if (this.channelNumber % 16 !== DEFAULT_PERCUSSION)
85
+ {
86
+ this.setDrums(false);
87
+ }
88
+ }
89
+ break;
90
+
91
+ case "gm2":
92
+ if (bankNr === 120)
93
+ {
94
+ this.setDrums(true);
95
+ }
96
+ }
97
+
98
+ if (this.drumChannel)
99
+ {
100
+ // 128 for percussion channel
101
+ bankNr = 128;
102
+ }
103
+ if (bankNr === 128 && !this.drumChannel)
104
+ {
105
+ // if a channel is not for percussion, default to bank current
106
+ bankNr = this.getBankSelect();
107
+ }
108
+ }
109
+
110
+ this.setBankSelect(bankNr);
111
+ break;
112
+
113
+ case midiControllers.lsbForControl0BankSelect:
114
+ if (this.synth.system === "xg")
115
+ {
116
+ if (!this.drumChannel)
117
+ {
118
+ // some soundfonts use 127 as drums and
119
+ // if it's not marked as drums by bank MSB (line 47), then we DO NOT want the drums!
120
+ if (controllerValue !== 127)
121
+ {
122
+ this.setBankSelect(controllerValue);
123
+ }
124
+ }
125
+ }
126
+ else if (this.synth.system === "gm2")
127
+ {
128
+ this.setBankSelect(controllerValue);
129
+ }
130
+ break;
131
+
132
+ // check for RPN and NPRN and data entry
133
+ case midiControllers.RPNLsb:
134
+ this.RPValue = this.RPValue << 7 | controllerValue;
135
+ this.dataEntryState = dataEntryStates.RPFine;
136
+ break;
137
+
138
+ case midiControllers.RPNMsb:
139
+ this.RPValue = controllerValue;
140
+ this.dataEntryState = dataEntryStates.RPCoarse;
141
+ break;
142
+
143
+ case midiControllers.NRPNMsb:
144
+ this.NRPCoarse = controllerValue;
145
+ this.dataEntryState = dataEntryStates.NRPCoarse;
146
+ break;
147
+
148
+ case midiControllers.NRPNLsb:
149
+ this.NRPFine = controllerValue;
150
+ this.dataEntryState = dataEntryStates.NRPFine;
151
+ break;
152
+
153
+ case midiControllers.dataEntryMsb:
154
+ this.dataEntryCoarse(controllerValue);
155
+ break;
156
+
157
+ case midiControllers.lsbForControl6DataEntry:
158
+ this.dataEntryFine(controllerValue);
159
+ break;
160
+
161
+ case midiControllers.resetAllControllers:
162
+ this.resetControllers();
163
+ break;
164
+
165
+ case midiControllers.sustainPedal:
166
+ if (controllerValue >= 64)
167
+ {
168
+ this.holdPedal = true;
169
+ }
170
+ else
171
+ {
172
+ this.holdPedal = false;
173
+ this.sustainedVoices.forEach(v =>
174
+ {
175
+ v.release();
176
+ });
177
+ this.sustainedVoices = [];
178
+ }
179
+ break;
180
+
181
+ // default: apply the controller to the table
182
+ default:
183
+ if (this.lockedControllers[controllerNumber])
184
+ {
185
+ return;
186
+ }
187
+ this.midiControllers[controllerNumber] = controllerValue << 7;
188
+ this.voices.forEach(v => computeModulators(v, this.midiControllers, 1, controllerNumber));
189
+ break;
190
+ }
191
+ this.synth.callEvent("controllerchange", {
192
+ channel: this.channelNumber,
193
+ controllerNumber: controllerNumber,
194
+ controllerValue: controllerValue
195
+ });
196
+ }
@@ -0,0 +1,34 @@
1
+ import { SYNTHESIZER_GAIN } from "../../main_processor.js";
2
+
3
+ /**
4
+ * @param volume {number} 0 to 1
5
+ * @this {SpessaSynthProcessor}
6
+ */
7
+ export function setMIDIVolume(volume)
8
+ {
9
+ this.midiVolume = volume;
10
+ this.setMasterPan(this.pan);
11
+ }
12
+
13
+ /**
14
+ * @param volume {number} 0-1
15
+ * @this {SpessaSynthProcessor}
16
+ */
17
+ export function setMasterGain(volume)
18
+ {
19
+ this.masterGain = volume * SYNTHESIZER_GAIN;
20
+ this.setMasterPan(this.pan);
21
+ }
22
+
23
+ /**
24
+ * @param pan {number} -1 to one
25
+ * @this {SpessaSynthProcessor}
26
+ */
27
+ export function setMasterPan(pan)
28
+ {
29
+ this.pan = pan;
30
+ // clamp to 0-1 (0 is left)
31
+ pan = (pan / 2) + 0.5;
32
+ this.panLeft = (1 - pan);
33
+ this.panRight = (pan);
34
+ }
@@ -1,17 +1,17 @@
1
- import { consoleColors } from "../../../utils/other.js";
2
- import { DEFAULT_PERCUSSION, DEFAULT_SYNTH_MODE } from "../../synthetizer.js";
3
- import { SpessaSynthInfo } from "../../../utils/loggin.js";
4
- import { modulatorSources } from "../../../soundfont/basic_soundfont/modulator.js";
1
+ import { consoleColors } from "../../../../utils/other.js";
2
+ import { DEFAULT_PERCUSSION, DEFAULT_SYNTH_MODE } from "../../../synthetizer.js";
3
+ import { SpessaSynthInfo } from "../../../../utils/loggin.js";
4
+ import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulator.js";
5
5
  import {
6
6
  customControllers,
7
7
  customResetArray,
8
8
  dataEntryStates,
9
9
  NON_CC_INDEX_OFFSET,
10
10
  resetArray
11
- } from "../worklet_utilities/controller_tables.js";
12
- import { getBankSelect, setBankSelect } from "../worklet_utilities/worklet_processor_channel.js";
11
+ } from "../../worklet_utilities/controller_tables.js";
13
12
 
14
13
  /**
14
+ * Full system reset
15
15
  * @this {SpessaSynthProcessor}
16
16
  * @param log {boolean}
17
17
  */
@@ -24,7 +24,7 @@ export function resetAllControllers(log = true)
24
24
  this.callEvent("allcontrollerreset", undefined);
25
25
  for (let channelNumber = 0; channelNumber < this.workletProcessorChannels.length; channelNumber++)
26
26
  {
27
- this.resetControllers(channelNumber);
27
+ this.workletProcessorChannels[channelNumber].resetControllers();
28
28
 
29
29
  /**
30
30
  * @type {WorkletProcessorChannel}
@@ -35,10 +35,10 @@ export function resetAllControllers(log = true)
35
35
  if (!ch.lockPreset)
36
36
  {
37
37
  ch.presetUsesOverride = true;
38
- setBankSelect(ch, 0);
38
+ ch.setBankSelect(0);
39
39
  if (channelNumber % 16 === DEFAULT_PERCUSSION)
40
40
  {
41
- this.setPreset(channelNumber, this.drumPreset);
41
+ this.workletProcessorChannels[channelNumber].setPreset(this.drumPreset);
42
42
  ch.drumChannel = true;
43
43
  this.callEvent("drumchange", {
44
44
  channel: channelNumber,
@@ -48,7 +48,7 @@ export function resetAllControllers(log = true)
48
48
  else
49
49
  {
50
50
  ch.drumChannel = false;
51
- this.setPreset(channelNumber, this.defaultPreset);
51
+ ch.setPreset(this.defaultPreset);
52
52
  this.callEvent("drumchange", {
53
53
  channel: channelNumber,
54
54
  isDrumChannel: false
@@ -67,7 +67,7 @@ export function resetAllControllers(log = true)
67
67
  this.callEvent("programchange", {
68
68
  channel: channelNumber,
69
69
  program: ch.preset.program,
70
- bank: getBankSelect(ch),
70
+ bank: ch.getBankSelect(),
71
71
  userCalled: false
72
72
  });
73
73
 
@@ -112,72 +112,66 @@ export function resetAllControllers(log = true)
112
112
 
113
113
  /**
114
114
  * Resets all controllers for channel
115
- * @param channel {number}
116
- * @this {SpessaSynthProcessor}
115
+ * @this {WorkletProcessorChannel}
117
116
  */
118
- export function resetControllers(channel)
117
+ export function resetControllers()
119
118
  {
120
- const channelObject = this.workletProcessorChannels[channel];
121
-
122
- channelObject.channelOctaveTuning.fill(0);
123
- channelObject.keyCentTuning.fill(0);
119
+ this.channelOctaveTuning.fill(0);
120
+ this.keyCentTuning.fill(0);
124
121
 
125
122
  // reset the array
126
123
  for (let i = 0; i < resetArray.length; i++)
127
124
  {
128
- if (channelObject.lockedControllers[i])
125
+ if (this.lockedControllers[i])
129
126
  {
130
127
  return;
131
128
  }
132
129
  const resetValue = resetArray[i];
133
- if (channelObject.midiControllers[i] !== resetValue && i < 127)
130
+ if (this.midiControllers[i] !== resetValue && i < 127)
134
131
  {
135
132
  // call cc change if reset
136
- this.callEvent("controllerchange", {
137
- channel: channel,
133
+ this.synth.callEvent("controllerchange", {
134
+ channel: this.channelNumber,
138
135
  controllerNumber: i,
139
136
  controllerValue: resetValue >> 7
140
137
  });
141
138
  }
142
- channelObject.midiControllers[i] = resetValue;
139
+ this.midiControllers[i] = resetValue;
143
140
  }
144
- channelObject.channelVibrato = { rate: 0, depth: 0, delay: 0 };
145
- channelObject.holdPedal = false;
146
- channelObject.randomPan = false;
141
+ this.channelVibrato = { rate: 0, depth: 0, delay: 0 };
142
+ this.holdPedal = false;
143
+ this.randomPan = false;
147
144
 
148
145
  // reset custom controllers
149
146
  // special case: transpose does not get affected
150
- const transpose = channelObject.customControllers[customControllers.channelTransposeFine];
151
- channelObject.customControllers.set(customResetArray);
152
- channelObject.customControllers[customControllers.channelTransposeFine] = transpose;
147
+ const transpose = this.customControllers[customControllers.channelTransposeFine];
148
+ this.customControllers.set(customResetArray);
149
+ this.customControllers[customControllers.channelTransposeFine] = transpose;
153
150
 
154
- this.resetParameters(channel);
151
+ this.resetParameters();
155
152
 
156
153
  }
157
154
 
158
155
  /**
159
- * @param channel {number}
160
- * @this {SpessaSynthProcessor}
156
+ * @this {WorkletProcessorChannel}
161
157
  */
162
- export function resetParameters(channel)
158
+ export function resetParameters()
163
159
  {
164
- const channelObject = this.workletProcessorChannels[channel];
165
-
166
160
  // reset parameters
167
161
  /**
168
162
  * @type {number}
169
163
  */
170
- channelObject.NRPCoarse = 0;
164
+ this.NRPCoarse = 0;
171
165
  /**
172
166
  * @type {number}
173
167
  */
174
- channelObject.NRPFine = 0;
168
+ this.NRPFine = 0;
175
169
  /**
176
170
  * @type {number}
177
171
  */
178
- channelObject.RPValue = 0;
172
+ this.RPValue = 0;
179
173
  /**
180
174
  * @type {string}
181
175
  */
182
- channelObject.dataEntryState = dataEntryStates.Idle;
176
+ this.dataEntryState = dataEntryStates.Idle;
183
177
  }
@@ -0,0 +1,26 @@
1
+ import { WorkletProcessorChannel } from "../worklet_utilities/worklet_processor_channel.js";
2
+ import { DEFAULT_PERCUSSION } from "../../synthetizer.js";
3
+
4
+ /**
5
+ * @param sendEvent {boolean}
6
+ * @this {SpessaSynthProcessor}
7
+ */
8
+ export function createWorkletChannel(sendEvent = false)
9
+ {
10
+ /**
11
+ * @type {WorkletProcessorChannel}
12
+ */
13
+ const channel = new WorkletProcessorChannel(this, this.defaultPreset, this.workletProcessorChannels.length);
14
+ this.workletProcessorChannels.push(channel);
15
+ channel.resetControllers();
16
+ this.sendChannelProperties();
17
+ if (sendEvent)
18
+ {
19
+ this.callEvent("newchannel", undefined);
20
+ }
21
+
22
+ if (channel.channelNumber % 16 === DEFAULT_PERCUSSION)
23
+ {
24
+ this.workletProcessorChannels[this.workletProcessorChannels.length - 1].setDrums(true);
25
+ }
26
+ }