spessasynth_core 4.3.2 → 4.3.4

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 CHANGED
@@ -956,11 +956,17 @@ declare class BasicSample {
956
956
  */
957
957
  sampleType: SampleType;
958
958
  /**
959
- * Relative to the start of the sample in sample points.
959
+ * The sample's loop start index, inclusive.
960
+ * In sample data points, relative to the start of the sample.
961
+ *
962
+ * Minimum allowed value is 0.
960
963
  */
961
964
  loopStart: number;
962
965
  /**
963
- * Relative to the start of the sample in sample points.
966
+ * The sample's loop end index, exclusive.
967
+ * In sample data points, relative to the start of the sample.
968
+ *
969
+ * Maximum allowed value is the sample data length.
964
970
  */
965
971
  loopEnd: number;
966
972
  /**
@@ -981,14 +987,14 @@ declare class BasicSample {
981
987
  */
982
988
  protected audioData?: Float32Array;
983
989
  /**
984
- * The basic representation of a sample
985
- * @param sampleName The sample's name
986
- * @param sampleRate The sample's rate in Hz
987
- * @param originalKey The sample's pitch as a MIDI note number
988
- * @param pitchCorrection The sample's pitch correction in cents
989
- * @param sampleType The sample's type, an enum that can indicate SF3
990
- * @param loopStart The sample's loop start relative to the sample start in sample points
991
- * @param loopEnd The sample's loop end relative to the sample start in sample points
990
+ * The basic representation of a sample.
991
+ * @param sampleName The sample's name.
992
+ * @param sampleRate The sample's rate in Hz.
993
+ * @param originalKey The sample's pitch as a MIDI note number.
994
+ * @param pitchCorrection The sample's pitch correction in cents.
995
+ * @param sampleType The sample's type, an enum that can indicate SF3.
996
+ * @param loopStart The sample's loop start relative to the sample start in sample points.
997
+ * @param loopEnd The sample's loop end relative to the sample start in sample points. Inclusive.
992
998
  */
993
999
  constructor(sampleName: string, sampleRate: number, originalKey: number, pitchCorrection: number, sampleType: SampleType, loopStart: number, loopEnd: number);
994
1000
  /**
@@ -2952,11 +2958,12 @@ declare abstract class WavetableOscillator {
2952
2958
  playbackStep: number;
2953
2959
  /**
2954
2960
  * Start position of the loop.
2961
+ * Inclusive.
2955
2962
  */
2956
2963
  loopStart: number;
2957
2964
  /**
2958
2965
  * End position of the loop.
2959
- * INCLUSIVE!!
2966
+ * Exclusive.
2960
2967
  */
2961
2968
  loopEnd: number;
2962
2969
  /**
@@ -2966,6 +2973,7 @@ declare abstract class WavetableOscillator {
2966
2973
  loopLength: number;
2967
2974
  /**
2968
2975
  * End position of the sample.
2976
+ * Exclusive
2969
2977
  */
2970
2978
  end: number;
2971
2979
  /**
package/dist/index.js CHANGED
@@ -2583,16 +2583,15 @@ function getNoteTimesInternal(midi, minDrumLength = 0) {
2583
2583
  let i = 0;
2584
2584
  let unfinished = 0;
2585
2585
  const unfinishedNotes = [];
2586
- for (let i = 0; i < 16; i++) unfinishedNotes.push([]);
2586
+ for (let i = 0; i < 16; i++) unfinishedNotes.push(/* @__PURE__ */ new Map());
2587
2587
  const noteOff = (midiNote, channel) => {
2588
- const noteIndex = unfinishedNotes[channel].findIndex((n) => n.midiNote === midiNote);
2589
- const note = unfinishedNotes[channel][noteIndex];
2590
- if (note) {
2591
- const time = elapsedTime - note.start;
2592
- note.length = time;
2593
- if (channel === 9) note.length = Math.max(time, minDrumLength);
2594
- unfinishedNotes[channel].splice(noteIndex, 1);
2595
- }
2588
+ const ch = unfinishedNotes[channel];
2589
+ const noteIndex = ch.get(midiNote);
2590
+ if (noteIndex === void 0) return;
2591
+ const note = noteTimes[channel][noteIndex];
2592
+ const time = elapsedTime - note.start;
2593
+ note.length = channel === 9 ? Math.max(time, minDrumLength) : time;
2594
+ ch.delete(midiNote);
2596
2595
  unfinished--;
2597
2596
  };
