spessasynth_lib 3.21.0 → 3.21.2

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.
@@ -16,12 +16,7 @@ export function noteOff(channel, midiNote)
16
16
  return;
17
17
  }
18
18
 
19
- let actualNote = midiNote + this.workletProcessorChannels[channel].channelTransposeKeyShift;
20
- const program = this.workletProcessorChannels[channel].preset.program;
21
- if (this.tunings[program]?.[midiNote]?.midiNote >= 0)
22
- {
23
- actualNote = this.tunings[program]?.[midiNote].midiNote;
24
- }
19
+ let realKey = midiNote + this.workletProcessorChannels[channel].channelTransposeKeyShift;
25
20
 
26
21
  // if high performance mode, kill notes instead of stopping them
27
22
  if (this.highPerformanceMode)
@@ -29,7 +24,7 @@ export function noteOff(channel, midiNote)
29
24
  // if the channel is percussion channel, do not kill the notes
30
25
  if (!this.workletProcessorChannels[channel].drumChannel)
31
26
  {
32
- this.killNote(channel, actualNote);
27
+ this.killNote(channel, realKey);
33
28
  return;
34
29
  }
35
30
  }
@@ -37,7 +32,7 @@ export function noteOff(channel, midiNote)
37
32
  const channelVoices = this.workletProcessorChannels[channel].voices;
