spessasynth_core 4.0.21 → 4.0.22

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
@@ -2873,7 +2873,7 @@ var BasicMIDI2 = class _BasicMIDI {
2873
2873
  /**
2874
2874
  * The loop points (in ticks) of the sequence, including both start and end points.
2875
2875
  */
2876
- loop = { start: 0, end: 0 };
2876
+ loop = { start: 0, end: 0, type: "hard" };
2877
2877
  /**
2878
2878
  * The file name of the MIDI sequence, if provided during parsing.
2879
2879
  */
@@ -3257,7 +3257,7 @@ var BasicMIDI2 = class _BasicMIDI {
3257
3257
  this.keyRange = { max: 0, min: 127 };
3258
3258
  this.lastVoiceEventTick = 0;
3259
3259
  this.portChannelOffsetMap = [0];
3260
- this.loop = { start: 0, end: 0 };
3260
+ this.loop = { start: 0, end: 0, type: "hard" };
3261
3261
  this.isKaraokeFile = false;
3262
3262
  this.isMultiPort = false;
3263
3263
  let nameDetected = false;
@@ -3266,6 +3266,7 @@ var BasicMIDI2 = class _BasicMIDI {
3266
3266
  }
3267
3267
  let loopStart = null;
3268
3268
  let loopEnd = null;
3269
+ let loopType = "hard";
3269
3270
  for (const track of this.tracks) {
3270
3271
  const usedChannels = /* @__PURE__ */ new Set();
3271
3272
  let trackHasVoiceMessages = false;
@@ -3293,6 +3294,7 @@ var BasicMIDI2 = class _BasicMIDI {
3293
3294
  // EMIDI/XMI
3294
3295
  case 117:
3295
3296
  if (loopEnd === null) {
3297
+ loopType = "soft";
3296
3298
  loopEnd = e.ticks;
3297
3299
  } else {
3298
3300
  loopEnd = 0;
@@ -3435,7 +3437,7 @@ var BasicMIDI2 = class _BasicMIDI {
3435
3437
  if (loopEnd === null || loopEnd === 0) {
3436
3438
  loopEnd = this.lastVoiceEventTick;
3437
3439
  }
3438
- this.loop = { start: loopStart, end: loopEnd };
3440
+ this.loop = { start: loopStart, end: loopEnd, type: loopType };
3439
3441
  SpessaSynthInfo(
3440
3442
  `%cLoop points: start: %c${this.loop.start}%c end: %c${this.loop.end}`,
3441
3443
  consoleColors.info,
@@ -3898,7 +3900,11 @@ function processTick() {
3898
3900
  newCount: this.loopCount
3899
3901
  });
3900
3902
  }
3901
- this.setTimeTicks(this._midiData.loop.start);
3903
+ if (this._midiData.loop.type === "soft") {
3904
+ this.jumpToTick(this._midiData.loop.start);
3905
+ } else {
3906
+ this.setTimeTicks(this._midiData.loop.start);
3907
+ }
3902
3908
  return;
3903
3909
  }
3904
3910
  if (nextTrack.events.length <= this.eventIndexes[nextTrackIndex] || // https://github.com/spessasus/spessasynth_core/issues/21
@@ -4905,8 +4911,8 @@ var SpessaSynthSequencer = class {
4905
4911
  retriggerPausedNotes = true;
4906
4912
  /**
4907
4913
  * The loop count of the sequencer.
4908
- * If infinite, it will loop forever.
4909
- * If zero, the loop is disabled.
4914
+ * If set to Infinity, it will loop forever.
4915
+ * If set to zero, the loop is disabled.
4910
4916
  */
4911
4917
  loopCount = 0;
4912
4918
  /**
@@ -5294,6 +5300,29 @@ var SpessaSynthSequencer = class {
5294
5300
  recalculateStartTime(time) {
5295
5301
  this.absoluteStartTime = this.synth.currentSynthTime - time / this._playbackRate;
5296
5302
  }
5303
+ /**
5304
+ * Jumps to a MIDI tick without any further processing.
5305
+ * @param tick The MIDI tick to jump to.
5306
+ * @protected
5307
+ */
5308
+ jumpToTick(tick) {
5309
+ if (!this._midiData) {
5310
+ return;
5311
+ }
5312
+ const seconds = this._midiData.midiTicksToSeconds(tick);
5313
+ this.callEvent("timeChange", { newTime: seconds });
5314
+ this.recalculateStartTime(seconds);
5315
+ this.playedTime = seconds;
5316
+ this.eventIndexes.length = 0;
5317
+ for (const track of this._midiData.tracks) {
5318
+ this.eventIndexes.push(
5319
+ Math.max(
5320
+ 0,
5321
+ track.events.findIndex((e) => e.ticks >= tick)
5322
+ )
5323
+ );
5324
+ }
5325
+ }
5297
5326
  /*
5298
5327
  SEND MIDI METHOD ABSTRACTIONS
5299
5328
  These abstract the difference between spessasynth and external MIDI
@@ -10499,15 +10528,15 @@ function renderVoice(voice, timeNow, outputLeft, outputRight, reverbOutputLeft,
10499
10528
  volumeExcursionCentibels += -modLfoValue * modVolDepth;
10500
10529
  lowpassExcursion += modLfoValue * modFilterDepth;
10501
10530
  }
10502
- if (this.channelVibrato.depth > 0) {
10503
- const channelVibrato = getLFOValue(
10531
+ if (
10532
+ // Only enabled when modulation wheel is disabled (to prevent overlap)
10533
+ this.midiControllers[midiControllers.modulationWheel] == 0 && this.channelVibrato.depth > 0
10534
+ ) {
10535
+ cents += getLFOValue(
10504
10536
  voice.startTime + this.channelVibrato.delay,
10505
10537
  this.channelVibrato.rate,
10506
10538
  timeNow
10507
- );
10508
- if (channelVibrato) {
10509
- cents += channelVibrato * this.channelVibrato.depth;
10510
- }
10539
+ ) * this.channelVibrato.depth;
10511
10540
  }
10512
10541
  const modEnvPitchDepth = voice.modulatedGenerators[generatorTypes.modEnvToPitch];
10513
10542
  const modEnvFilterDepth = voice.modulatedGenerators[generatorTypes.modEnvToFilterFc];