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.
Files changed (61) hide show
  1. package/midi_parser/basic_midi.js +457 -68
  2. package/midi_parser/midi_loader.js +18 -503
  3. package/midi_parser/midi_message.js +18 -5
  4. package/midi_parser/midi_sequence.js +2 -2
  5. package/package.json +1 -1
  6. package/sequencer/worklet_sequencer/process_event.js +1 -6
  7. package/synthetizer/synthetizer.js +13 -7
  8. package/synthetizer/worklet_processor.min.js +12 -12
  9. package/synthetizer/worklet_system/README.md +2 -2
  10. package/synthetizer/worklet_system/main_processor.js +106 -95
  11. package/synthetizer/worklet_system/message_protocol/handle_message.js +22 -17
  12. package/synthetizer/worklet_system/message_protocol/worklet_message.js +2 -1
  13. package/synthetizer/worklet_system/snapshot/apply_synthesizer_snapshot.js +14 -0
  14. package/synthetizer/worklet_system/snapshot/channel_snapshot.js +166 -0
  15. package/synthetizer/worklet_system/snapshot/send_synthesizer_snapshot.js +14 -0
  16. package/synthetizer/worklet_system/snapshot/synthesizer_snapshot.js +121 -0
  17. package/synthetizer/worklet_system/worklet_methods/controller_control/controller_change.js +196 -0
  18. package/synthetizer/worklet_system/worklet_methods/controller_control/master_parameters.js +34 -0
  19. package/synthetizer/worklet_system/worklet_methods/{reset_controllers.js → controller_control/reset_controllers.js} +33 -39
  20. package/synthetizer/worklet_system/worklet_methods/create_worklet_channel.js +26 -0
  21. package/synthetizer/worklet_system/worklet_methods/{data_entry.js → data_entry/data_entry_coarse.js} +38 -105
  22. package/synthetizer/worklet_system/worklet_methods/data_entry/data_entry_fine.js +64 -0
  23. package/synthetizer/worklet_system/worklet_methods/mute_channel.js +17 -0
  24. package/synthetizer/worklet_system/worklet_methods/note_on.js +36 -34
  25. package/synthetizer/worklet_system/worklet_methods/program_change.js +49 -0
  26. package/synthetizer/worklet_system/worklet_methods/{voice_control.js → render_voice.js} +37 -120
  27. package/synthetizer/worklet_system/worklet_methods/soundfont_management/clear_sound_font.js +35 -0
  28. package/synthetizer/worklet_system/worklet_methods/soundfont_management/get_preset.js +20 -0
  29. package/synthetizer/worklet_system/worklet_methods/soundfont_management/reload_sound_font.js +43 -0
  30. package/synthetizer/worklet_system/worklet_methods/soundfont_management/send_preset_list.js +31 -0
  31. package/synthetizer/worklet_system/worklet_methods/soundfont_management/set_embedded_sound_font.js +21 -0
  32. package/synthetizer/worklet_system/worklet_methods/stopping_notes/kill_note.js +20 -0
  33. package/synthetizer/worklet_system/worklet_methods/stopping_notes/note_off.js +55 -0
  34. package/synthetizer/worklet_system/worklet_methods/stopping_notes/stop_all_channels.js +16 -0
  35. package/synthetizer/worklet_system/worklet_methods/stopping_notes/stop_all_notes.js +30 -0
  36. package/synthetizer/worklet_system/worklet_methods/stopping_notes/voice_killing.js +63 -0
  37. package/synthetizer/worklet_system/worklet_methods/system_exclusive.js +31 -30
  38. package/synthetizer/worklet_system/worklet_methods/tuning_control/channel_pressure.js +24 -0
  39. package/synthetizer/worklet_system/worklet_methods/tuning_control/pitch_wheel.js +33 -0
  40. package/synthetizer/worklet_system/worklet_methods/tuning_control/poly_pressure.js +31 -0
  41. package/synthetizer/worklet_system/worklet_methods/tuning_control/set_master_tuning.js +15 -0
  42. package/synthetizer/worklet_system/worklet_methods/tuning_control/set_modulation_depth.js +27 -0
  43. package/synthetizer/worklet_system/worklet_methods/tuning_control/set_octave_tuning.js +15 -0
  44. package/synthetizer/worklet_system/worklet_methods/tuning_control/set_tuning.js +24 -0
  45. package/synthetizer/worklet_system/worklet_methods/tuning_control/set_tuning_semitones.js +19 -0
  46. package/synthetizer/worklet_system/worklet_methods/tuning_control/transpose_all_channels.js +15 -0
  47. package/synthetizer/worklet_system/worklet_methods/tuning_control/transpose_channel.js +31 -0
  48. package/synthetizer/worklet_system/worklet_utilities/controller_tables.js +10 -1
  49. package/synthetizer/worklet_system/worklet_utilities/lfo.js +2 -1
  50. package/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +4 -4
  51. package/synthetizer/worklet_system/worklet_utilities/modulator_curves.js +4 -5
  52. package/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +18 -18
  53. package/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +210 -206
  54. package/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +354 -108
  55. package/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +22 -9
  56. package/synthetizer/worklet_system/snapshot/snapshot.js +0 -311
  57. package/synthetizer/worklet_system/worklet_methods/controller_control.js +0 -260
  58. package/synthetizer/worklet_system/worklet_methods/note_off.js +0 -119
  59. package/synthetizer/worklet_system/worklet_methods/program_control.js +0 -282
  60. package/synthetizer/worklet_system/worklet_methods/tuning_control.js +0 -233
  61. package/synthetizer/worklet_system/worklet_methods/vibrato_control.js +0 -29
