spessasynth_core 4.3.7 → 4.3.9
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 +27 -12
- package/dist/index.js +73 -39
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1982,17 +1982,17 @@ interface ChannelMIDIParameter {
|
|
|
1982
1982
|
*/
|
|
1983
1983
|
randomPan: boolean;
|
|
1984
1984
|
/**
|
|
1985
|
-
* Assign mode for the channel
|
|
1986
|
-
*
|
|
1987
|
-
*
|
|
1985
|
+
* Assign mode for the channel:
|
|
1986
|
+
* - `0` - A new note will kill the previous one if it is still playing.
|
|
1987
|
+
* - Any other value - A new note will not kill the previous notes (default).
|
|
1988
1988
|
*
|
|
1989
|
-
*
|
|
1990
|
-
*
|
|
1991
|
-
* - 2 - FullMulti: If the same note is played multiple times in succession, the previously-sounding note(s) will continue sounding for their natural length even after the new note is sounded.
|
|
1989
|
+
* While GS and XG differentiate 1 (Limited Multi for GS/Multi for XG) and 2 (Full Multi for GS/Inst (for Drum)),
|
|
1990
|
+
* SpessaSynth treats them both as full Multi. (no note killing is performed)
|
|
1992
1991
|
*
|
|
1993
|
-
*
|
|
1994
|
-
*
|
|
1995
|
-
*
|
|
1992
|
+
* This may be useful for emulating SC-55 hi-hat cutoff or MSGS note cutoff.
|
|
1993
|
+
*
|
|
1994
|
+
* Refer to [SC-8850 Owner's Manual](https://cdn.roland.com/assets/media/pdf/SC-8850_OM.pdf), page 238 for more description.
|
|
1995
|
+
* Note that `SAME NOTE NUMBER KEY ON ASSIGN` in XG is also recognized as assign mode.
|
|
1996
1996
|
*/
|
|
1997
1997
|
assignMode: number;
|
|
1998
1998
|
/**
|
|
@@ -2217,6 +2217,8 @@ interface GlobalSystemParameter {
|
|
|
2217
2217
|
/**
|
|
2218
2218
|
* The master pan.
|
|
2219
2219
|
* From -1 (left) to 1 (right). 0 is center.
|
|
2220
|
+
*
|
|
2221
|
+
* This uses the cosine panning law, so the perceived loudness remains constant as the pan changes.
|
|
2220
2222
|
*/
|
|
2221
2223
|
pan: number;
|
|
2222
2224
|
/**
|
|
@@ -2827,13 +2829,17 @@ interface GlobalMIDIParameter {
|
|
|
2827
2829
|
*/
|
|
2828
2830
|
fineTune: number;
|
|
2829
2831
|
/**
|
|
2830
|
-
* The master
|
|
2831
|
-
* From 0 to
|
|
2832
|
+
* The master volume.
|
|
2833
|
+
* From 0 (silent) to 1 (full volume).
|
|
2834
|
+
*
|
|
2835
|
+
* This differs from the `gain` system parameter in that it is squared internally.
|
|
2832
2836
|
*/
|
|
2833
|
-
|
|
2837
|
+
volume: number;
|
|
2834
2838
|
/**
|
|
2835
2839
|
* The master pan.
|
|
2836
2840
|
* From -1 (left) to 1 (right). 0 is center.
|
|
2841
|
+
*
|
|
2842
|
+
* This uses the cosine panning law, so the perceived loudness remains constant as the pan changes.
|
|
2837
2843
|
*/
|
|
2838
2844
|
pan: number;
|
|
2839
2845
|
}
|
|
@@ -3389,6 +3395,14 @@ declare class BasicSoundBank {
|
|
|
3389
3395
|
* Indicates if the SF3/SF2Pack decoder is ready.
|
|
3390
3396
|
*/
|
|
3391
3397
|
static isSF3DecoderReady: Promise<boolean>;
|
|
3398
|
+
/**
|
|
3399
|
+
* The type of the sound bank that was loaded.
|
|
3400
|
+
* Either `sf2` for SoundFont2/SoundFont3 or `dls` for DownLoadable Sounds.
|
|
3401
|
+
*
|
|
3402
|
+
* Please note that SF3 or SFOGG files are parsed as `sf2` files, but with compressed samples.
|
|
3403
|
+
* The type is still `sf2`.
|
|
3404
|
+
*/
|
|
3405
|
+
readonly type: "sf2" | "dls";
|
|
3392
3406
|
/**
|
|
3393
3407
|
* Sound bank's info.
|
|
3394
3408
|
*/
|
|
@@ -3413,6 +3427,7 @@ declare class BasicSoundBank {
|
|
|
3413
3427
|
* If the sound bank has custom default modulators (DMOD).
|
|
3414
3428
|
*/
|
|
3415
3429
|
customDefaultModulators: boolean;
|
|
3430
|
+
constructor(type?: "sf2" | "dls");
|
|
3416
3431
|
private _isXGBank;
|
|
3417
3432
|
/**
|
|
3418
3433
|
* Checks for XG drum sets and considers if this sound bank is XG.
|
package/dist/index.js
CHANGED
|
@@ -1698,9 +1698,9 @@ var MIDIUtils = class MIDIUtils {
|
|
|
1698
1698
|
])];
|
|
1699
1699
|
}
|
|
1700
1700
|
}
|
|
1701
|
-
case "
|
|
1701
|
+
case "volume": switch (system) {
|
|
1702
1702
|
default: {
|
|
1703
|
-
const gainValue = Math.floor(
|
|
1703
|
+
const gainValue = Math.floor(value * 16383);
|
|
1704
1704
|
return [MIDIUtils.deviceControlMessage(ticks, 1, [gainValue & 127, gainValue >> 7 & 127])];
|
|
1705
1705
|
}
|
|
1706
1706
|
case "xg": {
|
|
@@ -1747,7 +1747,11 @@ var MIDIUtils = class MIDIUtils {
|
|
|
1747
1747
|
case "keyShift": return MIDIMessage.registeredParameter(ticks, channel, RegisteredParameterTypes.coarseTuning, value + 64 << 7);
|
|
1748
1748
|
case "fineTune": return MIDIMessage.registeredParameter(ticks, channel, RegisteredParameterTypes.fineTuning, Math.floor(value * 81.92 + 8192));
|
|
1749
1749
|
case "randomPan": return system === "xg" ? [MIDIUtils.xgMessage(ticks, 8, channel, 14, [0])] : [MIDIUtils.gsMessage(ticks, 64, 16 | gsChannel, 28, [0])];
|
|
1750
|
-
case "assignMode":
|
|
1750
|
+
case "assignMode": switch (system) {
|
|
1751
|
+
default:
|
|
1752
|
+
case "gs": return [MIDIUtils.gsMessage(ticks, 64, 16 | gsChannel, 20, [value])];
|
|
1753
|
+
case "xg": return [MIDIUtils.xgMessage(ticks, 8, channel, 6, [value])];
|
|
1754
|
+
}
|
|
1751
1755
|
case "efxAssign": return [MIDIUtils.gsMessage(ticks, 64, 16 | gsChannel, 34, [value])];
|
|
1752
1756
|
case "cc1": return [MIDIUtils.gsMessage(ticks, 64, 16 | gsChannel, 31, [value])];
|
|
1753
1757
|
case "cc2": return [MIDIUtils.gsMessage(ticks, 64, 16 | gsChannel, 32, [value])];
|
|
@@ -1924,7 +1928,7 @@ var MIDIUtils = class MIDIUtils {
|
|
|
1924
1928
|
const value = (syx[5] << 7 | syx[4]) / 16383;
|
|
1925
1929
|
return {
|
|
1926
1930
|
type: "Global MIDI Param",
|
|
1927
|
-
parameter: "
|
|
1931
|
+
parameter: "volume",
|
|
1928
1932
|
value: Math.pow(value, 2)
|
|
1929
1933
|
};
|
|
1930
1934
|
}
|
|
@@ -1949,11 +1953,12 @@ var MIDIUtils = class MIDIUtils {
|
|
|
1949
1953
|
default: return OTHER;
|
|
1950
1954
|
case 1: switch (syx[9]) {
|
|
1951
1955
|
default: return OTHER;
|
|
1952
|
-
case
|
|
1953
|
-
case
|
|
1956
|
+
case 0:
|
|
1957
|
+
case 1: return { type: "Reverb Param" };
|
|
1954
1958
|
}
|
|
1955
1959
|
case 2: switch (syx[9]) {
|
|
1956
1960
|
default: return OTHER;
|
|
1961
|
+
case 0:
|
|
1957
1962
|
case 1:
|
|
1958
1963
|
case 2:
|
|
1959
1964
|
case 3:
|
|
@@ -2015,7 +2020,6 @@ var MIDIUtils = class MIDIUtils {
|
|
|
2015
2020
|
if (a1 === 3 && a2 === 0) return { type: "Variation Param" };
|
|
2016
2021
|
if (a1 === 8) {
|
|
2017
2022
|
const channel = a2;
|
|
2018
|
-
if (channel >= 16) return OTHER;
|
|
2019
2023
|
switch (a3) {
|
|
2020
2024
|
default: return OTHER;
|
|
2021
2025
|
case 1: return {
|
|
@@ -2041,6 +2045,12 @@ var MIDIUtils = class MIDIUtils {
|
|
|
2041
2045
|
controller: data === 1 ? MIDIControllers.polyModeOn : MIDIControllers.monoModeOn,
|
|
2042
2046
|
value: 0
|
|
2043
2047
|
};
|
|
2048
|
+
case 6: return {
|
|
2049
|
+
type: "Channel MIDI Param",
|
|
2050
|
+
channel,
|
|
2051
|
+
parameter: "assignMode",
|
|
2052
|
+
value: data
|
|
2053
|
+
};
|
|
2044
2054
|
case 7: return {
|
|
2045
2055
|
type: "Drums On",
|
|
2046
2056
|
channel,
|
|
@@ -2145,7 +2155,7 @@ var MIDIUtils = class MIDIUtils {
|
|
|
2145
2155
|
};
|
|
2146
2156
|
case 4: return {
|
|
2147
2157
|
type: "Global MIDI Param",
|
|
2148
|
-
parameter: "
|
|
2158
|
+
parameter: "volume",
|
|
2149
2159
|
value: data / 127
|
|
2150
2160
|
};
|
|
2151
2161
|
case 5: return {
|
|
@@ -2160,7 +2170,8 @@ var MIDIUtils = class MIDIUtils {
|
|
|
2160
2170
|
};
|
|
2161
2171
|
case 127:
|
|
2162
2172
|
switch (data) {
|
|
2163
|
-
case 0:
|
|
2173
|
+
case 0:
|
|
2174
|
+
case 1: return {
|
|
2164
2175
|
type: "Global MIDI Param",
|
|
2165
2176
|
parameter: "system",
|
|
2166
2177
|
value: "gs"
|
|
@@ -2174,12 +2185,8 @@ var MIDIUtils = class MIDIUtils {
|
|
|
2174
2185
|
return OTHER;
|
|
2175
2186
|
}
|
|
2176
2187
|
if (a1 === 65) return { type: "Drum Setup" };
|
|
2177
|
-
if (a1 !== 64) return OTHER;
|
|
2178
|
-
|
|
2179
|
-
type: "Global MIDI Param",
|
|
2180
|
-
parameter: "keyShift",
|
|
2181
|
-
value: data - 64
|
|
2182
|
-
};
|
|
2188
|
+
if (a1 !== 64 && a1 !== 80) return OTHER;
|
|
2189
|
+
const channelOffset = a1 === 80 ? 16 : 0;
|
|
2183
2190
|
if (a2 === 1) {
|
|
2184
2191
|
if (a3 >= 48 && a3 <= 55) return { type: "Reverb Param" };
|
|
2185
2192
|
if (a3 >= 56 && a3 <= 64) return { type: "Chorus Param" };
|
|
@@ -2187,7 +2194,7 @@ var MIDIUtils = class MIDIUtils {
|
|
|
2187
2194
|
}
|
|
2188
2195
|
if (a2 === 3 && a3 >= 0 && a3 <= 127) return { type: "Insertion Param" };
|
|
2189
2196
|
if (a2 >> 4 === 1) {
|
|
2190
|
-
const channel = MIDIUtils.syxToChannel(a2 & 15);
|
|
2197
|
+
const channel = MIDIUtils.syxToChannel(a2 & 15) + channelOffset;
|
|
2191
2198
|
switch (a3) {
|
|
2192
2199
|
default: return OTHER;
|
|
2193
2200
|
case 0: return {
|
|
@@ -2329,7 +2336,7 @@ var MIDIUtils = class MIDIUtils {
|
|
|
2329
2336
|
}
|
|
2330
2337
|
}
|
|
2331
2338
|
if (a2 >> 4 === 4) {
|
|
2332
|
-
const channel = MIDIUtils.syxToChannel(a2 & 15);
|
|
2339
|
+
const channel = MIDIUtils.syxToChannel(a2 & 15) + channelOffset;
|
|
2333
2340
|
switch (a3) {
|
|
2334
2341
|
default: return OTHER;
|
|
2335
2342
|
case 0:
|
|
@@ -2389,6 +2396,7 @@ function correctBankOffsetInternal(mid, bankOffset, soundBank) {
|
|
|
2389
2396
|
default: return;
|
|
2390
2397
|
case "Drums On": {
|
|
2391
2398
|
const sysexChannel = syx.channel + portOffset;
|
|
2399
|
+
if (!channels[sysexChannel]) return;
|
|
2392
2400
|
channels[sysexChannel].isDrum = syx.isDrum;
|
|
2393
2401
|
return;
|
|
2394
2402
|
}
|
|
@@ -2403,6 +2411,7 @@ function correctBankOffsetInternal(mid, bankOffset, soundBank) {
|
|
|
2403
2411
|
break;
|
|
2404
2412
|
case "Controller Change": {
|
|
2405
2413
|
const t = mid.tracks[trackNum];
|
|
2414
|
+
if (syx.channel >= 16) return;
|
|
2406
2415
|
const newEvent = MIDIMessage.controllerChange(e.ticks, syx.channel, syx.controller, syx.value);
|
|
2407
2416
|
t.events[eventIndexes[trackNum]] = newEvent;
|
|
2408
2417
|
e = newEvent;
|
|
@@ -2410,6 +2419,7 @@ function correctBankOffsetInternal(mid, bankOffset, soundBank) {
|
|
|
2410
2419
|
break;
|
|
2411
2420
|
}
|
|
2412
2421
|
case "Program Change": {
|
|
2422
|
+
if (syx.channel >= 16) return;
|
|
2413
2423
|
const t = mid.tracks[trackNum];
|
|
2414
2424
|
const newEvent = MIDIMessage.programChange(e.ticks, syx.channel, syx.value);
|
|
2415
2425
|
t.events[eventIndexes[trackNum]] = newEvent;
|
|
@@ -2838,16 +2848,19 @@ function getUsedProgramsAndKeys(mid, soundBank) {
|
|
|
2838
2848
|
case "Channel MIDI Param":
|
|
2839
2849
|
if (syx.parameter === "keyShift") {
|
|
2840
2850
|
const ch = channels[syx.channel];
|
|
2851
|
+
if (!ch) break;
|
|
2841
2852
|
ch.keyShift = ch.isDrum ? 0 : syx.value;
|
|
2842
2853
|
}
|
|
2843
2854
|
break;
|
|
2844
2855
|
case "Drums On": {
|
|
2845
2856
|
const sysexChannel = syx.channel + channelOffset;
|
|
2857
|
+
if (!channels[sysexChannel]) break;
|
|
2846
2858
|
channels[sysexChannel].isDrum = syx.isDrum;
|
|
2847
2859
|
break;
|
|
2848
2860
|
}
|
|
2849
2861
|
case "Program Change": {
|
|
2850
2862
|
const ch = channels[syx.channel + channelOffset];
|
|
2863
|
+
if (!ch) break;
|
|
2851
2864
|
ch.preset = soundBank.getPreset({
|
|
2852
2865
|
bankMSB: ch.bankMSB,
|
|
2853
2866
|
bankLSB: ch.bankLSB,
|
|
@@ -2857,9 +2870,10 @@ function getUsedProgramsAndKeys(mid, soundBank) {
|
|
|
2857
2870
|
break;
|
|
2858
2871
|
}
|
|
2859
2872
|
case "Controller Change": {
|
|
2860
|
-
const
|
|
2861
|
-
if (
|
|
2862
|
-
|
|
2873
|
+
const ch = channels[syx.channel + channelOffset];
|
|
2874
|
+
if (!ch) break;
|
|
2875
|
+
if (syx.controller === MIDIControllers.bankSelectLSB) ch.bankLSB = syx.value;
|
|
2876
|
+
else if (syx.controller === MIDIControllers.bankSelect) ch.bankMSB = syx.value;
|
|
2863
2877
|
}
|
|
2864
2878
|
}
|
|
2865
2879
|
}
|
|
@@ -3307,7 +3321,7 @@ function modifyMIDIInternal(midi, opts) {
|
|
|
3307
3321
|
}
|
|
3308
3322
|
if (syx.parameter === "fineTune") {
|
|
3309
3323
|
const syxStatus = channelStatuses[syx.channel + portOffset];
|
|
3310
|
-
if (syxStatus.isFirstNoteOn && syxChannel) {
|
|
3324
|
+
if (syxStatus && syxStatus.isFirstNoteOn && syxChannel) {
|
|
3311
3325
|
const newTune = syxStatus.fineTune + syx.value;
|
|
3312
3326
|
syxStatus.currentKeyShift = Math.trunc(newTune / 100);
|
|
3313
3327
|
syxStatus.fineTune = newTune % 100;
|
|
@@ -5225,6 +5239,7 @@ function setTimeToInternal(time, ticks = void 0) {
|
|
|
5225
5239
|
break;
|
|
5226
5240
|
case "Controller Change": {
|
|
5227
5241
|
const { controller, value, channel } = analyzed;
|
|
5242
|
+
if (channel >= channelsToSave) break;
|
|
5228
5243
|
if (this._midiData.isMultiPort && track.channels.size === 0) break;
|
|
5229
5244
|
if (controller === MIDIControllers.resetAllControllers) {
|
|
5230
5245
|
resetAllControllers(channel);
|
|
@@ -11272,7 +11287,7 @@ var DownloadableSounds = class DownloadableSounds extends DLSVerifier {
|
|
|
11272
11287
|
*/
|
|
11273
11288
|
toSF() {
|
|
11274
11289
|
SpessaLog.group("%cConverting DLS to SF2...", ConsoleColors.info);
|
|
11275
|
-
const soundBank = new BasicSoundBank();
|
|
11290
|
+
const soundBank = new BasicSoundBank("dls");
|
|
11276
11291
|
soundBank.soundBankInfo.version.minor = 4;
|
|
11277
11292
|
soundBank.soundBankInfo.version.major = 2;
|
|
11278
11293
|
soundBank.soundBankInfo = { ...this.soundBankInfo };
|
|
@@ -11295,6 +11310,14 @@ var BasicSoundBank = class BasicSoundBank {
|
|
|
11295
11310
|
*/
|
|
11296
11311
|
static isSF3DecoderReady = stb.isInitialized;
|
|
11297
11312
|
/**
|
|
11313
|
+
* The type of the sound bank that was loaded.
|
|
11314
|
+
* Either `sf2` for SoundFont2/SoundFont3 or `dls` for DownLoadable Sounds.
|
|
11315
|
+
*
|
|
11316
|
+
* Please note that SF3 or SFOGG files are parsed as `sf2` files, but with compressed samples.
|
|
11317
|
+
* The type is still `sf2`.
|
|
11318
|
+
*/
|
|
11319
|
+
type;
|
|
11320
|
+
/**
|
|
11298
11321
|
* Sound bank's info.
|
|
11299
11322
|
*/
|
|
11300
11323
|
soundBankInfo = {
|
|
@@ -11327,6 +11350,9 @@ var BasicSoundBank = class BasicSoundBank {
|
|
|
11327
11350
|
* If the sound bank has custom default modulators (DMOD).
|
|
11328
11351
|
*/
|
|
11329
11352
|
customDefaultModulators = false;
|
|
11353
|
+
constructor(type = "sf2") {
|
|
11354
|
+
this.type = type;
|
|
11355
|
+
}
|
|
11330
11356
|
_isXGBank = false;
|
|
11331
11357
|
/**
|
|
11332
11358
|
* Checks for XG drum sets and considers if this sound bank is XG.
|
|
@@ -11916,7 +11942,7 @@ var SoundFont2 = class extends BasicSoundBank {
|
|
|
11916
11942
|
* Initializes a new SoundFont2 Parser and parses the given data array
|
|
11917
11943
|
*/
|
|
11918
11944
|
constructor(arrayBuffer, warnDeprecated = true) {
|
|
11919
|
-
super();
|
|
11945
|
+
super("sf2");
|
|
11920
11946
|
if (warnDeprecated) throw new Error("Using the constructor directly is deprecated. Use SoundBankLoader.fromArrayBuffer() instead.");
|
|
11921
11947
|
const mainFileArray = new IndexedByteArray(arrayBuffer);
|
|
11922
11948
|
SpessaLog.group("%cParsing a SoundFont2 file...", ConsoleColors.info);
|
|
@@ -14021,7 +14047,7 @@ var MIDIChannel = class {
|
|
|
14021
14047
|
this.currentTuning = this._drumChannel ? channelSystem.fineTune : globalSystem.fineTune + globalMIDI.fineTune + channelSystem.fineTune + channelMIDI.fineTune;
|
|
14022
14048
|
const currentPanNormalized = globalSystem.pan + globalMIDI.pan + channelSystem.pan;
|
|
14023
14049
|
this.currentPan = currentPanNormalized * 500;
|
|
14024
|
-
this.currentGain = SPESSASYNTH_GAIN_FACTOR * globalSystem.gain * globalMIDI.
|
|
14050
|
+
this.currentGain = SPESSASYNTH_GAIN_FACTOR * globalSystem.gain * Math.pow(globalMIDI.volume, 2) * channelSystem.gain;
|
|
14025
14051
|
}
|
|
14026
14052
|
/**
|
|
14027
14053
|
* Sets the channel to a given MIDI patch.
|
|
@@ -14330,8 +14356,7 @@ function universalSystemExclusive(syx, channelOffset = 0) {
|
|
|
14330
14356
|
break;
|
|
14331
14357
|
case 1: {
|
|
14332
14358
|
const vol = syx[5] << 7 | syx[4];
|
|
14333
|
-
|
|
14334
|
-
this.setMIDIParameter("gain", gain);
|
|
14359
|
+
this.setMIDIParameter("volume", vol / 16383);
|
|
14335
14360
|
SpessaLog.gmInfo("Master Volume", vol);
|
|
14336
14361
|
break;
|
|
14337
14362
|
}
|
|
@@ -14497,12 +14522,17 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
|
|
|
14497
14522
|
const a2 = syx[5];
|
|
14498
14523
|
const a3 = syx[6];
|
|
14499
14524
|
const data = Math.min(syx[7], 127);
|
|
14500
|
-
if (a1 === 0 && a2 === 0 && a3 === 127 && data === 0) {
|
|
14525
|
+
if (a1 === 0 && a2 === 0 && a3 === 127 && (data === 0 || data === 1)) {
|
|
14526
|
+
if (data === 1) {
|
|
14527
|
+
SpessaLog.gsInfo("Mode", "Double Module");
|
|
14528
|
+
while (this.midiChannels.length < 32) this.createMIDIChannel(true);
|
|
14529
|
+
}
|
|
14501
14530
|
SpessaLog.coolInfo("MIDI System", "Roland GS");
|
|
14502
14531
|
this.reset("gs");
|
|
14503
14532
|
return;
|
|
14504
14533
|
}
|
|
14505
|
-
if (a1 === 64) {
|
|
14534
|
+
if (a1 === 64 || a1 === 80) {
|
|
14535
|
+
if (a1 === 80) channelOffset += 16;
|
|
14506
14536
|
if (a2 === 0) {
|
|
14507
14537
|
switch (a3) {
|
|
14508
14538
|
case 0: {
|
|
@@ -14513,7 +14543,7 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
|
|
|
14513
14543
|
}
|
|
14514
14544
|
case 4:
|
|
14515
14545
|
SpessaLog.gsInfo("Master Volume", data);
|
|
14516
|
-
this.setMIDIParameter("
|
|
14546
|
+
this.setMIDIParameter("volume", data / 127);
|
|
14517
14547
|
break;
|
|
14518
14548
|
case 5: {
|
|
14519
14549
|
const transpose = data - 64;
|
|
@@ -14861,6 +14891,7 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
|
|
|
14861
14891
|
if (a2 >> 4 === 1) {
|
|
14862
14892
|
const channel = MIDIUtils.syxToChannel(a2 & 15) + channelOffset;
|
|
14863
14893
|
const ch = this.midiChannels[channel];
|
|
14894
|
+
if (!ch) SpessaLog.gsFail(`Patch Parameter for ${channel}`, syx, "Invalid channel number");
|
|
14864
14895
|
switch (a3) {
|
|
14865
14896
|
default:
|
|
14866
14897
|
SpessaLog.gsFail(`Patch Part Parameter for ${channel}`, [a3]);
|
|
@@ -15035,7 +15066,7 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
|
|
|
15035
15066
|
SpessaLog.gsFail("Patch Parameter", syx);
|
|
15036
15067
|
return;
|
|
15037
15068
|
}
|
|
15038
|
-
if (a1 === 65) {
|
|
15069
|
+
if (a1 === 65 || a1 === 81) {
|
|
15039
15070
|
if (this.systemParameters.drumLock) return;
|
|
15040
15071
|
const map = (a2 >> 4) + 1;
|
|
15041
15072
|
const drumKey = a3;
|
|
@@ -15046,7 +15077,8 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
|
|
|
15046
15077
|
return;
|
|
15047
15078
|
case 0: {
|
|
15048
15079
|
const patchName = readBinaryString(syx, 12, 7);
|
|
15049
|
-
SpessaLog.gsInfo(`
|
|
15080
|
+
SpessaLog.gsInfo(`Drum Map Name for MAP${map}`, patchName);
|
|
15081
|
+
this.callEvent("displayMessage", [...syx]);
|
|
15050
15082
|
break;
|
|
15051
15083
|
}
|
|
15052
15084
|
case 1: {
|
|
@@ -15121,12 +15153,10 @@ function rolandSystemExclusive(syx, channelOffset = 0) {
|
|
|
15121
15153
|
return;
|
|
15122
15154
|
}
|
|
15123
15155
|
case 69:
|
|
15124
|
-
if (syx[4] === 16)
|
|
15125
|
-
else if (syx[5] === 1) this.callEvent("displayMessage", [...syx]);
|
|
15126
|
-
else SpessaLog.gsFail("Display Data", syx);
|
|
15156
|
+
if (syx[4] === 16) this.callEvent("displayMessage", [...syx]);
|
|
15127
15157
|
return;
|
|
15128
15158
|
case 22: if (syx[4] === 16) {
|
|
15129
|
-
this.setMIDIParameter("
|
|
15159
|
+
this.setMIDIParameter("volume", syx[7] / 100);
|
|
15130
15160
|
SpessaLog.coolInfo("Roland Master Volume Control", syx[7]);
|
|
15131
15161
|
return;
|
|
15132
15162
|
} else SpessaLog.unsupported("Roland", syx);
|
|
@@ -15160,12 +15190,12 @@ function yamahaSystemExclusive(syx, channelOffset = 0) {
|
|
|
15160
15190
|
}
|
|
15161
15191
|
break;
|
|
15162
15192
|
case 4:
|
|
15163
|
-
this.setMIDIParameter("
|
|
15193
|
+
this.setMIDIParameter("volume", data / 127);
|
|
15164
15194
|
SpessaLog.xgInfo("Master Volume", data);
|
|
15165
15195
|
break;
|
|
15166
15196
|
case 5: {
|
|
15167
15197
|
const vol = 127 - data;
|
|
15168
|
-
this.setMIDIParameter("
|
|
15198
|
+
this.setMIDIParameter("volume", vol / 127);
|
|
15169
15199
|
SpessaLog.xgInfo("Master Attenuation", data);
|
|
15170
15200
|
break;
|
|
15171
15201
|
}
|
|
@@ -15225,6 +15255,10 @@ function yamahaSystemExclusive(syx, channelOffset = 0) {
|
|
|
15225
15255
|
SpessaLog.xgInfo(`Mono/poly on ${channel}`, poly ? "POLY" : "MONO");
|
|
15226
15256
|
break;
|
|
15227
15257
|
}
|
|
15258
|
+
case 6:
|
|
15259
|
+
ch.setMIDIParameter("assignMode", data);
|
|
15260
|
+
SpessaLog.xgInfo(`Same Note Number Key On Assign on ${channel}`, data);
|
|
15261
|
+
break;
|
|
15228
15262
|
case 7: {
|
|
15229
15263
|
const drums = data !== 0;
|
|
15230
15264
|
ch.setDrums(drums);
|
|
@@ -19740,7 +19774,7 @@ var SpessaSynthDelay = class {
|
|
|
19740
19774
|
//#endregion
|
|
19741
19775
|
//#region src/synthesizer/audio_engine/parameters/midi.ts
|
|
19742
19776
|
const DEFAULT_GLOBAL_MIDI_PARAMETERS = {
|
|
19743
|
-
|
|
19777
|
+
volume: 1,
|
|
19744
19778
|
pan: 0,
|
|
19745
19779
|
keyShift: 0,
|
|
19746
19780
|
fineTune: 0,
|
|
@@ -20138,7 +20172,7 @@ var SynthesizerCore = class {
|
|
|
20138
20172
|
reset(system = "gs") {
|
|
20139
20173
|
this.callEvent("reset", system);
|
|
20140
20174
|
this.setMIDIParameter("system", system);
|
|
20141
|
-
this.setMIDIParameter("
|
|
20175
|
+
this.setMIDIParameter("volume", 1);
|
|
20142
20176
|
this.setMIDIParameter("pan", 0);
|
|
20143
20177
|
this.setMIDIParameter("keyShift", 0);
|
|
20144
20178
|
this.setMIDIParameter("fineTune", 0);
|