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.
- package/midi_parser/basic_midi.js +457 -68
- package/midi_parser/midi_loader.js +18 -503
- package/midi_parser/midi_message.js +18 -5
- package/midi_parser/midi_sequence.js +2 -2
- package/package.json +1 -1
- package/sequencer/worklet_sequencer/process_event.js +1 -6
- package/synthetizer/synthetizer.js +9 -6
- package/synthetizer/worklet_processor.min.js +12 -12
- package/synthetizer/worklet_system/README.md +2 -2
- package/synthetizer/worklet_system/main_processor.js +106 -95
- package/synthetizer/worklet_system/message_protocol/handle_message.js +22 -17
- package/synthetizer/worklet_system/message_protocol/worklet_message.js +2 -1
- package/synthetizer/worklet_system/snapshot/apply_synthesizer_snapshot.js +14 -0
- package/synthetizer/worklet_system/snapshot/channel_snapshot.js +166 -0
- package/synthetizer/worklet_system/snapshot/send_synthesizer_snapshot.js +14 -0
- package/synthetizer/worklet_system/snapshot/synthesizer_snapshot.js +121 -0
- package/synthetizer/worklet_system/worklet_methods/controller_control/controller_change.js +196 -0
- package/synthetizer/worklet_system/worklet_methods/controller_control/master_parameters.js +34 -0
- package/synthetizer/worklet_system/worklet_methods/{reset_controllers.js → controller_control/reset_controllers.js} +33 -39
- package/synthetizer/worklet_system/worklet_methods/create_worklet_channel.js +26 -0
- package/synthetizer/worklet_system/worklet_methods/{data_entry.js → data_entry/data_entry_coarse.js} +38 -105
- package/synthetizer/worklet_system/worklet_methods/data_entry/data_entry_fine.js +64 -0
- package/synthetizer/worklet_system/worklet_methods/mute_channel.js +17 -0
- package/synthetizer/worklet_system/worklet_methods/note_on.js +36 -34
- package/synthetizer/worklet_system/worklet_methods/program_change.js +49 -0
- package/synthetizer/worklet_system/worklet_methods/{voice_control.js → render_voice.js} +37 -120
- package/synthetizer/worklet_system/worklet_methods/soundfont_management/clear_sound_font.js +35 -0
- package/synthetizer/worklet_system/worklet_methods/soundfont_management/get_preset.js +20 -0
- package/synthetizer/worklet_system/worklet_methods/soundfont_management/reload_sound_font.js +43 -0
- package/synthetizer/worklet_system/worklet_methods/soundfont_management/send_preset_list.js +31 -0
- package/synthetizer/worklet_system/worklet_methods/soundfont_management/set_embedded_sound_font.js +21 -0
- package/synthetizer/worklet_system/worklet_methods/stopping_notes/kill_note.js +19 -0
- package/synthetizer/worklet_system/worklet_methods/stopping_notes/note_off.js +51 -0
- package/synthetizer/worklet_system/worklet_methods/stopping_notes/stop_all_channels.js +16 -0
- package/synthetizer/worklet_system/worklet_methods/stopping_notes/stop_all_notes.js +30 -0
- package/synthetizer/worklet_system/worklet_methods/stopping_notes/voice_killing.js +63 -0
- package/synthetizer/worklet_system/worklet_methods/system_exclusive.js +31 -30
- package/synthetizer/worklet_system/worklet_methods/tuning_control/channel_pressure.js +24 -0
- package/synthetizer/worklet_system/worklet_methods/tuning_control/pitch_wheel.js +33 -0
- package/synthetizer/worklet_system/worklet_methods/tuning_control/poly_pressure.js +31 -0
- package/synthetizer/worklet_system/worklet_methods/tuning_control/set_master_tuning.js +15 -0
- package/synthetizer/worklet_system/worklet_methods/tuning_control/set_modulation_depth.js +27 -0
- package/synthetizer/worklet_system/worklet_methods/tuning_control/set_octave_tuning.js +15 -0
- package/synthetizer/worklet_system/worklet_methods/tuning_control/set_tuning.js +24 -0
- package/synthetizer/worklet_system/worklet_methods/tuning_control/set_tuning_semitones.js +19 -0
- package/synthetizer/worklet_system/worklet_methods/tuning_control/transpose_all_channels.js +15 -0
- package/synthetizer/worklet_system/worklet_methods/tuning_control/transpose_channel.js +31 -0
- package/synthetizer/worklet_system/worklet_utilities/controller_tables.js +10 -1
- package/synthetizer/worklet_system/worklet_utilities/lfo.js +2 -1
- package/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +4 -4
- package/synthetizer/worklet_system/worklet_utilities/modulator_curves.js +4 -5
- package/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +18 -18
- package/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +210 -206
- package/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +354 -108
- package/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +22 -9
- package/synthetizer/worklet_system/snapshot/snapshot.js +0 -311
- package/synthetizer/worklet_system/worklet_methods/controller_control.js +0 -260
- package/synthetizer/worklet_system/worklet_methods/note_off.js +0 -119
- package/synthetizer/worklet_system/worklet_methods/program_control.js +0 -282
- package/synthetizer/worklet_system/worklet_methods/tuning_control.js +0 -233
- 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 "
|
|
2
|
-
import { DEFAULT_PERCUSSION, DEFAULT_SYNTH_MODE } from "
|
|
3
|
-
import { SpessaSynthInfo } from "
|
|
4
|
-
import { modulatorSources } from "
|
|
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 "
|
|
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(
|
|
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(
|
|
38
|
+
ch.setBankSelect(0);
|
|
39
39
|
if (channelNumber % 16 === DEFAULT_PERCUSSION)
|
|
40
40
|
{
|
|
41
|
-
this.setPreset(
|
|
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
|
-
|
|
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(
|
|
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
|
-
* @
|
|
116
|
-
* @this {SpessaSynthProcessor}
|
|
115
|
+
* @this {WorkletProcessorChannel}
|
|
117
116
|
*/
|
|
118
|
-
export function resetControllers(
|
|
117
|
+
export function resetControllers()
|
|
119
118
|
{
|
|
120
|
-
|
|
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 (
|
|
125
|
+
if (this.lockedControllers[i])
|
|
129
126
|
{
|
|
130
127
|
return;
|
|
131
128
|
}
|
|
132
129
|
const resetValue = resetArray[i];
|
|
133
|
-
if (
|
|
130
|
+
if (this.midiControllers[i] !== resetValue && i < 127)
|
|
134
131
|
{
|
|
135
132
|
// call cc change if reset
|
|
136
|
-
this.callEvent("controllerchange", {
|
|
137
|
-
channel:
|
|
133
|
+
this.synth.callEvent("controllerchange", {
|
|
134
|
+
channel: this.channelNumber,
|
|
138
135
|
controllerNumber: i,
|
|
139
136
|
controllerValue: resetValue >> 7
|
|
140
137
|
});
|
|
141
138
|
}
|
|
142
|
-
|
|
139
|
+
this.midiControllers[i] = resetValue;
|
|
143
140
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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 =
|
|
151
|
-
|
|
152
|
-
|
|
147
|
+
const transpose = this.customControllers[customControllers.channelTransposeFine];
|
|
148
|
+
this.customControllers.set(customResetArray);
|
|
149
|
+
this.customControllers[customControllers.channelTransposeFine] = transpose;
|
|
153
150
|
|
|
154
|
-
this.resetParameters(
|
|
151
|
+
this.resetParameters();
|
|
155
152
|
|
|
156
153
|
}
|
|
157
154
|
|
|
158
155
|
/**
|
|
159
|
-
* @
|
|
160
|
-
* @this {SpessaSynthProcessor}
|
|
156
|
+
* @this {WorkletProcessorChannel}
|
|
161
157
|
*/
|
|
162
|
-
export function resetParameters(
|
|
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
|
-
|
|
164
|
+
this.NRPCoarse = 0;
|
|
171
165
|
/**
|
|
172
166
|
* @type {number}
|
|
173
167
|
*/
|
|
174
|
-
|
|
168
|
+
this.NRPFine = 0;
|
|
175
169
|
/**
|
|
176
170
|
* @type {number}
|
|
177
171
|
*/
|
|
178
|
-
|
|
172
|
+
this.RPValue = 0;
|
|
179
173
|
/**
|
|
180
174
|
* @type {string}
|
|
181
175
|
*/
|
|
182
|
-
|
|
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
|
+
}
|