@@ -14,246 +14,250 @@ export const interpolationTypes = {
14
14
  };
15
15
 
16
16
 
17
- /**
18
- * Fills the output buffer with raw sample data using linear interpolation
19
- * @param voice {WorkletVoice} the voice we're working on
20
- * @param outputBuffer {Float32Array} the output buffer to write to
21
- */
22
- export function getSampleLinear(voice, outputBuffer)
17
+ export class WavetableOscillator
23
18
  {
24
- const sample = voice.sample;
25
- let cur = sample.cursor;
26
- const sampleData = sample.sampleData;
27
19
 
28
- if (sample.isLooping)
20
+ /**
21
+ * Fills the output buffer with raw sample data using linear interpolation
22
+ * @param voice {WorkletVoice} the voice we're working on
23
+ * @param outputBuffer {Float32Array} the output buffer to write to
24
+ */
25
+ static getSampleLinear(voice, outputBuffer)
29
26
  {
30
- const loopLength = sample.loopEnd - sample.loopStart;
31
- for (let i = 0; i < outputBuffer.length; i++)
27
+ const sample = voice.sample;
28
+ let cur = sample.cursor;
29
+ const sampleData = sample.sampleData;
30
+
31
+ if (sample.isLooping)
32
32
  {
33
- // check for loop
34
- while (cur >= sample.loopEnd)
33
+ const loopLength = sample.loopEnd - sample.loopStart;
34
+ for (let i = 0; i < outputBuffer.length; i++)
35
35
  {
36
- cur -= loopLength;
36
+ // check for loop
37
+ while (cur >= sample.loopEnd)
38
+ {
39
+ cur -= loopLength;
40
+ }
41
+
42
+ // grab the 2 nearest points
43
+ const floor = ~~cur;
44
+ let ceil = floor + 1;
45
+
46
+ while (ceil >= sample.loopEnd)
47
+ {
48
+ ceil -= loopLength;
49
+ }
50
+
51
+ const fraction = cur - floor;
52
+
53
+ // grab the samples and interpolate
54
+ const upper = sampleData[ceil];
55
+ const lower = sampleData[floor];
56
+ outputBuffer[i] = (lower + (upper - lower) * fraction);
57
+
58
+ cur += sample.playbackStep * voice.currentTuningCalculated;
37
59
  }
38
-
39
- // grab the 2 nearest points
40
- const floor = ~~cur;
41
- let ceil = floor + 1;
42
-
43
- while (ceil >= sample.loopEnd)
44
- {
45
- ceil -= loopLength;
46
- }
47
-
48
- const fraction = cur - floor;
49
-
50
- // grab the samples and interpolate
51
- const upper = sampleData[ceil];
52
- const lower = sampleData[floor];
53
- outputBuffer[i] = (lower + (upper - lower) * fraction);
54
-
55
- cur += sample.playbackStep * voice.currentTuningCalculated;
56
60
  }
57
- }
58
- else
59
- {
60
- if (sample.loopingMode === 2 && !voice.isInRelease)
61
- {
62
- return;
63
- }
64
- for (let i = 0; i < outputBuffer.length; i++)
61
+ else
65
62
  {
66
-
67
- // linear interpolation
68
- const floor = ~~cur;
69
- const ceil = floor + 1;
70
-
71
- // flag the voice as finished if needed
72
- if (ceil >= sample.end)
63
+ if (sample.loopingMode === 2 && !voice.isInRelease)
73
64
  {
74
- voice.finished = true;
75
65
  return;
76
66
  }
77
-
78
- const fraction = cur - floor;
79
-
80
- // grab the samples and interpolate
81
- const upper = sampleData[ceil];
82
- const lower = sampleData[floor];
83
- outputBuffer[i] = (lower + (upper - lower) * fraction);
84
-
85
- cur += sample.playbackStep * voice.currentTuningCalculated;
86
- }
87
- }
88
- voice.sample.cursor = cur;
89
- }
90
-
91
- /**
92
- * Fills the output buffer with raw sample data using no interpolation (nearest neighbor)
93
- * @param voice {WorkletVoice} the voice we're working on
94
- * @param outputBuffer {Float32Array} the output buffer to write to
95
- */
96
- export function getSampleNearest(voice, outputBuffer)
97
- {
98
- const sample = voice.sample;
99
- let cur = sample.cursor;
100
- const loopLength = sample.loopEnd - sample.loopStart;
101
- const sampleData = sample.sampleData;
102
- if (voice.sample.isLooping)
103
- {
104
- for (let i = 0; i < outputBuffer.length; i++)
105
- {
106
- // check for loop
107
- while (cur >= sample.loopEnd)
108
- {
109
- cur -= loopLength;
110
- }
111
-
112
- // grab the nearest neighbor
113
- let ceil = ~~cur + 1;
114
-
115
- while (ceil >= sample.loopEnd)
116
- {
117
- ceil -= loopLength;
118
- }
119
-
120
- outputBuffer[i] = sampleData[ceil];
121
- cur += sample.playbackStep * voice.currentTuningCalculated;
122
- }
123
- }
124
- else
125
- {
126
- if (sample.loopingMode === 2 && !voice.isInRelease)
127
- {
128
- return;
129
- }
130
- for (let i = 0; i < outputBuffer.length; i++)
131
- {
132
-
133
- // nearest neighbor
134
- const ceil = ~~cur + 1;
135
-
136
- // flag the voice as finished if needed
137
- if (ceil >= sample.end)
67
+ for (let i = 0; i < outputBuffer.length; i++)
138
68
  {
139
- voice.finished = true;
140
- return;
69
+
70
+ // linear interpolation
71
+ const floor = ~~cur;
72
+ const ceil = floor + 1;
73
+
74
+ // flag the voice as finished if needed
75
+ if (ceil >= sample.end)
76
+ {
77
+ voice.finished = true;
78
+ return;
79
+ }
80
+
81
+ const fraction = cur - floor;
82
+
83
+ // grab the samples and interpolate
84
+ const upper = sampleData[ceil];
85
+ const lower = sampleData[floor];
86
+ outputBuffer[i] = (lower + (upper - lower) * fraction);
87
+
88
+ cur += sample.playbackStep * voice.currentTuningCalculated;
141
89
  }
142
-
143
- //nearest neighbor (uncomment to use)
144
- outputBuffer[i] = sampleData[ceil];
145
- cur += sample.playbackStep * voice.currentTuningCalculated;
146
90
  }
91
+ voice.sample.cursor = cur;
147
92
  }
148
- sample.cursor = cur;
149
- }
150
-
151
-
152
- /**
153
- * Fills the output buffer with raw sample data using cubic interpolation
154
- * @param voice {WorkletVoice} the voice we're working on
155
- * @param outputBuffer {Float32Array} the output buffer to write to
156
- */
157
- export function getSampleCubic(voice, outputBuffer)
158
- {
159
- const sample = voice.sample;
160
- let cur = sample.cursor;
161
- const sampleData = sample.sampleData;
162
93
 
163
- if (sample.isLooping)
94
+ /**
95
+ * Fills the output buffer with raw sample data using no interpolation (nearest neighbor)
96
+ * @param voice {WorkletVoice} the voice we're working on
97
+ * @param outputBuffer {Float32Array} the output buffer to write to
98
+ */
99
+ static getSampleNearest(voice, outputBuffer)
164
100
  {
101
+ const sample = voice.sample;
102
+ let cur = sample.cursor;
165
103
  const loopLength = sample.loopEnd - sample.loopStart;
166
- for (let i = 0; i < outputBuffer.length; i++)
104
+ const sampleData = sample.sampleData;
105
+ if (voice.sample.isLooping)
167
106
  {
168
- // check for loop
169
- while (cur >= sample.loopEnd)
107
+ for (let i = 0; i < outputBuffer.length; i++)
170
108
  {
171
- cur -= loopLength;
109
+ // check for loop
110
+ while (cur >= sample.loopEnd)
111
+ {
112
+ cur -= loopLength;
113
+ }
114
+
115
+ // grab the nearest neighbor
116
+ let ceil = ~~cur + 1;
117
+
118
+ while (ceil >= sample.loopEnd)
119
+ {
120
+ ceil -= loopLength;
121
+ }
122
+
123
+ outputBuffer[i] = sampleData[ceil];
124
+ cur += sample.playbackStep * voice.currentTuningCalculated;
172
125
  }
173
-
174
- // math comes from
175
- // https://stackoverflow.com/questions/1125666/how-do-you-do-bicubic-or-other-non-linear-interpolation-of-re-sampled-audio-da
176
-
177
- // grab the 4 points
178
- const y0 = ~~cur; // point before the cursor. twice bitwise not is just a faster Math.floor
179
- let y1 = y0 + 1; // point after the cursor
180
- let y2 = y1 + 1; // point 1 after the cursor
181
- let y3 = y2 + 1; // point 2 after the cursor
182
- const t = cur - y0; // distance from y0 to cursor
183
- // y0 is not handled here
184
- // as it's math.floor of cur which is handled above
185
- if (y1 >= sample.loopEnd)
186
- {
187
- y1 -= loopLength;
188
- }
189
- if (y2 >= sample.loopEnd)
126
+ }
127
+ else
128
+ {
129
+ if (sample.loopingMode === 2 && !voice.isInRelease)
190
130
  {
191
- y2 -= loopLength;
131
+ return;
192
132
  }
193
- if (y3 >= sample.loopEnd)
133
+ for (let i = 0; i < outputBuffer.length; i++)
194
134
  {
195
- y3 -= loopLength;
135
+
136
+ // nearest neighbor
137
+ const ceil = ~~cur + 1;
138
+
139
+ // flag the voice as finished if needed
140
+ if (ceil >= sample.end)
141
+ {
142
+ voice.finished = true;
143
+ return;
144
+ }
145
+
146
+ //nearest neighbor (uncomment to use)
147
+ outputBuffer[i] = sampleData[ceil];
148
+ cur += sample.playbackStep * voice.currentTuningCalculated;
196
149
  }
197
-
198
- // grab the samples
199
- const x0 = sampleData[y0];
200
- const x1 = sampleData[y1];
201
- const x2 = sampleData[y2];
202
- const x3 = sampleData[y3];
203
-
204
- // interpolate
205
- // const c0 = x1
206
- const c1 = 0.5 * (x2 - x0);
207
- const c2 = x0 - (2.5 * x1) + (2 * x2) - (0.5 * x3);
208
- const c3 = (0.5 * (x3 - x0)) + (1.5 * (x1 - x2));
209
- outputBuffer[i] = (((((c3 * t) + c2) * t) + c1) * t) + x1;
210
-
211
-
212
- cur += sample.playbackStep * voice.currentTuningCalculated;
213
150
  }
151
+ sample.cursor = cur;
214
152
  }
215
- else
153
+
154
+
155
+ /**
156
+ * Fills the output buffer with raw sample data using cubic interpolation
157
+ * @param voice {WorkletVoice} the voice we're working on
158
+ * @param outputBuffer {Float32Array} the output buffer to write to
159
+ */
160
+ static getSampleCubic(voice, outputBuffer)
216
161
  {
217
- if (sample.loopingMode === 2 && !voice.isInRelease)
162
+ const sample = voice.sample;
163
+ let cur = sample.cursor;
164
+ const sampleData = sample.sampleData;
165
+
166
+ if (sample.isLooping)
218
167
  {
219
- return;
168
+ const loopLength = sample.loopEnd - sample.loopStart;
169
+ for (let i = 0; i < outputBuffer.length; i++)
170
+ {
171
+ // check for loop
172
+ while (cur >= sample.loopEnd)
173
+ {
174
+ cur -= loopLength;
175
+ }
176
+
177
+ // math comes from
178
+ // https://stackoverflow.com/questions/1125666/how-do-you-do-bicubic-or-other-non-linear-interpolation-of-re-sampled-audio-da
179
+
180
+ // grab the 4 points
181
+ const y0 = ~~cur; // point before the cursor. twice bitwise not is just a faster Math.floor
182
+ let y1 = y0 + 1; // point after the cursor
183
+ let y2 = y1 + 1; // point 1 after the cursor
184
+ let y3 = y2 + 1; // point 2 after the cursor
185
+ const t = cur - y0; // distance from y0 to cursor
186
+ // y0 is not handled here
187
+ // as it's math.floor of cur which is handled above
188
+ if (y1 >= sample.loopEnd)
189
+ {
190
+ y1 -= loopLength;
191
+ }
192
+ if (y2 >= sample.loopEnd)
193
+ {
194
+ y2 -= loopLength;
195
+ }
196
+ if (y3 >= sample.loopEnd)
197
+ {
198
+ y3 -= loopLength;
199
+ }
200
+
201
+ // grab the samples
202
+ const x0 = sampleData[y0];
203
+ const x1 = sampleData[y1];
204
+ const x2 = sampleData[y2];
205
+ const x3 = sampleData[y3];
206
+
207
+ // interpolate
208
+ // const c0 = x1
209
+ const c1 = 0.5 * (x2 - x0);
210
+ const c2 = x0 - (2.5 * x1) + (2 * x2) - (0.5 * x3);
211
+ const c3 = (0.5 * (x3 - x0)) + (1.5 * (x1 - x2));
212
+ outputBuffer[i] = (((((c3 * t) + c2) * t) + c1) * t) + x1;
213
+
214
+
215
+ cur += sample.playbackStep * voice.currentTuningCalculated;
216
+ }
220
217
  }
221
- for (let i = 0; i < outputBuffer.length; i++)
218
+ else
222
219
  {
223
-
224
- // math comes from
225
- // https://stackoverflow.com/questions/1125666/how-do-you-do-bicubic-or-other-non-linear-interpolation-of-re-sampled-audio-da
226
-
227
- // grab the 4 points
228
- const y0 = ~~cur; // point before the cursor. twice bitwise not is just a faster Math.floor
229
- let y1 = y0 + 1; // point after the cursor
230
- let y2 = y1 + 1; // point 1 after the cursor
231
- let y3 = y2 + 1; // point 2 after the cursor
232
- const t = cur - y0; // distance from y0 to cursor
233
-
234
- // flag as finished if needed
235
- if (y1 >= sample.end ||
236
- y2 >= sample.end ||
237
- y3 >= sample.end)
220
+ if (sample.loopingMode === 2 && !voice.isInRelease)
238
221
  {
239
- voice.finished = true;
240
222
  return;
241
223
  }
242
-
243
- // grab the samples
244
- const x0 = sampleData[y0];
245
- const x1 = sampleData[y1];
246
- const x2 = sampleData[y2];
247
- const x3 = sampleData[y3];
248
-
249
- // interpolate
250
- const c1 = 0.5 * (x2 - x0);
251
- const c2 = x0 - (2.5 * x1) + (2 * x2) - (0.5 * x3);
252
- const c3 = (0.5 * (x3 - x0)) + (1.5 * (x1 - x2));
253
- outputBuffer[i] = (((((c3 * t) + c2) * t) + c1) * t) + x1;
254
-
255
- cur += sample.playbackStep * voice.currentTuningCalculated;
224
+ for (let i = 0; i < outputBuffer.length; i++)
225
+ {
226
+
227
+ // math comes from
228
+ // https://stackoverflow.com/questions/1125666/how-do-you-do-bicubic-or-other-non-linear-interpolation-of-re-sampled-audio-da
229
+
230
+ // grab the 4 points
231
+ const y0 = ~~cur; // point before the cursor. twice bitwise not is just a faster Math.floor
232
+ let y1 = y0 + 1; // point after the cursor
233
+ let y2 = y1 + 1; // point 1 after the cursor
234
+ let y3 = y2 + 1; // point 2 after the cursor
235
+ const t = cur - y0; // distance from y0 to cursor
236
+
237
+ // flag as finished if needed
238
+ if (y1 >= sample.end ||
239
+ y2 >= sample.end ||
240
+ y3 >= sample.end)
241
+ {
242
+ voice.finished = true;
243
+ return;
244
+ }
245
+
246
+ // grab the samples
247
+ const x0 = sampleData[y0];
248
+ const x1 = sampleData[y1];
249
+ const x2 = sampleData[y2];
250
+ const x3 = sampleData[y3];
251
+
252
+ // interpolate
253
+ const c1 = 0.5 * (x2 - x0);
254
+ const c2 = x0 - (2.5 * x1) + (2 * x2) - (0.5 * x3);
255
+ const c3 = (0.5 * (x3 - x0)) + (1.5 * (x1 - x2));
256
+ outputBuffer[i] = (((((c3 * t) + c2) * t) + c1) * t) + x1;
257
+
258
+ cur += sample.playbackStep * voice.currentTuningCalculated;
259
+ }
256
260
  }
261
+ voice.sample.cursor = cur;
257
262
  }
258
- voice.sample.cursor = cur;
259
263
  }