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.
Files changed (154) hide show
  1. package/.idea/modules.xml +8 -0
  2. package/.idea/spessasynth_lib.iml +12 -0
  3. package/.idea/vcs.xml +6 -0
  4. package/copy_version.sh +38 -0
  5. package/index.js +73 -0
  6. package/package/@types/externals/stbvorbis_sync/stbvorbis_sync.min.d.ts +1 -0
  7. package/package/@types/index.d.ts +34 -0
  8. package/package/@types/midi_handler/midi_handler.d.ts +39 -0
  9. package/package/@types/midi_handler/web_midi_link.d.ts +12 -0
  10. package/package/@types/midi_parser/midi_data.d.ts +95 -0
  11. package/package/@types/midi_parser/midi_editor.d.ts +45 -0
  12. package/package/@types/midi_parser/midi_loader.d.ts +100 -0
  13. package/package/@types/midi_parser/midi_message.d.ts +154 -0
  14. package/package/@types/midi_parser/midi_writer.d.ts +6 -0
  15. package/package/@types/midi_parser/rmidi_writer.d.ts +9 -0
  16. package/package/@types/midi_parser/used_keys_loaded.d.ts +7 -0
  17. package/package/@types/sequencer/sequencer.d.ts +180 -0
  18. package/package/@types/sequencer/worklet_sequencer/sequencer_message.d.ts +28 -0
  19. package/package/@types/soundfont/read/generators.d.ts +98 -0
  20. package/package/@types/soundfont/read/instruments.d.ts +50 -0
  21. package/package/@types/soundfont/read/modulators.d.ts +73 -0
  22. package/package/@types/soundfont/read/presets.d.ts +87 -0
  23. package/package/@types/soundfont/read/riff_chunk.d.ts +31 -0
  24. package/package/@types/soundfont/read/samples.d.ts +134 -0
  25. package/package/@types/soundfont/read/zones.d.ts +141 -0
  26. package/package/@types/soundfont/soundfont.d.ts +76 -0
  27. package/package/@types/soundfont/write/ibag.d.ts +6 -0
  28. package/package/@types/soundfont/write/igen.d.ts +6 -0
  29. package/package/@types/soundfont/write/imod.d.ts +6 -0
  30. package/package/@types/soundfont/write/inst.d.ts +6 -0
  31. package/package/@types/soundfont/write/pbag.d.ts +6 -0
  32. package/package/@types/soundfont/write/pgen.d.ts +6 -0
  33. package/package/@types/soundfont/write/phdr.d.ts +6 -0
  34. package/package/@types/soundfont/write/pmod.d.ts +6 -0
  35. package/package/@types/soundfont/write/sdta.d.ts +11 -0
  36. package/package/@types/soundfont/write/shdr.d.ts +8 -0
  37. package/package/@types/soundfont/write/soundfont_trimmer.d.ts +6 -0
  38. package/package/@types/soundfont/write/write.d.ts +21 -0
  39. package/package/@types/synthetizer/audio_effects/effects_config.d.ts +29 -0
  40. package/package/@types/synthetizer/audio_effects/fancy_chorus.d.ts +93 -0
  41. package/package/@types/synthetizer/audio_effects/reverb.d.ts +7 -0
  42. package/package/@types/synthetizer/synth_event_handler.d.ts +161 -0
  43. package/package/@types/synthetizer/synthetizer.d.ts +294 -0
  44. package/package/@types/synthetizer/worklet_system/message_protocol/worklet_message.d.ts +89 -0
  45. package/package/@types/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.d.ts +134 -0
  46. package/package/@types/synthetizer/worklet_url.d.ts +5 -0
  47. package/package/@types/utils/buffer_to_wav.d.ts +8 -0
  48. package/package/@types/utils/byte_functions/big_endian.d.ts +13 -0
  49. package/package/@types/utils/byte_functions/little_endian.d.ts +35 -0
  50. package/package/@types/utils/byte_functions/string.d.ts +22 -0
  51. package/package/@types/utils/byte_functions/variable_length_quantity.d.ts +12 -0
  52. package/package/@types/utils/indexed_array.d.ts +21 -0
  53. package/package/@types/utils/loggin.d.ts +26 -0
  54. package/package/@types/utils/other.d.ts +32 -0
  55. package/package/LICENSE +26 -0
  56. package/package/README.md +84 -0
  57. package/package/externals/NOTICE +9 -0
  58. package/package/externals/libvorbis/@types/OggVorbisEncoder.d.ts +34 -0
  59. package/package/externals/libvorbis/OggVorbisEncoder.min.js +1 -0
  60. package/package/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +12 -0
  61. package/package/externals/stbvorbis_sync/LICENSE +202 -0
  62. package/package/externals/stbvorbis_sync/stbvorbis_sync.min.js +1 -0
  63. package/package/index.js +73 -0
  64. package/package/midi_handler/README.md +3 -0
  65. package/package/midi_handler/midi_handler.js +118 -0
  66. package/package/midi_handler/web_midi_link.js +41 -0
  67. package/package/midi_parser/README.md +3 -0
  68. package/package/midi_parser/midi_data.js +121 -0
  69. package/package/midi_parser/midi_editor.js +557 -0
  70. package/package/midi_parser/midi_loader.js +502 -0
  71. package/package/midi_parser/midi_message.js +234 -0
  72. package/package/midi_parser/midi_writer.js +95 -0
  73. package/package/midi_parser/rmidi_writer.js +271 -0
  74. package/package/midi_parser/used_keys_loaded.js +172 -0
  75. package/package/package.json +43 -0
  76. package/package/sequencer/README.md +23 -0
  77. package/package/sequencer/sequencer.js +439 -0
  78. package/package/sequencer/worklet_sequencer/events.js +92 -0
  79. package/package/sequencer/worklet_sequencer/play.js +309 -0
  80. package/package/sequencer/worklet_sequencer/process_event.js +167 -0
  81. package/package/sequencer/worklet_sequencer/process_tick.js +85 -0
  82. package/package/sequencer/worklet_sequencer/sequencer_message.js +39 -0
  83. package/package/sequencer/worklet_sequencer/song_control.js +193 -0
  84. package/package/sequencer/worklet_sequencer/worklet_sequencer.js +218 -0
  85. package/package/soundfont/README.md +8 -0
  86. package/package/soundfont/read/generators.js +212 -0
  87. package/package/soundfont/read/instruments.js +125 -0
  88. package/package/soundfont/read/modulators.js +249 -0
  89. package/package/soundfont/read/presets.js +300 -0
  90. package/package/soundfont/read/riff_chunk.js +81 -0
  91. package/package/soundfont/read/samples.js +398 -0
  92. package/package/soundfont/read/zones.js +310 -0
  93. package/package/soundfont/soundfont.js +357 -0
  94. package/package/soundfont/write/ibag.js +39 -0
  95. package/package/soundfont/write/igen.js +75 -0
  96. package/package/soundfont/write/imod.js +46 -0
  97. package/package/soundfont/write/inst.js +34 -0
  98. package/package/soundfont/write/pbag.js +39 -0
  99. package/package/soundfont/write/pgen.js +77 -0
  100. package/package/soundfont/write/phdr.js +42 -0
  101. package/package/soundfont/write/pmod.js +46 -0
  102. package/package/soundfont/write/sdta.js +72 -0
  103. package/package/soundfont/write/shdr.js +54 -0
  104. package/package/soundfont/write/soundfont_trimmer.js +169 -0
  105. package/package/soundfont/write/write.js +180 -0
  106. package/package/synthetizer/README.md +6 -0
  107. package/package/synthetizer/audio_effects/effects_config.js +21 -0
  108. package/package/synthetizer/audio_effects/fancy_chorus.js +120 -0
  109. package/package/synthetizer/audio_effects/impulse_response_2.flac +0 -0
  110. package/package/synthetizer/audio_effects/reverb.js +24 -0
  111. package/package/synthetizer/synth_event_handler.js +156 -0
  112. package/package/synthetizer/synthetizer.js +766 -0
  113. package/package/synthetizer/worklet_processor.min.js +13 -0
  114. package/package/synthetizer/worklet_system/README.md +6 -0
  115. package/package/synthetizer/worklet_system/main_processor.js +363 -0
  116. package/package/synthetizer/worklet_system/message_protocol/handle_message.js +197 -0
  117. package/package/synthetizer/worklet_system/message_protocol/message_sending.js +74 -0
  118. package/package/synthetizer/worklet_system/message_protocol/worklet_message.js +121 -0
  119. package/package/synthetizer/worklet_system/minify_processor.sh +4 -0
  120. package/package/synthetizer/worklet_system/worklet_methods/controller_control.js +230 -0
  121. package/package/synthetizer/worklet_system/worklet_methods/data_entry.js +277 -0
  122. package/package/synthetizer/worklet_system/worklet_methods/note_off.js +109 -0
  123. package/package/synthetizer/worklet_system/worklet_methods/note_on.js +91 -0
  124. package/package/synthetizer/worklet_system/worklet_methods/program_control.js +183 -0
  125. package/package/synthetizer/worklet_system/worklet_methods/reset_controllers.js +177 -0
  126. package/package/synthetizer/worklet_system/worklet_methods/snapshot.js +129 -0
  127. package/package/synthetizer/worklet_system/worklet_methods/system_exclusive.js +272 -0
  128. package/package/synthetizer/worklet_system/worklet_methods/tuning_control.js +195 -0
  129. package/package/synthetizer/worklet_system/worklet_methods/vibrato_control.js +29 -0
  130. package/package/synthetizer/worklet_system/worklet_methods/voice_control.js +233 -0
  131. package/package/synthetizer/worklet_system/worklet_processor.js +9 -0
  132. package/package/synthetizer/worklet_system/worklet_utilities/lfo.js +23 -0
  133. package/package/synthetizer/worklet_system/worklet_utilities/lowpass_filter.js +130 -0
  134. package/package/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +73 -0
  135. package/package/synthetizer/worklet_system/worklet_utilities/modulator_curves.js +86 -0
  136. package/package/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +81 -0
  137. package/package/synthetizer/worklet_system/worklet_utilities/unit_converter.js +66 -0
  138. package/package/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +265 -0
  139. package/package/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +83 -0
  140. package/package/synthetizer/worklet_system/worklet_utilities/worklet_modulator.js +234 -0
  141. package/package/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +116 -0
  142. package/package/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +272 -0
  143. package/package/synthetizer/worklet_url.js +5 -0
  144. package/package/utils/README.md +4 -0
  145. package/package/utils/buffer_to_wav.js +101 -0
  146. package/package/utils/byte_functions/big_endian.js +28 -0
  147. package/package/utils/byte_functions/little_endian.js +74 -0
  148. package/package/utils/byte_functions/string.js +97 -0
  149. package/package/utils/byte_functions/variable_length_quantity.js +37 -0
  150. package/package/utils/encode_vorbis.js +30 -0
  151. package/package/utils/indexed_array.js +41 -0
  152. package/package/utils/loggin.js +79 -0
  153. package/package/utils/other.js +54 -0
  154. 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
+ }