spessasynth_core 4.3.12 → 4.3.14

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.js CHANGED
@@ -1800,7 +1800,7 @@ var MIDIUtils = class MIDIUtils {
1800
1800
  case "gs": return [MIDIUtils.gsMessage(ticks, 64, 16 | gsChannel, 20, [value])];
1801
1801
  case "xg": return [MIDIUtils.xgMessage(ticks, 8, channel, 6, [value])];
1802
1802
  }
1803
- case "efxAssign": return [MIDIUtils.gsMessage(ticks, 64, 16 | gsChannel, 34, [value])];
1803
+ case "efxAssign": return [MIDIUtils.gsMessage(ticks, 64, 64 | gsChannel, 34, [value ? 1 : 0])];
1804
1804
  case "cc1": return [MIDIUtils.gsMessage(ticks, 64, 16 | gsChannel, 31, [value])];
1805
1805
  case "cc2": return [MIDIUtils.gsMessage(ticks, 64, 16 | gsChannel, 32, [value])];
1806
1806
  case "drumMap": return [MIDIUtils.gsMessage(ticks, 64, 16 | gsChannel, 21, [value])];
@@ -2428,7 +2428,9 @@ function correctBankOffsetInternal(mid, bankOffset, soundBank) {
2428
2428
  isDrum: i % 16 === 9,
2429
2429
  lastBank: void 0,
2430
2430
  lastBankLSB: void 0,
2431
- hasBankSelect: false
2431
+ hasBankSelect: false,
2432
+ programChangeTrack: void 0,
2433
+ programChangeIndex: void 0
2432
2434
  });
