spessasynth_core 4.1.2 → 4.1.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
@@ -519,6 +519,7 @@ declare class ModulationEnvelope {
519
519
  * @param voice the voice this envelope belongs to.
520
520
  */
521
521
  init(voice: Voice): void;
522
+ private tc2Sec;
522
523
  }
523
524
 
524
525
  declare const interpolationTypes: {
@@ -2509,6 +2510,10 @@ declare class SynthesizerCore {
2509
2510
  * Current total amount of voices that are currently playing.
2510
2511
  */
2511
2512
  voiceCount: number;
2513
+ /**
2514
+ * For F5 system exclusive.
2515
+ */
2516
+ channelOffset: number;
2512
2517
  /**
2513
2518
  * Last time the priorities were assigned.
2514
2519
  * Used to prevent assigning priorities multiple times when more than one voice is triggered during a quantum.
package/dist/index.js CHANGED
@@ -7124,7 +7124,7 @@ var ModulationEnvelope = class {
7124
7124
  startRelease(voice) {
7125
7125
  this.releaseStartLevel = this.currentValue;
7126
7126
  this.enteredRelease = true;
7127
- const releaseTime = timecentsToSeconds(
7127
+ const releaseTime = this.tc2Sec(
7128
7128
  Math.max(
7129
7129
  voice.modulatedGenerators[generatorTypes.releaseModEnv],
7130
7130
  -7200
@@ -7139,25 +7139,27 @@ var ModulationEnvelope = class {
7139
7139
  init(voice) {
7140
7140
  this.enteredRelease = false;
7141
7141
  this.sustainLevel = 1 - voice.modulatedGenerators[generatorTypes.sustainModEnv] / 1e3;
7142
- this.attackDuration = timecentsToSeconds(
7142
+ this.attackDuration = this.tc2Sec(
7143
7143
  voice.modulatedGenerators[generatorTypes.attackModEnv]
7144
7144
  );
7145
7145
  const decayKeyExcursionCents = (60 - voice.midiNote) * voice.modulatedGenerators[generatorTypes.keyNumToModEnvDecay];
7146
- const decayTime = timecentsToSeconds(
7146
+ const decayTime = this.tc2Sec(
7147
7147
  voice.modulatedGenerators[generatorTypes.decayModEnv] + decayKeyExcursionCents
7148
7148
  );
7149
7149
  this.decayDuration = decayTime * (1 - this.sustainLevel);
7150
7150
  const holdKeyExcursionCents = (60 - voice.midiNote) * voice.modulatedGenerators[generatorTypes.keyNumToModEnvHold];
7151
- this.holdDuration = timecentsToSeconds(
7151
+ this.holdDuration = this.tc2Sec(
7152
7152
  holdKeyExcursionCents + voice.modulatedGenerators[generatorTypes.holdModEnv]
7153
7153
  );
7154
- this.delayEnd = voice.startTime + timecentsToSeconds(
7155
- voice.modulatedGenerators[generatorTypes.delayModEnv]
7156
- );
7154
+ this.delayEnd = voice.startTime + this.tc2Sec(voice.modulatedGenerators[generatorTypes.delayModEnv]);
7157
7155
  this.attackEnd = this.delayEnd + this.attackDuration;
7158
7156
  this.holdEnd = this.attackEnd + this.holdDuration;
7159
7157
  this.decayEnd = this.holdEnd + this.decayDuration;
7160
7158
  }
7159
+ tc2Sec(timecents) {
7160
+ if (timecents <= -10114) return 0;
7161
+ return timecentsToSeconds(timecents);
7162
+ }
7161
7163
  };
7162
7164
 
7163
7165
  // src/utils/byte_functions/bit_mask.ts
@@ -8065,6 +8067,7 @@ var Voice = class {
8065
8067
  this.isActive = true;
8066
8068
  this.isInRelease = false;
8067
8069
  this.hasRendered = false;
8070
+ this.isHeld = false;
8068
8071
  this.releaseStartTime = Infinity;
8069
8072
  this.pressure = 0;
8070
8073
  this.channel = channel;
@@ -12437,6 +12440,24 @@ function systemExclusiveInternal(syx, channelOffset) {
12437
12440
  handleXG.call(this, syx, channelOffset);
12438
12441
  break;
12439
12442
  }
12443
+ // Port select (Falcosoft MIDI Player)
12444
+ // https://www.vogons.org/viewtopic.php?p=1404746#p1404746
12445
+ case 245: {
12446
+ if (syx.length < 2) return;
12447
+ this.channelOffset = (syx[1] - 1) * 16;
12448
+ while (this.midiChannels.length <= this.channelOffset) {
12449
+ SpessaSynthInfo(
12450
+ `%cPort select, channel offset %c${this.channelOffset}%c. Creating a new port!`,
12451
+ consoleColors.info,
12452
+ consoleColors.value,
12453
+ consoleColors.info
12454
+ );
12455
+ for (let i = 0; i < 16; i++) {
12456
+ this.createMIDIChannel(true);
12457
+ }
12458
+ }
12459
+ break;
12460
+ }
12440
12461
  }
12441
12462
  }
12442
12463
 
@@ -12560,6 +12581,10 @@ var SynthesizerCore = class {
12560
12581
  * Current total amount of voices that are currently playing.
12561
12582
  */
12562
12583
  voiceCount = 0;
12584
+ /**
12585
+ * For F5 system exclusive.
12586
+ */
12587
+ channelOffset = 0;
12563
12588
  /**
12564
12589
  * Last time the priorities were assigned.
12565
12590
  * Used to prevent assigning priorities multiple times when more than one voice is triggered during a quantum.
@@ -12765,6 +12790,7 @@ var SynthesizerCore = class {
12765
12790
  this.setMIDIVolume(1);
12766
12791
  this.reverbSend = 1;
12767
12792
  this.chorusSend = 1;
12793
+ this.channelOffset = 0;
12768
12794
  if (!this.drumPreset || !this.defaultPreset) {
12769
12795
  return;
12770
12796
  }
@@ -12975,6 +13001,10 @@ var SynthesizerCore = class {
12975
13001
  */
12976
13002
  assignVoicePriorities() {
12977
13003
  if (this.lastPriorityAssignmentTime === this.currentTime) return;
13004
+ SpessaSynthInfo(
13005
+ "%cPolyphony exceeded, stealing voices",
13006
+ consoleColors.warn
13007
+ );
12978
13008
  this.lastPriorityAssignmentTime = this.currentTime;
12979
13009
  const cap = this.masterParameters.voiceCap;
12980
13010
  for (let i = 0; i < cap; i++) {
@@ -17757,7 +17787,10 @@ var SpessaSynthProcessor = class {
17757
17787
  * @param channelOffset The channel offset to apply (default is 0).
17758
17788
  */
17759
17789
  systemExclusive(syx, channelOffset = 0) {
17760
- this.synthCore.systemExclusive(syx, channelOffset);
17790
+ this.synthCore.systemExclusive(
17791
+ syx,
17792
+ channelOffset + this.synthCore.channelOffset
17793
+ );
17761
17794
  }
17762
17795
  /**
17763
17796
  * Sets a master parameter of the synthesizer.
@@ -17868,10 +17901,7 @@ var SpessaSynthProcessor = class {
17868
17901
  * @param controllerValue The value to set the controller to.
17869
17902
  */
17870
17903
  controllerChange(channel, controllerNumber, controllerValue) {
17871
- this.synthCore.midiChannels[channel].controllerChange(
17872
- controllerNumber,
17873
- controllerValue
17874
- );
17904
+ this.synthCore.midiChannels[channel + this.synthCore.channelOffset].controllerChange(controllerNumber, controllerValue);
17875
17905
  }
17876
17906
  /**
17877
17907
  * Executes a MIDI Note-on message on the specified channel.
@@ -17882,7 +17912,7 @@ var SpessaSynthProcessor = class {
17882
17912
  * If the velocity is 0, it will be treated as a Note-off message.
17883
17913
  */
17884
17914
  noteOn(channel, midiNote, velocity) {
17885
- this.synthCore.midiChannels[channel].noteOn(midiNote, velocity);
17915
+ this.synthCore.midiChannels[channel + this.synthCore.channelOffset].noteOn(midiNote, velocity);
17886
17916
  }
17887
17917
  /**
17888
17918
  * Executes a MIDI Note-off message on the specified channel.
@@ -17890,7 +17920,7 @@ var SpessaSynthProcessor = class {
17890
17920
  * @param midiNote The MIDI note number to stop playing.
17891
17921
  */
17892
17922
  noteOff(channel, midiNote) {
17893
- this.synthCore.midiChannels[channel].noteOff(midiNote);
17923
+ this.synthCore.midiChannels[channel + this.synthCore.channelOffset].noteOff(midiNote);
17894
17924
  }
17895
17925
  /**
17896
17926
  * Executes a MIDI Poly Pressure (Aftertouch) message on the specified channel.
@@ -17899,7 +17929,7 @@ var SpessaSynthProcessor = class {
17899
17929
  * @param pressure The pressure value, from 0 to 127.
17900
17930
  */
17901
17931
  polyPressure(channel, midiNote, pressure) {
17902
- this.synthCore.midiChannels[channel].polyPressure(midiNote, pressure);
17932
+ this.synthCore.midiChannels[channel + this.synthCore.channelOffset].polyPressure(midiNote, pressure);
17903
17933
  }
17904
17934
  /**
17905
17935
  * Executes a MIDI Channel Pressure (Aftertouch) message on the specified channel.
@@ -17907,7 +17937,7 @@ var SpessaSynthProcessor = class {
17907
17937
  * @param pressure The pressure value, from 0 to 127.
17908
17938
  */
17909
17939
  channelPressure(channel, pressure) {
17910
- this.synthCore.midiChannels[channel].channelPressure(pressure);
17940
+ this.synthCore.midiChannels[channel + this.synthCore.channelOffset].channelPressure(pressure);
17911
17941
  }
17912
17942
  /**
17913
17943
  * Executes a MIDI Pitch Wheel message on the specified channel.
@@ -17916,7 +17946,7 @@ var SpessaSynthProcessor = class {
17916
17946
  * @param midiNote The MIDI note number, pass -1 for the regular pitch wheel
17917
17947
  */
17918
17948
  pitchWheel(channel, pitch, midiNote = -1) {
17919
- this.synthCore.midiChannels[channel].pitchWheel(pitch, midiNote);
17949
+ this.synthCore.midiChannels[channel + this.synthCore.channelOffset].pitchWheel(pitch, midiNote);
17920
17950
  }
17921
17951
  /**
17922
17952
  * Executes a MIDI Program Change message on the specified channel.
@@ -17924,7 +17954,7 @@ var SpessaSynthProcessor = class {
17924
17954
  * @param programNumber The program number to change to, from 0 to 127.
17925
17955
  */
17926
17956
  programChange(channel, programNumber) {
17927
- this.synthCore.midiChannels[channel].programChange(programNumber);
17957
+ this.synthCore.midiChannels[channel + this.synthCore.channelOffset].programChange(programNumber);
17928
17958
  }
17929
17959
  // noinspection JSUnusedGlobalSymbols
17930
17960
  /**
@@ -17946,7 +17976,12 @@ var SpessaSynthProcessor = class {
17946
17976
  * @param options Additional options for scheduling the message.
17947
17977
  */
17948
17978
  processMessage(message, channelOffset = 0, force = false, options = DEFAULT_SYNTH_METHOD_OPTIONS) {
17949
- this.synthCore.processMessage(message, channelOffset, force, options);
17979
+ this.synthCore.processMessage(
17980
+ message,
17981
+ channelOffset + this.synthCore.channelOffset,
17982
+ force,
17983
+ options
17984
+ );
17950
17985
  }
17951
17986
  // noinspection JSUnusedGlobalSymbols
17952
17987
  /**