spessasynth_core 4.3.11 → 4.3.13

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
@@ -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]];
@@ -2489,6 +2491,9 @@ function correctBankOffsetInternal(mid, bankOffset, soundBank) {
2489
2491
  const targetPreset = soundBank.getPreset(patch, system);
2490
2492
  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
2493
  e.data[0] = targetPreset.program;
2494
+ ch.program = targetPreset.program;
2495
+ ch.programChangeTrack ??= trackNum;
2496
+ ch.programChangeIndex ??= eventIndexes[trackNum];
2492
2497
  if (targetPreset.isGMGSDrum && BankSelectHacks.isSystemXG(system)) return;
2493
2498
  if (ch.lastBank === void 0) return;
2494
2499
  ch.lastBank.data[1] = BankSelectHacks.addBankOffset(targetPreset.bankMSB, bankOffset, system === "xg");
@@ -2506,35 +2511,38 @@ function correctBankOffsetInternal(mid, bankOffset, soundBank) {
2506
2511
  const ch = channels[chNum];
2507
2512
  if (ch.hasBankSelect) continue;
2508
2513
  const midiChannel = chNum % 16;
2509
- const status = MIDIMessageTypes.programChange | midiChannel;
2510
2514
  const portOffset = Math.floor(chNum / 16) * 16;
2511
2515
  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);
2516
+ const tracksUsedByChannel = mid.tracks.filter((t) => t.port === port && t.channels.has(midiChannel));
2517
+ if (tracksUsedByChannel.length === 0) continue;
2518
+ let foundTrack = ch.programChangeTrack ? mid.tracks[ch.programChangeTrack] : void 0;
2519
+ let indexToAdd = ch.programChangeIndex ?? -1;
2520
+ if (!foundTrack) {
2521
+ const programChangeTrack = tracksUsedByChannel[0];
2522
+ const programIndex = programChangeTrack.events.findIndex((e) => e.statusByte >= 128 && e.statusByte < 240 && (e.statusByte & 15) === midiChannel);
2517
2523
  if (programIndex === -1) continue;
2518
- const programTicks = track.events[programIndex].ticks;
2524
+ const programTicks = programChangeTrack.events[programIndex].ticks;
2519
2525
  const targetProgram = soundBank.getPreset({
2520
2526
  bankMSB: 0,
2521
2527
  bankLSB: 0,
2522
2528
  program: 0,
2523
2529
  isGMGSDrum: false
2524
2530
  }, system).program;
2525
- track.addEvents(programIndex, MIDIMessage.programChange(programTicks, midiChannel, targetProgram));
2531
+ SpessaLog.info(`%cAdding default program change for %c${chNum}`, ConsoleColors.info, ConsoleColors.recognized);
2532
+ programChangeTrack.addEvents(programIndex, MIDIMessage.programChange(programTicks, midiChannel, targetProgram));
2526
2533
  indexToAdd = programIndex;
2534
+ foundTrack = programChangeTrack;
2527
2535
  }
2528
- SpessaLog.info(`%cAdding bank select for %c${chNum}`, ConsoleColors.info, ConsoleColors.recognized);
2529
- const ticks = track.events[indexToAdd].ticks;
2536
+ const ticks = foundTrack.events[indexToAdd].ticks;
2530
2537
  const targetPreset = soundBank.getPreset({
2531
2538
  bankLSB: 0,
2532
2539
  bankMSB: 0,
2533
2540
  program: ch.program,
2534
2541
  isGMGSDrum: ch.isDrum
2535
2542
  }, system);
2543
+ SpessaLog.info(`%cAdding bank select for %c${chNum}%c Targeting preset: %c${targetPreset.toString()}`, ConsoleColors.info, ConsoleColors.recognized, ConsoleColors.info, ConsoleColors.recognized);
2536
2544
  const targetBank = BankSelectHacks.addBankOffset(targetPreset.bankMSB, bankOffset, system === "xg");
2537
- track.addEvents(indexToAdd, MIDIMessage.controllerChange(ticks, midiChannel, MIDIControllers.bankSelect, targetBank));
2545
+ foundTrack.addEvents(indexToAdd, MIDIMessage.controllerChange(ticks, midiChannel, MIDIControllers.bankSelect, targetBank));
2538
2546
  }
