spessasynth_core 4.3.14 → 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 +13 -0
- package/dist/index.js +85 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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)
|
|
918
|
+
if (this.infoEnabled) this.logFunctions.info(...message);
|
|
894
919
|
}
|
|
895
920
|
static warn(...message) {
|
|
896
|
-
if (this.warnEnabled)
|
|
921
|
+
if (this.warnEnabled) this.logFunctions.warn(...message);
|
|
897
922
|
}
|
|
898
923
|
static group(...message) {
|
|
899
|
-
if (this.groupEnabled)
|
|
924
|
+
if (this.groupEnabled) this.logFunctions.group(...message);
|
|
900
925
|
}
|
|
901
926
|
static groupCollapsed(...message) {
|
|
902
|
-
if (this.groupEnabled)
|
|
927
|
+
if (this.groupEnabled) this.logFunctions.groupCollapsed(...message);
|
|
903
928
|
}
|
|
904
929
|
static groupEnd() {
|
|
905
|
-
if (this.groupEnabled)
|
|
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:
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
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:
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
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 {
|
|
@@ -10484,6 +10525,9 @@ var ConnectionBlock = class ConnectionBlock {
|
|
|
10484
10525
|
default:
|
|
10485
10526
|
SpessaLog.info(`%cFailed converting DLS articulator into SF generator: %c${this.toString()}%c\n(invalid destination)`, ConsoleColors.warn, ConsoleColors.value, ConsoleColors.unrecognized);
|
|
10486
10527
|
return;
|
|
10528
|
+
case DLSDestinations.keyNum:
|
|
10529
|
+
zone.setGenerator(GeneratorTypes.keyNum, value);
|
|
10530
|
+
break;
|
|
10487
10531
|
case DLSDestinations.pan:
|
|
10488
10532
|
zone.setGenerator(GeneratorTypes.pan, value);
|
|
10489
10533
|
break;
|
|
@@ -10633,7 +10677,7 @@ var ConnectionBlock = class ConnectionBlock {
|
|
|
10633
10677
|
newAmount: -amount
|
|
10634
10678
|
};
|
|
10635
10679
|
case DLSDestinations.pitch: return GeneratorTypes.fineTune;
|
|
10636
|
-
case DLSDestinations.keyNum: return GeneratorTypes.
|
|
10680
|
+
case DLSDestinations.keyNum: return GeneratorTypes.keyNum;
|
|
10637
10681
|
case DLSDestinations.volEnvDelay: return GeneratorTypes.delayVolEnv;
|
|
10638
10682
|
case DLSDestinations.volEnvAttack: return GeneratorTypes.attackVolEnv;
|
|
10639
10683
|
case DLSDestinations.volEnvHold: return GeneratorTypes.holdVolEnv;
|
|
@@ -10744,7 +10788,7 @@ var DownloadableSoundsArticulation = class extends DLSVerifier {
|
|
|
10744
10788
|
writeDword(art2Data, this.connectionBlocks.length);
|
|
10745
10789
|
const out = this.connectionBlocks.map((a) => a.write());
|
|
10746
10790
|
const art2 = RIFFChunk.getParts(this.mode === "dls2" ? "art2" : "art1", [art2Data, ...out]);
|
|
10747
|
-
return RIFFChunk.getParts(this.mode === "dls2" ? "lar2" : "lart", art2, true);
|
|
10791
|
+
return RIFFChunk.getParts(this.mode === "dls2" ? "lar2" : "lart", art2, false, true);
|
|
10748
10792
|
}
|
|
10749
10793
|
/**
|
|
10750
10794
|
* Converts DLS articulation into an SF zone.
|
|
@@ -11247,16 +11291,18 @@ var DownloadableSounds = class DownloadableSounds extends DLSVerifier {
|
|
|
11247
11291
|
const drumAliases = pgalData.slice(pgalData.currentIndex, pgalData.currentIndex + 128);
|
|
11248
11292
|
pgalData.currentIndex += 128;
|
|
11249
11293
|
for (let keyNum = 0; keyNum < 128; keyNum++) {
|
|
11250
|
-
const
|
|
11251
|
-
if (
|
|
11252
|
-
const region = drumInstrument.regions.find((r) => r.keyRange.max ===
|
|
11294
|
+
const source = drumAliases[keyNum];
|
|
11295
|
+
if (source === keyNum) continue;
|
|
11296
|
+
const region = drumInstrument.regions.find((r) => r.keyRange.max === source && r.keyRange.min === source);
|
|
11253
11297
|
if (!region) {
|
|
11254
|
-
SpessaLog.warn(`Invalid drum alias ${keyNum} to ${
|
|
11298
|
+
SpessaLog.warn(`Invalid drum alias ${keyNum} to ${source}: region does not exist.`);
|
|
11255
11299
|
continue;
|
|
11256
11300
|
}
|
|
11257
11301
|
const copied = DownloadableSoundsRegion.copyFrom(region);
|
|
11258
11302
|
copied.keyRange.max = keyNum;
|
|
11259
11303
|
copied.keyRange.min = keyNum;
|
|
11304
|
+
const fixedKeyBlock = new ConnectionBlock(new ConnectionSource(DLSSources.none, 0, false, false), new ConnectionSource(DLSSources.none, 0, false, false), DLSDestinations.keyNum, 0, source << 16);
|
|
11305
|
+
copied.articulation.connectionBlocks.push(fixedKeyBlock);
|
|
11260
11306
|
drumInstrument.regions.push(copied);
|
|
11261
11307
|
}
|
|
11262
11308
|
pgalData.currentIndex += 4;
|
|
@@ -12632,7 +12678,7 @@ function controllerChange(controller, value, sendEvent = true) {
|
|
|
12632
12678
|
this.setBankLSB(value);
|
|
12633
12679
|
break;
|
|
12634
12680
|
case MIDIControllers.variationDepth:
|
|
12635
|
-
this.synthCore.
|
|
12681
|
+
this.synthCore.updateActiveEffects();
|
|
12636
12682
|
break;
|
|
12637
12683
|
case MIDIControllers.registeredParameterLSB:
|
|
12638
12684
|
case MIDIControllers.registeredParameterMSB:
|
|
@@ -13149,12 +13195,12 @@ function noteOn(midiNote, velocity, emit = true) {
|
|
|
13149
13195
|
let reverbSend = 1;
|
|
13150
13196
|
let chorusSend = 1;
|
|
13151
13197
|
let delaySend = 1;
|
|
13152
|
-
if (this._midiParameters.randomPan) panOverride = Math.round(
|
|
13198
|
+
if (this._midiParameters.randomPan) panOverride = Math.round(randomGenerator() * 1e3 - 500);
|
|
13153
13199
|
if (this._drumChannel) {
|
|
13154
13200
|
const p = this.drumParams[midiNote];
|
|
13155
13201
|
if (!p.rxNoteOn) return;
|
|
13156
13202
|
const drumPan = p.pan - 64;
|
|
13157
|
-
if (drumPan !== 0) if (drumPan === -64) panOverride = Math.round(
|
|
13203
|
+
if (drumPan !== 0) if (drumPan === -64) panOverride = Math.round(randomGenerator() * 1e3 - 500);
|
|
13158
13204
|
else {
|
|
13159
13205
|
const channelPan = (this._midiControllers[MIDIControllers.pan] >> 7) - 64;
|
|
13160
13206
|
panOverride = Math.max(-63, Math.min(drumPan + channelPan, 63)) / 63 * 500 || 1;
|
|
@@ -13602,6 +13648,7 @@ function applySnapshot(snapshot) {
|
|
|
13602
13648
|
this.setSystemParameter("presetLock", false);
|
|
13603
13649
|
if (snapshot.patch) this.setPatch(snapshot.patch);
|
|
13604
13650
|
this.lockedSystem = snapshot.lockedSystem;
|
|
13651
|
+
for (const parameter of Object.keys(snapshot.lockedMIDIParameters)) this.lockMIDIParameter(parameter, false);
|
|
13605
13652
|
for (const [parameter, value] of Object.entries(snapshot.midiParameters)) this.setMIDIParameter(parameter, value);
|
|
13606
13653
|
for (const [parameter, isLocked] of Object.entries(snapshot.lockedMIDIParameters)) this.lockMIDIParameter(parameter, isLocked);
|
|
13607
13654
|
for (const [parameter, value] of Object.entries(snapshot.systemParameters)) this.setSystemParameter(parameter, value);
|
|
@@ -14690,7 +14737,6 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
|
|
|
14690
14737
|
if (isReverb && this.systemParameters.reverbLock) return;
|
|
14691
14738
|
if (isChorus && this.systemParameters.chorusLock) return;
|
|
14692
14739
|
if (isDelay && this.systemParameters.delayLock) return;
|
|
14693
|
-
this.delayActive ||= a3 === 64 || isDelay;
|
|
14694
14740
|
switch (a3) {
|
|
14695
14741
|
default:
|
|
14696
14742
|
SpessaLog.gsFail("Patch Common Parameter", [a3]);
|
|
@@ -14829,6 +14875,7 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
|
|
|
14829
14875
|
break;
|
|
14830
14876
|
case 64:
|
|
14831
14877
|
this.chorusProcessor.sendLevelToDelay = data;
|
|
14878
|
+
this.updateActiveEffects();
|
|
14832
14879
|
SpessaLog.gsInfo("Chorus Send Level To Delay", data);
|
|
14833
14880
|
this.callEvent("effectChange", {
|
|
14834
14881
|
effect: "chorus",
|
|
@@ -14989,7 +15036,7 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
|
|
|
14989
15036
|
return;
|
|
14990
15037
|
case 25:
|
|
14991
15038
|
this.insertionProcessor.sendLevelToDelay = data / 127 * EFX_SENDS_GAIN_CORRECTION;
|
|
14992
|
-
this.
|
|
15039
|
+
this.updateActiveEffects();
|
|
14993
15040
|
SpessaLog.gsInfo("EFX Send Level to Delay", data);
|
|
14994
15041
|
this.callEvent("effectChange", {
|
|
14995
15042
|
effect: "insertion",
|
|
@@ -15168,8 +15215,8 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
|
|
|
15168
15215
|
case 34: {
|
|
15169
15216
|
const efx = data === 1;
|
|
15170
15217
|
ch.setMIDIParameter("efxAssign", efx);
|
|
15171
|
-
this.insertionActive ||= efx;
|
|
15172
15218
|
SpessaLog.gsInfo(`EFX assign for ${channel}`, efx ? "EFX" : "BYPASS");
|
|
15219
|
+
this.updateActiveEffects();
|
|
15173
15220
|
}
|
|
15174
15221
|
}
|
|
15175
15222
|
return;
|
|
@@ -20296,7 +20343,7 @@ var SynthesizerCore = class {
|
|
|
20296
20343
|
this.resetInsertion();
|
|
20297
20344
|
if (!this.drumPreset || !this.defaultPreset) return;
|
|
20298
20345
|
for (const ch of this.midiChannels) ch.reset(false);
|
|
20299
|
-
|
|
20346
|
+
this.updateActiveEffects();
|
|
20300
20347
|
}
|
|
20301
20348
|
process(left, right, startIndex = 0, sampleCount = 0) {
|
|
20302
20349
|
this.processSplit([[left, right]], left, right, startIndex, sampleCount);
|
|
@@ -20417,6 +20464,14 @@ var SynthesizerCore = class {
|
|
|
20417
20464
|
callEvent(eventName, eventData) {
|
|
20418
20465
|
this.eventCallbackHandler(eventName, eventData);
|
|
20419
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
|
+
}
|
|
20420
20475
|
getInsertionSnapshot() {
|
|
20421
20476
|
return {
|
|
20422
20477
|
type: this.insertionProcessor.type,
|
|
@@ -20431,7 +20486,6 @@ var SynthesizerCore = class {
|
|
|
20431
20486
|
}
|
|
20432
20487
|
resetInsertion() {
|
|
20433
20488
|
if (this.systemParameters.insertionEffectLock) return;
|
|
20434
|
-
this.insertionActive = false;
|
|
20435
20489
|
this.insertionProcessor = this.insertionFallback;
|
|
20436
20490
|
this.insertionProcessor.reset();
|
|
20437
20491
|
this.resetInsertionParams();
|