2598
2597
  const { timeline, tracks } = midi;
@@ -2602,27 +2601,30 @@ function getNoteTimesInternal(midi, minDrumLength = 0) {
2602
2601
  const status = event.statusByte >> 4;
2603
2602
  const channel = event.statusByte & 15;
2604
2603
  if (status === 8) noteOff(event.data[0], channel);
2605
- else if (status === 9) if (event.data[1] === 0) noteOff(event.data[0], channel);
2606
- else {
2607
- noteOff(event.data[0], channel);
2608
- const noteTime = {
2609
- midiNote: event.data[0],
2610
- start: elapsedTime,
2611
- length: -1,
2612
- velocity: event.data[1] / 127
2613
- };
2614
- noteTimes[channel].push(noteTime);
2615
- unfinishedNotes[channel].push(noteTime);
2616
- unfinished++;
2617
- }
2618
- else if (event.statusByte === 81) oneTickToSeconds = 60 / (getTempo(event) * midi.timeDivision);
2604
+ else if (status === 9) {
2605
+ const midiNote = event.data[0];
2606
+ const velocity = event.data[1];
2607
+ if (velocity === 0) noteOff(midiNote, channel);
2608
+ else {
2609
+ noteOff(midiNote, channel);
2610
+ const noteTime = {
2611
+ midiNote,
2612
+ start: elapsedTime,
2613
+ length: -1,
2614
+ velocity
2615
+ };
2616
+ const times = noteTimes[channel];
2617
+ times.push(noteTime);
2618
+ unfinishedNotes[channel].set(midiNote, times.length - 1);
2619
+ unfinished++;
2620
+ }
2621
+ } else if (event.statusByte === 81) oneTickToSeconds = 60 / (getTempo(event) * midi.timeDivision);
2619
2622
  if (++i >= timeline.length) break;
2620
2623
  elapsedTime += oneTickToSeconds * (tracks[timeline[i].tr].events[timeline[i].ev].ticks - event.ticks);
2621
2624
  }
2622
- if (unfinished > 0) for (const [channel, channelNotes] of unfinishedNotes.entries()) for (const note of channelNotes) {
2623
- const time = elapsedTime - note.start;
2624
- note.length = time;
2625
- if (channel === 9) note.length = Math.max(time, minDrumLength);
2625
+ if (unfinished > 0) for (let channel = 0; channel < unfinishedNotes.length; channel++) for (const noteIndex of unfinishedNotes[channel].values()) {
2626
+ const note = noteTimes[channel][noteIndex];
2627
+ note.length = elapsedTime - note.start;
2626
2628
  }
2627
2629
  return noteTimes;
2628
2630
  }
@@ -6004,8 +6006,8 @@ function applySnapshot$1(snapshot) {
6004
6006
  this.systemExclusive(MIDIUtils.gsData(64, 3, 0, [is.type >> 8, is.type & 127]));
6005
6007
  for (let i = 0; i < is.params.length; i++) if (is.params[i] !== 255) this.systemExclusive(MIDIUtils.gsData(64, 3, 3 + i, [is.params[i]]));
6006
6008
  for (let channel = 0; channel < is.channels.length; channel++) this.systemExclusive(MIDIUtils.gsData(64, 64 | MIDIUtils.channelToSyx(channel), 34, [is.channels[channel] ? 1 : 0]));
6007
- for (const [parameter, value] of Object.entries(this.midiParameters)) this.setMIDIParameter(parameter, value);
6008
- for (const [parameter, value] of Object.entries(this.systemParameters)) this.setSystemParameter(parameter, value);
6009
+ for (const [parameter, value] of Object.entries(snapshot.midiParameters)) this.setMIDIParameter(parameter, value);
6010
+ for (const [parameter, value] of Object.entries(snapshot.systemParameters)) this.setSystemParameter(parameter, value);
6009
6011
  }