2539
2547
  if (system === "gm" && !BankSelectHacks.isSystemXG(system)) {
2540
2548
  for (const m of unwantedSystems) {
@@ -8211,9 +8219,7 @@ const defaultSpessaSynthModulators = [
8211
8219
  new DecodedModulator(getModSourceEnum(ModulatorCurveTypes.linear, true, false, true, MIDIControllers.decayTime), 0, GeneratorTypes.decayVolEnv, 3600, 0),
8212
8220
  new DecodedModulator(getModSourceEnum(ModulatorCurveTypes.linear, true, false, true, MIDIControllers.brightness), 0, GeneratorTypes.initialFilterFc, 9600, 0),
8213
8221
  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)
8222
+ new DecodedModulator(getModSourceEnum(ModulatorCurveTypes.switch, false, false, true, MIDIControllers.softPedal), 0, GeneratorTypes.initialFilterFc, -1200, 0)
8217
8223
  ];
8218
8224
  const SPESSASYNTH_DEFAULT_MODULATORS = [...defaultSoundFont2Modulators, ...defaultSpessaSynthModulators];
8219
8225
  //#endregion
@@ -8550,6 +8556,7 @@ var BasicSample = class {
8550
8556
  */
8551
8557
  setLinkedSample(sample, type) {
8552
8558
  if (sample.linkedSample) throw new Error(`${sample.name} is linked tp ${sample.linkedSample.name}. Unlink it first.`);
8559
+ if (this === sample) throw new Error(`${sample.name} cannot be linked to itself.`);
8553
8560
  this.linkedSample = sample;
8554
8561
  sample.linkedSample = this;
8555
8562
  switch (type) {
@@ -9304,6 +9311,9 @@ var SoundFontSample = class extends BasicSample {
9304
9311
  if (linked) if (linked.linkedSample) {
9305
9312
  SpessaLog.info(`%cInvalid linked sample for ${this.name}: ${linked.name} is already linked to ${linked.linkedSample.name}`, ConsoleColors.warn);
9306
9313
  this.unlinkSample();
9314
+ } else if (linked === this) {
9315
+ SpessaLog.info(`%cInvalid linked sample for ${this.name}: linked to itself.`, ConsoleColors.warn);
9316
+ this.unlinkSample();
9307
9317
  } else this.setLinkedSample(linked, this.sampleType);
9308
9318
  else {
9309
9319
  SpessaLog.info(`%cInvalid linked sample for ${this.name}. Setting to mono.`, ConsoleColors.warn);
@@ -13102,7 +13112,7 @@ function noteOn(midiNote, velocity, emit = true) {
13102
13112
  }
13103
13113
  const black = this.synthCore.systemParameters.blackMIDIMode;
13104
13114
  if (black && this.synthCore.voiceCount > 200 && velocity < 40 || black && velocity < 10 || this._systemParameters.isMuted || !this.preset) return;
13105
- let realVelocity = clamp(velocity * (this._midiParameters.velocitySenseDepth / 64) + (this._midiParameters.velocitySenseOffset - 64) * 2, 0, 127);
13115
+ let realVelocity = clamp(Math.floor(velocity * (this._midiParameters.velocitySenseDepth / 64) + (this._midiParameters.velocitySenseOffset - 64) * 2), 0, 127);
13106
13116
  let soundBankNote = midiNote + this.currentKeyShift;
13107
13117
  if (midiNote > 127 || midiNote < 0) return;
13108
13118
  const program = this.preset.program;
@@ -13338,10 +13348,12 @@ var DynamicModulatorManager = class {
13338
13348
  const centeredNormalized = centeredValue / 64;
13339
13349
  const normalizedNotCentered = data / 127;
13340
13350
  switch (addr3 & 15) {
13341
- case 0:
13342
- this.setModulator(source, isCC, GeneratorTypes.fineTune, centeredValue * 100, bipolar);
13343
- SpessaLog.coolInfo(`Channel ${this.channel} ${sourceName} pitch control`, centeredValue, "semitones");
13351
+ case 0: {
13352
+ const v = Math.min(24, Math.max(-24, centeredValue));
13353
+ this.setModulator(source, isCC, GeneratorTypes.fineTune, v * 100, bipolar);
13354
+ SpessaLog.coolInfo(`Channel ${this.channel} ${sourceName} pitch control`, v, "semitones");
13344
13355
  break;
13356
+ }
13345
13357
  case 1:
13346
13358
  this.setModulator(source, isCC, GeneratorTypes.initialFilterFc, centeredNormalized * 9600, bipolar);
13347
13359
  SpessaLog.coolInfo(`Channel ${this.channel} ${sourceName} filter control`, centeredNormalized * 9600, "cents");