spessasynth_core 4.3.15 → 4.3.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.
package/dist/index.d.ts CHANGED
@@ -95,6 +95,19 @@ declare class SpessaLog {
95
95
  * If grouping of the log messages is allowed. Recommended for the `info` verbosity level.
96
96
  */
97
97
  static groupEnabled: boolean;
98
+ /**
99
+ * The log functions that get called with the data.
100
+ * By default, they use `console` object.
101
+ *
102
+ * This may be overridden to capture the spessasynth log data.
103
+ */
104
+ static logFunctions: {
105
+ info: (...data: any[]) => void;
106
+ warn: (...data: any[]) => void;
107
+ group: (...data: any[]) => void;
108
+ groupEnd: () => void;
109
+ groupCollapsed: (...data: any[]) => void;
110
+ };
98
111
  /**
99
112
  * Enables or disables logging.
100
113
  * @param enableInfo enables info.
package/dist/index.js CHANGED
@@ -247,6 +247,18 @@ function writeVariableLengthQuantity(number) {
247
247
  * Other.ts
248
248
  * purpose: contains some useful functions that don't belong in any specific category
249
249
  */
250
+ function splitmix32(a) {
251
+ return function() {
252
+ a |= 0;
253
+ a = a + 2654435769 | 0;
254
+ let t = a ^ a >>> 16;
255
+ t = Math.imul(t, 569420461);
256
+ t = t ^ t >>> 15;
257
+ t = Math.imul(t, 1935289751);
258
+ return ((t ^ t >>> 15) >>> 0) / 4294967296;
259
+ };
260
+ }
261
+ const randomGenerator = splitmix32(81572);
250
262
  /**
251
263
  * Formats the given seconds to nice readable time
252
264
  * @param totalSeconds time in seconds
@@ -879,6 +891,19 @@ var SpessaLog = class SpessaLog {
879
891
  */
880
892
  static groupEnabled = false;
881
893
  /**
894
+ * The log functions that get called with the data.
895
+ * By default, they use `console` object.
896
+ *
897
+ * This may be overridden to capture the spessasynth log data.
898
+ */
899
+ static logFunctions = {
900
+ info: console.info.bind(console),
901
+ warn: console.warn.bind(console),
902
+ group: console.group.bind(console),
903
+ groupEnd: console.groupEnd.bind(console),
904
+ groupCollapsed: console.groupCollapsed.bind(console)
905
+ };
906
+ /**
882
907
  * Enables or disables logging.
883
908
  * @param enableInfo enables info.
884
909
  * @param enableWarn enables warning.
@@ -890,19 +915,19 @@ var SpessaLog = class SpessaLog {
890
915
  this.groupEnabled = enableGroup;
891
916
  }
892
917
  static info(...message) {
893
- if (this.infoEnabled) console.info(...message);
918
+ if (this.infoEnabled) this.logFunctions.info(...message);
894
919
  }
895
920
  static warn(...message) {
896
- if (this.warnEnabled) console.warn(...message);
921
+ if (this.warnEnabled) this.logFunctions.warn(...message);
897
922
  }
898
923
  static group(...message) {
899
- if (this.groupEnabled) console.group(...message);
924
+ if (this.groupEnabled) this.logFunctions.group(...message);
900
925
  }
901
926
  static groupCollapsed(...message) {
902
- if (this.groupEnabled) console.groupCollapsed(...message);
927
+ if (this.groupEnabled) this.logFunctions.groupCollapsed(...message);
903
928
  }
904
929
  static groupEnd() {
905
- if (this.groupEnabled) console.groupEnd();
930
+ if (this.groupEnabled) this.logFunctions.groupEnd();
906
931
  }
907
932
  /**
908
933
  * @internal
@@ -2116,12 +2141,19 @@ var MIDIUtils = class MIDIUtils {
2116
2141
  controller: MIDIControllers.mainVolume,
2117
2142
  value: data
2118
2143
  };
2119
- case 14: return {
2120
- type: "Controller Change",
2121
- channel,
2122
- controller: MIDIControllers.pan,
2123
- value: data
2124
- };
2144
+ case 14:
2145
+ if (data === 0) return {
2146
+ type: "Channel MIDI Param",
2147
+ channel,
2148
+ parameter: "randomPan",
2149
+ value: true
2150
+ };
2151
+ return {
2152
+ type: "Controller Change",
2153
+ channel,
2154
+ controller: MIDIControllers.pan,
2155
+ value: data
2156
+ };
2125
2157
  case 18: return {
2126
2158
  type: "Controller Change",
2127
2159
  channel,
@@ -2291,12 +2323,19 @@ var MIDIUtils = class MIDIUtils {
2291
2323
  parameter: "velocitySenseOffset",
2292
2324
  value: data
2293
2325
  };
2294
- case 28: return {
2295
- type: "Controller Change",
2296
- channel,
2297
- controller: MIDIControllers.pan,
2298
- value: data
2299
- };
2326
+ case 28:
2327
+ if (data === 0) return {
2328
+ type: "Channel MIDI Param",
2329
+ channel,
2330
+ parameter: "randomPan",
2331
+ value: true
2332
+ };
2333
+ return {
2334
+ type: "Controller Change",
2335
+ channel,
2336
+ controller: MIDIControllers.pan,
2337
+ value: data
2338
+ };
2300
2339
  case 31: return {
2301
2340
  type: "Channel MIDI Param",
2302
2341
  channel,
@@ -6457,9 +6496,11 @@ function applySnapshot$1(snapshot) {
6457
6496
  const is = snapshot.insertionProcessor;
6458
6497
  this.systemExclusive(MIDIUtils.gs(64, 3, 0, [is.type >> 8, is.type & 127]));
6459
6498
  for (let i = 0; i < is.params.length; i++) if (is.params[i] !== 255) this.systemExclusive(MIDIUtils.gs(64, 3, 3 + i, [is.params[i]]));
6499
+ for (const parameter of Object.keys(snapshot.lockedMIDIParameters)) this.lockMIDIParameter(parameter, false);
6460
6500
  for (const [parameter, value] of Object.entries(snapshot.midiParameters)) this.setMIDIParameter(parameter, value);
6461
6501
  for (const [parameter, isLocked] of Object.entries(snapshot.lockedMIDIParameters)) this.lockMIDIParameter(parameter, isLocked);
6462
6502
  for (const [parameter, value] of Object.entries(snapshot.systemParameters)) this.setSystemParameter(parameter, value);
6503
+ this.updateActiveEffects();
6463
6504
  }
6464
6505
  function getSynthesizerSnapshot() {
6465
6506
  return {
@@ -12637,7 +12678,7 @@ function controllerChange(controller, value, sendEvent = true) {
12637
12678
  this.setBankLSB(value);
12638
12679
  break;
12639
12680
  case MIDIControllers.variationDepth:
12640
- this.synthCore.delayActive = true;
12681
+ this.synthCore.updateActiveEffects();
12641
12682
  break;
12642
12683
  case MIDIControllers.registeredParameterLSB:
12643
12684
  case MIDIControllers.registeredParameterMSB:
@@ -13154,12 +13195,12 @@ function noteOn(midiNote, velocity, emit = true) {
13154
13195
  let reverbSend = 1;
13155
13196
  let chorusSend = 1;
13156
13197
  let delaySend = 1;
13157
- if (this._midiParameters.randomPan) panOverride = Math.round(Math.random() * 1e3 - 500);
13198
+ if (this._midiParameters.randomPan) panOverride = Math.round(randomGenerator() * 1e3 - 500);
13158
13199
  if (this._drumChannel) {
13159
13200
  const p = this.drumParams[midiNote];
13160
13201
  if (!p.rxNoteOn) return;
13161
13202
  const drumPan = p.pan - 64;
13162
- if (drumPan !== 0) if (drumPan === -64) panOverride = Math.round(Math.random() * 1e3 - 500);
13203
+ if (drumPan !== 0) if (drumPan === -64) panOverride = Math.round(randomGenerator() * 1e3 - 500);
13163
13204
  else {
13164
13205
  const channelPan = (this._midiControllers[MIDIControllers.pan] >> 7) - 64;
13165
13206
  panOverride = Math.max(-63, Math.min(drumPan + channelPan, 63)) / 63 * 500 || 1;
@@ -13607,6 +13648,7 @@ function applySnapshot(snapshot) {
13607
13648
  this.setSystemParameter("presetLock", false);
13608
13649
  if (snapshot.patch) this.setPatch(snapshot.patch);
13609
13650
  this.lockedSystem = snapshot.lockedSystem;
13651
+ for (const parameter of Object.keys(snapshot.lockedMIDIParameters)) this.lockMIDIParameter(parameter, false);
13610
13652
  for (const [parameter, value] of Object.entries(snapshot.midiParameters)) this.setMIDIParameter(parameter, value);
13611
13653
  for (const [parameter, isLocked] of Object.entries(snapshot.lockedMIDIParameters)) this.lockMIDIParameter(parameter, isLocked);
13612
13654
  for (const [parameter, value] of Object.entries(snapshot.systemParameters)) this.setSystemParameter(parameter, value);
@@ -14695,7 +14737,6 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
14695
14737
  if (isReverb && this.systemParameters.reverbLock) return;
14696
14738
  if (isChorus && this.systemParameters.chorusLock) return;
14697
14739
  if (isDelay && this.systemParameters.delayLock) return;
14698
- this.delayActive ||= a3 === 64 || isDelay;
14699
14740
  switch (a3) {
14700
14741
  default:
14701
14742
  SpessaLog.gsFail("Patch Common Parameter", [a3]);
@@ -14834,6 +14875,7 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
14834
14875
  break;
14835
14876
  case 64:
14836
14877
  this.chorusProcessor.sendLevelToDelay = data;
14878
+ this.updateActiveEffects();
14837
14879
  SpessaLog.gsInfo("Chorus Send Level To Delay", data);
14838
14880
  this.callEvent("effectChange", {
14839
14881
  effect: "chorus",
@@ -14994,7 +15036,7 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
14994
15036
  return;
14995
15037
  case 25:
14996
15038
  this.insertionProcessor.sendLevelToDelay = data / 127 * EFX_SENDS_GAIN_CORRECTION;
14997
- this.delayActive = true;
15039
+ this.updateActiveEffects();
14998
15040
  SpessaLog.gsInfo("EFX Send Level to Delay", data);
14999
15041
  this.callEvent("effectChange", {
15000
15042
  effect: "insertion",
@@ -15173,8 +15215,8 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
15173
15215
  case 34: {
15174
15216
  const efx = data === 1;
15175
15217
  ch.setMIDIParameter("efxAssign", efx);
15176
- this.insertionActive ||= efx;
15177
15218
  SpessaLog.gsInfo(`EFX assign for ${channel}`, efx ? "EFX" : "BYPASS");
15219
+ this.updateActiveEffects();
15178
15220
  }
15179
15221
  }
15180
15222
  return;
@@ -20301,7 +20343,7 @@ var SynthesizerCore = class {
20301
20343
  this.resetInsertion();
20302
20344
  if (!this.drumPreset || !this.defaultPreset) return;
20303
20345
  for (const ch of this.midiChannels) ch.reset(false);
20304
- if (!this.systemParameters.delayLock) this.delayActive = this.midiChannels.some((c) => c.midiControllers[MIDIControllers.variationDepth] > 0);
20346
+ this.updateActiveEffects();
20305
20347
  }
20306
20348
  process(left, right, startIndex = 0, sampleCount = 0) {
20307
20349
  this.processSplit([[left, right]], left, right, startIndex, sampleCount);
@@ -20422,6 +20464,14 @@ var SynthesizerCore = class {
20422
20464
  callEvent(eventName, eventData) {
20423
20465
  this.eventCallbackHandler(eventName, eventData);
20424
20466
  }
20467
+ /**
20468
+ * @internal
20469
+ * Checks if we can disable insertion and delay effects.
20470
+ */
20471
+ updateActiveEffects() {
20472
+ if (!this.systemParameters.insertionEffectLock) this.insertionActive = this.midiChannels.some((c) => c.midiParameters.efxAssign);
20473
+ if (!this.systemParameters.delayLock) this.delayActive = this.midiParameters.system === "xg" ? false : this.chorusProcessor.sendLevelToDelay > 0 || this.insertionProcessor.sendLevelToDelay > 0 || this.midiChannels.some((c) => c.midiControllers[MIDIControllers.variationDepth] > 0);
20474
+ }
20425
20475
  getInsertionSnapshot() {
20426
20476
  return {
20427
20477
  type: this.insertionProcessor.type,
@@ -20436,7 +20486,6 @@ var SynthesizerCore = class {
20436
20486
  }
20437
20487
  resetInsertion() {
20438
20488
  if (this.systemParameters.insertionEffectLock) return;
20439
- this.insertionActive = false;
20440
20489
  this.insertionProcessor = this.insertionFallback;
20441
20490
  this.insertionProcessor.reset();
20442
20491
  this.resetInsertionParams();