2433
2435
  mid.iterate((e, trackNum, eventIndexes) => {
2434
2436
  const portOffset = mid.portChannelOffsetMap[ports[trackNum]];
@@ -2436,7 +2438,7 @@ function correctBankOffsetInternal(mid, bankOffset, soundBank) {
2436
2438
  ports[trackNum] = e.data[0];
2437
2439
  return;
2438
2440
  }
2439
- const status = e.statusByte & 240;
2441
+ let status = e.statusByte & 240;
2440
2442
  if (status !== MIDIMessageTypes.controllerChange && status !== MIDIMessageTypes.programChange && status !== MIDIMessageTypes.systemExclusive) return;
2441
2443
  if (status === MIDIMessageTypes.systemExclusive) {
2442
2444
  const syx = MIDIUtils.analyzeSysEx(e.data);
@@ -2477,6 +2479,7 @@ function correctBankOffsetInternal(mid, bankOffset, soundBank) {
2477
2479
  }
2478
2480
  }
2479
2481
  }
2482
+ status = e.statusByte & 240;
2480
2483
  const chNum = (e.statusByte & 15) + portOffset;
2481
2484
  const ch = channels[chNum];
2482
2485
  if (status === MIDIMessageTypes.programChange) {
@@ -2489,6 +2492,9 @@ function correctBankOffsetInternal(mid, bankOffset, soundBank) {
2489
2492
  const targetPreset = soundBank.getPreset(patch, system);
2490
2493
  SpessaLog.info(`%cInput patch: %c${MIDIPatchTools.toMIDIString(patch)}%c. Channel %c${chNum}%c. Changing patch to ${targetPreset.toString()}.`, ConsoleColors.info, ConsoleColors.unrecognized, ConsoleColors.info, ConsoleColors.recognized, ConsoleColors.info);
2491
2494
  e.data[0] = targetPreset.program;
2495
+ ch.program = targetPreset.program;
2496
+ ch.programChangeTrack ??= trackNum;
2497
+ ch.programChangeIndex ??= eventIndexes[trackNum];
2492
2498
  if (targetPreset.isGMGSDrum && BankSelectHacks.isSystemXG(system)) return;
2493
2499
  if (ch.lastBank === void 0) return;
2494
2500
  ch.lastBank.data[1] = BankSelectHacks.addBankOffset(targetPreset.bankMSB, bankOffset, system === "xg");
@@ -2506,35 +2512,38 @@ function correctBankOffsetInternal(mid, bankOffset, soundBank) {
2506
2512
  const ch = channels[chNum];
2507
2513
  if (ch.hasBankSelect) continue;
2508
2514
  const midiChannel = chNum % 16;
2509
- const status = MIDIMessageTypes.programChange | midiChannel;
2510
2515
  const portOffset = Math.floor(chNum / 16) * 16;
2511
2516
  const port = mid.portChannelOffsetMap.indexOf(portOffset);
2512
- const track = mid.tracks.find((t) => t.port === port && t.channels.has(midiChannel));
2513
- if (track === void 0) continue;
2514
- let indexToAdd = track.events.findIndex((e) => e.statusByte === status);
2515
- if (indexToAdd === -1) {
2516
- const programIndex = track.events.findIndex((e) => e.statusByte > 128 && e.statusByte < 240 && (e.statusByte & 15) === midiChannel);
2517
+ const tracksUsedByChannel = mid.tracks.filter((t) => t.port === port && t.channels.has(midiChannel));
2518
+ if (tracksUsedByChannel.length === 0) continue;
2519
+ let foundTrack = ch.programChangeTrack ? mid.tracks[ch.programChangeTrack] : void 0;
2520
+ let indexToAdd = ch.programChangeIndex ?? -1;
2521
+ if (!foundTrack) {
2522
+ const programChangeTrack = tracksUsedByChannel[0];
2523
+ const programIndex = programChangeTrack.events.findIndex((e) => e.statusByte >= 128 && e.statusByte < 240 && (e.statusByte & 15) === midiChannel);
2517
2524
  if (programIndex === -1) continue;
2518
- const programTicks = track.events[programIndex].ticks;
2525
+ const programTicks = programChangeTrack.events[programIndex].ticks;
2519
2526
  const targetProgram = soundBank.getPreset({
2520
2527
  bankMSB: 0,
2521
2528
  bankLSB: 0,
2522
2529
  program: 0,
2523
2530
  isGMGSDrum: false
2524
2531
  }, system).program;
2525
- track.addEvents(programIndex, MIDIMessage.programChange(programTicks, midiChannel, targetProgram));
2532
+ SpessaLog.info(`%cAdding default program change for %c${chNum}`, ConsoleColors.info, ConsoleColors.recognized);
2533
+ programChangeTrack.addEvents(programIndex, MIDIMessage.programChange(programTicks, midiChannel, targetProgram));
2526
2534
  indexToAdd = programIndex;
2535
+ foundTrack = programChangeTrack;
2527
2536
  }
2528
- SpessaLog.info(`%cAdding bank select for %c${chNum}`, ConsoleColors.info, ConsoleColors.recognized);
2529
- const ticks = track.events[indexToAdd].ticks;
2537
+ const ticks = foundTrack.events[indexToAdd].ticks;
2530
2538
  const targetPreset = soundBank.getPreset({
2531
2539
  bankLSB: 0,
2532
2540
  bankMSB: 0,
2533
2541
  program: ch.program,
2534
2542
  isGMGSDrum: ch.isDrum
2535
2543
  }, system);
2544
+ SpessaLog.info(`%cAdding bank select for %c${chNum}%c Targeting preset: %c${targetPreset.toString()}`, ConsoleColors.info, ConsoleColors.recognized, ConsoleColors.info, ConsoleColors.recognized);
2536
2545
  const targetBank = BankSelectHacks.addBankOffset(targetPreset.bankMSB, bankOffset, system === "xg");
2537
- track.addEvents(indexToAdd, MIDIMessage.controllerChange(ticks, midiChannel, MIDIControllers.bankSelect, targetBank));
2546
+ foundTrack.addEvents(indexToAdd, MIDIMessage.controllerChange(ticks, midiChannel, MIDIControllers.bankSelect, targetBank));
2538
2547
  }
2539
2548
  if (system === "gm" && !BankSelectHacks.isSystemXG(system)) {
2540
2549
  for (const m of unwantedSystems) {
@@ -3227,7 +3236,7 @@ function modifyMIDIInternal(midi, opts) {
3227
3236
  case MIDIMessageTypes.controllerChange: {
3228
3237
  const ccNum = e.data[0];
3229
3238
  const value = e.data[1];
3230
- if (channelChange?.controllers?.get(ccNum)) {
3239
+ if (channelChange?.controllers?.get(ccNum) !== void 0) {
3231
3240
  deleteThisEvent();
3232
3241
  return;
3233
3242
  }
@@ -3256,7 +3265,7 @@ function modifyMIDIInternal(midi, opts) {
3256
3265
  case "Controller Change": {
3257
3266
  const ccNum = data.controller;
3258
3267
  const channel = data.channel;
3259
- if (channelChange?.controllers?.get(ccNum)) {
3268
+ if (channelChange?.controllers?.get(ccNum) !== void 0) {
3260
3269
  deleteParameter(channel);
3261
3270
  return;
3262
3271
  }
@@ -5358,8 +5367,8 @@ function setTimeToInternal(time, ticks = void 0) {
5358
5367
  if (ch.portamentoNote >= 0) if (this.externalMIDIPlayback) this.sendMIDICC(channel, MIDIControllers.portamentoControl, ch.portamentoNote);
5359
5368
  else this.synth.midiChannels[channel].setLastNote(ch.portamentoNote);
5360
5369
  for (let i = 0; i < 128; i++) {
5361
- const value = ch.controllers[i] >> 7;
5362
- if (value !== DEFAULT_MIDI_CONTROLLERS[i] && !nonSkippableCCs.has(i)) this.sendMIDICC(channel, i, value);
5370
+ const value = ch.controllers[i];
5371
+ if (value !== DEFAULT_MIDI_CONTROLLERS[i] && !nonSkippableCCs.has(i)) this.sendMIDICC(channel, i, value >> 7);
5363
5372
  }
5364
5373
  }
5365
5374
  if (savedTempo) this.callEvent("metaEvent", {
@@ -8211,9 +8220,7 @@ const defaultSpessaSynthModulators = [
8211
8220
  new DecodedModulator(getModSourceEnum(ModulatorCurveTypes.linear, true, false, true, MIDIControllers.decayTime), 0, GeneratorTypes.decayVolEnv, 3600, 0),
8212
8221
  new DecodedModulator(getModSourceEnum(ModulatorCurveTypes.linear, true, false, true, MIDIControllers.brightness), 0, GeneratorTypes.initialFilterFc, 9600, 0),
8213
8222
  new DecodedModulator(DEFAULT_RESONANT_MOD_SOURCE, 0, GeneratorTypes.initialFilterQ, 250, 0),
8214
- new DecodedModulator(getModSourceEnum(ModulatorCurveTypes.switch, false, false, true, MIDIControllers.softPedal), 0, GeneratorTypes.initialAttenuation, 50, 0),
8215
- new DecodedModulator(getModSourceEnum(ModulatorCurveTypes.switch, false, false, true, MIDIControllers.softPedal), 0, GeneratorTypes.initialFilterFc, -2400, 0),
8216
- new DecodedModulator(getModSourceEnum(ModulatorCurveTypes.linear, true, false, true, MIDIControllers.balance), 0, GeneratorTypes.pan, 500, 0)
8223
+ new DecodedModulator(getModSourceEnum(ModulatorCurveTypes.switch, false, false, true, MIDIControllers.softPedal), 0, GeneratorTypes.initialFilterFc, -1200, 0)
8217
8224
  ];
8218
8225
  const SPESSASYNTH_DEFAULT_MODULATORS = [...defaultSoundFont2Modulators, ...defaultSpessaSynthModulators];
8219
8226
  //#endregion
@@ -8550,6 +8557,7 @@ var BasicSample = class {
8550
8557
  */
8551
8558
  setLinkedSample(sample, type) {
8552
8559
  if (sample.linkedSample) throw new Error(`${sample.name} is linked tp ${sample.linkedSample.name}. Unlink it first.`);
8560
+ if (this === sample) throw new Error(`${sample.name} cannot be linked to itself.`);
8553
8561
  this.linkedSample = sample;
8554
8562
  sample.linkedSample = this;
8555
8563
  switch (type) {
@@ -9304,6 +9312,9 @@ var SoundFontSample = class extends BasicSample {
9304
9312
  if (linked) if (linked.linkedSample) {
9305
9313
  SpessaLog.info(`%cInvalid linked sample for ${this.name}: ${linked.name} is already linked to ${linked.linkedSample.name}`, ConsoleColors.warn);
9306
9314
  this.unlinkSample();
9315
+ } else if (linked === this) {
9316
+ SpessaLog.info(`%cInvalid linked sample for ${this.name}: linked to itself.`, ConsoleColors.warn);
9317
+ this.unlinkSample();
9307
9318
  } else this.setLinkedSample(linked, this.sampleType);
9308
9319
  else {
9309
9320
  SpessaLog.info(`%cInvalid linked sample for ${this.name}. Setting to mono.`, ConsoleColors.warn);
@@ -20282,10 +20293,10 @@ var SynthesizerCore = class {
20282
20293
  this.setReverbMacro(4);
20283
20294
  this.setChorusMacro(2);
20284
20295
  this.setDelayMacro(0);
20285
- if (!this.systemParameters.delayLock) this.delayActive = false;
20286
20296
  this.resetInsertion();
20287
20297
  if (!this.drumPreset || !this.defaultPreset) return;
20288
20298
  for (const ch of this.midiChannels) ch.reset(false);
20299
+ if (!this.systemParameters.delayLock) this.delayActive = this.midiChannels.some((c) => c.midiControllers[MIDIControllers.variationDepth] > 0);
20289
20300
  }
20290
20301
  process(left, right, startIndex = 0, sampleCount = 0) {
20291
20302
  this.processSplit([[left, right]], left, right, startIndex, sampleCount);