spessasynth_lib 3.24.25 → 3.24.26
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/midi_message.js +4 -4
- package/package.json +1 -1
- package/sequencer/worklet_sequencer/play.js +26 -1
- package/synthetizer/worklet_processor.min.js +11 -11
- package/synthetizer/worklet_system/message_protocol/handle_message.js +3 -2
- package/synthetizer/worklet_system/snapshot/channel_snapshot.js +0 -7
- package/synthetizer/worklet_system/worklet_methods/controller_control/controller_change.js +14 -7
- package/synthetizer/worklet_system/worklet_methods/controller_control/reset_controllers.js +67 -21
- package/synthetizer/worklet_system/worklet_methods/data_entry/data_entry_coarse.js +105 -71
- package/synthetizer/worklet_system/worklet_methods/data_entry/data_entry_fine.js +4 -2
- package/synthetizer/worklet_system/worklet_methods/render_voice.js +0 -1
- package/synthetizer/worklet_system/worklet_methods/tuning_control/set_tuning.js +5 -2
- package/synthetizer/worklet_system/worklet_utilities/controller_tables.js +9 -4
- package/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +11 -33
- package/synthetizer/worklet_system/worklet_methods/tuning_control/set_tuning_semitones.js +0 -19
|
@@ -87,13 +87,14 @@ export function handleMessage(message)
|
|
|
87
87
|
{
|
|
88
88
|
for (let i = 0; i < this.workletProcessorChannels.length; i++)
|
|
89
89
|
{
|
|
90
|
+
const chan = this.workletProcessorChannels[i];
|
|
90
91
|
if (data.rate === -1)
|
|
91
92
|
{
|
|
92
|
-
|
|
93
|
+
chan.disableAndLockGSNRPN();
|
|
93
94
|
}
|
|
94
95
|
else
|
|
95
96
|
{
|
|
96
|
-
|
|
97
|
+
chan.setVibrato(data.depth, data.rate, data.delay);
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
}
|
|
@@ -72,12 +72,6 @@ export class ChannelSnapshot
|
|
|
72
72
|
*/
|
|
73
73
|
channelOctaveTuning;
|
|
74
74
|
|
|
75
|
-
/**
|
|
76
|
-
* Tuning of individual keys in cents.
|
|
77
|
-
* @type {Int16Array}
|
|
78
|
-
*/
|
|
79
|
-
keyCentTuning;
|
|
80
|
-
|
|
81
75
|
/**
|
|
82
76
|
* Indicates whether the channel is muted.
|
|
83
77
|
* @type {boolean}
|
|
@@ -124,7 +118,6 @@ export class ChannelSnapshot
|
|
|
124
118
|
// tuning and transpose data
|
|
125
119
|
channelSnapshot.channelTransposeKeyShift = channelObject.channelTransposeKeyShift;
|
|
126
120
|
channelSnapshot.channelOctaveTuning = channelObject.channelOctaveTuning;
|
|
127
|
-
channelSnapshot.keyCentTuning = channelObject.keyCentTuning;
|
|
128
121
|
|
|
129
122
|
// other data
|
|
130
123
|
channelSnapshot.isMuted = channelObject.isMuted;
|
|
@@ -51,6 +51,11 @@ export function controllerChange(controllerNumber, controllerValue, force = fals
|
|
|
51
51
|
{
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
+
|
|
55
|
+
// apply the cc to the table
|
|
56
|
+
this.midiControllers[controllerNumber] = controllerValue << 7;
|
|
57
|
+
|
|
58
|
+
// interpret special CCs
|
|
54
59
|
switch (controllerNumber)
|
|
55
60
|
{
|
|
56
61
|
case midiControllers.allNotesOff:
|
|
@@ -97,6 +102,13 @@ export function controllerChange(controllerNumber, controllerValue, force = fals
|
|
|
97
102
|
{
|
|
98
103
|
this.setDrums(true);
|
|
99
104
|
}
|
|
105
|
+
else
|
|
106
|
+
{
|
|
107
|
+
if (this.channelNumber % 16 !== DEFAULT_PERCUSSION)
|
|
108
|
+
{
|
|
109
|
+
this.setDrums(false);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
100
112
|
}
|
|
101
113
|
|
|
102
114
|
if (this.drumChannel)
|
|
@@ -135,22 +147,18 @@ export function controllerChange(controllerNumber, controllerValue, force = fals
|
|
|
135
147
|
|
|
136
148
|
// check for RPN and NPRN and data entry
|
|
137
149
|
case midiControllers.RPNLsb:
|
|
138
|
-
this.RPValue = this.RPValue << 7 | controllerValue;
|
|
139
150
|
this.dataEntryState = dataEntryStates.RPFine;
|
|
140
151
|
break;
|
|
141
152
|
|
|
142
153
|
case midiControllers.RPNMsb:
|
|
143
|
-
this.RPValue = controllerValue;
|
|
144
154
|
this.dataEntryState = dataEntryStates.RPCoarse;
|
|
145
155
|
break;
|
|
146
156
|
|
|
147
157
|
case midiControllers.NRPNMsb:
|
|
148
|
-
this.NRPCoarse = controllerValue;
|
|
149
158
|
this.dataEntryState = dataEntryStates.NRPCoarse;
|
|
150
159
|
break;
|
|
151
160
|
|
|
152
161
|
case midiControllers.NRPNLsb:
|
|
153
|
-
this.NRPFine = controllerValue;
|
|
154
162
|
this.dataEntryState = dataEntryStates.NRPFine;
|
|
155
163
|
break;
|
|
156
164
|
|
|
@@ -163,7 +171,7 @@ export function controllerChange(controllerNumber, controllerValue, force = fals
|
|
|
163
171
|
break;
|
|
164
172
|
|
|
165
173
|
case midiControllers.resetAllControllers:
|
|
166
|
-
this.
|
|
174
|
+
this.resetControllersRP15Compliant();
|
|
167
175
|
break;
|
|
168
176
|
|
|
169
177
|
case midiControllers.sustainPedal:
|
|
@@ -182,9 +190,8 @@ export function controllerChange(controllerNumber, controllerValue, force = fals
|
|
|
182
190
|
}
|
|
183
191
|
break;
|
|
184
192
|
|
|
185
|
-
// default:
|
|
193
|
+
// default: just compute modulators
|
|
186
194
|
default:
|
|
187
|
-
this.midiControllers[controllerNumber] = controllerValue << 7;
|
|
188
195
|
this.voices.forEach(v => computeModulators(v, this.midiControllers, 1, controllerNumber));
|
|
189
196
|
break;
|
|
190
197
|
}
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
NON_CC_INDEX_OFFSET,
|
|
10
10
|
resetArray
|
|
11
11
|
} from "../../worklet_utilities/controller_tables.js";
|
|
12
|
+
import { midiControllers } from "../../../../midi_parser/midi_message.js";
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* Full system reset
|
|
@@ -117,7 +119,6 @@ export function resetAllControllers(log = true)
|
|
|
117
119
|
export function resetControllers()
|
|
118
120
|
{
|
|
119
121
|
this.channelOctaveTuning.fill(0);
|
|
120
|
-
this.keyCentTuning.fill(0);
|
|
121
122
|
|
|
122
123
|
// reset the array
|
|
123
124
|
for (let i = 0; i < resetArray.length; i++)
|
|
@@ -129,14 +130,14 @@ export function resetControllers()
|
|
|
129
130
|
const resetValue = resetArray[i];
|
|
130
131
|
if (this.midiControllers[i] !== resetValue && i < 127)
|
|
131
132
|
{
|
|
132
|
-
//
|
|
133
|
-
this.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
// reset if reset
|
|
134
|
+
this.controllerChange(i, resetValue >> 7);
|
|
135
|
+
}
|
|
136
|
+
else
|
|
137
|
+
{
|
|
138
|
+
// out of range, do a regular reset
|
|
139
|
+
this.midiControllers[i] = resetValue;
|
|
138
140
|
}
|
|
139
|
-
this.midiControllers[i] = resetValue;
|
|
140
141
|
}
|
|
141
142
|
this.channelVibrato = { rate: 0, depth: 0, delay: 0 };
|
|
142
143
|
this.holdPedal = false;
|
|
@@ -152,26 +153,71 @@ export function resetControllers()
|
|
|
152
153
|
|
|
153
154
|
}
|
|
154
155
|
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* @type {Set<midiControllers|number>}
|
|
159
|
+
*/
|
|
160
|
+
export const nonResetableCCs = new Set([
|
|
161
|
+
midiControllers.bankSelect,
|
|
162
|
+
midiControllers.lsbForControl0BankSelect,
|
|
163
|
+
midiControllers.mainVolume,
|
|
164
|
+
midiControllers.lsbForControl7MainVolume,
|
|
165
|
+
midiControllers.pan,
|
|
166
|
+
midiControllers.lsbForControl10Pan,
|
|
167
|
+
midiControllers.reverbDepth,
|
|
168
|
+
midiControllers.tremoloDepth,
|
|
169
|
+
midiControllers.chorusDepth,
|
|
170
|
+
midiControllers.detuneDepth,
|
|
171
|
+
midiControllers.phaserDepth,
|
|
172
|
+
midiControllers.soundVariation,
|
|
173
|
+
midiControllers.filterResonance,
|
|
174
|
+
midiControllers.releaseTime,
|
|
175
|
+
midiControllers.attackTime,
|
|
176
|
+
midiControllers.brightness,
|
|
177
|
+
midiControllers.decayTime,
|
|
178
|
+
midiControllers.vibratoRate,
|
|
179
|
+
midiControllers.vibratoDepth,
|
|
180
|
+
midiControllers.vibratoDelay,
|
|
181
|
+
midiControllers.soundController10
|
|
182
|
+
]);
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Reset all controllers for channel, but RP-15 compliant
|
|
186
|
+
* https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf
|
|
187
|
+
* @this {WorkletProcessorChannel}
|
|
188
|
+
*/
|
|
189
|
+
export function resetControllersRP15Compliant()
|
|
190
|
+
{
|
|
191
|
+
// reset tunings
|
|
192
|
+
this.channelOctaveTuning.fill(0);
|
|
193
|
+
|
|
194
|
+
// reset pitch bend
|
|
195
|
+
this.pitchWheel(64, 0);
|
|
196
|
+
|
|
197
|
+
this.channelVibrato = { rate: 0, depth: 0, delay: 0 };
|
|
198
|
+
|
|
199
|
+
for (let i = 0; i < 128; i++)
|
|
200
|
+
{
|
|
201
|
+
const resetValue = resetArray[i];
|
|
202
|
+
if (!nonResetableCCs.has(i) && resetValue !== this.midiControllers[i])
|
|
203
|
+
{
|
|
204
|
+
this.controllerChange(i, resetValue);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
155
209
|
/**
|
|
156
210
|
* @this {WorkletProcessorChannel}
|
|
157
211
|
*/
|
|
158
212
|
export function resetParameters()
|
|
159
213
|
{
|
|
160
|
-
// reset parameters
|
|
161
|
-
/**
|
|
162
|
-
* @type {number}
|
|
163
|
-
*/
|
|
164
|
-
this.NRPCoarse = 0;
|
|
165
|
-
/**
|
|
166
|
-
* @type {number}
|
|
167
|
-
*/
|
|
168
|
-
this.NRPFine = 0;
|
|
169
|
-
/**
|
|
170
|
-
* @type {number}
|
|
171
|
-
*/
|
|
172
|
-
this.RPValue = 0;
|
|
173
214
|
/**
|
|
215
|
+
* reset the state machine to idle
|
|
174
216
|
* @type {string}
|
|
175
217
|
*/
|
|
176
218
|
this.dataEntryState = dataEntryStates.Idle;
|
|
219
|
+
SpessaSynthInfo(
|
|
220
|
+
"%cResetting Registered and Non-Registered Parameters!",
|
|
221
|
+
consoleColors.info
|
|
222
|
+
);
|
|
177
223
|
}
|
|
@@ -1,9 +1,41 @@
|
|
|
1
|
-
import { dataEntryStates, NON_CC_INDEX_OFFSET } from "../../worklet_utilities/controller_tables.js";
|
|
1
|
+
import { customControllers, dataEntryStates, NON_CC_INDEX_OFFSET } from "../../worklet_utilities/controller_tables.js";
|
|
2
2
|
import { SpessaSynthInfo, SpessaSynthWarn } from "../../../../utils/loggin.js";
|
|
3
3
|
import { consoleColors } from "../../../../utils/other.js";
|
|
4
4
|
import { midiControllers } from "../../../../midi_parser/midi_message.js";
|
|
5
5
|
import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulator.js";
|
|
6
6
|
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @enum {number}
|
|
10
|
+
*/
|
|
11
|
+
const registeredParameterTypes = {
|
|
12
|
+
pitchBendRange: 0x0000,
|
|
13
|
+
fineTuning: 0x0001,
|
|
14
|
+
coarseTuning: 0x0002,
|
|
15
|
+
modulationDepth: 0x0005,
|
|
16
|
+
resetParameters: 0x3FFF
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* https://cdn.roland.com/assets/media/pdf/SC-88PRO_OM.pdf
|
|
21
|
+
* http://hummer.stanford.edu/sig/doc/classes/MidiOutput/rpn.html
|
|
22
|
+
* @enum {number}
|
|
23
|
+
*/
|
|
24
|
+
const nonRegisteredParameterNumbers = {
|
|
25
|
+
partParameter: 0x01,
|
|
26
|
+
|
|
27
|
+
vibratoRate: 0x08,
|
|
28
|
+
vibratoDepth: 0x09,
|
|
29
|
+
vibratoDelay: 0x0A,
|
|
30
|
+
|
|
31
|
+
EGAttackTime: 0x64,
|
|
32
|
+
EGReleaseTime: 0x66,
|
|
33
|
+
|
|
34
|
+
TVFFilterCutoff: 0x20,
|
|
35
|
+
drumReverb: 0x1D
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
|
|
7
39
|
/**
|
|
8
40
|
* Executes a data entry for an NRP for a sc88pro NRP (because touhou yes) and RPN tuning
|
|
9
41
|
* @param dataValue {number} dataEntryCoarse MSB
|
|
@@ -12,7 +44,7 @@ import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulato
|
|
|
12
44
|
*/
|
|
13
45
|
export function dataEntryCoarse(dataValue)
|
|
14
46
|
{
|
|
15
|
-
|
|
47
|
+
const addDefaultVibrato = () =>
|
|
16
48
|
{
|
|
17
49
|
if (this.channelVibrato.delay === 0 && this.channelVibrato.rate === 0 && this.channelVibrato.depth === 0)
|
|
18
50
|
{
|
|
@@ -21,24 +53,43 @@ export function dataEntryCoarse(dataValue)
|
|
|
21
53
|
this.channelVibrato.delay = 0.6;
|
|
22
54
|
}
|
|
23
55
|
};
|
|
56
|
+
|
|
57
|
+
const coolInfo = (what, value, type) =>
|
|
58
|
+
{
|
|
59
|
+
if (type.length > 0)
|
|
60
|
+
{
|
|
61
|
+
type = " " + type;
|
|
62
|
+
}
|
|
63
|
+
SpessaSynthInfo(
|
|
64
|
+
`%c${what} for %c${this.channelNumber}%c is now set to %c${value}%c${type}.`,
|
|
65
|
+
consoleColors.info,
|
|
66
|
+
consoleColors.recognized,
|
|
67
|
+
consoleColors.info,
|
|
68
|
+
consoleColors.value,
|
|
69
|
+
consoleColors.info
|
|
70
|
+
);
|
|
71
|
+
};
|
|
24
72
|
switch (this.dataEntryState)
|
|
25
73
|
{
|
|
26
74
|
default:
|
|
27
75
|
case dataEntryStates.Idle:
|
|
28
76
|
break;
|
|
29
77
|
|
|
30
|
-
//
|
|
31
|
-
// http://hummer.stanford.edu/sig/doc/classes/MidiOutput/rpn.html
|
|
78
|
+
// process GS NRPNs
|
|
32
79
|
case dataEntryStates.NRPFine:
|
|
33
|
-
if (this.synth.system !== "gs")
|
|
34
|
-
{
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
80
|
if (this.lockGSNRPNParams)
|
|
38
81
|
{
|
|
39
82
|
return;
|
|
40
83
|
}
|
|
41
|
-
|
|
84
|
+
/**
|
|
85
|
+
* @type {number}
|
|
86
|
+
*/
|
|
87
|
+
const NRPNCoarse = this.midiControllers[midiControllers.NRPNMsb] >> 7;
|
|
88
|
+
/**
|
|
89
|
+
* @type {number}
|
|
90
|
+
*/
|
|
91
|
+
const NRPNFine = this.midiControllers[midiControllers.NRPNLsb] >> 7;
|
|
92
|
+
switch (NRPNCoarse)
|
|
42
93
|
{
|
|
43
94
|
default:
|
|
44
95
|
if (dataValue === 64)
|
|
@@ -47,8 +98,8 @@ export function dataEntryCoarse(dataValue)
|
|
|
47
98
|
return;
|
|
48
99
|
}
|
|
49
100
|
SpessaSynthWarn(
|
|
50
|
-
`%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${
|
|
51
|
-
.toUpperCase()} 0x${
|
|
101
|
+
`%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${NRPNFine.toString(16)
|
|
102
|
+
.toUpperCase()} 0x${NRPNFine.toString(
|
|
52
103
|
16).toUpperCase()})%c data value: %c${dataValue}`,
|
|
53
104
|
consoleColors.warn,
|
|
54
105
|
consoleColors.recognized,
|
|
@@ -60,8 +111,8 @@ export function dataEntryCoarse(dataValue)
|
|
|
60
111
|
break;
|
|
61
112
|
|
|
62
113
|
// part parameters: vibrato, cutoff
|
|
63
|
-
case
|
|
64
|
-
switch (
|
|
114
|
+
case nonRegisteredParameterNumbers.partParameter:
|
|
115
|
+
switch (NRPNFine)
|
|
65
116
|
{
|
|
66
117
|
default:
|
|
67
118
|
if (dataValue === 64)
|
|
@@ -70,7 +121,7 @@ export function dataEntryCoarse(dataValue)
|
|
|
70
121
|
return;
|
|
71
122
|
}
|
|
72
123
|
SpessaSynthWarn(
|
|
73
|
-
`%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${
|
|
124
|
+
`%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${NRPNCoarse.toString(16)} 0x${NRPNFine.toString(
|
|
74
125
|
16)})%c data value: %c${dataValue}`,
|
|
75
126
|
consoleColors.warn,
|
|
76
127
|
consoleColors.recognized,
|
|
@@ -82,96 +133,81 @@ export function dataEntryCoarse(dataValue)
|
|
|
82
133
|
break;
|
|
83
134
|
|
|
84
135
|
// vibrato rate
|
|
85
|
-
case
|
|
136
|
+
case nonRegisteredParameterNumbers.vibratoRate:
|
|
86
137
|
if (dataValue === 64)
|
|
87
138
|
{
|
|
88
139
|
return;
|
|
89
140
|
}
|
|
90
141
|
addDefaultVibrato();
|
|
91
142
|
this.channelVibrato.rate = (dataValue / 64) * 8;
|
|
92
|
-
|
|
93
|
-
`%cVibrato rate for %c${this.channelNumber}%c is now set to %c${dataValue} = ${this.channelVibrato.rate}%cHz.`,
|
|
94
|
-
consoleColors.info,
|
|
95
|
-
consoleColors.recognized,
|
|
96
|
-
consoleColors.info,
|
|
97
|
-
consoleColors.value,
|
|
98
|
-
consoleColors.info
|
|
99
|
-
);
|
|
143
|
+
coolInfo("Vibrato rate", `${dataValue} = ${this.channelVibrato.rate}`, "Hz");
|
|
100
144
|
break;
|
|
101
145
|
|
|
102
146
|
// vibrato depth
|
|
103
|
-
case
|
|
147
|
+
case nonRegisteredParameterNumbers.vibratoDepth:
|
|
104
148
|
if (dataValue === 64)
|
|
105
149
|
{
|
|
106
150
|
return;
|
|
107
151
|
}
|
|
108
152
|
addDefaultVibrato();
|
|
109
153
|
this.channelVibrato.depth = dataValue / 2;
|
|
110
|
-
|
|
111
|
-
`%cVibrato depth for %c${this.channelNumber}%c is now set to %c${dataValue} = ${this.channelVibrato.depth}%c cents range of detune.`,
|
|
112
|
-
consoleColors.info,
|
|
113
|
-
consoleColors.recognized,
|
|
114
|
-
consoleColors.info,
|
|
115
|
-
consoleColors.value,
|
|
116
|
-
consoleColors.info
|
|
117
|
-
);
|
|
154
|
+
coolInfo("Vibrato depth", `${dataValue} = ${this.channelVibrato.depth}`, "cents of detune");
|
|
118
155
|
break;
|
|
119
156
|
|
|
120
157
|
// vibrato delay
|
|
121
|
-
case
|
|
158
|
+
case nonRegisteredParameterNumbers.vibratoDelay:
|
|
122
159
|
if (dataValue === 64)
|
|
123
160
|
{
|
|
124
161
|
return;
|
|
125
162
|
}
|
|
126
163
|
addDefaultVibrato();
|
|
127
164
|
this.channelVibrato.delay = (dataValue / 64) / 3;
|
|
128
|
-
|
|
129
|
-
`%cVibrato delay for %c${this.channelNumber}%c is now set to %c${dataValue} = ${this.channelVibrato.delay}%c seconds.`,
|
|
130
|
-
consoleColors.info,
|
|
131
|
-
consoleColors.recognized,
|
|
132
|
-
consoleColors.info,
|
|
133
|
-
consoleColors.value,
|
|
134
|
-
consoleColors.info
|
|
135
|
-
);
|
|
165
|
+
coolInfo("Vibrato delay", `${dataValue} = ${this.channelVibrato.delay}`, "seconds");
|
|
136
166
|
break;
|
|
137
167
|
|
|
138
168
|
// filter cutoff
|
|
139
|
-
case
|
|
169
|
+
case nonRegisteredParameterNumbers.TVFFilterCutoff:
|
|
140
170
|
// affect the "brightness" controller as we have a default modulator that controls it
|
|
141
|
-
const ccValue = dataValue;
|
|
142
171
|
this.controllerChange(midiControllers.brightness, dataValue);
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
);
|
|
172
|
+
coolInfo("Filter cutoff", dataValue.toString(), "");
|
|
173
|
+
break;
|
|
174
|
+
|
|
175
|
+
// attack time
|
|
176
|
+
case nonRegisteredParameterNumbers.EGAttackTime:
|
|
177
|
+
// affect the "attack time" controller as we have a default modulator that controls it
|
|
178
|
+
this.controllerChange(midiControllers.attackTime, dataValue);
|
|
179
|
+
coolInfo("EG attack time", dataValue.toString(), "");
|
|
180
|
+
break;
|
|
181
|
+
|
|
182
|
+
// release time
|
|
183
|
+
case nonRegisteredParameterNumbers.EGReleaseTime:
|
|
184
|
+
// affect the "release time" controller as we have a default modulator that controls it
|
|
185
|
+
this.controllerChange(midiControllers.releaseTime, dataValue);
|
|
186
|
+
coolInfo("EG release time", dataValue.toString(), "");
|
|
187
|
+
break;
|
|
150
188
|
}
|
|
151
189
|
break;
|
|
152
190
|
|
|
153
191
|
// drum reverb
|
|
154
|
-
case
|
|
192
|
+
case nonRegisteredParameterNumbers.drumReverb:
|
|
155
193
|
const reverb = dataValue;
|
|
156
194
|
this.controllerChange(midiControllers.reverbDepth, reverb);
|
|
157
|
-
|
|
158
|
-
`%cGS Drum reverb for %c${this.channelNumber}%c: %c${reverb}`,
|
|
159
|
-
consoleColors.info,
|
|
160
|
-
consoleColors.recognized,
|
|
161
|
-
consoleColors.info,
|
|
162
|
-
consoleColors.value
|
|
163
|
-
);
|
|
195
|
+
coolInfo("GS Drum reverb", reverb.toString(), "percent");
|
|
164
196
|
break;
|
|
165
197
|
}
|
|
166
198
|
break;
|
|
167
199
|
|
|
168
200
|
case dataEntryStates.RPCoarse:
|
|
169
201
|
case dataEntryStates.RPFine:
|
|
170
|
-
|
|
202
|
+
/**
|
|
203
|
+
* @type {number}
|
|
204
|
+
*/
|
|
205
|
+
const rpnValue = this.midiControllers[midiControllers.RPNMsb] | (this.midiControllers[midiControllers.RPNLsb] >> 7);
|
|
206
|
+
switch (rpnValue)
|
|
171
207
|
{
|
|
172
208
|
default:
|
|
173
209
|
SpessaSynthWarn(
|
|
174
|
-
`%cUnrecognized RPN for %c${this.channelNumber}%c: %c(0x${
|
|
210
|
+
`%cUnrecognized RPN for %c${this.channelNumber}%c: %c(0x${rpnValue.toString(16)})%c data value: %c${dataValue}`,
|
|
175
211
|
consoleColors.warn,
|
|
176
212
|
consoleColors.recognized,
|
|
177
213
|
consoleColors.warn,
|
|
@@ -182,34 +218,32 @@ export function dataEntryCoarse(dataValue)
|
|
|
182
218
|
break;
|
|
183
219
|
|
|
184
220
|
// pitch bend range
|
|
185
|
-
case
|
|
221
|
+
case registeredParameterTypes.pitchBendRange:
|
|
186
222
|
this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] = dataValue << 7;
|
|
187
|
-
|
|
188
|
-
`%cChannel ${this.channelNumber} bend range. Semitones: %c${dataValue}`,
|
|
189
|
-
consoleColors.info,
|
|
190
|
-
consoleColors.value
|
|
191
|
-
);
|
|
223
|
+
coolInfo("Pitch bend range", dataValue.toString(), "semitones");
|
|
192
224
|
break;
|
|
193
225
|
|
|
194
226
|
// coarse tuning
|
|
195
|
-
case
|
|
227
|
+
case registeredParameterTypes.coarseTuning:
|
|
196
228
|
// semitones
|
|
197
|
-
|
|
229
|
+
const semitones = dataValue - 64;
|
|
230
|
+
this.setCustomController(customControllers.channelTuningSemitones, semitones);
|
|
231
|
+
coolInfo("Coarse tuning", semitones.toString(), "semitones");
|
|
198
232
|
break;
|
|
199
233
|
|
|
200
234
|
// fine-tuning
|
|
201
|
-
case
|
|
235
|
+
case registeredParameterTypes.fineTuning:
|
|
202
236
|
// note: this will not work properly unless the lsb is sent!
|
|
203
237
|
// here we store the raw value to then adjust in fine
|
|
204
238
|
this.setTuning(dataValue - 64, false);
|
|
205
239
|
break;
|
|
206
240
|
|
|
207
241
|
// modulation depth
|
|
208
|
-
case
|
|
242
|
+
case registeredParameterTypes.modulationDepth:
|
|
209
243
|
this.setModulationDepth(dataValue * 100);
|
|
210
244
|
break;
|
|
211
245
|
|
|
212
|
-
case
|
|
246
|
+
case registeredParameterTypes.resetParameters:
|
|
213
247
|
this.resetParameters();
|
|
214
248
|
break;
|
|
215
249
|
|
|
@@ -2,6 +2,7 @@ import { consoleColors } from "../../../../utils/other.js";
|
|
|
2
2
|
import { SpessaSynthInfo } from "../../../../utils/loggin.js";
|
|
3
3
|
import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulator.js";
|
|
4
4
|
import { customControllers, dataEntryStates, NON_CC_INDEX_OFFSET } from "../../worklet_utilities/controller_tables.js";
|
|
5
|
+
import { midiControllers } from "../../../../midi_parser/midi_message.js";
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Executes a data entry for an RPN tuning
|
|
@@ -18,7 +19,8 @@ export function dataEntryFine(dataValue)
|
|
|
18
19
|
|
|
19
20
|
case dataEntryStates.RPCoarse:
|
|
20
21
|
case dataEntryStates.RPFine:
|
|
21
|
-
|
|
22
|
+
const rpnValue = this.midiControllers[midiControllers.RPNMsb] | (this.midiControllers[midiControllers.RPNLsb] >> 7);
|
|
23
|
+
switch (rpnValue)
|
|
22
24
|
{
|
|
23
25
|
default:
|
|
24
26
|
break;
|
|
@@ -31,7 +33,7 @@ export function dataEntryFine(dataValue)
|
|
|
31
33
|
}
|
|
32
34
|
// 14-bit value, so upper 7 are coarse and lower 7 are fine!
|
|
33
35
|
this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] |= dataValue;
|
|
34
|
-
const actualTune = (this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] >> 7) + dataValue /
|
|
36
|
+
const actualTune = (this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange] >> 7) + dataValue / 128;
|
|
35
37
|
SpessaSynthInfo(
|
|
36
38
|
`%cChannel ${this.channelNumber} bend range. Semitones: %c${actualTune}`,
|
|
37
39
|
consoleColors.info,
|
|
@@ -62,7 +62,6 @@ export function renderVoice(
|
|
|
62
62
|
// calculate tuning
|
|
63
63
|
let cents = voice.modulatedGenerators[generatorTypes.fineTune] // soundfont fine tune
|
|
64
64
|
+ this.channelOctaveTuning[voice.midiNote] // MTS octave tuning
|
|
65
|
-
+ this.keyCentTuning[voice.midiNote] // SysEx key tuning
|
|
66
65
|
+ this.channelTuningCents; // channel tuning
|
|
67
66
|
let semitones = voice.modulatedGenerators[generatorTypes.coarseTune]; // soundfont coarse tuning
|
|
68
67
|
|
|
@@ -17,8 +17,11 @@ export function setTuning(cents, log = true)
|
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
19
|
SpessaSynthInfo(
|
|
20
|
-
`%
|
|
20
|
+
`%cFine tuning for %c${this.channelNumber}%c is now set to %c${cents}%c cents.`,
|
|
21
21
|
consoleColors.info,
|
|
22
|
-
consoleColors.
|
|
22
|
+
consoleColors.recognized,
|
|
23
|
+
consoleColors.info,
|
|
24
|
+
consoleColors.value,
|
|
25
|
+
consoleColors.info
|
|
23
26
|
);
|
|
24
27
|
}
|
|
@@ -29,13 +29,18 @@ setResetValue(midiControllers.releaseTime, 64);
|
|
|
29
29
|
setResetValue(midiControllers.attackTime, 64);
|
|
30
30
|
setResetValue(midiControllers.brightness, 64);
|
|
31
31
|
|
|
32
|
-
setResetValue(midiControllers.
|
|
33
|
-
setResetValue(midiControllers.
|
|
34
|
-
setResetValue(midiControllers.
|
|
35
|
-
setResetValue(midiControllers.
|
|
32
|
+
setResetValue(midiControllers.decayTime, 64);
|
|
33
|
+
setResetValue(midiControllers.vibratoRate, 64);
|
|
34
|
+
setResetValue(midiControllers.vibratoDepth, 64);
|
|
35
|
+
setResetValue(midiControllers.vibratoDelay, 64);
|
|
36
36
|
setResetValue(midiControllers.generalPurposeController6, 64);
|
|
37
37
|
setResetValue(midiControllers.generalPurposeController8, 64);
|
|
38
38
|
|
|
39
|
+
setResetValue(midiControllers.RPNLsb, 127);
|
|
40
|
+
setResetValue(midiControllers.RPNMsb, 127);
|
|
41
|
+
setResetValue(midiControllers.NRPNLsb, 127);
|
|
42
|
+
setResetValue(midiControllers.NRPNMsb, 127);
|
|
43
|
+
|
|
39
44
|
|
|
40
45
|
// special case: portamento control
|
|
41
46
|
// since it is only 7-bit, only the values at multiple of 128 are allowed.
|