spessasynth_lib 3.24.13 → 3.24.16
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 +13 -7
- 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 +20 -0
- package/synthetizer/worklet_system/worklet_methods/stopping_notes/note_off.js +55 -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
|
@@ -1,282 +0,0 @@
|
|
|
1
|
-
import { returnMessageType } from "../message_protocol/worklet_message.js";
|
|
2
|
-
import { SpessaSynthInfo, SpessaSynthWarn } from "../../../utils/loggin.js";
|
|
3
|
-
import { consoleColors } from "../../../utils/other.js";
|
|
4
|
-
import { loadSoundFont } from "../../../soundfont/load_soundfont.js";
|
|
5
|
-
import { getBankSelect } from "../worklet_utilities/worklet_processor_channel.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* executes a program change
|
|
9
|
-
* @param channel {number}
|
|
10
|
-
* @param programNumber {number}
|
|
11
|
-
* @param userChange {boolean}
|
|
12
|
-
* @this {SpessaSynthProcessor}
|
|
13
|
-
*/
|
|
14
|
-
export function programChange(channel, programNumber, userChange = false)
|
|
15
|
-
{
|
|
16
|
-
/**
|
|
17
|
-
* @type {WorkletProcessorChannel}
|
|
18
|
-
*/
|
|
19
|
-
const channelObject = this.workletProcessorChannels[channel];
|
|
20
|
-
if (channelObject === undefined)
|
|
21
|
-
{
|
|
22
|
-
SpessaSynthWarn(`Trying to access channel ${channel} which does not exist... ignoring!`);
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
if (channelObject.lockPreset)
|
|
26
|
-
{
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
// always 128 for percussion
|
|
30
|
-
const bank = getBankSelect(channelObject);
|
|
31
|
-
let sentBank;
|
|
32
|
-
let preset;
|
|
33
|
-
|
|
34
|
-
// check if override
|
|
35
|
-
if (this.overrideSoundfont)
|
|
36
|
-
{
|
|
37
|
-
const bankWithOffset = bank === 128 ? 128 : bank - this.soundfontBankOffset;
|
|
38
|
-
const p = this.overrideSoundfont.getPresetNoFallback(bankWithOffset, programNumber);
|
|
39
|
-
if (p)
|
|
40
|
-
{
|
|
41
|
-
sentBank = bank;
|
|
42
|
-
preset = p;
|
|
43
|
-
channelObject.presetUsesOverride = true;
|
|
44
|
-
}
|
|
45
|
-
else
|
|
46
|
-
{
|
|
47
|
-
preset = this.soundfontManager.getPreset(bank, programNumber);
|
|
48
|
-
sentBank = preset.bank;
|
|
49
|
-
channelObject.presetUsesOverride = false;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
else
|
|
53
|
-
{
|
|
54
|
-
preset = this.soundfontManager.getPreset(bank, programNumber);
|
|
55
|
-
sentBank = preset.bank;
|
|
56
|
-
channelObject.presetUsesOverride = false;
|
|
57
|
-
}
|
|
58
|
-
this.setPreset(channel, preset);
|
|
59
|
-
this.callEvent("programchange", {
|
|
60
|
-
channel: channel,
|
|
61
|
-
program: preset.program,
|
|
62
|
-
bank: sentBank,
|
|
63
|
-
userCalled: userChange
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* @this {SpessaSynthProcessor}
|
|
69
|
-
* @param program {number}
|
|
70
|
-
* @param bank {number}
|
|
71
|
-
* @returns {BasicPreset}
|
|
72
|
-
*/
|
|
73
|
-
export function getPreset(bank, program)
|
|
74
|
-
{
|
|
75
|
-
if (this.overrideSoundfont)
|
|
76
|
-
{
|
|
77
|
-
// if overriden soundfont
|
|
78
|
-
const bankWithOffset = bank === 128 ? 128 : bank - this.soundfontBankOffset;
|
|
79
|
-
const preset = this.overrideSoundfont.getPresetNoFallback(bankWithOffset, program);
|
|
80
|
-
if (preset)
|
|
81
|
-
{
|
|
82
|
-
return preset;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return this.soundfontManager.getPreset(bank, program);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* @param channel {number}
|
|
91
|
-
* @param preset {BasicPreset}
|
|
92
|
-
* @this {SpessaSynthProcessor}
|
|
93
|
-
*/
|
|
94
|
-
export function setPreset(channel, preset)
|
|
95
|
-
{
|
|
96
|
-
if (this.workletProcessorChannels[channel].lockPreset)
|
|
97
|
-
{
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
delete this.workletProcessorChannels[channel].preset;
|
|
101
|
-
this.workletProcessorChannels[channel].preset = preset;
|
|
102
|
-
|
|
103
|
-
// reset cached voices
|
|
104
|
-
this.workletProcessorChannels[channel].cachedVoices = [];
|
|
105
|
-
for (let i = 0; i < 128; i++)
|
|
106
|
-
{
|
|
107
|
-
this.workletProcessorChannels[channel].cachedVoices.push([]);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Toggles drums on a given channel
|
|
113
|
-
* @param channel {number}
|
|
114
|
-
* @param isDrum {boolean}
|
|
115
|
-
* @this {SpessaSynthProcessor}
|
|
116
|
-
*/
|
|
117
|
-
export function setDrums(channel, isDrum)
|
|
118
|
-
{
|
|
119
|
-
const channelObject = this.workletProcessorChannels[channel];
|
|
120
|
-
if (channelObject.lockPreset)
|
|
121
|
-
{
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
if (channelObject.drumChannel === isDrum)
|
|
125
|
-
{
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
if (isDrum)
|
|
129
|
-
{
|
|
130
|
-
// clear transpose
|
|
131
|
-
channelObject.channelTransposeKeyShift = 0;
|
|
132
|
-
channelObject.drumChannel = true;
|
|
133
|
-
this.setPreset(channel, this.getPreset(getBankSelect(channelObject), channelObject.preset.program));
|
|
134
|
-
}
|
|
135
|
-
else
|
|
136
|
-
{
|
|
137
|
-
channelObject.drumChannel = false;
|
|
138
|
-
this.setPreset(
|
|
139
|
-
channel,
|
|
140
|
-
this.getPreset(
|
|
141
|
-
getBankSelect(channelObject),
|
|
142
|
-
channelObject.preset.program
|
|
143
|
-
)
|
|
144
|
-
);
|
|
145
|
-
}
|
|
146
|
-
channelObject.presetUsesOverride = false;
|
|
147
|
-
this.callEvent("drumchange", {
|
|
148
|
-
channel: channel,
|
|
149
|
-
isDrumChannel: channelObject.drumChannel
|
|
150
|
-
});
|
|
151
|
-
this.sendChannelProperties();
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* @this {SpessaSynthProcessor}
|
|
156
|
-
*/
|
|
157
|
-
export function sendPresetList()
|
|
158
|
-
{
|
|
159
|
-
/**
|
|
160
|
-
* @type {{bank: number, presetName: string, program: number}[]}
|
|
161
|
-
*/
|
|
162
|
-
const mainFont = this.soundfontManager.getPresetList();
|
|
163
|
-
if (this.overrideSoundfont !== undefined)
|
|
164
|
-
{
|
|
165
|
-
this.overrideSoundfont.presets.forEach(p =>
|
|
166
|
-
{
|
|
167
|
-
const bankCheck = p.bank === 128 ? 128 : p.bank + this.soundfontBankOffset;
|
|
168
|
-
const exists = mainFont.find(pr => pr.bank === bankCheck && pr.program === p.program);
|
|
169
|
-
if (exists !== undefined)
|
|
170
|
-
{
|
|
171
|
-
exists.presetName = p.presetName;
|
|
172
|
-
}
|
|
173
|
-
else
|
|
174
|
-
{
|
|
175
|
-
mainFont.push({
|
|
176
|
-
presetName: p.presetName,
|
|
177
|
-
bank: bankCheck,
|
|
178
|
-
program: p.program
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
this.callEvent("presetlistchange", mainFont);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* @this {SpessaSynthProcessor}
|
|
188
|
-
* @param sendPresets {boolean}
|
|
189
|
-
* @param clearOverride {boolean}
|
|
190
|
-
*/
|
|
191
|
-
export function clearSoundFont(sendPresets = true, clearOverride = true)
|
|
192
|
-
{
|
|
193
|
-
this.stopAllChannels(true);
|
|
194
|
-
if (clearOverride)
|
|
195
|
-
{
|
|
196
|
-
delete this.overrideSoundfont;
|
|
197
|
-
this.overrideSoundfont = undefined;
|
|
198
|
-
}
|
|
199
|
-
this.defaultPreset = this.getPreset(0, 0);
|
|
200
|
-
this.drumPreset = this.getPreset(128, 0);
|
|
201
|
-
|
|
202
|
-
for (let i = 0; i < this.workletProcessorChannels.length; i++)
|
|
203
|
-
{
|
|
204
|
-
const channelObject = this.workletProcessorChannels[i];
|
|
205
|
-
channelObject.cachedVoices = [];
|
|
206
|
-
for (let j = 0; j < 128; j++)
|
|
207
|
-
{
|
|
208
|
-
channelObject.cachedVoices.push([]);
|
|
209
|
-
}
|
|
210
|
-
if (!clearOverride || (clearOverride && channelObject.presetUsesOverride))
|
|
211
|
-
{
|
|
212
|
-
channelObject.lockPreset = false;
|
|
213
|
-
}
|
|
214
|
-
this.programChange(i, channelObject.preset.program);
|
|
215
|
-
}
|
|
216
|
-
if (sendPresets)
|
|
217
|
-
{
|
|
218
|
-
this.sendPresetList();
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* @param buffer {ArrayBuffer}
|
|
224
|
-
* @param isOverride {Boolean}
|
|
225
|
-
* @this {SpessaSynthProcessor}
|
|
226
|
-
*/
|
|
227
|
-
export function reloadSoundFont(buffer, isOverride = false)
|
|
228
|
-
{
|
|
229
|
-
this.clearSoundFont(false, isOverride);
|
|
230
|
-
try
|
|
231
|
-
{
|
|
232
|
-
if (isOverride)
|
|
233
|
-
{
|
|
234
|
-
this.overrideSoundfont = loadSoundFont(buffer);
|
|
235
|
-
// assign sample offset
|
|
236
|
-
this.overrideSoundfont.setSampleIDOffset(this.soundfontManager.totalSoundfontOffset);
|
|
237
|
-
}
|
|
238
|
-
else
|
|
239
|
-
{
|
|
240
|
-
this.soundfontManager.reloadManager(buffer);
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
catch (e)
|
|
244
|
-
{
|
|
245
|
-
this.post({
|
|
246
|
-
messageType: returnMessageType.soundfontError,
|
|
247
|
-
messageData: e
|
|
248
|
-
});
|
|
249
|
-
return;
|
|
250
|
-
}
|
|
251
|
-
this.defaultPreset = this.getPreset(0, 0);
|
|
252
|
-
this.drumPreset = this.getPreset(128, 0);
|
|
253
|
-
this.workletProcessorChannels.forEach((c, cNum) =>
|
|
254
|
-
{
|
|
255
|
-
this.programChange(cNum, c.preset.program);
|
|
256
|
-
});
|
|
257
|
-
this.post({ messageType: returnMessageType.ready, messageData: undefined });
|
|
258
|
-
this.sendPresetList();
|
|
259
|
-
SpessaSynthInfo("%cSpessaSynth is ready!", consoleColors.recognized);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Sets the embedded (RMI soundfont)
|
|
264
|
-
* @param font {ArrayBuffer}
|
|
265
|
-
* @param offset {number}
|
|
266
|
-
* @this {SpessaSynthProcessor}
|
|
267
|
-
*/
|
|
268
|
-
export function setEmbeddedSoundFont(font, offset)
|
|
269
|
-
{
|
|
270
|
-
// set offet
|
|
271
|
-
this.soundfontBankOffset = offset;
|
|
272
|
-
this.reloadSoundFont(font, true);
|
|
273
|
-
// preload all samples
|
|
274
|
-
this.overrideSoundfont.samples.forEach(s => s.getAudioData());
|
|
275
|
-
|
|
276
|
-
// apply snapshot again if applicable
|
|
277
|
-
if (this._snapshot !== undefined)
|
|
278
|
-
{
|
|
279
|
-
this.applySynthesizerSnapshot(this._snapshot);
|
|
280
|
-
this.resetAllControllers();
|
|
281
|
-
}
|
|
282
|
-
}
|
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
import { consoleColors } from "../../../utils/other.js";
|
|
2
|
-
import { computeModulators } from "../worklet_utilities/worklet_modulator.js";
|
|
3
|
-
import { SpessaSynthInfo } from "../../../utils/loggin.js";
|
|
4
|
-
import { modulatorSources } from "../../../soundfont/basic_soundfont/modulator.js";
|
|
5
|
-
import { customControllers, NON_CC_INDEX_OFFSET } from "../worklet_utilities/controller_tables.js";
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Transposes all channels by given amount of semitones
|
|
9
|
-
* @this {SpessaSynthProcessor}
|
|
10
|
-
* @param semitones {number} Can be float
|
|
11
|
-
* @param force {boolean} defaults to false, if true transposes the channel even if it's a drum channel
|
|
12
|
-
*/
|
|
13
|
-
export function transposeAllChannels(semitones, force = false)
|
|
14
|
-
{
|
|
15
|
-
this.transposition = 0;
|
|
16
|
-
for (let i = 0; i < this.workletProcessorChannels.length; i++)
|
|
17
|
-
{
|
|
18
|
-
this.transposeChannel(i, semitones, force);
|
|
19
|
-
}
|
|
20
|
-
this.transposition = semitones;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Transposes the channel by given amount of semitones
|
|
25
|
-
* @this {SpessaSynthProcessor}
|
|
26
|
-
* @param channel {number}
|
|
27
|
-
* @param semitones {number} Can be float
|
|
28
|
-
* @param force {boolean} defaults to false, if true transposes the channel even if it's a drum channel
|
|
29
|
-
*/
|
|
30
|
-
export function transposeChannel(channel, semitones, force = false)
|
|
31
|
-
{
|
|
32
|
-
const channelObject = this.workletProcessorChannels[channel];
|
|
33
|
-
if (!channelObject.drumChannel)
|
|
34
|
-
{
|
|
35
|
-
semitones += this.transposition;
|
|
36
|
-
}
|
|
37
|
-
const keyShift = Math.trunc(semitones);
|
|
38
|
-
const currentTranspose = channelObject.channelTransposeKeyShift + channelObject.customControllers[customControllers.channelTransposeFine] / 100;
|
|
39
|
-
if (
|
|
40
|
-
(channelObject.drumChannel && !force)
|
|
41
|
-
|| semitones === currentTranspose
|
|
42
|
-
)
|
|
43
|
-
{
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
if (keyShift !== channelObject.channelTransposeKeyShift)
|
|
47
|
-
{
|
|
48
|
-
this.stopAll(channel, false);
|
|
49
|
-
}
|
|
50
|
-
// apply transpose
|
|
51
|
-
channelObject.channelTransposeKeyShift = keyShift;
|
|
52
|
-
channelObject.customControllers[customControllers.channelTransposeFine] = (semitones - keyShift) * 100;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Sets the channel's tuning
|
|
57
|
-
* @this {SpessaSynthProcessor}
|
|
58
|
-
* @param channel {number}
|
|
59
|
-
* @param cents {number}
|
|
60
|
-
* @param log {boolean}
|
|
61
|
-
*/
|
|
62
|
-
export function setChannelTuning(channel, cents, log = true)
|
|
63
|
-
{
|
|
64
|
-
const channelObject = this.workletProcessorChannels[channel];
|
|
65
|
-
cents = Math.round(cents);
|
|
66
|
-
channelObject.customControllers[customControllers.channelTuning] = cents;
|
|
67
|
-
if (!log)
|
|
68
|
-
{
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
SpessaSynthInfo(
|
|
72
|
-
`%cChannel ${channel} fine tuning. Cents: %c${cents}`,
|
|
73
|
-
consoleColors.info,
|
|
74
|
-
consoleColors.value
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Sets the channel's tuning in semitones
|
|
80
|
-
* @param channel {number}
|
|
81
|
-
* @param semitones {number}
|
|
82
|
-
* @this {SpessaSynthProcessor}
|
|
83
|
-
*/
|
|
84
|
-
export function setChannelTuningSemitones(channel, semitones)
|
|
85
|
-
{
|
|
86
|
-
const channelObject = this.workletProcessorChannels[channel];
|
|
87
|
-
semitones = Math.round(semitones);
|
|
88
|
-
channelObject.customControllers[customControllers.channelTuningSemitones] = semitones;
|
|
89
|
-
SpessaSynthInfo(
|
|
90
|
-
`%cChannel ${channel} coarse tuning. Semitones: %c${semitones}`,
|
|
91
|
-
consoleColors.info,
|
|
92
|
-
consoleColors.value
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Sets the worklet's master tuning
|
|
98
|
-
* @this {SpessaSynthProcessor}
|
|
99
|
-
* @param cents {number}
|
|
100
|
-
*/
|
|
101
|
-
export function setMasterTuning(cents)
|
|
102
|
-
{
|
|
103
|
-
cents = Math.round(cents);
|
|
104
|
-
for (let i = 0; i < this.workletProcessorChannels.length; i++)
|
|
105
|
-
{
|
|
106
|
-
this.workletProcessorChannels[i].customControllers[customControllers.masterTuning] = cents;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* @this {SpessaSynthProcessor}
|
|
112
|
-
* @param channel {number}
|
|
113
|
-
* @param cents {number}
|
|
114
|
-
*/
|
|
115
|
-
export function setModulationDepth(channel, cents)
|
|
116
|
-
{
|
|
117
|
-
let channelObject = this.workletProcessorChannels[channel];
|
|
118
|
-
cents = Math.round(cents);
|
|
119
|
-
SpessaSynthInfo(
|
|
120
|
-
`%cChannel ${channel} modulation depth. Cents: %c${cents}`,
|
|
121
|
-
consoleColors.info,
|
|
122
|
-
consoleColors.value
|
|
123
|
-
);
|
|
124
|
-
/* ==============
|
|
125
|
-
IMPORTANT
|
|
126
|
-
here we convert cents into a multiplier.
|
|
127
|
-
midi spec assumes the default is 50 cents,
|
|
128
|
-
but it might be different for the soundfont
|
|
129
|
-
so we create a multiplier by divinging cents by 50.
|
|
130
|
-
for example, if we want 100 cents, then multiplier will be 2,
|
|
131
|
-
which for a preset with depth of 50 will create 100.
|
|
132
|
-
================ */
|
|
133
|
-
channelObject.customControllers[customControllers.modulationMultiplier] = cents / 50;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Sets the pitch of the given channel
|
|
138
|
-
* @this {SpessaSynthProcessor}
|
|
139
|
-
* @param channel {number} usually 0-15: the channel to change pitch
|
|
140
|
-
* @param MSB {number} SECOND byte of the MIDI pitchWheel message
|
|
141
|
-
* @param LSB {number} FIRST byte of the MIDI pitchWheel message
|
|
142
|
-
*/
|
|
143
|
-
export function pitchWheel(channel, MSB, LSB)
|
|
144
|
-
{
|
|
145
|
-
if (this.workletProcessorChannels[channel].lockedControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel])
|
|
146
|
-
{
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
const bend = (LSB | (MSB << 7));
|
|
150
|
-
this.callEvent("pitchwheel", {
|
|
151
|
-
channel: channel,
|
|
152
|
-
MSB: MSB,
|
|
153
|
-
LSB: LSB
|
|
154
|
-
});
|
|
155
|
-
this.workletProcessorChannels[channel].midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel] = bend;
|
|
156
|
-
this.workletProcessorChannels[channel].voices.forEach(v =>
|
|
157
|
-
// compute pitch modulators
|
|
158
|
-
computeModulators(
|
|
159
|
-
v,
|
|
160
|
-
this.workletProcessorChannels[channel].midiControllers,
|
|
161
|
-
0,
|
|
162
|
-
modulatorSources.pitchWheel
|
|
163
|
-
));
|
|
164
|
-
this.sendChannelProperties();
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Sets the pressure of the given channel
|
|
169
|
-
* @this {SpessaSynthProcessor}
|
|
170
|
-
* @param channel {number} usually 0-15: the channel to change pitch
|
|
171
|
-
* @param pressure {number} the pressure of the channel
|
|
172
|
-
*/
|
|
173
|
-
export function channelPressure(channel, pressure)
|
|
174
|
-
{
|
|
175
|
-
const channelObject = this.workletProcessorChannels[channel];
|
|
176
|
-
channelObject.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.channelPressure] = pressure << 7;
|
|
177
|
-
this.workletProcessorChannels[channel].voices.forEach(v =>
|
|
178
|
-
computeModulators(
|
|
179
|
-
v,
|
|
180
|
-
channelObject.midiControllers,
|
|
181
|
-
0,
|
|
182
|
-
modulatorSources.channelPressure
|
|
183
|
-
));
|
|
184
|
-
this.callEvent("channelpressure", {
|
|
185
|
-
channel: channel,
|
|
186
|
-
pressure: pressure
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Sets the pressure of the given note on a specific channel
|
|
192
|
-
* @this {SpessaSynthProcessor}
|
|
193
|
-
* @param channel {number} usually 0-15: the channel to change pitch
|
|
194
|
-
* @param midiNote {number} 0-127
|
|
195
|
-
* @param pressure {number} the pressure of the note
|
|
196
|
-
*/
|
|
197
|
-
export function polyPressure(channel, midiNote, pressure)
|
|
198
|
-
{
|
|
199
|
-
this.workletProcessorChannels[channel].voices.forEach(v =>
|
|
200
|
-
{
|
|
201
|
-
if (v.midiNote !== midiNote)
|
|
202
|
-
{
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
v.pressure = pressure;
|
|
206
|
-
computeModulators(
|
|
207
|
-
v,
|
|
208
|
-
this.workletProcessorChannels[channel].midiControllers,
|
|
209
|
-
0,
|
|
210
|
-
modulatorSources.polyPressure
|
|
211
|
-
);
|
|
212
|
-
});
|
|
213
|
-
this.callEvent("polypressure", {
|
|
214
|
-
channel: channel,
|
|
215
|
-
midiNote: midiNote,
|
|
216
|
-
pressure: pressure
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Sets the octave tuning for a given channel
|
|
222
|
-
* @this {SpessaSynthProcessor}
|
|
223
|
-
* @param channel {number} usually 0-15: the channel to use
|
|
224
|
-
* @param tuning {Int8Array} LENGTH of 12!!! relative cent tuning. min -128 max 127.
|
|
225
|
-
*/
|
|
226
|
-
export function setOctaveTuning(channel, tuning)
|
|
227
|
-
{
|
|
228
|
-
if (tuning.length !== 12)
|
|
229
|
-
{
|
|
230
|
-
throw new Error("Tuning is not the length of 12.");
|
|
231
|
-
}
|
|
232
|
-
this.workletProcessorChannels[channel].channelOctaveTuning = tuning;
|
|
233
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @param channel {number}
|
|
3
|
-
* @this {SpessaSynthProcessor}
|
|
4
|
-
*/
|
|
5
|
-
export function disableAndLockGSNRPN(channel)
|
|
6
|
-
{
|
|
7
|
-
this.workletProcessorChannels[channel].lockGSNRPNParams = true;
|
|
8
|
-
this.workletProcessorChannels[channel].channelVibrato.rate = 0;
|
|
9
|
-
this.workletProcessorChannels[channel].channelVibrato.delay = 0;
|
|
10
|
-
this.workletProcessorChannels[channel].channelVibrato.depth = 0;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @param channel {number}
|
|
15
|
-
* @param depth {number}
|
|
16
|
-
* @param rate {number}
|
|
17
|
-
* @param delay {number}
|
|
18
|
-
* @this {SpessaSynthProcessor}
|
|
19
|
-
*/
|
|
20
|
-
export function setVibrato(channel, depth, rate, delay)
|
|
21
|
-
{
|
|
22
|
-
if (this.workletProcessorChannels[channel].lockGSNRPNParams)
|
|
23
|
-
{
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
this.workletProcessorChannels[channel].channelVibrato.rate = rate;
|
|
27
|
-
this.workletProcessorChannels[channel].channelVibrato.delay = delay;
|
|
28
|
-
this.workletProcessorChannels[channel].channelVibrato.depth = depth;
|
|
29
|
-
}
|