38
33
  channelVoices.forEach(v =>
39
34
  {
40
- if (v.midiNote !== actualNote || v.isInRelease === true)
35
+ if (v.realKey !== realKey || v.isInRelease === true)
41
36
  {
42
37
  return;
43
38
  }
@@ -67,7 +62,7 @@ export function killNote(channel, midiNote)
67
62
  {
68
63
  this.workletProcessorChannels[channel].voices.forEach(v =>
69
64
  {
70
- if (v.midiNote !== midiNote)
65
+ if (v.realKey !== midiNote)
71
66
  {
72
67
  return;
73
68
  }
@@ -31,7 +31,8 @@ export function noteOn(channel, midiNote, velocity, enableDebugging = false, sen
31
31
  return;
32
32
  }
33
33
 
34
- let sentMidiNote = midiNote + channelObject.channelTransposeKeyShift;
34
+ const realKey = midiNote + channelObject.channelTransposeKeyShift;
35
+ let sentMidiNote = realKey;
35
36
 
36
37
  if (midiNote > 127 || midiNote < 0)
37
38
  {
@@ -56,6 +57,7 @@ export function noteOn(channel, midiNote, velocity, enableDebugging = false, sen
56
57
  velocity,
57
58
  channelObject,
58
59
  startTime,
60
+ realKey,
59
61
  enableDebugging
60
62
  );
61
63
 
@@ -78,7 +78,7 @@ export function renderVoice(
78
78
  + channel.customControllers[customControllers.channelTuningSemitones]; // RPN channel coarse tuning
79
79
 
80
80
  // midi tuning standard
81
- const tuning = this.tunings[channel.preset.program]?.[targetKey];
81
+ const tuning = this.tunings[channel.preset.program]?.[voice.realKey];
82
82
  if (tuning?.midiNote >= 0)
83
83
  {
84
84
  // override key
@@ -111,123 +111,131 @@ import { Modulator } from "../../../soundfont/basic_soundfont/modulator.js";
111
111
  class WorkletVoice
112
112
  {
113
113
  /**
114
- * Creates a new voice
114
+ * The sample of the voice.
115
115
  * @type {WorkletSample}
116
116
  */
117
117
  sample;
118
118
 
119
119
  /**
120
- * Lowpass filter appl.
121
- the voice.
120
+ * Lowpass filter applied to the voice.
122
121
  * @type {WorkletLowpassFilter}
123
122
  */
124
123
  filter = new WorkletLowpassFilter();
125
124
 
126
125
  /**
127
- * The unmodulated (coied to) generators of the voice.
126
+ * The unmodulated (copied to) generators of the voice.
128
127
  * @type {Int16Array}
129
128
  */
130
129
  generators;
131
130
 
132
131
  /**
133
- * The voice's modulatnstant * Grouped by the destination.
132
+ * The voice's modulators.
134
133
  * @type {Modulator[]}
135
134
  */
136
135
  modulators = [];
137
136
 
138
137
  /**
139
- * The generators moduors.
140
- by the modulators.
138
+ * The generators in real-time, affected by modulators.
139
+ * This is used during rendering.
141
140
  * @type {Int16Array}
142
141
  */
143
142
  modulatedGenerators;
144
143
 
145
144
  /**
146
- * Indicates if the volated s finished.
145
+ * Indicates if the voice is finished.
147
146
  * @type {boolean}
148
147
  */
149
148
  finished = false;
150
149
 
151
150
  /**
152
- * Indicates if the voice ha in the release phase.
151
+ * Indicates if the voice is in the release phase.
153
152
  * @type {boolean}
154
153
  */
155
154
  isInRelease = false;
156
155
 
157
156
  /**
158
- * MIDI channel numberice is * @type {number}
157
+ * MIDI channel number.
158
+ * @type {number}
159
159
  */
160
160
  channelNumber = 0;
161
161
 
162
162
  /**
163
- * Velocity of the not.
163
+ * Velocity of the note.
164
164
  * @type {number}
165
165
  */
166
166
  velocity = 0;
167
167
 
168
168
  /**
169
169
  * MIDI note number.
170
- e.
171
- @type {number}
170
+ * @type {number}
172
171
  */
173
172
  midiNote = 0;
174
173
 
175
174
  /**
176
- * The pressure of the *
175
+ * The pressure of the voice
177
176
  * @type {number}
178
177
  */
179
178
  pressure = 0;
180
179
 
181
180
  /**
182
- * Target key for the note. * @type {number}
181
+ * Target key for the note.
182
+ * @type {number}
183
183
  */
184
184
  targetKey = 0;
185
185
 
186
186
  /**
187
- * Modulation envelopenote.
187
+ * Modulation envelope.
188
188
  * @type {WorkletModulationEnvelope}
189
189
  */
190
190
  modulationEnvelope = new WorkletModulationEnvelope();
191
191
 
192
192
  /**
193
193
  * Volume envelope.
194
- .
195
- type {WorkletVolumeEnvelope}
194
+ * @type {WorkletVolumeEnvelope}
196
195
  */
197
196
  volumeEnvelope;
198
197
 
199
198
  /**
200
- * Start time of the v * @bsolute.
199
+ * Start time of the voice, absolute.
201
200
  * @type {number}
202
201
  */
203
202
  startTime = 0;
204
203
 
205
204
  /**
206
- * Start time of the roice a phase absolute.
205
+ * Start time of the release phase, absolute.
207
206
  * @type {number}
208
207
  */
209
208
  releaseStartTime = Infinity;
210
209
 
211
210
  /**
212
- * Current tuning adjuelease in cents.
211
+ * Current tuning in cents.
213
212
  * @type {number}
214
213
  */
215
214
  currentTuningCents = 0;
216
215
 
217
216
  /**
218
- * Calculated tuning astmentent.
217
+ * Current calculated tuning. (as in ratio)
219
218
  * @type {number}
220
219
  */
221
220
  currentTuningCalculated = 1;
222
221
 
223
222
  /**
224
223
  * From 0 to 1.
225
- *djustm {number}
224
+ * @param {number}
226
225
  */
227
226
  currentPan = 0.5;
228
227
 
229
228
  /**
230
- * Copies a workletVoi @type
229
+ * If MIDI Tuning Standard is already applied (at note-on time),
230
+ * this will be used to take the values at real-time tuning as "midiNote"
231
+ * property contains the tuned number.
232
+ * see #29 comment by @paulikaro
233
+ * @type {number}
234
+ */
235
+ realKey;
236
+
237
+ /**
238
+ * Creates a workletVoice
231
239
  * @param sampleRate {number}
232
240
  * @param workletSample {WorkletSample}
233
241
  * @param midiNote {number}
@@ -235,6 +243,7 @@ class WorkletVoice
235
243
  * @param channel {number}
236
244
  * @param currentTime {number}
237
245
  * @param targetKey {number}
246
+ * @param realKey {number}
238
247
  * @param generators {Int16Array}
239
248
  * @param modulators {Modulator[]}
240
249
  */
@@ -246,6 +255,7 @@ class WorkletVoice
246
255
  channel,
247
256
  currentTime,
248
257
  targetKey,
258
+ realKey,
249
259
  generators,
250
260
  modulators
251
261
  )
@@ -260,12 +270,12 @@ class WorkletVoice
260
270
  this.channelNumber = channel;
261
271
  this.startTime = currentTime;
262
272
  this.targetKey = targetKey;
273
+ this.realKey = realKey;
263
274
  this.volumeEnvelope = new WorkletVolumeEnvelope(sampleRate, generators[generatorTypes.sustainVolEnv]);
264
275
  }
265
276
 
266
277
  /**
267
- * Sample ID for voicece ins
268
- tance
278
+ * copies the voice
269
279
  * @param voice {WorkletVoice}
270
280
  * @param currentTime {number}
271
281
  * @returns WorkletVoice
@@ -291,6 +301,7 @@ class WorkletVoice
291
301
  voice.channelNumber,
292
302
  currentTime,
293
303
  voice.targetKey,
304
+ voice.realKey,
294
305
  voice.generators,
295
306
  voice.modulators.map(m => Modulator.copy(m))
296
307
  );
@@ -299,20 +310,21 @@ class WorkletVoice
299
310
 
300
311
  /**
301
312
  * @param channel {number} a hint for the processor to recalculate sample cursors when sample dumping
302
- * @param midiNote {number}
303
- * @param velocity {number}
304
- * @param channelObject {WorkletProcessorChannel}
305
- * @param currentTime {number}
306
- * output is an array of WorkletVoices
307
- * @param debug {boolean}
313
+ * @param midiNote {number} the MIDI note to use
314
+ * @param velocity {number} the velocity to use
315
+ * @param channelObject {WorkletProcessorChannel} the channel this will belong to
316
+ * @param currentTime {number} the current time in seconds
317
+ * @param realKey {number} the real MIDI note if the "midiNote" was changed by MIDI Tuning Standard
318
+ * @param debug {boolean} enable debugging?
308
319
  * @this {SpessaSynthProcessor}
309
- * @returns {WorkletVoice[]}
320
+ * @returns {WorkletVoice[]} output is an array of WorkletVoices
310
321
  */
311
322
  export function getWorkletVoices(channel,
312
323
  midiNote,
313
324
  velocity,
314
325
  channelObject,
315
326
  currentTime,
327
+ realKey,
316
328
  debug = false)
317
329
  {
318
330
  /**
@@ -419,6 +431,7 @@ export function getWorkletVoices(channel,
419
431
  channel,
420
432
  currentTime,
421
433
  targetKey,
434
+ realKey,
422
435
  generators,
423
436
  sampleAndGenerators.modulators.map(m => Modulator.copy(m))
424
437
  )