6010
6012
  function getSynthesizerSnapshot() {
6011
6013
  return {
@@ -7150,11 +7152,12 @@ var WavetableOscillator = class {
7150
7152
  playbackStep = 0;
7151
7153
  /**
7152
7154
  * Start position of the loop.
7155
+ * Inclusive.
7153
7156
  */
7154
7157
  loopStart = 0;
7155
7158
  /**
7156
7159
  * End position of the loop.
7157
- * INCLUSIVE!!
7160
+ * Exclusive.
7158
7161
  */
7159
7162
  loopEnd = 0;
7160
7163
  /**
@@ -7164,6 +7167,7 @@ var WavetableOscillator = class {
7164
7167
  loopLength = 0;
7165
7168
  /**
7166
7169
  * End position of the sample.
7170
+ * Exclusive
7167
7171
  */
7168
7172
  end = 0;
7169
7173
  /**
@@ -7178,10 +7182,10 @@ var LinearOscillator = class extends WavetableOscillator {
7178
7182
  const { loopEnd, loopLength, end } = this;
7179
7183
  let cursor = this.cursor;
7180
7184
  if (this.isLooping) for (let i = 0; i < sampleCount; i++) {
7181
- if (cursor > loopEnd) cursor -= loopLength;
7185
+ while (cursor >= loopEnd) cursor -= loopLength;
7182
7186
  const floor = cursor | 0;
7183
7187
  let ceil = floor + 1;
7184
- if (ceil > loopEnd) ceil -= loopLength;
7188
+ if (ceil >= loopEnd) ceil -= loopLength;
7185
7189
  const fraction = cursor - floor;
7186
7190
  const upper = data[ceil];
7187
7191
  const lower = data[floor];
@@ -7212,7 +7216,7 @@ var NearestOscillator = class extends WavetableOscillator {
7212
7216
  const { loopEnd, loopLength, end } = this;
7213
7217
  let cursor = this.cursor;
7214
7218
  if (this.isLooping) for (let i = 0; i < sampleCount; i++) {
7215
- if (cursor > loopEnd) cursor -= loopLength;
7219
+ while (cursor >= loopEnd) cursor -= loopLength;
7216
7220
  outputBuffer[i] = sampleData[cursor | 0];
7217
7221
  cursor += step;
7218
7222
  }
@@ -7235,15 +7239,15 @@ var HermiteOscillator = class extends WavetableOscillator {
7235
7239
  const { loopEnd, loopLength, end } = this;
7236
7240
  let cursor = this.cursor;
7237
7241
  if (this.isLooping) for (let i = 0; i < sampleCount; i++) {
7238
- if (cursor > loopEnd) cursor -= loopLength;
7242
+ while (cursor >= loopEnd) cursor -= loopLength;
7239
7243
  const y0 = cursor | 0;
7240
7244
  let y1 = y0 + 1;
7241
7245
  let y2 = y0 + 2;
7242
7246
  let y3 = y0 + 3;
7243
7247
  const t = cursor - y0;
7244
- if (y1 > loopEnd) y1 -= loopLength;
7245
- if (y2 > loopEnd) y2 -= loopLength;
7246
- if (y3 > loopEnd) y3 -= loopLength;
7248
+ if (y1 >= loopEnd) y1 -= loopLength;
7249
+ if (y2 >= loopEnd) y2 -= loopLength;
7250
+ if (y3 >= loopEnd) y3 -= loopLength;
7247
7251
  const xm1 = sampleData[y0];
7248
7252
  const x0 = sampleData[y1];
7249
7253
  const x1 = sampleData[y2];
@@ -7959,11 +7963,17 @@ var BasicSample = class {
7959
7963
  */
7960
7964
  sampleType;
7961
7965
  /**
7962
- * Relative to the start of the sample in sample points.
7966
+ * The sample's loop start index, inclusive.
7967
+ * In sample data points, relative to the start of the sample.
7968
+ *
7969
+ * Minimum allowed value is 0.
7963
7970
  */
7964
7971
  loopStart;
7965
7972
  /**
7966
- * Relative to the start of the sample in sample points.
7973
+ * The sample's loop end index, exclusive.
7974
+ * In sample data points, relative to the start of the sample.
7975
+ *
7976
+ * Maximum allowed value is the sample data length.
7967
7977
  */
7968
7978
  loopEnd;
7969
7979
  /**
@@ -7984,14 +7994,14 @@ var BasicSample = class {
7984
7994
  */
7985
7995
  audioData;
7986
7996
  /**
7987
- * The basic representation of a sample
7988
- * @param sampleName The sample's name
7989
- * @param sampleRate The sample's rate in Hz
7990
- * @param originalKey The sample's pitch as a MIDI note number
7991
- * @param pitchCorrection The sample's pitch correction in cents
7992
- * @param sampleType The sample's type, an enum that can indicate SF3
7993
- * @param loopStart The sample's loop start relative to the sample start in sample points
7994
- * @param loopEnd The sample's loop end relative to the sample start in sample points
7997
+ * The basic representation of a sample.
7998
+ * @param sampleName The sample's name.
7999
+ * @param sampleRate The sample's rate in Hz.
8000
+ * @param originalKey The sample's pitch as a MIDI note number.
8001
+ * @param pitchCorrection The sample's pitch correction in cents.
8002
+ * @param sampleType The sample's type, an enum that can indicate SF3.
8003
+ * @param loopStart The sample's loop start relative to the sample start in sample points.
8004
+ * @param loopEnd The sample's loop end relative to the sample start in sample points. Inclusive.
7995
8005
  */
7996
8006
  constructor(sampleName, sampleRate, originalKey, pitchCorrection, sampleType, loopStart, loopEnd) {
7997
8007
  this.name = sampleName;
@@ -12678,18 +12688,18 @@ function noteOn(midiNote, velocity) {
12678
12688
  const endOffset = voice.modulatedGenerators[GeneratorTypes.endAddrOffset] + voice.modulatedGenerators[GeneratorTypes.endAddrsCoarseOffset] * 32768;
12679
12689
  const loopStartOffset = voice.modulatedGenerators[GeneratorTypes.startloopAddrsOffset] + voice.modulatedGenerators[GeneratorTypes.startloopAddrsCoarseOffset] * 32768;
12680
12690
  const loopEndOffset = voice.modulatedGenerators[GeneratorTypes.endloopAddrsOffset] + voice.modulatedGenerators[GeneratorTypes.endloopAddrsCoarseOffset] * 32768;
12681
- const lastSample = cached.sampleData.length - 1;
12682
- voice.wavetable.cursor = clamp(cursorStartOffset, 0, lastSample);
12683
- voice.wavetable.end = clamp(lastSample + endOffset, 0, lastSample);
12684
- voice.wavetable.loopStart = clamp(cached.loopStart + loopStartOffset, 0, lastSample);
12685
- voice.wavetable.loopEnd = clamp(cached.loopEnd + loopEndOffset, 0, lastSample);
12691
+ const endExclusive = cached.sampleData.length;
12692
+ voice.wavetable.cursor = clamp(cursorStartOffset, 0, endExclusive - 1);
12693
+ voice.wavetable.end = clamp(endExclusive + endOffset, 0, endExclusive);
12694
+ voice.wavetable.loopStart = clamp(cached.loopStart + loopStartOffset, 0, endExclusive);
12695
+ voice.wavetable.loopEnd = clamp(cached.loopEnd + loopEndOffset, 0, endExclusive);
12686
12696
  if (voice.wavetable.loopEnd < voice.wavetable.loopStart) {
12687
12697
  const temp = voice.wavetable.loopStart;
12688
12698
  voice.wavetable.loopStart = voice.wavetable.loopEnd;
12689
12699
  voice.wavetable.loopEnd = temp;
12690
12700
  }
12691
12701
  if (voice.wavetable.loopEnd - voice.wavetable.loopStart < 1 && (voice.loopingMode === 1 || voice.loopingMode === 3)) voice.loopingMode = 0;
12692
- voice.wavetable.loopLength = voice.wavetable.loopEnd - voice.wavetable.loopStart + 1;
12702
+ voice.wavetable.loopLength = voice.wavetable.loopEnd - voice.wavetable.loopStart;
12693
12703
  voice.wavetable.isLooping = voice.loopingMode === 1 || voice.loopingMode === 3;
12694
12704
  voice.portamentoFromKey = portaFromKey;
12695
12705
  voice.portamentoDuration = portaTime;
@@ -13049,8 +13059,8 @@ function applySnapshot(snapshot) {
13049
13059
  this.setSystemParameter("presetLock", false);
13050
13060
  if (snapshot.patch) this.setPatch(snapshot.patch);
13051
13061
  this.lockedSystem = snapshot.lockedSystem;
13052
- for (const [parameter, value] of Object.entries(this._midiParameters)) this.setMIDIParameter(parameter, value);
13053
- for (const [parameter, value] of Object.entries(this._systemParameters)) this.setSystemParameter(parameter, value);
13062
+ for (const [parameter, value] of Object.entries(snapshot.midiParameters)) this.setMIDIParameter(parameter, value);
13063
+ for (const [parameter, value] of Object.entries(snapshot.systemParameters)) this.setSystemParameter(parameter, value);
13054
13064
  }
13055
13065
  //#endregion
13056
13066
  //#region src/synthesizer/audio_engine/channel/parameters/midi.ts