spessasynth_lib 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/modules.xml +8 -0
- package/.idea/spessasynth_lib.iml +12 -0
- package/.idea/vcs.xml +6 -0
- package/copy_version.sh +38 -0
- package/index.js +73 -0
- package/package/@types/externals/stbvorbis_sync/stbvorbis_sync.min.d.ts +1 -0
- package/package/@types/index.d.ts +34 -0
- package/package/@types/midi_handler/midi_handler.d.ts +39 -0
- package/package/@types/midi_handler/web_midi_link.d.ts +12 -0
- package/package/@types/midi_parser/midi_data.d.ts +95 -0
- package/package/@types/midi_parser/midi_editor.d.ts +45 -0
- package/package/@types/midi_parser/midi_loader.d.ts +100 -0
- package/package/@types/midi_parser/midi_message.d.ts +154 -0
- package/package/@types/midi_parser/midi_writer.d.ts +6 -0
- package/package/@types/midi_parser/rmidi_writer.d.ts +9 -0
- package/package/@types/midi_parser/used_keys_loaded.d.ts +7 -0
- package/package/@types/sequencer/sequencer.d.ts +180 -0
- package/package/@types/sequencer/worklet_sequencer/sequencer_message.d.ts +28 -0
- package/package/@types/soundfont/read/generators.d.ts +98 -0
- package/package/@types/soundfont/read/instruments.d.ts +50 -0
- package/package/@types/soundfont/read/modulators.d.ts +73 -0
- package/package/@types/soundfont/read/presets.d.ts +87 -0
- package/package/@types/soundfont/read/riff_chunk.d.ts +31 -0
- package/package/@types/soundfont/read/samples.d.ts +134 -0
- package/package/@types/soundfont/read/zones.d.ts +141 -0
- package/package/@types/soundfont/soundfont.d.ts +76 -0
- package/package/@types/soundfont/write/ibag.d.ts +6 -0
- package/package/@types/soundfont/write/igen.d.ts +6 -0
- package/package/@types/soundfont/write/imod.d.ts +6 -0
- package/package/@types/soundfont/write/inst.d.ts +6 -0
- package/package/@types/soundfont/write/pbag.d.ts +6 -0
- package/package/@types/soundfont/write/pgen.d.ts +6 -0
- package/package/@types/soundfont/write/phdr.d.ts +6 -0
- package/package/@types/soundfont/write/pmod.d.ts +6 -0
- package/package/@types/soundfont/write/sdta.d.ts +11 -0
- package/package/@types/soundfont/write/shdr.d.ts +8 -0
- package/package/@types/soundfont/write/soundfont_trimmer.d.ts +6 -0
- package/package/@types/soundfont/write/write.d.ts +21 -0
- package/package/@types/synthetizer/audio_effects/effects_config.d.ts +29 -0
- package/package/@types/synthetizer/audio_effects/fancy_chorus.d.ts +93 -0
- package/package/@types/synthetizer/audio_effects/reverb.d.ts +7 -0
- package/package/@types/synthetizer/synth_event_handler.d.ts +161 -0
- package/package/@types/synthetizer/synthetizer.d.ts +294 -0
- package/package/@types/synthetizer/worklet_system/message_protocol/worklet_message.d.ts +89 -0
- package/package/@types/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.d.ts +134 -0
- package/package/@types/synthetizer/worklet_url.d.ts +5 -0
- package/package/@types/utils/buffer_to_wav.d.ts +8 -0
- package/package/@types/utils/byte_functions/big_endian.d.ts +13 -0
- package/package/@types/utils/byte_functions/little_endian.d.ts +35 -0
- package/package/@types/utils/byte_functions/string.d.ts +22 -0
- package/package/@types/utils/byte_functions/variable_length_quantity.d.ts +12 -0
- package/package/@types/utils/indexed_array.d.ts +21 -0
- package/package/@types/utils/loggin.d.ts +26 -0
- package/package/@types/utils/other.d.ts +32 -0
- package/package/LICENSE +26 -0
- package/package/README.md +84 -0
- package/package/externals/NOTICE +9 -0
- package/package/externals/libvorbis/@types/OggVorbisEncoder.d.ts +34 -0
- package/package/externals/libvorbis/OggVorbisEncoder.min.js +1 -0
- package/package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +12 -0
- package/package/externals/stbvorbis_sync/LICENSE +202 -0
- package/package/externals/stbvorbis_sync/stbvorbis_sync.min.js +1 -0
- package/package/index.js +73 -0
- package/package/midi_handler/README.md +3 -0
- package/package/midi_handler/midi_handler.js +118 -0
- package/package/midi_handler/web_midi_link.js +41 -0
- package/package/midi_parser/README.md +3 -0
- package/package/midi_parser/midi_data.js +121 -0
- package/package/midi_parser/midi_editor.js +557 -0
- package/package/midi_parser/midi_loader.js +502 -0
- package/package/midi_parser/midi_message.js +234 -0
- package/package/midi_parser/midi_writer.js +95 -0
- package/package/midi_parser/rmidi_writer.js +271 -0
- package/package/midi_parser/used_keys_loaded.js +172 -0
- package/package/package.json +43 -0
- package/package/sequencer/README.md +23 -0
- package/package/sequencer/sequencer.js +439 -0
- package/package/sequencer/worklet_sequencer/events.js +92 -0
- package/package/sequencer/worklet_sequencer/play.js +309 -0
- package/package/sequencer/worklet_sequencer/process_event.js +167 -0
- package/package/sequencer/worklet_sequencer/process_tick.js +85 -0
- package/package/sequencer/worklet_sequencer/sequencer_message.js +39 -0
- package/package/sequencer/worklet_sequencer/song_control.js +193 -0
- package/package/sequencer/worklet_sequencer/worklet_sequencer.js +218 -0
- package/package/soundfont/README.md +8 -0
- package/package/soundfont/read/generators.js +212 -0
- package/package/soundfont/read/instruments.js +125 -0
- package/package/soundfont/read/modulators.js +249 -0
- package/package/soundfont/read/presets.js +300 -0
- package/package/soundfont/read/riff_chunk.js +81 -0
- package/package/soundfont/read/samples.js +398 -0
- package/package/soundfont/read/zones.js +310 -0
- package/package/soundfont/soundfont.js +357 -0
- package/package/soundfont/write/ibag.js +39 -0
- package/package/soundfont/write/igen.js +75 -0
- package/package/soundfont/write/imod.js +46 -0
- package/package/soundfont/write/inst.js +34 -0
- package/package/soundfont/write/pbag.js +39 -0
- package/package/soundfont/write/pgen.js +77 -0
- package/package/soundfont/write/phdr.js +42 -0
- package/package/soundfont/write/pmod.js +46 -0
- package/package/soundfont/write/sdta.js +72 -0
- package/package/soundfont/write/shdr.js +54 -0
- package/package/soundfont/write/soundfont_trimmer.js +169 -0
- package/package/soundfont/write/write.js +180 -0
- package/package/synthetizer/README.md +6 -0
- package/package/synthetizer/audio_effects/effects_config.js +21 -0
- package/package/synthetizer/audio_effects/fancy_chorus.js +120 -0
- package/package/synthetizer/audio_effects/impulse_response_2.flac +0 -0
- package/package/synthetizer/audio_effects/reverb.js +24 -0
- package/package/synthetizer/synth_event_handler.js +156 -0
- package/package/synthetizer/synthetizer.js +766 -0
- package/package/synthetizer/worklet_processor.min.js +13 -0
- package/package/synthetizer/worklet_system/README.md +6 -0
- package/package/synthetizer/worklet_system/main_processor.js +363 -0
- package/package/synthetizer/worklet_system/message_protocol/handle_message.js +197 -0
- package/package/synthetizer/worklet_system/message_protocol/message_sending.js +74 -0
- package/package/synthetizer/worklet_system/message_protocol/worklet_message.js +121 -0
- package/package/synthetizer/worklet_system/minify_processor.sh +4 -0
- package/package/synthetizer/worklet_system/worklet_methods/controller_control.js +230 -0
- package/package/synthetizer/worklet_system/worklet_methods/data_entry.js +277 -0
- package/package/synthetizer/worklet_system/worklet_methods/note_off.js +109 -0
- package/package/synthetizer/worklet_system/worklet_methods/note_on.js +91 -0
- package/package/synthetizer/worklet_system/worklet_methods/program_control.js +183 -0
- package/package/synthetizer/worklet_system/worklet_methods/reset_controllers.js +177 -0
- package/package/synthetizer/worklet_system/worklet_methods/snapshot.js +129 -0
- package/package/synthetizer/worklet_system/worklet_methods/system_exclusive.js +272 -0
- package/package/synthetizer/worklet_system/worklet_methods/tuning_control.js +195 -0
- package/package/synthetizer/worklet_system/worklet_methods/vibrato_control.js +29 -0
- package/package/synthetizer/worklet_system/worklet_methods/voice_control.js +233 -0
- package/package/synthetizer/worklet_system/worklet_processor.js +9 -0
- package/package/synthetizer/worklet_system/worklet_utilities/lfo.js +23 -0
- package/package/synthetizer/worklet_system/worklet_utilities/lowpass_filter.js +130 -0
- package/package/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +73 -0
- package/package/synthetizer/worklet_system/worklet_utilities/modulator_curves.js +86 -0
- package/package/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +81 -0
- package/package/synthetizer/worklet_system/worklet_utilities/unit_converter.js +66 -0
- package/package/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +265 -0
- package/package/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +83 -0
- package/package/synthetizer/worklet_system/worklet_utilities/worklet_modulator.js +234 -0
- package/package/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +116 -0
- package/package/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +272 -0
- package/package/synthetizer/worklet_url.js +5 -0
- package/package/utils/README.md +4 -0
- package/package/utils/buffer_to_wav.js +101 -0
- package/package/utils/byte_functions/big_endian.js +28 -0
- package/package/utils/byte_functions/little_endian.js +74 -0
- package/package/utils/byte_functions/string.js +97 -0
- package/package/utils/byte_functions/variable_length_quantity.js +37 -0
- package/package/utils/encode_vorbis.js +30 -0
- package/package/utils/indexed_array.js +41 -0
- package/package/utils/loggin.js +79 -0
- package/package/utils/other.js +54 -0
- package/package.json +43 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { arrayToHexString, consoleColors } from '../../../utils/other.js'
|
|
2
|
+
import { SpessaSynthInfo, SpessaSynthWarn } from '../../../utils/loggin.js'
|
|
3
|
+
/**
|
|
4
|
+
* Executes a system exclusive
|
|
5
|
+
* @param messageData {number[]|IndexedByteArray} - the message data without f0
|
|
6
|
+
* @param channelOffset {number}
|
|
7
|
+
* @this {SpessaSynthProcessor}
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export function systemExclusive(messageData, channelOffset = 0)
|
|
11
|
+
{
|
|
12
|
+
const type = messageData[0];
|
|
13
|
+
switch (type)
|
|
14
|
+
{
|
|
15
|
+
default:
|
|
16
|
+
SpessaSynthWarn(`%cUnrecognized SysEx: %c${arrayToHexString(messageData)}`,
|
|
17
|
+
consoleColors.warn,
|
|
18
|
+
consoleColors.unrecognized);
|
|
19
|
+
break;
|
|
20
|
+
|
|
21
|
+
// non realtime
|
|
22
|
+
case 0x7E:
|
|
23
|
+
// gm system
|
|
24
|
+
if(messageData[2] === 0x09)
|
|
25
|
+
{
|
|
26
|
+
if(messageData[3] === 0x01)
|
|
27
|
+
{
|
|
28
|
+
SpessaSynthInfo("%cGM system on", consoleColors.info);
|
|
29
|
+
this.system = "gm";
|
|
30
|
+
}
|
|
31
|
+
else if(messageData[3] === 0x03)
|
|
32
|
+
{
|
|
33
|
+
SpessaSynthInfo("%cGM2 system on", consoleColors.info);
|
|
34
|
+
this.system = "gm2";
|
|
35
|
+
}
|
|
36
|
+
else
|
|
37
|
+
{
|
|
38
|
+
SpessaSynthInfo("%cGM system off, defaulting to GS", consoleColors.info);
|
|
39
|
+
this.system = "gs";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
break;
|
|
43
|
+
|
|
44
|
+
// realtime
|
|
45
|
+
case 0x7F:
|
|
46
|
+
if(messageData[2] === 0x04 && messageData[3] === 0x01)
|
|
47
|
+
{
|
|
48
|
+
// main volume
|
|
49
|
+
const vol = messageData[5] << 7 | messageData[4];
|
|
50
|
+
this.setMIDIVolume(vol / 16384);
|
|
51
|
+
SpessaSynthInfo(`%cMaster Volume. Volume: %c${vol}`,
|
|
52
|
+
consoleColors.info,
|
|
53
|
+
consoleColors.value);
|
|
54
|
+
}
|
|
55
|
+
else
|
|
56
|
+
if(messageData[2] === 0x04 && messageData[3] === 0x03)
|
|
57
|
+
{
|
|
58
|
+
// fine tuning
|
|
59
|
+
const tuningValue = ((messageData[5] << 7) | messageData[6]) - 8192;
|
|
60
|
+
const cents = Math.floor(tuningValue / 81.92); // [-100;+99] cents range
|
|
61
|
+
this.setMasterTuning(cents);
|
|
62
|
+
SpessaSynthInfo(`%cMaster Fine Tuning. Cents: %c${cents}`,
|
|
63
|
+
consoleColors.info,
|
|
64
|
+
consoleColors.value)
|
|
65
|
+
}
|
|
66
|
+
else
|
|
67
|
+
if(messageData[2] === 0x04 && messageData[3] === 0x04)
|
|
68
|
+
{
|
|
69
|
+
// coarse tuning
|
|
70
|
+
// lsb is ignored
|
|
71
|
+
const semitones = messageData[5] - 64;
|
|
72
|
+
const cents = semitones * 100;
|
|
73
|
+
this.setMasterTuning(cents);
|
|
74
|
+
SpessaSynthInfo(`%cMaster Coarse Tuning. Cents: %c${cents}`,
|
|
75
|
+
consoleColors.info,
|
|
76
|
+
consoleColors.value)
|
|
77
|
+
}
|
|
78
|
+
else
|
|
79
|
+
{
|
|
80
|
+
SpessaSynthWarn(
|
|
81
|
+
`%cUnrecognized MIDI Real-time message: %c${arrayToHexString(messageData)}`,
|
|
82
|
+
consoleColors.warn,
|
|
83
|
+
consoleColors.unrecognized)
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
|
|
87
|
+
// this is a roland sysex
|
|
88
|
+
// http://www.bandtrax.com.au/sysex.htm
|
|
89
|
+
// https://cdn.roland.com/assets/media/pdf/AT-20R_30R_MI.pdf
|
|
90
|
+
case 0x41:
|
|
91
|
+
// messagedata[1] is device id (ignore as we're everything >:) )
|
|
92
|
+
if(messageData[2] === 0x42 && messageData[3] === 0x12)
|
|
93
|
+
{
|
|
94
|
+
// this is a GS sysex
|
|
95
|
+
// messageData[5] and [6] is the system parameter, messageData[7] is the value
|
|
96
|
+
const messageValue = messageData[7];
|
|
97
|
+
if(messageData[6] === 0x7F)
|
|
98
|
+
{
|
|
99
|
+
// GS mode set
|
|
100
|
+
if(messageValue === 0x00)
|
|
101
|
+
{
|
|
102
|
+
// this is a GS reset
|
|
103
|
+
SpessaSynthInfo("%cGS system on", consoleColors.info);
|
|
104
|
+
this.system = "gs";
|
|
105
|
+
}
|
|
106
|
+
else if(messageValue === 0x7F)
|
|
107
|
+
{
|
|
108
|
+
// GS mode off
|
|
109
|
+
SpessaSynthInfo("%cGS system off, switching to GM2", consoleColors.info);
|
|
110
|
+
this.system = "gm2";
|
|
111
|
+
}
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
else
|
|
115
|
+
if(messageData[4] === 0x40)
|
|
116
|
+
{
|
|
117
|
+
// this is a system parameter
|
|
118
|
+
if((messageData[5] & 0x10) > 0)
|
|
119
|
+
{
|
|
120
|
+
// this is an individual part (channel) parameter
|
|
121
|
+
// determine the channel 0 means channel 10 (default), 1 means 1 etc.
|
|
122
|
+
let channel = [9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15][messageData[5] & 0x0F] + channelOffset;
|
|
123
|
+
// for example 1A means A = 11, which corresponds to channel 12 (counting from 1)
|
|
124
|
+
switch (messageData[6])
|
|
125
|
+
{
|
|
126
|
+
default:
|
|
127
|
+
break;
|
|
128
|
+
|
|
129
|
+
case 0x15:
|
|
130
|
+
// this is the Use for Drum Part sysex (multiple drums)
|
|
131
|
+
const isDrums = messageValue > 0 && messageData[5] >> 4; // if set to other than 0, is a drum channel
|
|
132
|
+
this.setDrums(channel, isDrums);
|
|
133
|
+
SpessaSynthInfo(
|
|
134
|
+
`%cChannel %c${channel}%c ${isDrums ?
|
|
135
|
+
"is now a drum channel"
|
|
136
|
+
:
|
|
137
|
+
"now isn't a drum channel"
|
|
138
|
+
}%c via: %c${arrayToHexString(messageData)}`,
|
|
139
|
+
consoleColors.info,
|
|
140
|
+
consoleColors.value,
|
|
141
|
+
consoleColors.recognized,
|
|
142
|
+
consoleColors.info,
|
|
143
|
+
consoleColors.value);
|
|
144
|
+
return;
|
|
145
|
+
|
|
146
|
+
case 0x16:
|
|
147
|
+
// this is the pitch key shift sysex
|
|
148
|
+
const keyShift = messageValue - 64;
|
|
149
|
+
this.transposeChannel(channel, keyShift);
|
|
150
|
+
SpessaSynthInfo(`%cChannel %c${channel}%c pitch shift. Semitones %c${keyShift}%c, with %c${arrayToHexString(messageData)}`,
|
|
151
|
+
consoleColors.info,
|
|
152
|
+
consoleColors.recognized,
|
|
153
|
+
consoleColors.info,
|
|
154
|
+
consoleColors.value,
|
|
155
|
+
consoleColors.info,
|
|
156
|
+
consoleColors.value);
|
|
157
|
+
return;
|
|
158
|
+
|
|
159
|
+
case 0x40:
|
|
160
|
+
case 0x41:
|
|
161
|
+
case 0x42:
|
|
162
|
+
case 0x43:
|
|
163
|
+
case 0x44:
|
|
164
|
+
case 0x45:
|
|
165
|
+
case 0x46:
|
|
166
|
+
case 0x47:
|
|
167
|
+
case 0x48:
|
|
168
|
+
case 0x49:
|
|
169
|
+
case 0x4A:
|
|
170
|
+
case 0x4B:
|
|
171
|
+
// scale tuning
|
|
172
|
+
const cents = messageValue - 64;
|
|
173
|
+
SpessaSynthInfo(`%cChannel %c${channel}%c tuning. Cents %c${cents}%c, with %c${arrayToHexString(messageData)}`,
|
|
174
|
+
consoleColors.info,
|
|
175
|
+
consoleColors.recognized,
|
|
176
|
+
consoleColors.info,
|
|
177
|
+
consoleColors.value,
|
|
178
|
+
consoleColors.info,
|
|
179
|
+
consoleColors.value);
|
|
180
|
+
this.setChannelTuning(channel, cents);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else
|
|
184
|
+
// this is a global system parameter
|
|
185
|
+
if(messageData[5] === 0x00 && messageData[6] === 0x06)
|
|
186
|
+
{
|
|
187
|
+
// roland master pan
|
|
188
|
+
SpessaSynthInfo(`%cRoland GS Master Pan set to: %c${messageValue}%c with: %c${arrayToHexString(messageData)}`,
|
|
189
|
+
consoleColors.info,
|
|
190
|
+
consoleColors.value,
|
|
191
|
+
consoleColors.info,
|
|
192
|
+
consoleColors.value);
|
|
193
|
+
this.setMasterPan((messageValue - 64) / 64);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
else
|
|
197
|
+
if(messageData[5] === 0x00 && messageData[6] === 0x05)
|
|
198
|
+
{
|
|
199
|
+
// roland master key shift (transpose)
|
|
200
|
+
const transpose = messageValue - 64;
|
|
201
|
+
SpessaSynthInfo(`%cRoland GS Master Key-Shift set to: %c${transpose}%c with: %c${arrayToHexString(messageData)}`,
|
|
202
|
+
consoleColors.info,
|
|
203
|
+
consoleColors.value,
|
|
204
|
+
consoleColors.info,
|
|
205
|
+
consoleColors.value);
|
|
206
|
+
this.setMasterTuning(transpose * 100);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
else
|
|
210
|
+
if(messageData[5] === 0x00 && messageData[6] === 0x04)
|
|
211
|
+
{
|
|
212
|
+
// roland GS master volume
|
|
213
|
+
SpessaSynthInfo(`%cRoland GS Master Volume set to: %c${messageValue}%c with: %c${arrayToHexString(messageData)}`,
|
|
214
|
+
consoleColors.info,
|
|
215
|
+
consoleColors.value,
|
|
216
|
+
consoleColors.info,
|
|
217
|
+
consoleColors.value);
|
|
218
|
+
this.setMIDIVolume(messageValue / 127);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// this is some other GS sysex...
|
|
223
|
+
SpessaSynthWarn(`%cUnrecognized Roland %cGS %cSysEx: %c${arrayToHexString(messageData)}`,
|
|
224
|
+
consoleColors.warn,
|
|
225
|
+
consoleColors.recognized,
|
|
226
|
+
consoleColors.warn,
|
|
227
|
+
consoleColors.unrecognized);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
else
|
|
231
|
+
if(messageData[2] === 0x16 && messageData[3] === 0x12 && messageData[4] === 0x10)
|
|
232
|
+
{
|
|
233
|
+
// this is a roland master volume message
|
|
234
|
+
this.setMIDIVolume(messageData[7] / 100);
|
|
235
|
+
SpessaSynthInfo(`%cRoland Master Volume control set to: %c${messageData[7]}%c via: %c${arrayToHexString(messageData)}`,
|
|
236
|
+
consoleColors.info,
|
|
237
|
+
consoleColors.value,
|
|
238
|
+
consoleColors.info,
|
|
239
|
+
consoleColors.value);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
else
|
|
243
|
+
{
|
|
244
|
+
// this is something else...
|
|
245
|
+
SpessaSynthWarn(`%cUnrecognized Roland SysEx: %c${arrayToHexString(messageData)}`,
|
|
246
|
+
consoleColors.warn,
|
|
247
|
+
consoleColors.unrecognized);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// yamaha
|
|
252
|
+
case 0x43:
|
|
253
|
+
// XG on
|
|
254
|
+
if(messageData[2] === 0x4C && messageData[5] === 0x7E && messageData[6] === 0x00)
|
|
255
|
+
{
|
|
256
|
+
SpessaSynthInfo("%cXG system on", consoleColors.info);
|
|
257
|
+
this.system = "xg";
|
|
258
|
+
}
|
|
259
|
+
else
|
|
260
|
+
{
|
|
261
|
+
if(this.system === "xg")
|
|
262
|
+
{
|
|
263
|
+
SpessaSynthWarn(`%cUnrecognized Yamaha SysEx: %c${arrayToHexString(messageData)}`,
|
|
264
|
+
consoleColors.warn,
|
|
265
|
+
consoleColors.unrecognized);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
break;
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
}
|
|
272
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { customControllers, NON_CC_INDEX_OFFSET } from '../worklet_utilities/worklet_processor_channel.js'
|
|
2
|
+
import { consoleColors } from '../../../utils/other.js'
|
|
3
|
+
import { modulatorSources } from '../../../soundfont/read/modulators.js'
|
|
4
|
+
import { computeModulators } from '../worklet_utilities/worklet_modulator.js'
|
|
5
|
+
import { SpessaSynthInfo } from '../../../utils/loggin.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(`%cChannel ${channel} fine tuning. Cents: %c${cents}`,
|
|
72
|
+
consoleColors.info,
|
|
73
|
+
consoleColors.value);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Sets the channel's tuning in semitones
|
|
78
|
+
* @param channel {number}
|
|
79
|
+
* @param semitones {number}
|
|
80
|
+
* @this {SpessaSynthProcessor}
|
|
81
|
+
*/
|
|
82
|
+
export function setChannelTuningSemitones(channel, semitones)
|
|
83
|
+
{
|
|
84
|
+
const channelObject = this.workletProcessorChannels[channel];
|
|
85
|
+
semitones = Math.round(semitones);
|
|
86
|
+
channelObject.customControllers[customControllers.channelTuningSemitones] = semitones;
|
|
87
|
+
SpessaSynthInfo(`%cChannel ${channel} coarse tuning. Semitones: %c${semitones}`,
|
|
88
|
+
consoleColors.info,
|
|
89
|
+
consoleColors.value);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Sets the worklet's master tuning
|
|
94
|
+
* @this {SpessaSynthProcessor}
|
|
95
|
+
* @param cents {number}
|
|
96
|
+
*/
|
|
97
|
+
export function setMasterTuning(cents)
|
|
98
|
+
{
|
|
99
|
+
cents = Math.round(cents);
|
|
100
|
+
for (let i = 0; i < this.workletProcessorChannels.length; i++) {
|
|
101
|
+
this.workletProcessorChannels[i].customControllers[customControllers.masterTuning] = cents;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @this {SpessaSynthProcessor}
|
|
107
|
+
* @param channel {number}
|
|
108
|
+
* @param cents {number}
|
|
109
|
+
*/
|
|
110
|
+
export function setModulationDepth(channel, cents)
|
|
111
|
+
{
|
|
112
|
+
let channelObject = this.workletProcessorChannels[channel];
|
|
113
|
+
cents = Math.round(cents);
|
|
114
|
+
SpessaSynthInfo(`%cChannel ${channel} modulation depth. Cents: %c${cents}`,
|
|
115
|
+
consoleColors.info,
|
|
116
|
+
consoleColors.value);
|
|
117
|
+
/* ==============
|
|
118
|
+
IMPORTANT
|
|
119
|
+
here we convert cents into a multiplier.
|
|
120
|
+
midi spec assumes the default is 50 cents,
|
|
121
|
+
but it might be different for the soundfont
|
|
122
|
+
so we create a multiplier by divinging cents by 50.
|
|
123
|
+
for example, if we want 100 cents, then multiplier will be 2,
|
|
124
|
+
which for a preset with depth of 50 will create 100.
|
|
125
|
+
================ */
|
|
126
|
+
channelObject.customControllers[customControllers.modulationMultiplier] = cents / 50;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Sets the pitch of the given channel
|
|
131
|
+
* @this {SpessaSynthProcessor}
|
|
132
|
+
* @param channel {number} usually 0-15: the channel to change pitch
|
|
133
|
+
* @param MSB {number} SECOND byte of the MIDI pitchWheel message
|
|
134
|
+
* @param LSB {number} FIRST byte of the MIDI pitchWheel message
|
|
135
|
+
*/
|
|
136
|
+
export function pitchWheel(channel, MSB, LSB)
|
|
137
|
+
{
|
|
138
|
+
if(this.workletProcessorChannels[channel].lockedControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel])
|
|
139
|
+
{
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const bend = (LSB | (MSB << 7));
|
|
143
|
+
this.callEvent("pitchwheel", {
|
|
144
|
+
channel: channel,
|
|
145
|
+
MSB: MSB,
|
|
146
|
+
LSB: LSB
|
|
147
|
+
});
|
|
148
|
+
this.workletProcessorChannels[channel].midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel] = bend;
|
|
149
|
+
this.workletProcessorChannels[channel].voices.forEach(v =>
|
|
150
|
+
// compute pitch modulators
|
|
151
|
+
computeModulators(v, this.workletProcessorChannels[channel].midiControllers, 0, modulatorSources.pitchWheel));
|
|
152
|
+
this.sendChannelProperties();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Sets the pressure of the given channel
|
|
157
|
+
* @this {SpessaSynthProcessor}
|
|
158
|
+
* @param channel {number} usually 0-15: the channel to change pitch
|
|
159
|
+
* @param pressure {number} the pressure of the channel
|
|
160
|
+
*/
|
|
161
|
+
export function channelPressure(channel, pressure)
|
|
162
|
+
{
|
|
163
|
+
const channelObject = this.workletProcessorChannels[channel];
|
|
164
|
+
channelObject.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.channelPressure] = pressure << 7;
|
|
165
|
+
this.workletProcessorChannels[channel].voices.forEach(v =>
|
|
166
|
+
computeModulators(v, channelObject.midiControllers, 0, modulatorSources.channelPressure));
|
|
167
|
+
this.callEvent("channelpressure",{
|
|
168
|
+
channel: channel,
|
|
169
|
+
pressure: pressure
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Sets the pressure of the given note on a specific channel
|
|
175
|
+
* @this {SpessaSynthProcessor}
|
|
176
|
+
* @param channel {number} usually 0-15: the channel to change pitch
|
|
177
|
+
* @param midiNote {number} 0-127
|
|
178
|
+
* @param pressure {number} the pressure of the note
|
|
179
|
+
*/
|
|
180
|
+
export function polyPressure(channel, midiNote, pressure)
|
|
181
|
+
{
|
|
182
|
+
this.workletProcessorChannels[channel].voices.forEach(v => {
|
|
183
|
+
if(v.midiNote !== midiNote)
|
|
184
|
+
{
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
v.pressure = pressure;
|
|
188
|
+
computeModulators(v, this.workletProcessorChannels[channel].midiControllers, 0, modulatorSources.polyPressure);
|
|
189
|
+
});
|
|
190
|
+
this.callEvent("polypressure", {
|
|
191
|
+
channel: channel,
|
|
192
|
+
midiNote: midiNote,
|
|
193
|
+
pressure: pressure
|
|
194
|
+
});
|
|
195
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param channel {number}
|
|
3
|
+
* @this {SpessaSynthProcessor}
|
|
4
|
+
*/
|
|
5
|
+
export function disableAndLockVibrato(channel)
|
|
6
|
+
{
|
|
7
|
+
this.workletProcessorChannels[channel].lockVibrato = 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].lockVibrato)
|
|
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
|
+
}
|