spessasynth_core 4.0.24 → 4.1.0

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
@@ -15,15 +15,6 @@ declare class IndexedByteArray extends Uint8Array {
15
15
  slice(start?: number, end?: number): IndexedByteArray;
16
16
  }
17
17
 
18
- /**
19
- * Writes an audio into a valid WAV file.
20
- * @param audioData the audio data channels.
21
- * @param sampleRate the sample rate, in Hertz.
22
- * @param options Additional options for writing the file.
23
- * @returns the binary file.
24
- */
25
- declare function audioToWav(audioData: Float32Array[], sampleRate: number, options?: Partial<WaveWriteOptions>): ArrayBuffer;
26
-
27
18
  /**
28
19
  * Reads number as Big endian.
29
20
  * @param dataArray the array to read from.
@@ -69,10 +60,19 @@ declare function SpessaSynthGroup(...message: unknown[]): void;
69
60
  declare function SpessaSynthGroupCollapsed(...message: unknown[]): void;
70
61
  declare function SpessaSynthGroupEnd(): void;
71
62
 
63
+ /**
64
+ * Writes an audio into a valid WAV file.
65
+ * @param audioData the audio data channels.
66
+ * @param sampleRate the sample rate, in Hertz.
67
+ * @param options Additional options for writing the file.
68
+ * @returns the binary file.
69
+ */
70
+ declare function audioToWav(audioData: Float32Array[], sampleRate: number, options?: Partial<WaveWriteOptions>): ArrayBuffer;
71
+
72
72
  /**
73
73
  * All SoundFont2 Generator enumerations.
74
74
  */
75
- declare const generatorTypes: {
75
+ declare const generatorTypes: Readonly<{
76
76
  readonly INVALID: -1;
77
77
  readonly startAddrsOffset: 0;
78
78
  readonly endAddrOffset: 1;
@@ -137,19 +137,20 @@ declare const generatorTypes: {
137
137
  readonly endOper: 60;
138
138
  readonly vibLfoToVolume: 61;
139
139
  readonly vibLfoToFilterFc: 62;
140
- };
140
+ }>;
141
141
  type GeneratorType = (typeof generatorTypes)[keyof typeof generatorTypes];
142
142
  declare const GENERATORS_AMOUNT: number;
143
143
  declare const MAX_GENERATOR: number;
144
144
  /**
145
- * Min: minimum value, max: maximum value, def: default value, nrpn: nrpn scale...
145
+ * Min: minimum value, max: maximum value, def: default value, nrpn: nrpn scale
146
146
  */
147
- declare const generatorLimits: {
147
+ declare const generatorLimits: Readonly<Record<number, {
148
148
  min: number;
149
149
  max: number;
150
150
  def: number;
151
151
  nrpn: number;
152
- }[];
152
+ }>>;
153
+ declare const defaultGeneratorValues: Int16Array<ArrayBuffer>;
153
154
 
154
155
  declare const sampleTypes: {
155
156
  readonly monoSample: 1;
@@ -245,6 +246,281 @@ declare const DLSLoopTypes: {
245
246
  };
246
247
  type DLSLoopType = (typeof DLSLoopTypes)[keyof typeof DLSLoopTypes];
247
248
 
249
+ declare class LowpassFilter {
250
+ /**
251
+ * Cached coefficient calculations.
252
+ * stored as cachedCoefficients[resonanceCb + currentInitialFc * 961].
253
+ */
254
+ private static cachedCoefficients;
255
+ /**
256
+ * For smoothing the filter cutoff frequency.
257
+ */
258
+ private static smoothingConstant;
259
+ /**
260
+ * Resonance in centibels.
261
+ */
262
+ resonanceCb: number;
263
+ /**
264
+ * Current cutoff frequency in absolute cents.
265
+ */
266
+ currentInitialFc: number;
267
+ /**
268
+ * Filter coefficient 1.
269
+ */
270
+ private a0;
271
+ /**
272
+ * Filter coefficient 2.
273
+ */
274
+ private a1;
275
+ /**
276
+ * Filter coefficient 3.
277
+ */
278
+ private a2;
279
+ /**
280
+ * Filter coefficient 4.
281
+ */
282
+ private a3;
283
+ /**
284
+ * Filter coefficient 5.
285
+ */
286
+ private a4;
287
+ /**
288
+ * Input history 1.
289
+ */
290
+ private x1;
291
+ /**
292
+ * Input history 2.
293
+ */
294
+ private x2;
295
+ /**
296
+ * Output history 1.
297
+ */
298
+ private y1;
299
+ /**
300
+ * Output history 2.
301
+ */
302
+ private y2;
303
+ /**
304
+ * For tracking the last cutoff frequency in the apply method, absolute cents.
305
+ * Set to infinity to force recalculation.
306
+ */
307
+ private lastTargetCutoff;
308
+ /**
309
+ * Used for tracking if the filter has been initialized.
310
+ */
311
+ private initialized;
312
+ /**
313
+ * Filter's sample rate in Hz.
314
+ */
315
+ private readonly sampleRate;
316
+ /**
317
+ * Maximum cutoff frequency in Hz.
318
+ * This is used to prevent aliasing and ensure the filter operates within the valid frequency range.
319
+ */
320
+ private readonly maxCutoff;
321
+ /**
322
+ * Initializes a new instance of the filter.
323
+ * @param sampleRate the sample rate of the audio engine in Hz.
324
+ */
325
+ constructor(sampleRate: number);
326
+ static initCache(sampleRate: number): void;
327
+ init(): void;
328
+ /**
329
+ * Applies the lowpass filter to the output buffer of a voice.
330
+ * @param sampleCount The amount of samples to write.
331
+ * @param voice The voice to apply the filter to.
332
+ * @param outputBuffer The output buffer to filter.
333
+ * @param fcOffset The frequency excursion in cents to apply to the filter.
334
+ */
335
+ process(sampleCount: number, voice: Voice, outputBuffer: Float32Array, fcOffset: number): void;
336
+ /**
337
+ * Calculates the filter coefficients based on the current resonance and cutoff frequency and caches them.
338
+ * @param cutoffCents The cutoff frequency in cents.
339
+ */
340
+ calculateCoefficients(cutoffCents: number): void;
341
+ }
342
+
343
+ /**
344
+ * VOL ENV STATES:
345
+ * 0 - delay
346
+ * 1 - attack
347
+ * 2 - hold/peak
348
+ * 3 - decay
349
+ * 4 - sustain
350
+ * release indicates by isInRelease property
351
+ */
352
+ type VolumeEnvelopeState = 0 | 1 | 2 | 3 | 4;
353
+ declare class VolumeEnvelope {
354
+ /**
355
+ * The sample rate in Hz.
356
+ */
357
+ readonly sampleRate: number;
358
+ /**
359
+ * The current attenuation of the envelope in cB.
360
+ */
361
+ attenuationCb: number;
362
+ /**
363
+ * The current stage of the volume envelope.
364
+ */
365
+ state: VolumeEnvelopeState;
366
+ /**
367
+ * The envelope's current time in samples.
368
+ */
369
+ private sampleTime;
370
+ /**
371
+ * The dB attenuation of the envelope when it entered the release stage.
372
+ */
373
+ private releaseStartCb;
374
+ /**
375
+ * The time in samples relative to the start of the envelope.
376
+ */
377
+ private releaseStartTimeSamples;
378
+ /**
379
+ * The attack duration in samples.
380
+ */
381
+ private attackDuration;
382
+ /**
383
+ * The decay duration in samples.
384
+ */
385
+ private decayDuration;
386
+ /**
387
+ * The release duration in samples.
388
+ */
389
+ private releaseDuration;
390
+ /**
391
+ * The voice's sustain amount in cB.
392
+ */
393
+ private sustainCb;
394
+ /**
395
+ * The time in samples to the end of delay stage, relative to the start of the envelope.
396
+ */
397
+ private delayEnd;
398
+ /**
399
+ * The time in samples to the end of attack stage, relative to the start of the envelope.
400
+ */
401
+ private attackEnd;
402
+ /**
403
+ * The time in samples to the end of hold stage, relative to the start of the envelope.
404
+ */
405
+ private holdEnd;
406
+ /**
407
+ * The time in samples to the end of decay stage, relative to the start of the envelope.
408
+ */
409
+ private decayEnd;
410
+ /**
411
+ * If the volume envelope has ever entered the release phase.
412
+ * @private
413
+ */
414
+ private enteredRelease;
415
+ /**
416
+ * If sustain stage is silent,
417
+ * then we can turn off the voice when it is silent.
418
+ * We can't do that with modulated as it can silence the volume and then raise it again, and the voice must keep playing.
419
+ */
420
+ private canEndOnSilentSustain;
421
+ private readonly gainSmoothing;
422
+ private currentGain;
423
+ /**
424
+ * @param sampleRate Hz
425
+ */
426
+ constructor(sampleRate: number);
427
+ /**
428
+ * Applies volume envelope gain to the given output buffer.
429
+ * Essentially we use approach of 100dB is silence, 0dB is peak.
430
+ * @param sampleCount the amount of samples to write
431
+ * @param buffer the audio buffer to modify
432
+ * @param gainTarget the gain target to smooth.
433
+ * @param centibelOffset the centibel offset to apply.
434
+ * @returns if the voice is still active
435
+ */
436
+ process(sampleCount: number, buffer: Float32Array, gainTarget: number, centibelOffset: number): boolean;
437
+ /**
438
+ * Starts the release phase in the envelope.
439
+ * @param voice the voice this envelope belongs to.
440
+ */
441
+ startRelease(voice: Voice): void;
442
+ /**
443
+ * Initialize the volume envelope
444
+ * @param voice The voice this envelope belongs to
445
+ */
446
+ init(voice: Voice): void;
447
+ private timecentsToSamples;
448
+ private releasePhase;
449
+ private delayPhase;
450
+ private attackPhase;
451
+ private holdPhase;
452
+ private decayPhase;
453
+ private sustainPhase;
454
+ }
455
+
456
+ declare class ModulationEnvelope {
457
+ /**
458
+ * The attack duration, in seconds.
459
+ */
460
+ private attackDuration;
461
+ /**
462
+ * The decay duration, in seconds.
463
+ */
464
+ private decayDuration;
465
+ /**
466
+ * The hold duration, in seconds.
467
+ */
468
+ private holdDuration;
469
+ /**
470
+ * Release duration, in seconds.
471
+ */
472
+ private releaseDuration;
473
+ /**
474
+ * The sustain level 0-1.
475
+ */
476
+ private sustainLevel;
477
+ /**
478
+ * Delay phase end time in seconds, absolute (audio context time).
479
+ */
480
+ private delayEnd;
481
+ /**
482
+ * Attack phase end time in seconds, absolute (audio context time).
483
+ */
484
+ private attackEnd;
485
+ /**
486
+ * Hold phase end time in seconds, absolute (audio context time).
487
+ */
488
+ private holdEnd;
489
+ /**
490
+ * The level of the envelope when the release phase starts.
491
+ */
492
+ private releaseStartLevel;
493
+ /**
494
+ * The current modulation envelope value.
495
+ */
496
+ private currentValue;
497
+ /**
498
+ * If the modulation envelope has ever entered the release phase.
499
+ */
500
+ private enteredRelease;
501
+ /**
502
+ * Decay phase end time in seconds, absolute (audio context time).
503
+ */
504
+ private decayEnd;
505
+ /**
506
+ * Calculates the current modulation envelope value for the given time and voice.
507
+ * @param voice the voice we are working on.
508
+ * @param currentTime in seconds.
509
+ * @returns mod env value, from 0 to 1.
510
+ */
511
+ process(voice: Voice, currentTime: number): number;
512
+ /**
513
+ * Starts the release phase in the envelope.
514
+ * @param voice the voice this envelope belongs to.
515
+ */
516
+ startRelease(voice: Voice): void;
517
+ /**
518
+ * Initializes the modulation envelope.
519
+ * @param voice the voice this envelope belongs to.
520
+ */
521
+ init(voice: Voice): void;
522
+ }
523
+
248
524
  declare const interpolationTypes: {
249
525
  readonly linear: 0;
250
526
  readonly nearestNeighbor: 1;
@@ -325,36 +601,254 @@ declare class MIDIPatchTools {
325
601
  static sorter(a: MIDIPatch, b: MIDIPatch): number;
326
602
  }
327
603
 
328
- type SynthSystem = "gm" | "gm2" | "gs" | "xg";
329
- interface NoteOnCallback {
330
- /** The MIDI note number. */
331
- midiNote: number;
332
- /** The MIDI channel number. */
333
- channel: number;
334
- /** The velocity of the note. */
335
- velocity: number;
336
- }
337
- interface NoteOffCallback {
338
- /** The MIDI note number. */
339
- midiNote: number;
340
- /** The MIDI channel number. */
341
- channel: number;
342
- }
343
- interface DrumChangeCallback {
344
- /** The MIDI channel number. */
345
- channel: number;
346
- /** Indicates if the channel is a drum channel. */
347
- isDrumChannel: boolean;
348
- }
349
- interface ProgramChangeCallback extends MIDIPatch {
350
- /** The MIDI channel number. */
351
- channel: number;
352
- }
353
- interface ControllerChangeCallback {
354
- /** The MIDI channel number. */
355
- channel: number;
604
+ /**
605
+ * Represents a cached voice
606
+ */
607
+ declare class CachedVoice {
608
+ /**
609
+ * Sample data of this voice.
610
+ */
611
+ readonly sampleData: Float32Array;
612
+ /**
613
+ * The unmodulated (copied to) generators of the voice.
614
+ */
615
+ readonly generators: Int16Array;
616
+ /**
617
+ * The voice's modulators.
618
+ */
619
+ readonly modulators: Modulator[];
620
+ /**
621
+ * Exclusive class number for hi-hats etc.
622
+ */
623
+ readonly exclusiveClass: number;
624
+ /**
625
+ * Target key of the voice (can be overridden by generators)
626
+ */
627
+ readonly targetKey: number;
628
+ /**
629
+ * Target velocity of the voice (can be overridden by generators)
630
+ */
631
+ readonly velocity: number;
632
+ /**
633
+ * MIDI root key of the sample
634
+ */
635
+ readonly rootKey: number;
636
+ /**
637
+ * Start position of the loop
638
+ */
639
+ readonly loopStart: number;
640
+ /**
641
+ * End position of the loop
642
+ */
643
+ readonly loopEnd: number;
644
+ /**
645
+ * Playback step (rate) for sample pitch correction
646
+ */
647
+ readonly playbackStep: number;
648
+ readonly loopingMode: SampleLoopingMode;
649
+ constructor(voiceParams: VoiceParameters, midiNote: number, velocity: number, sampleRate: number);
650
+ }
651
+
652
+ declare const midiMessageTypes: {
653
+ readonly noteOff: 128;
654
+ readonly noteOn: 144;
655
+ readonly polyPressure: 160;
656
+ readonly controllerChange: 176;
657
+ readonly programChange: 192;
658
+ readonly channelPressure: 208;
659
+ readonly pitchWheel: 224;
660
+ readonly systemExclusive: 240;
661
+ readonly timecode: 241;
662
+ readonly songPosition: 242;
663
+ readonly songSelect: 243;
664
+ readonly tuneRequest: 246;
665
+ readonly clock: 248;
666
+ readonly start: 250;
667
+ readonly continue: 251;
668
+ readonly stop: 252;
669
+ readonly activeSensing: 254;
670
+ readonly reset: 255;
671
+ readonly sequenceNumber: 0;
672
+ readonly text: 1;
673
+ readonly copyright: 2;
674
+ readonly trackName: 3;
675
+ readonly instrumentName: 4;
676
+ readonly lyric: 5;
677
+ readonly marker: 6;
678
+ readonly cuePoint: 7;
679
+ readonly programName: 8;
680
+ readonly midiChannelPrefix: 32;
681
+ readonly midiPort: 33;
682
+ readonly endOfTrack: 47;
683
+ readonly setTempo: 81;
684
+ readonly smpteOffset: 84;
685
+ readonly timeSignature: 88;
686
+ readonly keySignature: 89;
687
+ readonly sequenceSpecific: 127;
688
+ };
689
+ type MIDIMessageType = (typeof midiMessageTypes)[keyof typeof midiMessageTypes];
690
+ declare const midiControllers: {
691
+ readonly bankSelect: 0;
692
+ readonly modulationWheel: 1;
693
+ readonly breathController: 2;
694
+ readonly undefinedCC3: 3;
695
+ readonly footController: 4;
696
+ readonly portamentoTime: 5;
697
+ readonly dataEntryMSB: 6;
698
+ readonly mainVolume: 7;
699
+ readonly balance: 8;
700
+ readonly undefinedCC9: 9;
701
+ readonly pan: 10;
702
+ readonly expressionController: 11;
703
+ readonly effectControl1: 12;
704
+ readonly effectControl2: 13;
705
+ readonly undefinedCC14: 14;
706
+ readonly undefinedCC15: 15;
707
+ readonly generalPurposeController1: 16;
708
+ readonly generalPurposeController2: 17;
709
+ readonly generalPurposeController3: 18;
710
+ readonly generalPurposeController4: 19;
711
+ readonly undefinedCC20: 20;
712
+ readonly undefinedCC21: 21;
713
+ readonly undefinedCC22: 22;
714
+ readonly undefinedCC23: 23;
715
+ readonly undefinedCC24: 24;
716
+ readonly undefinedCC25: 25;
717
+ readonly undefinedCC26: 26;
718
+ readonly undefinedCC27: 27;
719
+ readonly undefinedCC28: 28;
720
+ readonly undefinedCC29: 29;
721
+ readonly undefinedCC30: 30;
722
+ readonly undefinedCC31: 31;
723
+ readonly bankSelectLSB: 32;
724
+ readonly modulationWheelLSB: 33;
725
+ readonly breathControllerLSB: 34;
726
+ readonly undefinedCC3LSB: 35;
727
+ readonly footControllerLSB: 36;
728
+ readonly portamentoTimeLSB: 37;
729
+ readonly dataEntryLSB: 38;
730
+ readonly mainVolumeLSB: 39;
731
+ readonly balanceLSB: 40;
732
+ readonly undefinedCC9LSB: 41;
733
+ readonly panLSB: 42;
734
+ readonly expressionControllerLSB: 43;
735
+ readonly effectControl1LSB: 44;
736
+ readonly effectControl2LSB: 45;
737
+ readonly undefinedCC14LSB: 46;
738
+ readonly undefinedCC15LSB: 47;
739
+ readonly undefinedCC16LSB: 48;
740
+ readonly undefinedCC17LSB: 49;
741
+ readonly undefinedCC18LSB: 50;
742
+ readonly undefinedCC19LSB: 51;
743
+ readonly undefinedCC20LSB: 52;
744
+ readonly undefinedCC21LSB: 53;
745
+ readonly undefinedCC22LSB: 54;
746
+ readonly undefinedCC23LSB: 55;
747
+ readonly undefinedCC24LSB: 56;
748
+ readonly undefinedCC25LSB: 57;
749
+ readonly undefinedCC26LSB: 58;
750
+ readonly undefinedCC27LSB: 59;
751
+ readonly undefinedCC28LSB: 60;
752
+ readonly undefinedCC29LSB: 61;
753
+ readonly undefinedCC30LSB: 62;
754
+ readonly undefinedCC31LSB: 63;
755
+ readonly sustainPedal: 64;
756
+ readonly portamentoOnOff: 65;
757
+ readonly sostenutoPedal: 66;
758
+ readonly softPedal: 67;
759
+ readonly legatoFootswitch: 68;
760
+ readonly hold2Pedal: 69;
761
+ readonly soundVariation: 70;
762
+ readonly filterResonance: 71;
763
+ readonly releaseTime: 72;
764
+ readonly attackTime: 73;
765
+ readonly brightness: 74;
766
+ readonly decayTime: 75;
767
+ readonly vibratoRate: 76;
768
+ readonly vibratoDepth: 77;
769
+ readonly vibratoDelay: 78;
770
+ readonly soundController10: 79;
771
+ readonly generalPurposeController5: 80;
772
+ readonly generalPurposeController6: 81;
773
+ readonly generalPurposeController7: 82;
774
+ readonly generalPurposeController8: 83;
775
+ readonly portamentoControl: 84;
776
+ readonly undefinedCC85: 85;
777
+ readonly undefinedCC86: 86;
778
+ readonly undefinedCC87: 87;
779
+ readonly undefinedCC88: 88;
780
+ readonly undefinedCC89: 89;
781
+ readonly undefinedCC90: 90;
782
+ readonly reverbDepth: 91;
783
+ readonly tremoloDepth: 92;
784
+ readonly chorusDepth: 93;
785
+ readonly detuneDepth: 94;
786
+ readonly phaserDepth: 95;
787
+ readonly dataIncrement: 96;
788
+ readonly dataDecrement: 97;
789
+ readonly nonRegisteredParameterLSB: 98;
790
+ readonly nonRegisteredParameterMSB: 99;
791
+ readonly registeredParameterLSB: 100;
792
+ readonly registeredParameterMSB: 101;
793
+ readonly undefinedCC102LSB: 102;
794
+ readonly undefinedCC103LSB: 103;
795
+ readonly undefinedCC104LSB: 104;
796
+ readonly undefinedCC105LSB: 105;
797
+ readonly undefinedCC106LSB: 106;
798
+ readonly undefinedCC107LSB: 107;
799
+ readonly undefinedCC108LSB: 108;
800
+ readonly undefinedCC109LSB: 109;
801
+ readonly undefinedCC110LSB: 110;
802
+ readonly undefinedCC111LSB: 111;
803
+ readonly undefinedCC112LSB: 112;
804
+ readonly undefinedCC113LSB: 113;
805
+ readonly undefinedCC114LSB: 114;
806
+ readonly undefinedCC115LSB: 115;
807
+ readonly undefinedCC116LSB: 116;
808
+ readonly undefinedCC117LSB: 117;
809
+ readonly undefinedCC118LSB: 118;
810
+ readonly undefinedCC119LSB: 119;
811
+ readonly allSoundOff: 120;
812
+ readonly resetAllControllers: 121;
813
+ readonly localControlOnOff: 122;
814
+ readonly allNotesOff: 123;
815
+ readonly omniModeOff: 124;
816
+ readonly omniModeOn: 125;
817
+ readonly monoModeOn: 126;
818
+ readonly polyModeOn: 127;
819
+ };
820
+ type MIDIController = (typeof midiControllers)[keyof typeof midiControllers];
821
+
822
+ type SynthSystem = "gm" | "gm2" | "gs" | "xg";
823
+ interface NoteOnCallback {
824
+ /** The MIDI note number. */
825
+ midiNote: number;
826
+ /** The MIDI channel number. */
827
+ channel: number;
828
+ /** The velocity of the note. */
829
+ velocity: number;
830
+ }
831
+ interface NoteOffCallback {
832
+ /** The MIDI note number. */
833
+ midiNote: number;
834
+ /** The MIDI channel number. */
835
+ channel: number;
836
+ }
837
+ interface DrumChangeCallback {
838
+ /** The MIDI channel number. */
839
+ channel: number;
840
+ /** Indicates if the channel is a drum channel. */
841
+ isDrumChannel: boolean;
842
+ }
843
+ interface ProgramChangeCallback extends MIDIPatch {
844
+ /** The MIDI channel number. */
845
+ channel: number;
846
+ }
847
+ interface ControllerChangeCallback {
848
+ /** The MIDI channel number. */
849
+ channel: number;
356
850
  /** The controller number. */
357
- controllerNumber: number;
851
+ controllerNumber: MIDIController;
358
852
  /** The value of the controller. */
359
853
  controllerValue: number;
360
854
  }
@@ -385,6 +879,10 @@ interface PitchWheelCallback {
385
879
  * The unsigned 14-bit value of the pitch: 0 - 16383.
386
880
  */
387
881
  pitch: number;
882
+ /**
883
+ * If the pitch wheel was note-specific, this is the MIDI note number that was altered. Set to -1 otherwise.
884
+ */
885
+ midiNote: number;
388
886
  }
389
887
  interface ChannelPressureCallback {
390
888
  /** The MIDI channel number. */
@@ -518,20 +1016,6 @@ interface SynthMethodOptions {
518
1016
  */
519
1017
  time: number;
520
1018
  }
521
- /**
522
- * KeyNum: tuning.
523
- */
524
- type MTSProgramTuning = MTSNoteTuning[];
525
- interface MTSNoteTuning {
526
- /**
527
- * The base MIDI note to use, -1 means no change.
528
- */
529
- midiNote: number;
530
- /**
531
- * Additional tuning.
532
- */
533
- centTuning: number | null;
534
- }
535
1019
  /**
536
1020
  * Looping mode of the sample.
537
1021
  * 0 - no loop.
@@ -543,7 +1027,7 @@ type SampleLoopingMode = 0 | 1 | 2 | 3;
543
1027
  /**
544
1028
  * A list of voices for a given key:velocity.
545
1029
  */
546
- type VoiceList = Voice[];
1030
+ type CachedVoiceList = CachedVoice[];
547
1031
  interface ChannelProperty {
548
1032
  /**
549
1033
  * The channel's current voice amount.
@@ -637,286 +1121,305 @@ interface MasterParameterType {
637
1121
  }
638
1122
 
639
1123
  /**
640
- * Sets a master parameter of the synthesizer.
641
- * @param parameter The type of the master parameter to set.
642
- * @param value The value to set for the master parameter.
643
- */
644
- declare function setMasterParameterInternal<P extends keyof MasterParameterType>(this: SpessaSynthProcessor, parameter: P, value: MasterParameterType[P]): void;
645
- /**
646
- * Gets a master parameter of the synthesizer.
647
- * @param type The type of the master parameter to get.
648
- * @returns The value of the master parameter.
649
- */
650
- declare function getMasterParameterInternal<P extends keyof MasterParameterType>(this: SpessaSynthProcessor, type: P): MasterParameterType[P];
651
- /**
652
- * Gets all master parameters of the synthesizer.
653
- * @returns All the master parameters.
1124
+ * Wavetable_oscillator.ts
1125
+ * purpose: plays back raw audio data at an arbitrary playback rate
654
1126
  */
655
- declare function getAllMasterParametersInternal(this: SpessaSynthProcessor): MasterParameterType;
656
-
657
- declare class Generator {
1127
+ declare abstract class WavetableOscillator {
658
1128
  /**
659
- * The generator's SF2 type.
1129
+ * Is the loop on?
660
1130
  */
661
- generatorType: GeneratorType;
1131
+ isLooping: boolean;
662
1132
  /**
663
- * The generator's 16-bit value.
1133
+ * Sample data of the voice.
664
1134
  */
665
- generatorValue: number;
1135
+ sampleData?: Float32Array;
666
1136
  /**
667
- * Constructs a new generator
668
- * @param type generator type
669
- * @param value generator value
670
- * @param validate if the limits should be validated
1137
+ * Playback step (rate) for sample pitch correction.
671
1138
  */
672
- constructor(type: GeneratorType, value: number, validate?: boolean);
673
- write(genData: IndexedByteArray): void;
674
- toString(): string;
675
- }
676
-
677
- declare class BasicZone {
1139
+ playbackStep: number;
678
1140
  /**
679
- * The zone's velocity range.
680
- * min -1 means that it is a default value
1141
+ * Start position of the loop.
681
1142
  */
682
- velRange: GenericRange;
1143
+ loopStart: number;
683
1144
  /**
684
- * The zone's key range.
685
- * min -1 means that it is a default value.
1145
+ * End position of the loop.
686
1146
  */
687
- keyRange: GenericRange;
1147
+ loopEnd: number;
688
1148
  /**
689
- * The zone's generators.
1149
+ * Length of the loop.
1150
+ * @private
690
1151
  */
691
- generators: Generator[];
1152
+ loopLength: number;
692
1153
  /**
693
- * The zone's modulators.
1154
+ * End position of the sample.
694
1155
  */
695
- modulators: Modulator[];
696
- get hasKeyRange(): boolean;
697
- get hasVelRange(): boolean;
1156
+ end: number;
698
1157
  /**
699
- * The current tuning in cents, taking in both coarse and fine generators.
1158
+ * The current cursor of the sample.
700
1159
  */
701
- get fineTuning(): number;
1160
+ cursor: number;
702
1161
  /**
703
- * The current tuning in cents, taking in both coarse and fine generators.
1162
+ * Fills the output buffer with raw sample data using a given interpolation.
1163
+ * @param sampleCount The amount of samples to write into the buffer.
1164
+ * @param tuningRatio the tuning ratio to apply.
1165
+ * @param outputBuffer The output buffer to write to.
704
1166
  */
705
- set fineTuning(tuningCents: number);
1167
+ abstract process(sampleCount: number, tuningRatio: number, outputBuffer: Float32Array): boolean;
1168
+ }
1169
+
1170
+ /**
1171
+ * Voice.ts
1172
+ * purpose: prepares Voices from sample and generator data
1173
+ */
1174
+
1175
+ /**
1176
+ * Voice represents a single instance of the
1177
+ * SoundFont2 synthesis model.
1178
+ * That is:
1179
+ * A wavetable oscillator (sample)
1180
+ * A volume envelope (volEnv)
1181
+ * A modulation envelope (modEnv)
1182
+ * Generators (generators and modulatedGenerators)
1183
+ * Modulators (modulators)
1184
+ * And MIDI params such as channel, MIDI note, velocity
1185
+ */
1186
+ declare class Voice {
706
1187
  /**
707
- * Adds to a given generator, or its default value.
1188
+ * All oscillators currently available to the voice.
708
1189
  */
709
- addToGenerator(type: GeneratorType, value: number, validate?: boolean): void;
1190
+ readonly oscillators: Record<InterpolationType, WavetableOscillator>;
710
1191
  /**
711
- * Sets a generator to a given value if preset, otherwise adds a new one.
1192
+ * The oscillator currently used by this voice.
712
1193
  */
713
- setGenerator(type: GeneratorType, value: number | null, validate?: boolean): void;
1194
+ wavetable: WavetableOscillator;
714
1195
  /**
715
- * Adds generators to the zone.
716
- * @param generators
1196
+ * Lowpass filter applied to the voice.
717
1197
  */
718
- addGenerators(...generators: Generator[]): void;
719
- addModulators(...modulators: Modulator[]): void;
720
- getGenerator<K>(generatorType: GeneratorType, notFoundValue: number | K): number | K;
721
- copyFrom(zone: BasicZone): void;
1198
+ readonly filter: LowpassFilter;
722
1199
  /**
723
- * Filters the generators and prepends the range generators.
1200
+ * The unmodulated (copied to) generators of the voice.
724
1201
  */
725
- getWriteGenerators(bank: BasicSoundBank): Generator[];
726
- }
727
-
728
- declare class BasicGlobalZone extends BasicZone {
729
- }
730
-
731
- declare class BasicSample {
1202
+ readonly generators: Int16Array<ArrayBuffer>;
732
1203
  /**
733
- * The sample's name.
1204
+ * The generators in real-time, affected by modulators.
1205
+ * This is used during rendering.
734
1206
  */
735
- name: string;
1207
+ readonly modulatedGenerators: Int16Array<ArrayBuffer>;
736
1208
  /**
737
- * Sample rate in Hz.
1209
+ * The voice's modulators.
738
1210
  */
739
- sampleRate: number;
1211
+ modulators: Modulator[];
740
1212
  /**
741
- * Original pitch of the sample as a MIDI note number.
1213
+ * The current values for the respective modulators.
1214
+ * If there are more modulators, the array must be resized.
742
1215
  */
743
- originalKey: number;
1216
+ modulatorValues: Int16Array<ArrayBuffer>;
744
1217
  /**
745
- * Pitch correction, in cents. Can be negative.
1218
+ * Modulation envelope.
746
1219
  */
747
- pitchCorrection: number;
1220
+ readonly modEnv: ModulationEnvelope;
748
1221
  /**
749
- * Linked sample, unused if mono.
1222
+ * Volume envelope.
750
1223
  */
751
- linkedSample?: BasicSample;
1224
+ readonly volEnv: VolumeEnvelope;
752
1225
  /**
753
- * The type of the sample.
1226
+ * The buffer to use when rendering the voice (to avoid memory allocations)
1227
+ * If the user supplied a larger one, it must be resized.
754
1228
  */
755
- sampleType: SampleType;
1229
+ buffer: Float32Array<ArrayBuffer>;
756
1230
  /**
757
- * Relative to the start of the sample in sample points.
1231
+ * Resonance offset, it is affected by the default resonant modulator
758
1232
  */
759
- loopStart: number;
1233
+ resonanceOffset: number;
760
1234
  /**
761
- * Relative to the start of the sample in sample points.
1235
+ * Priority of the voice. Used for stealing.
762
1236
  */
763
- loopEnd: number;
1237
+ priority: number;
764
1238
  /**
765
- * Sample's linked instruments (the instruments that use it)
766
- * note that duplicates are allowed since one instrument can use the same sample multiple times.
1239
+ * If the voice is currently active.
1240
+ * If not, it can be used.
767
1241
  */
768
- linkedTo: BasicInstrument[];
1242
+ isActive: boolean;
769
1243
  /**
770
- * Indicates if the data was overridden, so it cannot be copied back unchanged.
1244
+ * Indicates if the voice has rendered at least one buffer.
1245
+ * Used for exclusive class to prevent killing voices set on the same note.
771
1246
  */
772
- protected dataOverridden: boolean;
1247
+ hasRendered: boolean;
773
1248
  /**
774
- * The compressed sample data if the sample has been compressed.
1249
+ * Indicates if the voice is in the release phase.
775
1250
  */
776
- protected compressedData?: Uint8Array;
1251
+ isInRelease: boolean;
777
1252
  /**
778
- * The sample's audio data.
1253
+ * Indicates if the voice is currently held by the sustain pedal.
779
1254
  */
780
- protected audioData?: Float32Array;
1255
+ isHeld: boolean;
781
1256
  /**
782
- * The basic representation of a sample
783
- * @param sampleName The sample's name
784
- * @param sampleRate The sample's rate in Hz
785
- * @param originalKey The sample's pitch as a MIDI note number
786
- * @param pitchCorrection The sample's pitch correction in cents
787
- * @param sampleType The sample's type, an enum that can indicate SF3
788
- * @param loopStart The sample's loop start relative to the sample start in sample points
789
- * @param loopEnd The sample's loop end relative to the sample start in sample points
1257
+ * MIDI channel number of the voice.
790
1258
  */
791
- constructor(sampleName: string, sampleRate: number, originalKey: number, pitchCorrection: number, sampleType: SampleType, loopStart: number, loopEnd: number);
1259
+ channel: number;
792
1260
  /**
793
- * Indicates if the sample is compressed using vorbis SF3.
1261
+ * Velocity of the note.
794
1262
  */
795
- get isCompressed(): boolean;
1263
+ velocity: number;
796
1264
  /**
797
- * If the sample is linked to another sample.
1265
+ * MIDI note number.
798
1266
  */
799
- get isLinked(): boolean;
1267
+ midiNote: number;
800
1268
  /**
801
- * The sample's use count
1269
+ * The root key of the voice.
802
1270
  */
803
- get useCount(): number;
1271
+ rootKey: number;
804
1272
  /**
805
- * Get raw data for writing the file, either a compressed bit stream or signed 16-bit little endian PCM data.
806
- * @param allowVorbis if vorbis file data is allowed.
807
- * @return either s16le or vorbis data.
1273
+ * Target key for the note.
808
1274
  */
809
- getRawData(allowVorbis: boolean): Uint8Array;
1275
+ targetKey: number;
810
1276
  /**
811
- * Resamples the audio data to a given sample rate.
1277
+ * The pressure of the voice
812
1278
  */
813
- resampleData(newSampleRate: number): void;
1279
+ pressure: number;
814
1280
  /**
815
- * Compresses the audio data
816
- * @param encodeVorbis the compression function to use when compressing
1281
+ * Linear gain of the voice. Used with Key Modifiers.
817
1282
  */
818
- compressSample(encodeVorbis: SampleEncodingFunction): Promise<void>;
1283
+ gainModifier: number;
819
1284
  /**
820
- * Sets the sample type and unlinks if needed.
821
- * @param type The type to set it to.
1285
+ * Looping mode of the sample:
1286
+ * 0 - no loop
1287
+ * 1 - loop
1288
+ * 2 - UNOFFICIAL: polyphone 2.4 added start on release
1289
+ * 3 - loop then play when released
822
1290
  */
823
- setSampleType(type: SampleType): void;
1291
+ loopingMode: SampleLoopingMode;
824
1292
  /**
825
- * Unlinks the sample from its stereo link if it has any.
1293
+ * Start time of the voice, absolute.
826
1294
  */
827
- unlinkSample(): void;
1295
+ startTime: number;
828
1296
  /**
829
- * Links a stereo sample.
830
- * @param sample the sample to link to.
831
- * @param type either left, right or linked.
1297
+ * Start time of the release phase, absolute.
832
1298
  */
833
- setLinkedSample(sample: BasicSample, type: SampleType): void;
1299
+ releaseStartTime: number;
834
1300
  /**
835
- * Links the sample to a given instrument
836
- * @param instrument the instrument to link to
1301
+ * Current tuning in cents.
837
1302
  */
838
- linkTo(instrument: BasicInstrument): void;
1303
+ tuningCents: number;
839
1304
  /**
840
- * Unlinks the sample from a given instrument
841
- * @param instrument the instrument to unlink from
1305
+ * Current calculated tuning. (as in ratio)
842
1306
  */
843
- unlinkFrom(instrument: BasicInstrument): void;
1307
+ tuningRatio: number;
844
1308
  /**
845
- * Get the float32 audio data.
846
- * Note that this either decodes the compressed data or passes the ready sampleData.
847
- * If neither are set then it will throw an error!
848
- * @returns the audio data
1309
+ * From -500 to 500. Used for smoothing.
849
1310
  */
850
- getAudioData(): Float32Array;
1311
+ currentPan: number;
851
1312
  /**
852
- * Replaces the audio data *in-place*.
853
- * @param audioData The new audio data as Float32.
854
- * @param sampleRate The new sample rate, in Hertz.
1313
+ * If MIDI Tuning Standard is already applied (at note-on time),
1314
+ * this will be used to take the values at real-time tuning as "midiNote"
1315
+ * property contains the tuned number.
1316
+ * see SpessaSynth#29 comment by @paulikaro
855
1317
  */
856
- setAudioData(audioData: Float32Array, sampleRate: number): void;
1318
+ realKey: number;
857
1319
  /**
858
- * Replaces the audio with a compressed data sample and flags the sample as compressed
859
- * @param data the new compressed data
1320
+ * Initial key to glide from, MIDI Note number. If -1, the portamento is OFF.
860
1321
  */
861
- setCompressedData(data: Uint8Array): void;
1322
+ portamentoFromKey: number;
862
1323
  /**
863
- * Encodes s16le sample
864
- * @return the encoded data
1324
+ * Duration of the linear glide, in seconds.
865
1325
  */
866
- protected encodeS16LE(): IndexedByteArray;
1326
+ portamentoDuration: number;
867
1327
  /**
868
- * Decode binary vorbis into a float32 pcm
1328
+ * From -500 to 500, where zero means disabled (use the channel pan). Used for random pan.
869
1329
  */
870
- protected decodeVorbis(): Float32Array;
871
- }
872
- declare class EmptySample extends BasicSample {
1330
+ overridePan: number;
873
1331
  /**
874
- * A simplified class for creating samples.
1332
+ * Exclusive class number for hi-hats etc.
875
1333
  */
876
- constructor();
877
- }
878
-
879
- declare class BasicInstrumentZone extends BasicZone {
1334
+ exclusiveClass: number;
880
1335
  /**
881
- * The instrument this zone belongs to.
1336
+ * In timecents, where zero means disabled (use the modulatedGenerators table).
1337
+ * Used for exclusive notes and killing notes.
882
1338
  */
883
- readonly parentInstrument: BasicInstrument;
1339
+ overrideReleaseVolEnv: number;
1340
+ constructor(sampleRate: number);
884
1341
  /**
885
- * For tracking on the individual zone level, since multiple presets can refer to the same instrument.
1342
+ * Computes a given modulator
1343
+ * @param controllerTable all midi controllers as 14bit values + the non-controller indexes, starting at 128
1344
+ * @param pitchWheel the pitch wheel value, as channel determines if it's a per-note or a global value.
1345
+ * @param modulatorIndex the modulator to compute
1346
+ * @returns the computed value
886
1347
  */
887
- useCount: number;
1348
+ computeModulator(this: Voice, controllerTable: Int16Array, pitchWheel: number, modulatorIndex: number): number;
888
1349
  /**
889
- * Creates a new instrument zone.
890
- * @param instrument The parent instrument.
891
- * @param sample The sample to use in this zone.
1350
+ * Releases the voice as exclusiveClass.
892
1351
  */
893
- constructor(instrument: BasicInstrument, sample: BasicSample);
1352
+ exclusiveRelease(currentTime: number, minExclusiveLength?: number): void;
894
1353
  /**
895
- * Zone's sample.
1354
+ * Stops the voice
1355
+ * @param currentTime
1356
+ * @param minNoteLength minimum note length in seconds
896
1357
  */
897
- private _sample;
1358
+ releaseVoice(currentTime: number, minNoteLength?: number): void;
1359
+ setup(currentTime: number, channel: number, midiNote: number, velocity: number, realKey: number): void;
1360
+ }
1361
+
1362
+ declare class ModulatorSource {
898
1363
  /**
899
- * Zone's sample.
1364
+ * If this field is set to false, the controller should be mapped with a minimum value of 0 and a maximum value of 1. This is also
1365
+ * called Unipolar. Thus, it behaves similar to the Modulation Wheel controller of the MIDI specification.
1366
+ *
1367
+ * If this field is set to true, the controller sound be mapped with a minimum value of -1 and a maximum value of 1. This is also
1368
+ * called Bipolar. Thus, it behaves similar to the Pitch Wheel controller of the MIDI specification.
900
1369
  */
901
- get sample(): BasicSample;
1370
+ isBipolar: boolean;
902
1371
  /**
903
- * Sets a sample for this zone.
904
- * @param sample the sample to set.
1372
+ * If this field is set true, the direction of the controller should be from the maximum value to the minimum value. So, for
1373
+ * example, if the controller source is Key Number, then a Key Number value of 0 corresponds to the maximum possible
1374
+ * controller output, and the Key Number value of 127 corresponds to the minimum possible controller input.
905
1375
  */
906
- set sample(sample: BasicSample);
907
- getWriteGenerators(bank: BasicSoundBank): Generator[];
908
- }
909
-
910
- /**
911
- * Returned structure containing extended SF2 chunks.
912
- */
913
- interface ExtendedSF2Chunks {
1376
+ isNegative: boolean;
914
1377
  /**
915
- * The PDTA part of the chunk.
1378
+ * The index of the source.
1379
+ * It can point to one of the MIDI controllers or one of the predefined sources, depending on the 'isCC' flag.
916
1380
  */
917
- pdta: IndexedByteArray;
1381
+ index: ModulatorSourceIndex;
918
1382
  /**
919
- * The XDTA (https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md) part of the chunk.
1383
+ * If this field is set to true, the MIDI Controller Palette is selected. The ‘index’ field value corresponds to one of the 128
1384
+ * MIDI Continuous Controller messages as defined in the MIDI specification.
1385
+ */
1386
+ isCC: boolean;
1387
+ /**
1388
+ * This field specifies how the minimum value approaches the maximum value.
1389
+ */
1390
+ curveType: ModulatorCurveType;
1391
+ constructor(index?: ModulatorSourceIndex, curveType?: ModulatorCurveType, isCC?: boolean, isBipolar?: boolean, isNegative?: boolean);
1392
+ private get sourceName();
1393
+ private get curveTypeName();
1394
+ static fromSourceEnum(sourceEnum: number): ModulatorSource;
1395
+ /**
1396
+ * Copies the modulator source.
1397
+ * @param source The source to copy from.
1398
+ * @returns the copied source.
1399
+ */
1400
+ static copyFrom(source: ModulatorSource): ModulatorSource;
1401
+ toString(): string;
1402
+ toSourceEnum(): number;
1403
+ isIdentical(source: ModulatorSource): boolean;
1404
+ /**
1405
+ * Gets the current value from this source.
1406
+ * @param midiControllers The MIDI controller + modulator source array.
1407
+ * @param pitchWheel the pitch wheel value, as channel determines if it's a per-note or a global value.
1408
+ * @param voice The voice to get the data for.
1409
+ */
1410
+ getValue(midiControllers: Int16Array, pitchWheel: number, voice: Voice): number;
1411
+ }
1412
+
1413
+ /**
1414
+ * Returned structure containing extended SF2 chunks.
1415
+ */
1416
+ interface ExtendedSF2Chunks {
1417
+ /**
1418
+ * The PDTA part of the chunk.
1419
+ */
1420
+ pdta: IndexedByteArray;
1421
+ /**
1422
+ * The XDTA (https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md) part of the chunk.
920
1423
  */
921
1424
  xdta: IndexedByteArray;
922
1425
  }
@@ -942,62 +1445,175 @@ interface SoundFontWriteIndexes {
942
1445
  hdr: number;
943
1446
  }
944
1447
 
945
- /**
946
- * Represents a single instrument
947
- */
948
- declare class BasicInstrument {
1448
+ declare class Modulator {
949
1449
  /**
950
- * The instrument's name
1450
+ * The generator destination of this modulator.
951
1451
  */
952
- name: string;
1452
+ destination: GeneratorType;
953
1453
  /**
954
- * The instrument's zones
1454
+ * The transform amount for this modulator.
955
1455
  */
956
- zones: BasicInstrumentZone[];
1456
+ transformAmount: number;
957
1457
  /**
958
- * Instrument's global zone
1458
+ * The transform type for this modulator.
959
1459
  */
960
- readonly globalZone: BasicGlobalZone;
1460
+ transformType: ModulatorTransformType;
961
1461
  /**
962
- * Instrument's linked presets (the presets that use it)
963
- * note that duplicates are allowed since one preset can use the same instrument multiple times.
1462
+ * Indicates if the given modulator is chorus or reverb effects modulator.
1463
+ * This is done to simulate BASSMIDI effects behavior:
1464
+ * - defaults to 1000 transform amount rather than 200
1465
+ * - values can be changed, but anything above 200 is 1000
1466
+ * (except for values above 1000, they are copied directly)
1467
+ * - all values below are multiplied by 5 (200 * 5 = 1000)
1468
+ * - still can be disabled if the soundfont has its own modulator curve
1469
+ * - this fixes the very low amount of reverb by default and doesn't break soundfonts
964
1470
  */
965
- readonly linkedTo: BasicPreset[];
1471
+ readonly isEffectModulator: boolean;
966
1472
  /**
967
- * How many presets is this instrument used by
1473
+ * The default resonant modulator does not affect the filter gain.
1474
+ * Neither XG nor GS responded to cc #74 in that way.
968
1475
  */
969
- get useCount(): number;
1476
+ readonly isDefaultResonantModulator: boolean;
970
1477
  /**
971
- * Creates a new instrument zone and returns it.
972
- * @param sample The sample to use in the zone.
1478
+ * The primary source of this modulator.
973
1479
  */
974
- createZone(sample: BasicSample): BasicInstrumentZone;
1480
+ readonly primarySource: ModulatorSource;
975
1481
  /**
976
- * Links the instrument ta a given preset
977
- * @param preset the preset to link to
1482
+ * The secondary source of this modulator.
978
1483
  */
979
- linkTo(preset: BasicPreset): void;
1484
+ readonly secondarySource: ModulatorSource;
980
1485
  /**
981
- * Unlinks the instrument from a given preset
982
- * @param preset the preset to unlink from
1486
+ * Creates a new SF2 Modulator
983
1487
  */
984
- unlinkFrom(preset: BasicPreset): void;
985
- deleteUnusedZones(): void;
986
- delete(): void;
1488
+ constructor(primarySource?: ModulatorSource, secondarySource?: ModulatorSource, destination?: GeneratorType, amount?: number, transformType?: ModulatorTransformType, isEffectModulator?: boolean, isDefaultResonantModulator?: boolean);
1489
+ private get destinationName();
987
1490
  /**
988
- * Deletes a given instrument zone if it has no uses
989
- * @param index the index of the zone to delete
990
- * @param force ignores the use count and deletes forcibly
991
- * @returns if the zone has been deleted
1491
+ * Checks if the pair of modulators is identical (in SF2 terms)
1492
+ * @param mod1 modulator 1
1493
+ * @param mod2 modulator 2
1494
+ * @param checkAmount if the amount should be checked too.
1495
+ * @returns if they are identical
992
1496
  */
993
- deleteZone(index: number, force?: boolean): boolean;
1497
+ static isIdentical(mod1: Modulator, mod2: Modulator, checkAmount?: boolean): boolean;
994
1498
  /**
995
- * Globalizes the instrument *in-place.*
996
- * This means trying to move as many generators and modulators
997
- * to the global zone as possible to reduce clutter and the count of parameters.
1499
+ * Copies a modulator.
1500
+ * @param mod The modulator to copy.
1501
+ * @returns The copied modulator.
998
1502
  */
999
- globalize(): void;
1000
- write(instData: ExtendedSF2Chunks, index: number): void;
1503
+ static copyFrom(mod: Modulator): Modulator;
1504
+ toString(): string;
1505
+ write(modData: IndexedByteArray, indexes?: SoundFontWriteIndexes): void;
1506
+ /**
1507
+ * Sums transform and create a NEW modulator
1508
+ * @param modulator the modulator to sum with
1509
+ * @returns the new modulator
1510
+ */
1511
+ sumTransform(modulator: Modulator): Modulator;
1512
+ }
1513
+
1514
+ declare class Generator {
1515
+ /**
1516
+ * The generator's SF2 type.
1517
+ */
1518
+ generatorType: GeneratorType;
1519
+ /**
1520
+ * The generator's 16-bit value.
1521
+ */
1522
+ generatorValue: number;
1523
+ /**
1524
+ * Constructs a new generator
1525
+ * @param type generator type
1526
+ * @param value generator value
1527
+ * @param validate if the limits should be validated
1528
+ */
1529
+ constructor(type: GeneratorType, value: number, validate?: boolean);
1530
+ write(genData: IndexedByteArray): void;
1531
+ toString(): string;
1532
+ }
1533
+
1534
+ declare class BasicZone {
1535
+ /**
1536
+ * The zone's velocity range.
1537
+ * min -1 means that it is a default value
1538
+ */
1539
+ velRange: GenericRange;
1540
+ /**
1541
+ * The zone's key range.
1542
+ * min -1 means that it is a default value.
1543
+ */
1544
+ keyRange: GenericRange;
1545
+ /**
1546
+ * The zone's generators.
1547
+ */
1548
+ generators: Generator[];
1549
+ /**
1550
+ * The zone's modulators.
1551
+ */
1552
+ modulators: Modulator[];
1553
+ get hasKeyRange(): boolean;
1554
+ get hasVelRange(): boolean;
1555
+ /**
1556
+ * The current tuning in cents, taking in both coarse and fine generators.
1557
+ */
1558
+ get fineTuning(): number;
1559
+ /**
1560
+ * The current tuning in cents, taking in both coarse and fine generators.
1561
+ */
1562
+ set fineTuning(tuningCents: number);
1563
+ /**
1564
+ * Adds to a given generator, or its default value.
1565
+ */
1566
+ addToGenerator(type: GeneratorType, value: number, validate?: boolean): void;
1567
+ /**
1568
+ * Sets a generator to a given value if preset, otherwise adds a new one.
1569
+ */
1570
+ setGenerator(type: GeneratorType, value: number | null, validate?: boolean): void;
1571
+ /**
1572
+ * Adds generators to the zone.
1573
+ * @param generators
1574
+ */
1575
+ addGenerators(...generators: Generator[]): void;
1576
+ addModulators(...modulators: Modulator[]): void;
1577
+ getGenerator<K>(generatorType: GeneratorType, notFoundValue: number | K): number | K;
1578
+ copyFrom(zone: BasicZone): void;
1579
+ /**
1580
+ * Filters the generators and prepends the range generators.
1581
+ */
1582
+ getWriteGenerators(bank: BasicSoundBank): Generator[];
1583
+ }
1584
+
1585
+ declare class BasicGlobalZone extends BasicZone {
1586
+ }
1587
+
1588
+ declare class BasicInstrumentZone extends BasicZone {
1589
+ /**
1590
+ * The instrument this zone belongs to.
1591
+ */
1592
+ readonly parentInstrument: BasicInstrument;
1593
+ /**
1594
+ * For tracking on the individual zone level, since multiple presets can refer to the same instrument.
1595
+ */
1596
+ useCount: number;
1597
+ /**
1598
+ * Creates a new instrument zone.
1599
+ * @param instrument The parent instrument.
1600
+ * @param sample The sample to use in this zone.
1601
+ */
1602
+ constructor(instrument: BasicInstrument, sample: BasicSample);
1603
+ /**
1604
+ * Zone's sample.
1605
+ */
1606
+ private _sample;
1607
+ /**
1608
+ * Zone's sample.
1609
+ */
1610
+ get sample(): BasicSample;
1611
+ /**
1612
+ * Sets a sample for this zone.
1613
+ * @param sample the sample to set.
1614
+ */
1615
+ set sample(sample: BasicSample);
1616
+ getWriteGenerators(bank: BasicSoundBank): Generator[];
1001
1617
  }
1002
1618
 
1003
1619
  declare class BasicPresetZone extends BasicZone {
@@ -1071,6 +1687,9 @@ declare class BasicPreset implements MIDIPatchNamed {
1071
1687
  * Checks if this preset is a drum preset
1072
1688
  */
1073
1689
  get isAnyDrums(): boolean;
1690
+ private static isInRange;
1691
+ private static addUniqueModulators;
1692
+ private static subtractRanges;
1074
1693
  /**
1075
1694
  * Unlinks everything from this preset.
1076
1695
  */
@@ -1095,12 +1714,12 @@ declare class BasicPreset implements MIDIPatchNamed {
1095
1714
  */
1096
1715
  matches(preset: MIDIPatch): boolean;
1097
1716
  /**
1098
- * Returns the synthesis data from this preset
1099
- * @param midiNote the MIDI note number
1100
- * @param velocity the MIDI velocity
1101
- * @returns the returned sound data
1717
+ * Returns the voice synthesis data for this preset.
1718
+ * @param midiNote the MIDI note number.
1719
+ * @param velocity the MIDI velocity.
1720
+ * @returns the returned sound data.
1102
1721
  */
1103
- getSynthesisData(midiNote: number, velocity: number): VoiceSynthesisData[];
1722
+ getVoiceParameters(midiNote: number, velocity: number): VoiceParameters[];
1104
1723
  /**
1105
1724
  * BankMSB:bankLSB:program:isGMGSDrum
1106
1725
  */
@@ -1120,802 +1739,405 @@ declare class BasicPreset implements MIDIPatchNamed {
1120
1739
  write(phdrData: ExtendedSF2Chunks, index: number): void;
1121
1740
  }
1122
1741
 
1123
- declare class SoundBankManager {
1742
+ /**
1743
+ * Represents a single instrument
1744
+ */
1745
+ declare class BasicInstrument {
1124
1746
  /**
1125
- * All the sound banks, ordered from the most important to the least.
1747
+ * The instrument's name
1126
1748
  */
1127
- soundBankList: SoundBankManagerListEntry[];
1128
- private readonly presetListChangeCallback;
1129
- private selectablePresetList;
1749
+ name: string;
1130
1750
  /**
1131
- * @param presetListChangeCallback Supplied by the parent synthesizer class,
1132
- * this is called whenever the preset list changes.
1751
+ * The instrument's zones
1133
1752
  */
1134
- constructor(presetListChangeCallback: () => unknown);
1135
- private _presetList;
1753
+ zones: BasicInstrumentZone[];
1136
1754
  /**
1137
- * The list of all presets in the sound bank stack.
1755
+ * Instrument's global zone
1138
1756
  */
1139
- get presetList(): PresetListEntry[];
1757
+ readonly globalZone: BasicGlobalZone;
1140
1758
  /**
1141
- * The current sound bank priority order.
1142
- * @returns The IDs of the sound banks in the current order.
1759
+ * Instrument's linked presets (the presets that use it)
1760
+ * note that duplicates are allowed since one preset can use the same instrument multiple times.
1143
1761
  */
1144
- get priorityOrder(): string[];
1762
+ readonly linkedTo: BasicPreset[];
1145
1763
  /**
1146
- * The current sound bank priority order.
1147
- * @param newList The new order of sound bank IDs.
1764
+ * How many presets is this instrument used by
1148
1765
  */
1149
- set priorityOrder(newList: string[]);
1766
+ get useCount(): number;
1150
1767
  /**
1151
- * Deletes a given sound bank by its ID.
1152
- * @param id the ID of the sound bank to delete.
1153
- */
1154
- deleteSoundBank(id: string): void;
1155
- /**
1156
- * Adds a new sound bank with a given ID, or replaces an existing one.
1157
- * @param font the sound bank to add.
1158
- * @param id the ID of the sound bank.
1159
- * @param bankOffset the bank offset of the sound bank.
1160
- */
1161
- addSoundBank(font: BasicSoundBank, id: string, bankOffset?: number): void;
1162
- /**
1163
- * Gets a given preset from the sound bank stack.
1164
- * @param patch The MIDI patch to search for.
1165
- * @param system The MIDI system to select the preset for.
1166
- * @returns An object containing the preset and its bank offset.
1167
- */
1168
- getPreset(patch: MIDIPatch, system: SynthSystem): BasicPreset;
1169
- destroy(): void;
1170
- private generatePresetList;
1171
- }
1172
-
1173
- /**
1174
- * Kills the specified number of voices based on their priority.
1175
- * This function will remove the least important voices from all channels.
1176
- * @param amount The number of voices to remove.
1177
- */
1178
- declare function killVoicesIntenral(this: SpessaSynthProcessor, amount: number): void;
1179
-
1180
- type SysExAcceptedArray = number[] | IndexedByteArray | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Uint8ClampedArray | Float32Array | Float64Array;
1181
-
1182
- /**
1183
- * Executes a system exclusive message for the synthesizer.
1184
- * @param syx The system exclusive message as an array of bytes.
1185
- * @param channelOffset The channel offset to apply (default is 0).
1186
- * @remarks
1187
- * This is a rather extensive method that handles various system exclusive messages,
1188
- * including Roland GS, MIDI Tuning Standard, and other non-realtime messages.
1189
- */
1190
- declare function systemExclusiveInternal(this: SpessaSynthProcessor, syx: SysExAcceptedArray, channelOffset?: number): void;
1191
-
1192
- declare const midiMessageTypes: {
1193
- readonly noteOff: 128;
1194
- readonly noteOn: 144;
1195
- readonly polyPressure: 160;
1196
- readonly controllerChange: 176;
1197
- readonly programChange: 192;
1198
- readonly channelPressure: 208;
1199
- readonly pitchWheel: 224;
1200
- readonly systemExclusive: 240;
1201
- readonly timecode: 241;
1202
- readonly songPosition: 242;
1203
- readonly songSelect: 243;
1204
- readonly tuneRequest: 246;
1205
- readonly clock: 248;
1206
- readonly start: 250;
1207
- readonly continue: 251;
1208
- readonly stop: 252;
1209
- readonly activeSensing: 254;
1210
- readonly reset: 255;
1211
- readonly sequenceNumber: 0;
1212
- readonly text: 1;
1213
- readonly copyright: 2;
1214
- readonly trackName: 3;
1215
- readonly instrumentName: 4;
1216
- readonly lyric: 5;
1217
- readonly marker: 6;
1218
- readonly cuePoint: 7;
1219
- readonly programName: 8;
1220
- readonly midiChannelPrefix: 32;
1221
- readonly midiPort: 33;
1222
- readonly endOfTrack: 47;
1223
- readonly setTempo: 81;
1224
- readonly smpteOffset: 84;
1225
- readonly timeSignature: 88;
1226
- readonly keySignature: 89;
1227
- readonly sequenceSpecific: 127;
1228
- };
1229
- type MIDIMessageType = (typeof midiMessageTypes)[keyof typeof midiMessageTypes];
1230
- declare const midiControllers: {
1231
- readonly bankSelect: 0;
1232
- readonly modulationWheel: 1;
1233
- readonly breathController: 2;
1234
- readonly undefinedCC3: 3;
1235
- readonly footController: 4;
1236
- readonly portamentoTime: 5;
1237
- readonly dataEntryMSB: 6;
1238
- readonly mainVolume: 7;
1239
- readonly balance: 8;
1240
- readonly undefinedCC9: 9;
1241
- readonly pan: 10;
1242
- readonly expressionController: 11;
1243
- readonly effectControl1: 12;
1244
- readonly effectControl2: 13;
1245
- readonly undefinedCC14: 14;
1246
- readonly undefinedCC15: 15;
1247
- readonly generalPurposeController1: 16;
1248
- readonly generalPurposeController2: 17;
1249
- readonly generalPurposeController3: 18;
1250
- readonly generalPurposeController4: 19;
1251
- readonly undefinedCC20: 20;
1252
- readonly undefinedCC21: 21;
1253
- readonly undefinedCC22: 22;
1254
- readonly undefinedCC23: 23;
1255
- readonly undefinedCC24: 24;
1256
- readonly undefinedCC25: 25;
1257
- readonly undefinedCC26: 26;
1258
- readonly undefinedCC27: 27;
1259
- readonly undefinedCC28: 28;
1260
- readonly undefinedCC29: 29;
1261
- readonly undefinedCC30: 30;
1262
- readonly undefinedCC31: 31;
1263
- readonly bankSelectLSB: 32;
1264
- readonly modulationWheelLSB: 33;
1265
- readonly breathControllerLSB: 34;
1266
- readonly undefinedCC3LSB: 35;
1267
- readonly footControllerLSB: 36;
1268
- readonly portamentoTimeLSB: 37;
1269
- readonly dataEntryLSB: 38;
1270
- readonly mainVolumeLSB: 39;
1271
- readonly balanceLSB: 40;
1272
- readonly undefinedCC9LSB: 41;
1273
- readonly panLSB: 42;
1274
- readonly expressionControllerLSB: 43;
1275
- readonly effectControl1LSB: 44;
1276
- readonly effectControl2LSB: 45;
1277
- readonly undefinedCC14LSB: 46;
1278
- readonly undefinedCC15LSB: 47;
1279
- readonly undefinedCC16LSB: 48;
1280
- readonly undefinedCC17LSB: 49;
1281
- readonly undefinedCC18LSB: 50;
1282
- readonly undefinedCC19LSB: 51;
1283
- readonly undefinedCC20LSB: 52;
1284
- readonly undefinedCC21LSB: 53;
1285
- readonly undefinedCC22LSB: 54;
1286
- readonly undefinedCC23LSB: 55;
1287
- readonly undefinedCC24LSB: 56;
1288
- readonly undefinedCC25LSB: 57;
1289
- readonly undefinedCC26LSB: 58;
1290
- readonly undefinedCC27LSB: 59;
1291
- readonly undefinedCC28LSB: 60;
1292
- readonly undefinedCC29LSB: 61;
1293
- readonly undefinedCC30LSB: 62;
1294
- readonly undefinedCC31LSB: 63;
1295
- readonly sustainPedal: 64;
1296
- readonly portamentoOnOff: 65;
1297
- readonly sostenutoPedal: 66;
1298
- readonly softPedal: 67;
1299
- readonly legatoFootswitch: 68;
1300
- readonly hold2Pedal: 69;
1301
- readonly soundVariation: 70;
1302
- readonly filterResonance: 71;
1303
- readonly releaseTime: 72;
1304
- readonly attackTime: 73;
1305
- readonly brightness: 74;
1306
- readonly decayTime: 75;
1307
- readonly vibratoRate: 76;
1308
- readonly vibratoDepth: 77;
1309
- readonly vibratoDelay: 78;
1310
- readonly soundController10: 79;
1311
- readonly generalPurposeController5: 80;
1312
- readonly generalPurposeController6: 81;
1313
- readonly generalPurposeController7: 82;
1314
- readonly generalPurposeController8: 83;
1315
- readonly portamentoControl: 84;
1316
- readonly undefinedCC85: 85;
1317
- readonly undefinedCC86: 86;
1318
- readonly undefinedCC87: 87;
1319
- readonly undefinedCC88: 88;
1320
- readonly undefinedCC89: 89;
1321
- readonly undefinedCC90: 90;
1322
- readonly reverbDepth: 91;
1323
- readonly tremoloDepth: 92;
1324
- readonly chorusDepth: 93;
1325
- readonly detuneDepth: 94;
1326
- readonly phaserDepth: 95;
1327
- readonly dataIncrement: 96;
1328
- readonly dataDecrement: 97;
1329
- readonly nonRegisteredParameterLSB: 98;
1330
- readonly nonRegisteredParameterMSB: 99;
1331
- readonly registeredParameterLSB: 100;
1332
- readonly registeredParameterMSB: 101;
1333
- readonly undefinedCC102LSB: 102;
1334
- readonly undefinedCC103LSB: 103;
1335
- readonly undefinedCC104LSB: 104;
1336
- readonly undefinedCC105LSB: 105;
1337
- readonly undefinedCC106LSB: 106;
1338
- readonly undefinedCC107LSB: 107;
1339
- readonly undefinedCC108LSB: 108;
1340
- readonly undefinedCC109LSB: 109;
1341
- readonly undefinedCC110LSB: 110;
1342
- readonly undefinedCC111LSB: 111;
1343
- readonly undefinedCC112LSB: 112;
1344
- readonly undefinedCC113LSB: 113;
1345
- readonly undefinedCC114LSB: 114;
1346
- readonly undefinedCC115LSB: 115;
1347
- readonly undefinedCC116LSB: 116;
1348
- readonly undefinedCC117LSB: 117;
1349
- readonly undefinedCC118LSB: 118;
1350
- readonly undefinedCC119LSB: 119;
1351
- readonly allSoundOff: 120;
1352
- readonly resetAllControllers: 121;
1353
- readonly localControlOnOff: 122;
1354
- readonly allNotesOff: 123;
1355
- readonly omniModeOff: 124;
1356
- readonly omniModeOn: 125;
1357
- readonly monoModeOn: 126;
1358
- readonly polyModeOn: 127;
1359
- };
1360
- type MIDIController = (typeof midiControllers)[keyof typeof midiControllers];
1361
-
1362
- /**
1363
- * Executes a data entry fine (LSB) change for the current channel.
1364
- * @param dataValue The value to set for the data entry fine controller (0-127).
1365
- */
1366
- declare function dataEntryFine(this: MIDIChannel, dataValue: number): void;
1367
-
1368
- /**
1369
- * Handles MIDI controller changes for a channel.
1370
- * @param controllerNumber The MIDI controller number (0-127).
1371
- * @param controllerValue The value of the controller (0-127).
1372
- * @param sendEvent If an event should be emitted.
1373
- * @remarks
1374
- * This function processes MIDI controller changes, updating the channel's
1375
- * midiControllers table and handling special cases like bank select,
1376
- * data entry, and sustain pedal. It also computes modulators for all voices
1377
- * in the channel based on the controller change.
1378
- * If the controller number is greater than 127, it is treated as a channel
1379
- * configuration controller, and the `force` parameter must be set to true
1380
- * to allow changes.
1381
- */
1382
- declare function controllerChange(this: MIDIChannel, controllerNumber: MIDIController, controllerValue: number, sendEvent?: boolean): void;
1383
-
1384
- /**
1385
- * Executes a data entry coarse (MSB) change for the current channel.
1386
- * @param dataValue The value to set for the data entry coarse controller (0-127).
1387
- */
1388
- declare function dataEntryCoarse(this: MIDIChannel, dataValue: number): void;
1389
-
1390
- /**
1391
- * Sends a "MIDI Note on" message and starts a note.
1392
- * @param midiNote The MIDI note number (0-127).
1393
- * @param velocity The velocity of the note (0-127). If less than 1, it will send a note off instead.
1394
- */
1395
- declare function noteOn(this: MIDIChannel, midiNote: number, velocity: number): void;
1396
-
1397
- /**
1398
- * Releases a note by its MIDI note number.
1399
- * If the note is in high performance mode and the channel is not a drum channel,
1400
- * it kills the note instead of releasing it.
1401
- * @param midiNote The MIDI note number to release (0-127).
1402
- */
1403
- declare function noteOff(this: MIDIChannel, midiNote: number): void;
1404
-
1405
- /**
1406
- * Changes the program (preset) of the channel.
1407
- * @param program The program number (0-127) to change to.
1408
- */
1409
- declare function programChange(this: MIDIChannel, program: number): void;
1410
-
1411
- /**
1412
- * A class for dynamic modulators
1413
- * that are assigned for more complex system exclusive messages
1414
- */
1415
- declare class DynamicModulatorSystem {
1416
- /**
1417
- * The current dynamic modulator list.
1418
- */
1419
- modulatorList: {
1420
- mod: Modulator;
1421
- id: string;
1422
- }[];
1423
- resetModulators(): void;
1424
- /**
1425
- * @param source Like in midiControllers: values below NON_CC_INDEX_OFFSET are CCs,
1426
- * above are regular modulator sources.
1427
- * @param destination The generator type to modulate.
1428
- * @param amount The amount of modulation to apply.
1429
- * @param isBipolar If true, the modulation is bipolar (ranges from -1 to 1 instead of from 0 to 1).
1430
- * @param isNegative If true, the modulation is negative (goes from 1 to 0 instead of from 0 to 1).
1431
- */
1432
- setModulator(source: ModulatorSourceEnum, destination: GeneratorType, amount: number, isBipolar?: boolean, isNegative?: boolean): void;
1433
- private getModulatorID;
1434
- private deleteModulator;
1435
- }
1436
-
1437
- declare class ProtectedSynthValues {
1438
- /**
1439
- * This.tunings[program][key] = tuning
1440
- */
1441
- readonly tunings: MTSProgramTuning[];
1442
- masterParameters: MasterParameterType;
1443
- /**
1444
- * The volume gain, set by MIDI sysEx
1445
- */
1446
- midiVolume: number;
1447
- /**
1448
- * Set via system exclusive.
1449
- * Note: Remember to reset in system reset!
1450
- */
1451
- reverbSend: number;
1452
- /**
1453
- * Set via system exclusive.
1454
- * Note: Remember to reset in system reset!
1455
- */
1456
- chorusSend: number;
1457
- /**
1458
- * The pan of the left channel.
1459
- */
1460
- panLeft: number;
1461
- /**
1462
- * The pan of the right channel.
1463
- */
1464
- panRight: number;
1465
- /**
1466
- * Synth's default (reset) preset.
1768
+ * Creates a new instrument zone and returns it.
1769
+ * @param sample The sample to use in the zone.
1467
1770
  */
1468
- defaultPreset: BasicPreset | undefined;
1771
+ createZone(sample: BasicSample): BasicInstrumentZone;
1469
1772
  /**
1470
- * Synth's default (reset) drum preset.
1773
+ * Links the instrument ta a given preset
1774
+ * @param preset the preset to link to
1471
1775
  */
1472
- drumPreset: BasicPreset | undefined;
1473
- readonly volumeEnvelopeSmoothingFactor: number;
1474
- readonly panSmoothingFactor: number;
1475
- readonly filterSmoothingFactor: number;
1776
+ linkTo(preset: BasicPreset): void;
1476
1777
  /**
1477
- * Calls when an event occurs.
1478
- * @param eventType The event type.
1479
- * @param eventData The event data.
1778
+ * Unlinks the instrument from a given preset
1779
+ * @param preset the preset to unlink from
1480
1780
  */
1481
- eventCallbackHandler: <K extends keyof SynthProcessorEventData>(eventType: K, eventData: SynthProcessorEventData[K]) => unknown;
1482
- getVoices: (channel: number, midiNote: number, velocity: number, realKey: number) => VoiceList;
1483
- voiceKilling: (amount: number) => unknown;
1781
+ unlinkFrom(preset: BasicPreset): void;
1782
+ deleteUnusedZones(): void;
1783
+ delete(): void;
1484
1784
  /**
1485
- * Cached voices for all presets for this synthesizer.
1486
- * Nesting is calculated in getCachedVoiceIndex, returns a list of voices for this note.
1785
+ * Deletes a given instrument zone if it has no uses
1786
+ * @param index the index of the zone to delete
1787
+ * @param force ignores the use count and deletes forcibly
1788
+ * @returns if the zone has been deleted
1487
1789
  */
1488
- cachedVoices: VoiceList[];
1489
- constructor(eventCallbackHandler: <K extends keyof SynthProcessorEventData>(eventType: K, eventData: SynthProcessorEventData[K]) => unknown, getVoices: (channel: number, midiNote: number, velocity: number, realKey: number) => VoiceList, voiceKillingFunction: (amount: number) => unknown, volumeEnvelopeSmoothingFactor: number, panSmoothingFactor: number, filterSmoothingFactor: number);
1790
+ deleteZone(index: number, force?: boolean): boolean;
1490
1791
  /**
1491
- * Copied callback so MIDI channels can call it.
1792
+ * Globalizes the instrument *in-place.*
1793
+ * This means trying to move as many generators and modulators
1794
+ * to the global zone as possible to reduce clutter and the count of parameters.
1492
1795
  */
1493
- callEvent<K extends keyof SynthProcessorEventData>(eventName: K, eventData: SynthProcessorEventData[K]): void;
1796
+ globalize(): void;
1797
+ write(instData: ExtendedSF2Chunks, index: number): void;
1494
1798
  }
1495
1799
 
1496
- /**
1497
- * This class represents a single MIDI Channel within the synthesizer.
1498
- */
1499
- declare class MIDIChannel {
1500
- readonly midiControllers: Int16Array;
1501
- /**
1502
- * An array indicating if a controller, at the equivalent index in the midiControllers array, is locked
1503
- * (i.e., not allowed changing).
1504
- * A locked controller cannot be modified.
1505
- */
1506
- lockedControllers: boolean[];
1507
- /**
1508
- * An array of custom (non-SF2) control values such as RPN pitch tuning, transpose, modulation depth, etc.
1509
- * Refer to controller_tables.ts for the index definitions.
1510
- */
1511
- readonly customControllers: Float32Array;
1512
- /**
1513
- * The key shift of the channel (in semitones).
1514
- */
1515
- channelTransposeKeyShift: number;
1516
- /**
1517
- * An array of octave tuning values for each note on the channel.
1518
- * Each index corresponds to a note (0 = C, 1 = C#, ..., 11 = B).
1519
- * Note: Repeated every 12 notes.
1520
- */
1521
- channelOctaveTuning: Int8Array;
1522
- /**
1523
- * A system for dynamic modulator assignment for advanced system exclusives.
1524
- */
1525
- sysExModulators: DynamicModulatorSystem;
1526
- /**
1527
- * Indicates whether this channel is a drum channel.
1528
- */
1529
- drumChannel: boolean;
1800
+ declare class BasicSample {
1530
1801
  /**
1531
- * Enables random panning for every note played on this channel.
1802
+ * The sample's name.
1532
1803
  */
1533
- randomPan: boolean;
1804
+ name: string;
1534
1805
  /**
1535
- * The current state of the data entry for the channel.
1806
+ * Sample rate in Hz.
1536
1807
  */
1537
- dataEntryState: DataEntryState;
1808
+ sampleRate: number;
1538
1809
  /**
1539
- * The currently selected MIDI patch of the channel.
1540
- * Note that the exact matching preset may not be available, but this represents exactly what MIDI asks for.
1810
+ * Original pitch of the sample as a MIDI note number.
1541
1811
  */
1542
- readonly patch: MIDIPatch;
1812
+ originalKey: number;
1543
1813
  /**
1544
- * The preset currently assigned to the channel.
1814
+ * Pitch correction, in cents. Can be negative.
1545
1815
  */
1546
- preset?: BasicPreset;
1816
+ pitchCorrection: number;
1547
1817
  /**
1548
- * Indicates whether the program on this channel is locked.
1818
+ * Linked sample, unused if mono.
1549
1819
  */
1550
- lockPreset: boolean;
1820
+ linkedSample?: BasicSample;
1551
1821
  /**
1552
- * Indicates the MIDI system when the preset was locked.
1822
+ * The type of the sample.
1553
1823
  */
1554
- lockedSystem: SynthSystem;
1824
+ sampleType: SampleType;
1555
1825
  /**
1556
- * Indicates whether the GS NRPN parameters are enabled for this channel.
1826
+ * Relative to the start of the sample in sample points.
1557
1827
  */
1558
- lockGSNRPNParams: boolean;
1828
+ loopStart: number;
1559
1829
  /**
1560
- * The vibrato settings for the channel.
1561
- * @property depth - Depth of the vibrato effect in cents.
1562
- * @property delay - Delay before the vibrato effect starts (in seconds).
1563
- * @property rate - Rate of the vibrato oscillation (in Hz).
1830
+ * Relative to the start of the sample in sample points.
1564
1831
  */
1565
- channelVibrato: {
1566
- delay: number;
1567
- depth: number;
1568
- rate: number;
1569
- };
1832
+ loopEnd: number;
1570
1833
  /**
1571
- * An array of voices currently active on the channel.
1834
+ * Sample's linked instruments (the instruments that use it)
1835
+ * note that duplicates are allowed since one instrument can use the same sample multiple times.
1572
1836
  */
1573
- voices: VoiceList;
1837
+ linkedTo: BasicInstrument[];
1574
1838
  /**
1575
- * An array of voices that are sustained on the channel.
1839
+ * Indicates if the data was overridden, so it cannot be copied back unchanged.
1576
1840
  */
1577
- sustainedVoices: VoiceList;
1841
+ protected dataOverridden: boolean;
1578
1842
  /**
1579
- * The channel's number (0-based index)
1843
+ * The compressed sample data if the sample has been compressed.
1580
1844
  */
1581
- readonly channelNumber: number;
1845
+ protected compressedData?: Uint8Array;
1582
1846
  /**
1583
- * Parent processor instance.
1847
+ * The sample's audio data.
1584
1848
  */
1585
- synth: SpessaSynthProcessor;
1849
+ protected audioData?: Float32Array;
1586
1850
  /**
1587
- * Grants access to protected synth values.
1851
+ * The basic representation of a sample
1852
+ * @param sampleName The sample's name
1853
+ * @param sampleRate The sample's rate in Hz
1854
+ * @param originalKey The sample's pitch as a MIDI note number
1855
+ * @param pitchCorrection The sample's pitch correction in cents
1856
+ * @param sampleType The sample's type, an enum that can indicate SF3
1857
+ * @param loopStart The sample's loop start relative to the sample start in sample points
1858
+ * @param loopEnd The sample's loop end relative to the sample start in sample points
1588
1859
  */
1589
- synthProps: ProtectedSynthValues;
1860
+ constructor(sampleName: string, sampleRate: number, originalKey: number, pitchCorrection: number, sampleType: SampleType, loopStart: number, loopEnd: number);
1590
1861
  /**
1591
- * Sends a "MIDI Note on" message and starts a note.
1592
- * @param midiNote The MIDI note number (0-127).
1593
- * @param velocity The velocity of the note (0-127). If less than 1, it will send a note off instead.
1862
+ * Indicates if the sample is compressed using vorbis SF3.
1594
1863
  */
1595
- noteOn: typeof noteOn;
1864
+ get isCompressed(): boolean;
1596
1865
  /**
1597
- * Releases a note by its MIDI note number.
1598
- * If the note is in high performance mode and the channel is not a drum channel,
1599
- * it kills the note instead of releasing it.
1600
- * @param midiNote The MIDI note number to release (0-127).
1866
+ * If the sample is linked to another sample.
1601
1867
  */
1602
- noteOff: typeof noteOff;
1868
+ get isLinked(): boolean;
1603
1869
  /**
1604
- * Changes the program (preset) of the channel.
1605
- * @param programNumber The program number (0-127) to change to.
1870
+ * The sample's use count
1606
1871
  */
1607
- programChange: typeof programChange;
1608
- controllerChange: typeof controllerChange;
1872
+ get useCount(): number;
1609
1873
  /**
1610
- * Reset all controllers for channel.
1611
- * This will reset all controllers to their default values,
1612
- * except for the locked controllers.
1874
+ * Get raw data for writing the file, either a compressed bit stream or signed 16-bit little endian PCM data.
1875
+ * @param allowVorbis if vorbis file data is allowed.
1876
+ * @return either s16le or vorbis data.
1613
1877
  */
1614
- readonly resetControllers: typeof resetControllers;
1615
- readonly resetPreset: typeof resetPreset;
1878
+ getRawData(allowVorbis: boolean): Uint8Array;
1616
1879
  /**
1617
- * https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf
1618
- * Reset controllers according to RP-15 Recommended Practice.
1880
+ * Resamples the audio data to a given sample rate.
1619
1881
  */
1620
- readonly resetControllersRP15Compliant: typeof resetControllersRP15Compliant;
1882
+ resampleData(newSampleRate: number): void;
1621
1883
  /**
1622
- * Reset all parameters to their default values.
1623
- * This includes NRPN and RPN controllers, data entry state,
1624
- * and generator overrides and offsets.
1884
+ * Compresses the audio data
1885
+ * @param encodeVorbis the compression function to use when compressing
1625
1886
  */
1626
- resetParameters: typeof resetParameters;
1887
+ compressSample(encodeVorbis: SampleEncodingFunction): Promise<void>;
1627
1888
  /**
1628
- * Executes a data entry fine (LSB) change for the current channel.
1629
- * @param dataValue The value to set for the data entry fine controller (0-127).
1889
+ * Sets the sample type and unlinks if needed.
1890
+ * @param type The type to set it to.
1630
1891
  */
1631
- dataEntryFine: typeof dataEntryFine;
1892
+ setSampleType(type: SampleType): void;
1632
1893
  /**
1633
- * Executes a data entry coarse (MSB) change for the current channel.
1634
- * @param dataValue The value to set for the data entry coarse controller (0-127).
1894
+ * Unlinks the sample from its stereo link if it has any.
1635
1895
  */
1636
- dataEntryCoarse: typeof dataEntryCoarse;
1896
+ unlinkSample(): void;
1637
1897
  /**
1638
- * Will be updated every time something tuning-related gets changed.
1639
- * This is used to avoid a big addition for every voice rendering call.
1898
+ * Links a stereo sample.
1899
+ * @param sample the sample to link to.
1900
+ * @param type either left, right or linked.
1640
1901
  */
1641
- protected channelTuningCents: number;
1902
+ setLinkedSample(sample: BasicSample, type: SampleType): void;
1642
1903
  /**
1643
- * An array of offsets generators for SF2 nrpn support.
1644
- * A value of 0 means no change; -10 means 10 lower, etc.
1904
+ * Links the sample to a given instrument
1905
+ * @param instrument the instrument to link to
1645
1906
  */
1646
- protected generatorOffsets: Int16Array;
1907
+ linkTo(instrument: BasicInstrument): void;
1647
1908
  /**
1648
- * A small optimization that disables applying offsets until at least one is set.
1909
+ * Unlinks the sample from a given instrument
1910
+ * @param instrument the instrument to unlink from
1649
1911
  */
1650
- protected generatorOffsetsEnabled: boolean;
1912
+ unlinkFrom(instrument: BasicInstrument): void;
1651
1913
  /**
1652
- * An array of override generators for AWE32 support.
1653
- * A value of 32,767 means unchanged, as it is not allowed anywhere.
1914
+ * Get the float32 audio data.
1915
+ * Note that this either decodes the compressed data or passes the ready sampleData.
1916
+ * If neither are set then it will throw an error!
1917
+ * @returns the audio data
1654
1918
  */
1655
- protected generatorOverrides: Int16Array;
1919
+ getAudioData(): Float32Array;
1656
1920
  /**
1657
- * A small optimization that disables applying overrides until at least one is set.
1921
+ * Replaces the audio data *in-place*.
1922
+ * @param audioData The new audio data as Float32.
1923
+ * @param sampleRate The new sample rate, in Hertz.
1658
1924
  */
1659
- protected generatorOverridesEnabled: boolean;
1660
- protected renderVoice: (voice: Voice, timeNow: number, outputLeft: Float32Array<ArrayBufferLike>, outputRight: Float32Array<ArrayBufferLike>, reverbOutputLeft: Float32Array<ArrayBufferLike>, reverbOutputRight: Float32Array<ArrayBufferLike>, chorusOutputLeft: Float32Array<ArrayBufferLike>, chorusOutputRight: Float32Array<ArrayBufferLike>, startIndex: number, sampleCount: number) => boolean;
1661
- protected panAndMixVoice: (voice: Voice, inputBuffer: Float32Array<ArrayBufferLike>, outputLeft: Float32Array<ArrayBufferLike>, outputRight: Float32Array<ArrayBufferLike>, reverbLeft: Float32Array<ArrayBufferLike>, reverbRight: Float32Array<ArrayBufferLike>, chorusLeft: Float32Array<ArrayBufferLike>, chorusRight: Float32Array<ArrayBufferLike>, startIndex: number) => void;
1662
- protected computeModulators: (voice: Voice, sourceUsesCC?: 0 | 1 | -1 | undefined, sourceIndex?: number | undefined) => void;
1925
+ setAudioData(audioData: Float32Array, sampleRate: number): void;
1663
1926
  /**
1664
- * Constructs a new MIDI channel.
1927
+ * Replaces the audio with a compressed data sample and flags the sample as compressed
1928
+ * @param data the new compressed data
1665
1929
  */
1666
- constructor(synth: SpessaSynthProcessor, synthProps: ProtectedSynthValues, preset: BasicPreset | undefined, channelNumber: number);
1930
+ setCompressedData(data: Uint8Array): void;
1667
1931
  /**
1668
- * Indicates whether the channel is muted.
1932
+ * Encodes s16le sample
1933
+ * @return the encoded data
1669
1934
  */
1670
- protected _isMuted: boolean;
1935
+ protected encodeS16LE(): IndexedByteArray;
1671
1936
  /**
1672
- * Indicates whether the channel is muted.
1937
+ * Decode binary vorbis into a float32 pcm
1673
1938
  */
1674
- get isMuted(): boolean;
1939
+ protected decodeVorbis(): Float32Array;
1940
+ }
1941
+ declare class EmptySample extends BasicSample {
1675
1942
  /**
1676
- * Indicates whether the sustain (hold) pedal is active.
1943
+ * A simplified class for creating samples.
1677
1944
  */
1678
- get holdPedal(): boolean;
1679
- protected get channelSystem(): SynthSystem;
1945
+ constructor();
1946
+ }
1947
+
1948
+ /**
1949
+ * Midi_message.ts
1950
+ * purpose: contains enums for midi events and controllers and functions to parse them
1951
+ */
1952
+
1953
+ declare class MIDIMessage {
1680
1954
  /**
1681
- * Transposes the channel by given amount of semitones.
1682
- * @param semitones The number of semitones to transpose the channel by. Can be decimal.
1683
- * @param force Defaults to false, if true, it will force the transpose even if the channel is a drum channel.
1955
+ * Absolute number of MIDI ticks from the start of the track.
1684
1956
  */
1685
- transposeChannel(semitones: number, force?: boolean): void;
1957
+ ticks: number;
1686
1958
  /**
1687
- * Sets the octave tuning for a given channel.
1688
- * @param tuning The tuning array of 12 values, each representing the tuning for a note in the octave.
1689
- * @remarks
1690
- * Cent tunings are relative.
1959
+ * The MIDI message status byte. Note that for meta events, it is the second byte. (not 0xFF)
1691
1960
  */
1692
- setOctaveTuning(tuning: Int8Array): void;
1961
+ statusByte: MIDIMessageType;
1693
1962
  /**
1694
- * Sets the modulation depth for the channel.
1695
- * @param cents The modulation depth in cents to set.
1696
- * @remarks
1697
- * This method sets the modulation depth for the channel by converting the given cents value into a
1698
- * multiplier. The MIDI specification assumes the default modulation depth is 50 cents,
1699
- * but it may vary for different sound banks.
1700
- * For example, if you want a modulation depth of 100 cents,
1701
- * the multiplier will be 2,
1702
- * which, for a preset with a depth of 50,
1703
- * will create a total modulation depth of 100 cents.
1704
- *
1963
+ * Message's binary data
1705
1964
  */
1706
- setModulationDepth(cents: number): void;
1965
+ data: Uint8Array<ArrayBuffer>;
1707
1966
  /**
1708
- * Sets the channel's tuning.
1709
- * @param cents The tuning in cents to set.
1710
- * @param log If true, logs the change to the console.
1967
+ * Creates a new MIDI message
1968
+ * @param ticks time of this message in absolute MIDI ticks
1969
+ * @param byte the message status byte
1970
+ * @param data the message's binary data
1711
1971
  */
1712
- setTuning(cents: number, log?: boolean): void;
1972
+ constructor(ticks: number, byte: MIDIMessageType, data: Uint8Array<ArrayBuffer>);
1973
+ }
1974
+
1975
+ /**
1976
+ * RMIDInfoData type represents metadata for an RMIDI file.
1977
+ */
1978
+ interface RMIDInfoData {
1713
1979
  /**
1714
- * Sets the pitch of the given channel.
1715
- * @param pitch The pitch (0 - 16384)
1980
+ * The name of the song.
1716
1981
  */
1717
- pitchWheel(pitch: number): void;
1982
+ name: string;
1718
1983
  /**
1719
- * Sets the channel pressure (MIDI Aftertouch).
1720
- * @param pressure the pressure of the channel.
1984
+ * The engineer who worked on the sound bank file.
1721
1985
  */
1722
- channelPressure(pressure: number): void;
1986
+ engineer: string;
1723
1987
  /**
1724
- * Sets the pressure of the given note on a specific channel.
1725
- * This is used for polyphonic pressure (aftertouch).
1726
- * @param midiNote 0 - 127, the MIDI note number to set the pressure for.
1727
- * @param pressure 0 - 127, the pressure value to set for the note.
1988
+ * The artist of the MIDI file.
1728
1989
  */
1729
- polyPressure(midiNote: number, pressure: number): void;
1730
- setCustomController(type: CustomController, value: number): void;
1731
- updateChannelTuning(): void;
1990
+ artist: string;
1732
1991
  /**
1733
- * Renders Float32 audio for this channel.
1734
- * @param outputLeft the left output buffer.
1735
- * @param outputRight the right output buffer.
1736
- * @param reverbOutputLeft left output for reverb.
1737
- * @param reverbOutputRight right output for reverb.
1738
- * @param chorusOutputLeft left output for chorus.
1739
- * @param chorusOutputRight right output for chorus.
1740
- * @param startIndex start index offset.
1741
- * @param sampleCount sample count to render.
1992
+ * The album of the song.
1742
1993
  */
1743
- renderAudio(outputLeft: Float32Array, outputRight: Float32Array, reverbOutputLeft: Float32Array, reverbOutputRight: Float32Array, chorusOutputLeft: Float32Array, chorusOutputRight: Float32Array, startIndex: number, sampleCount: number): void;
1994
+ album: string;
1744
1995
  /**
1745
- * Locks or unlocks the preset from MIDI program changes.
1746
- * @param locked If the preset should be locked.
1996
+ * The genre of the song.
1747
1997
  */
1748
- setPresetLock(locked: boolean): void;
1998
+ genre: string;
1749
1999
  /**
1750
- * Changes the preset to, or from drums.
1751
- * Note that this executes a program change.
1752
- * @param isDrum If the channel should be a drum preset or not.
2000
+ * The image for the file (album cover).
1753
2001
  */
1754
- setDrums(isDrum: boolean): void;
2002
+ picture: ArrayBuffer;
1755
2003
  /**
1756
- * Sets the channel to a given MIDI patch.
1757
- * Note that this executes a program change.
1758
- * @param patch The MIDI patch to set the channel to.
2004
+ * The comment of the file.
1759
2005
  */
1760
- setPatch(patch: MIDIPatch): void;
2006
+ comment: string;
1761
2007
  /**
1762
- * Sets the GM/GS drum flag.
1763
- * @param drums
2008
+ * The creation date of the file.
1764
2009
  */
1765
- setGSDrums(drums: boolean): void;
2010
+ creationDate: Date;
1766
2011
  /**
1767
- * Sets a custom vibrato.
1768
- * @param depth In cents.
1769
- * @param rate In Hertz.
1770
- * @param delay seconds.
2012
+ * The copyright of the file.
1771
2013
  */
1772
- setVibrato(depth: number, rate: number, delay: number): void;
2014
+ copyright: string;
1773
2015
  /**
1774
- * Disables and locks all GS NPRN parameters, including the custom vibrato.
2016
+ * The encoding of the RMIDI info.
1775
2017
  */
1776
- disableAndLockGSNRPN(): void;
1777
- resetGeneratorOverrides(): void;
1778
- setGeneratorOverride(gen: GeneratorType, value: number, realtime?: boolean): void;
1779
- resetGeneratorOffsets(): void;
1780
- setGeneratorOffset(gen: GeneratorType, value: number): void;
2018
+ infoEncoding: string;
1781
2019
  /**
1782
- * Stops a note nearly instantly.
1783
- * @param midiNote The note to stop.
1784
- * @param releaseTime in timecents, defaults to -12000 (very short release).
2020
+ * The encoding of the MIDI file's text messages.
1785
2021
  */
1786
- killNote(midiNote: number, releaseTime?: number): void;
2022
+ midiEncoding: string;
1787
2023
  /**
1788
- * Stops all notes on the channel.
1789
- * @param force If true, stops all notes immediately, otherwise applies release time.
2024
+ * The software used to write the file.
1790
2025
  */
1791
- stopAllNotes(force?: boolean): void;
2026
+ software: string;
1792
2027
  /**
1793
- * Mutes or unmutes a channel.
1794
- * @param isMuted If the channel should be muted.
2028
+ * The subject of the file.
1795
2029
  */
1796
- muteChannel(isMuted: boolean): void;
2030
+ subject: string;
2031
+ }
2032
+ interface TempoChange {
1797
2033
  /**
1798
- * Sends this channel's property
2034
+ * MIDI ticks of the change, absolute value from the start of the MIDI file.
1799
2035
  */
1800
- sendChannelProperty(): void;
1801
- protected setBankMSB(bankMSB: number): void;
1802
- protected setBankLSB(bankLSB: number): void;
2036
+ ticks: number;
1803
2037
  /**
1804
- * Sets drums on channel.
2038
+ * New tempo in BPM.
1805
2039
  */
1806
- protected setDrumFlag(isDrum: boolean): void;
2040
+ tempo: number;
1807
2041
  }
1808
-
1809
- /**
1810
- * Executes a full system reset of all controllers.
1811
- * This will reset all controllers to their default values,
1812
- * except for the locked controllers.
1813
- */
1814
- declare function resetAllControllersInternal(this: SpessaSynthProcessor, system?: SynthSystem): void;
1815
- /**
1816
- * Reset all controllers for channel.
1817
- * This will reset all controllers to their default values,
1818
- * except for the locked controllers.
1819
- */
1820
- declare function resetControllers(this: MIDIChannel, sendCCEvents?: boolean): void;
1821
- declare function resetPreset(this: MIDIChannel): void;
1822
- /**
1823
- * https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf
1824
- * Reset controllers according to RP-15 Recommended Practice.
1825
- */
1826
- declare function resetControllersRP15Compliant(this: MIDIChannel): void;
1827
- /**
1828
- * Reset all parameters to their default values.
1829
- * This includes NRPN and RPN controllers, data entry state,
1830
- * and generator overrides and offsets.
1831
- */
1832
- declare function resetParameters(this: MIDIChannel): void;
1833
-
1834
- /**
1835
- * Represents a snapshot of a single channel's state in the synthesizer.
1836
- */
1837
- declare class ChannelSnapshot {
2042
+ type MIDILoopType = "soft" | "hard";
2043
+ interface MIDILoop {
1838
2044
  /**
1839
- * The MIDI patch that the channel is using.
2045
+ * Start of the loop, in MIDI ticks.
1840
2046
  */
1841
- patch: MIDIPatchNamed;
2047
+ start: number;
1842
2048
  /**
1843
- * Indicates whether the channel's program change is disabled.
2049
+ * End of the loop, in MIDI ticks.
1844
2050
  */
1845
- lockPreset: boolean;
2051
+ end: number;
1846
2052
  /**
1847
- * Indicates the MIDI system when the preset was locked
2053
+ * The type of the loop detected:
2054
+ * - Soft - the playback will immediately jump to the loop start pointer without any further processing.
2055
+ * - Hard - the playback will quickly process all messages from
2056
+ * the start of the file to ensure that synthesizer is in the correct state.
2057
+ * This is the default behavior.
2058
+ *
2059
+ * Soft loop types are enabled for Touhou and GameMaker loop points.
1848
2060
  */
1849
- lockedSystem: SynthSystem;
2061
+ type: MIDILoopType;
2062
+ }
2063
+ type MIDIFormat = 0 | 1 | 2;
2064
+ interface NoteTime {
1850
2065
  /**
1851
- * The array of all MIDI controllers (in 14-bit values) with the modulator sources at the end.
2066
+ * The MIDI key number.
1852
2067
  */
1853
- midiControllers: Int16Array;
2068
+ midiNote: number;
1854
2069
  /**
1855
- * An array of booleans, indicating if the controller with a current index is locked.
2070
+ * Start of the note, in seconds.
1856
2071
  */
1857
- lockedControllers: boolean[];
2072
+ start: number;
1858
2073
  /**
1859
- * Array of custom (not SF2) control values such as RPN pitch tuning, transpose, modulation depth, etc.
2074
+ * Length of the note, in seconds.
1860
2075
  */
1861
- customControllers: Float32Array;
2076
+ length: number;
1862
2077
  /**
1863
- * Indicates whether the channel vibrato is locked.
2078
+ * The MIDI velocity of the note.
1864
2079
  */
1865
- lockVibrato: boolean;
2080
+ velocity: number;
2081
+ }
2082
+ /**
2083
+ * Represents a desired program change for a MIDI channel.
2084
+ */
2085
+ interface DesiredProgramChange extends MIDIPatch {
1866
2086
  /**
1867
- * The channel's vibrato settings.
1868
- * @property depth Vibrato depth, in gain.
1869
- * @property delay Vibrato delay from note on in seconds.
1870
- * @property rate Vibrato rate in Hz.
2087
+ * The channel number.
1871
2088
  */
1872
- channelVibrato: {
1873
- depth: number;
1874
- delay: number;
1875
- rate: number;
1876
- };
2089
+ channel: number;
2090
+ }
2091
+ /**
2092
+ * Represents a desired controller change for a MIDI channel.
2093
+ */
2094
+ interface DesiredControllerChange {
1877
2095
  /**
1878
- * Key shift for the channel.
2096
+ * The channel number.
1879
2097
  */
1880
- channelTransposeKeyShift: number;
2098
+ channel: number;
1881
2099
  /**
1882
- * The channel's octave tuning in cents.
2100
+ * The MIDI controller number.
1883
2101
  */
1884
- channelOctaveTuning: Int8Array;
2102
+ controllerNumber: number;
1885
2103
  /**
1886
- * Indicates whether the channel is muted.
2104
+ * The new controller value.
1887
2105
  */
1888
- isMuted: boolean;
2106
+ controllerValue: number;
2107
+ }
2108
+ /**
2109
+ * Represents a desired channel transpose change.
2110
+ */
2111
+ interface DesiredChannelTranspose {
1889
2112
  /**
1890
- * Indicates whether the channel is a drum channel.
2113
+ * The channel number.
2114
+ */
2115
+ channel: number;
2116
+ /**
2117
+ * The number of semitones to transpose.
2118
+ * This can use floating point numbers, which will be used to fine-tune the pitch in cents using RPN.
1891
2119
  */
1892
- drumChannel: boolean;
2120
+ keyShift: number;
2121
+ }
2122
+ interface RMIDIWriteOptions {
1893
2123
  /**
1894
- * The channel number this snapshot represents.
2124
+ * The bank offset for RMIDI.
1895
2125
  */
1896
- channelNumber: number;
1897
- constructor(patch: MIDIPatchNamed, lockPreset: boolean, lockedSystem: SynthSystem, midiControllers: Int16Array, lockedControllers: boolean[], customControllers: Float32Array, lockVibrato: boolean, channelVibrato: {
1898
- delay: number;
1899
- depth: number;
1900
- rate: number;
1901
- }, channelTransposeKeyShift: number, channelOctaveTuning: Int8Array, isMuted: boolean, drumChannel: boolean, channelNumber: number);
2126
+ bankOffset: number;
1902
2127
  /**
1903
- * Creates a copy of existing snapshot.
1904
- * @param snapshot The snapshot to create a copy from.
2128
+ * The metadata of the file. Optional.
1905
2129
  */
1906
- static copyFrom(snapshot: ChannelSnapshot): ChannelSnapshot;
2130
+ metadata: Partial<Omit<RMIDInfoData, "infoEncoding">>;
1907
2131
  /**
1908
- * Creates a snapshot of the channel's state.
1909
- * @param spessaSynthProcessor The synthesizer processor containing the channel.
1910
- * @param channelNumber The channel number to snapshot.
2132
+ * If the MIDI file should internally be corrected to work with the set bank offset.
1911
2133
  */
1912
- static create(spessaSynthProcessor: SpessaSynthProcessor, channelNumber: number): ChannelSnapshot;
2134
+ correctBankOffset: boolean;
1913
2135
  /**
1914
- * Applies the snapshot to the specified channel.
1915
- * @param spessaSynthProcessor The processor containing the channel.
2136
+ * The optional sound bank instance used to correct bank offset.
1916
2137
  */
1917
- apply(spessaSynthProcessor: SpessaSynthProcessor): void;
2138
+ soundBank?: BasicSoundBank;
1918
2139
  }
2140
+ type RMIDInfoFourCC = "INAM" | "IPRD" | "IALB" | "IART" | "IGNR" | "IPIC" | "ICOP" | "ICRD" | "ICRT" | "ICMT" | "IENG" | "ISFT" | "ISBJ" | "IENC" | "MENC" | "DBNK";
1919
2141
 
1920
2142
  /**
1921
2143
  * A manager for custom key overrides for channels
@@ -1998,1057 +2220,1055 @@ declare class KeyModifierManager {
1998
2220
  getPatch(channel: number, midiNote: number): MIDIPatch;
1999
2221
  }
2000
2222
 
2001
- /**
2002
- * Represents a snapshot of the synthesizer's state.
2003
- */
2004
- declare class SynthesizerSnapshot {
2005
- /**
2006
- * The individual channel snapshots.
2007
- */
2008
- channelSnapshots: ChannelSnapshot[];
2009
- /**
2010
- * Key modifiers.
2011
- */
2012
- keyMappings: (KeyModifier | undefined)[][];
2013
- masterParameters: MasterParameterType;
2014
- constructor(channelSnapshots: ChannelSnapshot[], masterParameters: MasterParameterType, keyMappings: (KeyModifier | undefined)[][]);
2015
- /**
2016
- * Creates a new synthesizer snapshot from the given SpessaSynthProcessor.
2017
- * @param processor the processor to take a snapshot of.
2018
- * @returns The snapshot.
2019
- */
2020
- static create(processor: SpessaSynthProcessor): SynthesizerSnapshot;
2021
- /**
2022
- * Creates a copy of existing snapshot.
2023
- * @param snapshot The snapshot to create a copy from.
2024
- */
2025
- static copyFrom(snapshot: SynthesizerSnapshot): SynthesizerSnapshot;
2026
- /**
2027
- * Applies the snapshot to the synthesizer.
2028
- * @param processor the processor to apply the snapshot to.
2029
- */
2030
- apply(processor: SpessaSynthProcessor): void;
2031
- }
2032
-
2033
- /**
2034
- * Processor.ts
2035
- * purpose: the core synthesis engine
2036
- */
2037
- declare class SpessaSynthProcessor {
2038
- soundBankManager: SoundBankManager;
2039
- /**
2040
- * All MIDI channels of the synthesizer.
2041
- */
2042
- midiChannels: MIDIChannel[];
2043
- /**
2044
- * Handles the custom key overrides: velocity and preset
2045
- */
2046
- keyModifierManager: KeyModifierManager;
2047
- /**
2048
- * Current total amount of voices that are currently playing.
2049
- */
2050
- totalVoicesAmount: number;
2051
- /**
2052
- * Controls if the processor is fully initialized.
2053
- */
2054
- readonly processorInitialized: Promise<boolean>;
2055
- /**
2056
- * The current time of the synthesizer, in seconds. You probably should not modify this directly.
2057
- */
2058
- currentSynthTime: number;
2059
- /**
2060
- * Sample rate in Hertz.
2061
- */
2062
- readonly sampleRate: number;
2063
- /**
2064
- * Are the chorus and reverb effects enabled?
2065
- */
2066
- enableEffects: boolean;
2067
- /**
2068
- * Is the event system enabled?
2069
- */
2070
- enableEventSystem: boolean;
2071
- /**
2072
- * Calls when an event occurs.
2073
- * @param event The event that occurred.
2074
- */
2075
- onEventCall?: (event: SynthProcessorEvent) => unknown;
2076
- /**
2077
- * Executes a system exclusive message for the synthesizer.
2078
- * @param syx The system exclusive message as an array of bytes.
2079
- * @param channelOffset The channel offset to apply (default is 0).
2080
- */
2081
- readonly systemExclusive: typeof systemExclusiveInternal;
2082
- /**
2083
- * Executes a full system reset of all controllers.
2084
- * This will reset all controllers to their default values,
2085
- * except for the locked controllers.
2086
- */
2087
- readonly resetAllControllers: typeof resetAllControllersInternal;
2088
- /**
2089
- * Sets a master parameter of the synthesizer.
2090
- * @param type The type of the master parameter to set.
2091
- * @param value The value to set for the master parameter.
2092
- */
2093
- readonly setMasterParameter: typeof setMasterParameterInternal;
2094
- /**
2095
- * Gets a master parameter of the synthesizer.
2096
- * @param type The type of the master parameter to get.
2097
- * @returns The value of the master parameter.
2098
- */
2099
- readonly getMasterParameter: typeof getMasterParameterInternal;
2100
- /**
2101
- * Gets all master parameters of the synthesizer.
2102
- * @returns All the master parameters.
2103
- */
2104
- readonly getAllMasterParameters: typeof getAllMasterParametersInternal;
2105
- /**
2106
- * Gets voices for a preset.
2107
- * @param preset The preset to get voices for.
2108
- * @param bankMSB The bank to cache the voices in.
2109
- * @param program Program to cache the voices in.
2110
- * @param midiNote The MIDI note to use.
2111
- * @param velocity The velocity to use.
2112
- * @param realKey The real MIDI note if the "midiNote" was changed by MIDI Tuning Standard.
2113
- * @returns Output is an array of voices.
2114
- * @remarks
2115
- * This is a public method, but it is only intended to be used by the sequencer.
2116
- */
2117
- readonly getVoicesForPreset: typeof getVoicesForPresetInternal;
2118
- /**
2119
- * Kills the specified number of voices based on their priority.
2120
- * @param amount The number of voices to remove.
2121
- */
2122
- readonly killVoices: typeof killVoicesIntenral;
2123
- protected readonly getVoices: (channel: number, midiNote: number, velocity: number, realKey: number) => VoiceList;
2124
- protected privateProps: ProtectedSynthValues;
2125
- /**
2126
- * Tor applying the snapshot after an override sound bank too.
2127
- */
2128
- protected savedSnapshot?: SynthesizerSnapshot;
2129
- /**
2130
- * Synth's event queue from the main thread
2131
- */
2132
- protected eventQueue: {
2133
- callback: () => unknown;
2134
- time: number;
2135
- }[];
2136
- private readonly sampleTime;
2137
- /**
2138
- * Creates a new synthesizer engine.
2139
- * @param sampleRate sample rate, in Hertz.
2140
- * @param opts the processor's options.
2141
- */
2142
- constructor(sampleRate: number, opts?: Partial<SynthProcessorOptions>);
2143
- /**
2144
- * Applies the snapshot to the synth
2145
- */
2146
- applySynthesizerSnapshot(snapshot: SynthesizerSnapshot): void;
2147
- /**
2148
- * Gets a synthesizer snapshot from this processor instance.
2149
- */
2150
- getSnapshot(): SynthesizerSnapshot;
2151
- /**
2152
- * Sets the embedded sound bank.
2153
- * @param bank The sound bank file to set.
2154
- * @param offset The bank offset of the embedded sound bank.
2155
- */
2156
- setEmbeddedSoundBank(bank: ArrayBuffer, offset: number): void;
2157
- clearEmbeddedBank(): void;
2158
- createMIDIChannel(): void;
2223
+ declare class SoundBankManager {
2159
2224
  /**
2160
- * Stops all notes on all channels.
2161
- * @param force if true, all notes are stopped immediately, otherwise they are stopped gracefully.
2225
+ * All the sound banks, ordered from the most important to the least.
2162
2226
  */
2163
- stopAllChannels(force?: boolean): void;
2227
+ soundBankList: SoundBankManagerListEntry[];
2228
+ private readonly presetListChangeCallback;
2229
+ private selectablePresetList;
2164
2230
  /**
2165
- * Renders float32 audio data to stereo outputs; buffer size of 128 is recommended.
2166
- * All float arrays must have the same length.
2167
- * @param outputs output stereo channels (L, R).
2168
- * @param reverb reverb stereo channels (L, R).
2169
- * @param chorus chorus stereo channels (L, R).
2170
- * @param startIndex start offset of the passed arrays, rendering starts at this index, defaults to 0.
2171
- * @param sampleCount the length of the rendered buffer, defaults to float32array length - startOffset.
2231
+ * @param presetListChangeCallback Supplied by the parent synthesizer class,
2232
+ * this is called whenever the preset list changes.
2172
2233
  */
2173
- renderAudio(outputs: Float32Array[], reverb: Float32Array[], chorus: Float32Array[], startIndex?: number, sampleCount?: number): void;
2234
+ constructor(presetListChangeCallback: () => unknown);
2235
+ private _presetList;
2174
2236
  /**
2175
- * Renders the float32 audio data of each channel; buffer size of 128 is recommended.
2176
- * All float arrays must have the same length.
2177
- * @param reverbChannels reverb stereo channels (L, R).
2178
- * @param chorusChannels chorus stereo channels (L, R).
2179
- * @param separateChannels a total of 16 stereo pairs (L, R) for each MIDI channel.
2180
- * @param startIndex start offset of the passed arrays, rendering starts at this index, defaults to 0.
2181
- * @param sampleCount the length of the rendered buffer, defaults to float32array length - startOffset.
2237
+ * The list of all presets in the sound bank stack.
2182
2238
  */
2183
- renderAudioSplit(reverbChannels: Float32Array[], chorusChannels: Float32Array[], separateChannels: Float32Array[][], startIndex?: number, sampleCount?: number): void;
2239
+ get presetList(): PresetListEntry[];
2184
2240
  /**
2185
- * Destroy the synthesizer processor, clearing all channels and voices.
2186
- * This is irreversible, so use with caution.
2241
+ * The current sound bank priority order.
2242
+ * @returns The IDs of the sound banks in the current order.
2187
2243
  */
2188
- destroySynthProcessor(): void;
2244
+ get priorityOrder(): string[];
2189
2245
  /**
2190
- * Executes a MIDI controller change message on the specified channel.
2191
- * @param channel The MIDI channel to change the controller on.
2192
- * @param controllerNumber The MIDI controller number to change.
2193
- * @param controllerValue The value to set the controller to.
2246
+ * The current sound bank priority order.
2247
+ * @param newList The new order of sound bank IDs.
2194
2248
  */
2195
- controllerChange(channel: number, controllerNumber: MIDIController, controllerValue: number): void;
2249
+ set priorityOrder(newList: string[]);
2196
2250
  /**
2197
- * Executes a MIDI Note-on message on the specified channel.
2198
- * @param channel The MIDI channel to send the note on.
2199
- * @param midiNote The MIDI note number to play.
2200
- * @param velocity The velocity of the note, from 0 to 127.
2201
- * @remarks
2202
- * If the velocity is 0, it will be treated as a Note-off message.
2251
+ * Deletes a given sound bank by its ID.
2252
+ * @param id the ID of the sound bank to delete.
2203
2253
  */
2204
- noteOn(channel: number, midiNote: number, velocity: number): void;
2254
+ deleteSoundBank(id: string): void;
2205
2255
  /**
2206
- * Executes a MIDI Note-off message on the specified channel.
2207
- * @param channel The MIDI channel to send the note off.
2208
- * @param midiNote The MIDI note number to stop playing.
2256
+ * Adds a new sound bank with a given ID, or replaces an existing one.
2257
+ * @param font the sound bank to add.
2258
+ * @param id the ID of the sound bank.
2259
+ * @param bankOffset the bank offset of the sound bank.
2209
2260
  */
2210
- noteOff(channel: number, midiNote: number): void;
2261
+ addSoundBank(font: BasicSoundBank, id: string, bankOffset?: number): void;
2211
2262
  /**
2212
- * Executes a MIDI Poly Pressure (Aftertouch) message on the specified channel.
2213
- * @param channel The MIDI channel to send the poly pressure on.
2214
- * @param midiNote The MIDI note number to apply the pressure to.
2215
- * @param pressure The pressure value, from 0 to 127.
2263
+ * Gets a given preset from the sound bank stack.
2264
+ * @param patch The MIDI patch to search for.
2265
+ * @param system The MIDI system to select the preset for.
2266
+ * @returns An object containing the preset and its bank offset.
2216
2267
  */
2217
- polyPressure(channel: number, midiNote: number, pressure: number): void;
2268
+ getPreset(patch: MIDIPatch, system: SynthSystem): BasicPreset | undefined;
2269
+ destroy(): void;
2270
+ private generatePresetList;
2271
+ }
2272
+
2273
+ /**
2274
+ * Reset all controllers for channel.
2275
+ * This will reset all controllers to their default values,
2276
+ * except for the locked controllers.
2277
+ */
2278
+ declare function resetControllers(this: MIDIChannel, sendCCEvents?: boolean): void;
2279
+ declare function resetPreset(this: MIDIChannel): void;
2280
+ /**
2281
+ * https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf
2282
+ * Reset controllers according to RP-15 Recommended Practice.
2283
+ */
2284
+ declare function resetControllersRP15Compliant(this: MIDIChannel): void;
2285
+ /**
2286
+ * Reset all parameters to their default values.
2287
+ * This includes NRPN and RPN controllers, data entry state,
2288
+ * and generator overrides and offsets.
2289
+ */
2290
+ declare function resetParameters(this: MIDIChannel): void;
2291
+
2292
+ /**
2293
+ * Executes a data entry fine (LSB) change for the current channel.
2294
+ * @param dataValue The value to set for the data entry fine controller (0-127).
2295
+ */
2296
+ declare function dataEntryFine(this: MIDIChannel, dataValue: number): void;
2297
+
2298
+ /**
2299
+ * Handles MIDI controller changes for a channel.
2300
+ * @param controllerNumber The MIDI controller number (0-127).
2301
+ * @param controllerValue The value of the controller (0-127).
2302
+ * @param sendEvent If an event should be emitted.
2303
+ * @remarks
2304
+ * This function processes MIDI controller changes, updating the channel's
2305
+ * midiControllers table and handling special cases like bank select,
2306
+ * data entry, and sustain pedal. It also computes modulators for all voices
2307
+ * in the channel based on the controller change.
2308
+ * If the controller number is greater than 127, it is treated as a channel
2309
+ * configuration controller, and the `force` parameter must be set to true
2310
+ * to allow changes.
2311
+ */
2312
+ declare function controllerChange(this: MIDIChannel, controllerNumber: MIDIController, controllerValue: number, sendEvent?: boolean): void;
2313
+
2314
+ /**
2315
+ * Executes a data entry coarse (MSB) change for the current channel.
2316
+ * @param dataValue The value to set for the data entry coarse controller (0-127).
2317
+ */
2318
+ declare function dataEntryCoarse(this: MIDIChannel, dataValue: number): void;
2319
+
2320
+ /**
2321
+ * Sends a "MIDI Note on" message and starts a note.
2322
+ * @param midiNote The MIDI note number (0-127).
2323
+ * @param velocity The velocity of the note (0-127). If less than 1, it will send a note off instead.
2324
+ */
2325
+ declare function noteOn(this: MIDIChannel, midiNote: number, velocity: number): void;
2326
+
2327
+ /**
2328
+ * Releases a note by its MIDI note number.
2329
+ * If the note is in high performance mode and the channel is not a drum channel,
2330
+ * it kills the note instead of releasing it.
2331
+ * @param midiNote The MIDI note number to release (0-127).
2332
+ */
2333
+ declare function noteOff(this: MIDIChannel, midiNote: number): void;
2334
+
2335
+ /**
2336
+ * Changes the program (preset) of the channel.
2337
+ * @param program The program number (0-127) to change to.
2338
+ */
2339
+ declare function programChange(this: MIDIChannel, program: number): void;
2340
+
2341
+ /**
2342
+ * A class for dynamic modulators
2343
+ * that are assigned for more complex system exclusive messages
2344
+ */
2345
+ declare class DynamicModulatorSystem {
2218
2346
  /**
2219
- * Executes a MIDI Channel Pressure (Aftertouch) message on the specified channel.
2220
- * @param channel The MIDI channel to send the channel pressure on.
2221
- * @param pressure The pressure value, from 0 to 127.
2347
+ * The current dynamic modulator list.
2222
2348
  */
2223
- channelPressure(channel: number, pressure: number): void;
2349
+ modulatorList: {
2350
+ mod: Modulator;
2351
+ id: string;
2352
+ }[];
2353
+ resetModulators(): void;
2224
2354
  /**
2225
- * Executes a MIDI Pitch Wheel message on the specified channel.
2226
- * @param channel The MIDI channel to send the pitch wheel on.
2227
- * @param pitch The new pitch value: 0-16384
2355
+ * @param source Like in midiControllers: values below NON_CC_INDEX_OFFSET are CCs,
2356
+ * above are regular modulator sources.
2357
+ * @param destination The generator type to modulate.
2358
+ * @param amount The amount of modulation to apply.
2359
+ * @param isBipolar If true, the modulation is bipolar (ranges from -1 to 1 instead of from 0 to 1).
2360
+ * @param isNegative If true, the modulation is negative (goes from 1 to 0 instead of from 0 to 1).
2228
2361
  */
2229
- pitchWheel(channel: number, pitch: number): void;
2362
+ setModulator(source: ModulatorSourceEnum, destination: GeneratorType, amount: number, isBipolar?: boolean, isNegative?: boolean): void;
2363
+ private getModulatorID;
2364
+ private deleteModulator;
2365
+ }
2366
+
2367
+ /**
2368
+ * Sets a master parameter of the synthesizer.
2369
+ * @param parameter The type of the master parameter to set.
2370
+ * @param value The value to set for the master parameter.
2371
+ */
2372
+ declare function setMasterParameterInternal<P extends keyof MasterParameterType>(this: SynthesizerCore, parameter: P, value: MasterParameterType[P]): void;
2373
+ /**
2374
+ * Gets a master parameter of the synthesizer.
2375
+ * @param type The type of the master parameter to get.
2376
+ * @returns The value of the master parameter.
2377
+ */
2378
+ declare function getMasterParameterInternal<P extends keyof MasterParameterType>(this: SynthesizerCore, type: P): MasterParameterType[P];
2379
+ /**
2380
+ * Gets all master parameters of the synthesizer.
2381
+ * @returns All the master parameters.
2382
+ */
2383
+ declare function getAllMasterParametersInternal(this: SynthesizerCore): MasterParameterType;
2384
+
2385
+ type SysExAcceptedArray = number[] | IndexedByteArray | Uint8Array | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Uint8ClampedArray | Float32Array | Float64Array;
2386
+
2387
+ /**
2388
+ * Executes a system exclusive message for the synthesizer.
2389
+ * @param syx The system exclusive message as an array of bytes.
2390
+ * @param channelOffset The channel offset to apply (default is 0).
2391
+ * @remarks
2392
+ * This is a rather extensive method that handles various system exclusive messages,
2393
+ * including Roland GS, MIDI Tuning Standard, and other non-realtime messages.
2394
+ */
2395
+ declare function systemExclusiveInternal(this: SynthesizerCore, syx: SysExAcceptedArray, channelOffset: number): void;
2396
+
2397
+ /**
2398
+ * The core synthesis engine which interacts with channels and holds all the synth parameters.
2399
+ */
2400
+ declare class SynthesizerCore {
2230
2401
  /**
2231
- * Executes a MIDI Program Change message on the specified channel.
2232
- * @param channel The MIDI channel to send the program change on.
2233
- * @param programNumber The program number to change to, from 0 to 127.
2402
+ * Voices of this synthesizer, as a fixed voice pool.
2234
2403
  */
2235
- programChange(channel: number, programNumber: number): void;
2404
+ readonly voices: Voice[];
2236
2405
  /**
2237
- * Processes a raw MIDI message.
2238
- * @param message The message to process.
2239
- * @param channelOffset The channel offset for the message.
2240
- * @param force If true, forces the message to be processed.
2241
- * @param options Additional options for scheduling the message.
2406
+ * All MIDI channels of the synthesizer.
2242
2407
  */
2243
- processMessage(message: Uint8Array | number[], channelOffset?: number, force?: boolean, options?: SynthMethodOptions): void;
2244
- clearCache(): void;
2408
+ midiChannels: MIDIChannel[];
2245
2409
  /**
2246
- * @param volume {number} 0 to 1
2410
+ * The sound bank manager, which manages all sound banks and presets.
2247
2411
  */
2248
- protected setMIDIVolume(volume: number): void;
2412
+ soundBankManager: SoundBankManager;
2249
2413
  /**
2250
- * Sets the synth's primary tuning.
2251
- * @param cents
2414
+ * Handles the custom key overrides: velocity and preset
2252
2415
  */
2253
- protected setMasterTuning(cents: number): void;
2416
+ keyModifierManager: KeyModifierManager;
2417
+ readonly sampleRate: number;
2254
2418
  /**
2255
- * Calls synth event
2256
- * @param eventName the event name
2257
- * @param eventData the event data
2419
+ * This.tunings[program * 128 + key] = midiNote,cents (fraction)
2420
+ * All MIDI Tuning Standard tunings, 128 keys for each of 128 programs.
2421
+ * -1 means no change.
2258
2422
  */
2259
- protected callEvent<K extends keyof SynthProcessorEventData>(eventName: K, eventData: SynthProcessorEventData[K]): void;
2260
- protected getCachedVoice(patch: MIDIPatch, midiNote: number, velocity: number): VoiceList | undefined;
2261
- protected setCachedVoice(patch: MIDIPatch, midiNote: number, velocity: number, voices: VoiceList): void;
2262
- private getCachedVoiceIndex;
2263
- private createMIDIChannelInternal;
2264
- private updatePresetList;
2265
- private getDefaultPresets;
2266
- }
2267
-
2268
- declare class LowpassFilter {
2423
+ readonly tunings: Float32Array<ArrayBuffer>;
2269
2424
  /**
2270
- * Cached coefficient calculations.
2271
- * stored as cachedCoefficients[resonanceCb][currentInitialFc].
2425
+ * The master parameters of the synthesizer.
2272
2426
  */
2273
- private static cachedCoefficients;
2427
+ masterParameters: MasterParameterType;
2274
2428
  /**
2275
- * Resonance in centibels.
2429
+ * The current time of the synthesizer, in seconds.
2276
2430
  */
2277
- resonanceCb: number;
2431
+ currentTime: number;
2278
2432
  /**
2279
- * Current cutoff frequency in absolute cents.
2433
+ * The volume gain, set by MIDI sysEx
2280
2434
  */
2281
- currentInitialFc: number;
2435
+ midiVolume: number;
2282
2436
  /**
2283
- * Filter coefficient 1.
2437
+ * Set via system exclusive.
2438
+ * Note: Remember to reset in system reset!
2284
2439
  */
2285
- private a0;
2440
+ reverbSend: number;
2286
2441
  /**
2287
- * Filter coefficient 2.
2442
+ * Are the chorus and reverb effects enabled?
2288
2443
  */
2289
- private a1;
2444
+ enableEffects: boolean;
2290
2445
  /**
2291
- * Filter coefficient 3.
2446
+ * Is the event system enabled?
2292
2447
  */
2293
- private a2;
2448
+ enableEventSystem: boolean;
2294
2449
  /**
2295
- * Filter coefficient 4.
2450
+ * Set via system exclusive.
2451
+ * Note: Remember to reset in system reset!
2296
2452
  */
2297
- private a3;
2453
+ chorusSend: number;
2298
2454
  /**
2299
- * Filter coefficient 5.
2455
+ * The pan of the left channel.
2300
2456
  */
2301
- private a4;
2457
+ panLeft: number;
2302
2458
  /**
2303
- * Input history 1.
2459
+ * The pan of the right channel.
2304
2460
  */
2305
- private x1;
2461
+ panRight: number;
2306
2462
  /**
2307
- * Input history 2.
2463
+ * Synth's default (reset) preset.
2308
2464
  */
2309
- private x2;
2465
+ defaultPreset: BasicPreset | undefined;
2310
2466
  /**
2311
- * Output history 1.
2467
+ * Synth's default (reset) drum preset.
2312
2468
  */
2313
- private y1;
2469
+ drumPreset: BasicPreset | undefined;
2314
2470
  /**
2315
- * Output history 2.
2471
+ * Gain smoothing factor, adjusted to the sample rate.
2316
2472
  */
2317
- private y2;
2473
+ readonly gainSmoothingFactor: number;
2318
2474
  /**
2319
- * For tracking the last cutoff frequency in the apply method, absolute cents.
2320
- * Set to infinity to force recalculation.
2475
+ * Pan smoothing factor, adjusted to the sample rate.
2321
2476
  */
2322
- private lastTargetCutoff;
2477
+ readonly panSmoothingFactor: number;
2323
2478
  /**
2324
- * Used for tracking if the filter has been initialized.
2479
+ * Calls when an event occurs.
2480
+ * @param eventType The event type.
2481
+ * @param eventData The event data.
2325
2482
  */
2326
- private initialized;
2483
+ eventCallbackHandler: <K extends keyof SynthProcessorEventData>(eventType: K, eventData: SynthProcessorEventData[K]) => unknown;
2484
+ readonly missingPresetHandler: (patch: MIDIPatch, system: SynthSystem) => undefined | BasicPreset;
2327
2485
  /**
2328
- * Filter's sample rate in Hz.
2486
+ * Cached voices for all presets for this synthesizer.
2487
+ * Nesting is calculated in getCachedVoiceIndex, returns a list of voices for this note.
2329
2488
  */
2330
- private sampleRate;
2489
+ readonly cachedVoices: Map<number, CachedVoiceList>;
2331
2490
  /**
2332
- * Maximum cutoff frequency in Hz.
2333
- * This is used to prevent aliasing and ensure the filter operates within the valid frequency range.
2491
+ * Sets a master parameter of the synthesizer.
2492
+ * @param type The type of the master parameter to set.
2493
+ * @param value The value to set for the master parameter.
2334
2494
  */
2335
- private maxCutoff;
2495
+ readonly setMasterParameter: typeof setMasterParameterInternal;
2336
2496
  /**
2337
- * Initializes a new instance of the filter.
2338
- * @param sampleRate the sample rate of the audio engine in Hz.
2497
+ * Gets a master parameter of the synthesizer.
2498
+ * @param type The type of the master parameter to get.
2499
+ * @returns The value of the master parameter.
2339
2500
  */
2340
- constructor(sampleRate: number);
2501
+ readonly getMasterParameter: typeof getMasterParameterInternal;
2341
2502
  /**
2342
- * Applies the lowpass filter to the output buffer of a voice.
2343
- * @param voice The voice to apply the filter to.
2344
- * @param outputBuffer The output buffer to filter.
2345
- * @param fcExcursion The frequency excursion in cents to apply to the filter.
2346
- * @param smoothingFactor The smoothing factor for the filter as determined by the parent synthesizer.
2503
+ * Gets all master parameters of the synthesizer.
2504
+ * @returns All the master parameters.
2347
2505
  */
2348
- static apply(voice: Voice, outputBuffer: Float32Array, fcExcursion: number, smoothingFactor: number): void;
2506
+ readonly getAllMasterParameters: typeof getAllMasterParametersInternal;
2507
+ readonly systemExclusive: typeof systemExclusiveInternal;
2349
2508
  /**
2350
- * Calculates the filter coefficients based on the current resonance and cutoff frequency and caches them.
2351
- * @param filter The lowpass filter instance to calculate coefficients for.
2352
- * @param cutoffCents The cutoff frequency in cents.
2509
+ * Current total amount of voices that are currently playing.
2353
2510
  */
2354
- static calculateCoefficients(filter: LowpassFilter, cutoffCents: number): void;
2355
- }
2356
-
2357
- /**
2358
- * VOL ENV STATES:
2359
- * 0 - delay
2360
- * 1 - attack
2361
- * 2 - hold/peak
2362
- * 3 - decay
2363
- * 4 - sustain
2364
- * release indicates by isInRelease property
2365
- */
2366
- type VolumeEnvelopeState = 0 | 1 | 2 | 3 | 4;
2367
- declare class VolumeEnvelope {
2511
+ voiceCount: number;
2368
2512
  /**
2369
- * The sample rate in Hz.
2513
+ * Last time the priorities were assigned.
2514
+ * Used to prevent assigning priorities multiple times when more than one voice is triggered during a quantum.
2370
2515
  */
2371
- sampleRate: number;
2516
+ private lastPriorityAssignmentTime;
2372
2517
  /**
2373
- * The current attenuation of the envelope in dB.
2518
+ * Synth's event queue from the main thread
2374
2519
  */
2375
- currentAttenuationDb: number;
2520
+ private eventQueue;
2376
2521
  /**
2377
- * The current stage of the volume envelope.
2522
+ * The time of a single sample, in seconds.
2378
2523
  */
2379
- state: VolumeEnvelopeState;
2524
+ private readonly sampleTime;
2525
+ constructor(eventCallbackHandler: <K extends keyof SynthProcessorEventData>(eventType: K, eventData: SynthProcessorEventData[K]) => unknown, missingPresetHandler: (patch: MIDIPatch, system: SynthSystem) => BasicPreset | undefined, sampleRate: number, options: SynthProcessorOptions);
2380
2526
  /**
2381
- * The voice's absolute attenuation as linear gain.
2527
+ * Assigns the first available voice for use.
2528
+ * If none available, will assign priorities.
2382
2529
  */
2383
- attenuation: number;
2530
+ assignVoice(): Voice;
2384
2531
  /**
2385
- * The attenuation target, which the "attenuation" property is linearly interpolated towards (gain).
2532
+ * Stops all notes on all channels.
2533
+ * @param force if true, all notes are stopped immediately, otherwise they are stopped gracefully.
2386
2534
  */
2387
- attenuationTargetGain: number;
2535
+ stopAllChannels(force: boolean): void;
2388
2536
  /**
2389
- * The envelope's current time in samples.
2537
+ * Processes a raw MIDI message.
2538
+ * @param message The message to process.
2539
+ * @param channelOffset The channel offset for the message.
2540
+ * @param force If true, forces the message to be processed.
2541
+ * @param options Additional options for scheduling the message.
2390
2542
  */
2391
- protected currentSampleTime: number;
2543
+ processMessage(message: Uint8Array | number[], channelOffset: number, force: boolean, options: SynthMethodOptions): void;
2544
+ destroySynthProcessor(): void;
2392
2545
  /**
2393
- * The dB attenuation of the envelope when it entered the release stage.
2546
+ * @param channel channel to get voices for
2547
+ * @param midiNote the MIDI note to use
2548
+ * @param velocity the velocity to use
2549
+ * @returns output is an array of Voices
2394
2550
  */
2395
- protected releaseStartDb: number;
2551
+ getVoices(channel: number, midiNote: number, velocity: number): CachedVoiceList;
2552
+ createMIDIChannel(sendEvent: boolean): void;
2396
2553
  /**
2397
- * The time in samples relative to the start of the envelope.
2554
+ * Executes a full system reset of all controllers.
2555
+ * This will reset all controllers to their default values,
2556
+ * except for the locked controllers.
2398
2557
  */
2399
- protected releaseStartTimeSamples: number;
2558
+ resetAllControllers(system?: SynthSystem): void;
2559
+ renderAudio(outputs: Float32Array[], reverb: Float32Array[], chorus: Float32Array[], startIndex?: number, sampleCount?: number): void;
2400
2560
  /**
2401
- * The current gain applied to the voice in the release stage.
2561
+ * Renders the float32 audio data of each channel; buffer size of 128 is recommended.
2562
+ * All float arrays must have the same length.
2563
+ * @param reverb reverb stereo channels (L, R).
2564
+ * @param chorus chorus stereo channels (L, R).
2565
+ * @param separate a total of 16 stereo pairs (L, R) for each MIDI channel.
2566
+ * @param startIndex start offset of the passed arrays, rendering starts at this index, defaults to 0.
2567
+ * @param sampleCount the length of the rendered buffer, defaults to float32array length - startOffset.
2402
2568
  */
2403
- protected currentReleaseGain: number;
2569
+ renderAudioSplit(reverb: Float32Array[], chorus: Float32Array[], separate: Float32Array[][], startIndex?: number, sampleCount?: number): void;
2404
2570
  /**
2405
- * The attack duration in samples.
2571
+ * Gets voices for a preset.
2572
+ * @param preset The preset to get voices for.
2573
+ * @param midiNote The MIDI note to use.
2574
+ * @param velocity The velocity to use.
2575
+ * @returns Output is an array of voices.
2406
2576
  */
2407
- protected attackDuration: number;
2577
+ getVoicesForPreset(preset: BasicPreset, midiNote: number, velocity: number): CachedVoiceList;
2578
+ clearCache(): void;
2408
2579
  /**
2409
- * The decay duration in samples.
2580
+ * Copied callback so MIDI channels can call it.
2410
2581
  */
2411
- protected decayDuration: number;
2582
+ callEvent<K extends keyof SynthProcessorEventData>(eventName: K, eventData: SynthProcessorEventData[K]): void;
2412
2583
  /**
2413
- * The release duration in samples.
2584
+ * @param volume {number} 0 to 1
2414
2585
  */
2415
- protected releaseDuration: number;
2586
+ protected setMIDIVolume(volume: number): void;
2416
2587
  /**
2417
- * The attenuation target, which the "attenuation" property is linearly interpolated towards (dB).
2588
+ * Sets the synth's primary tuning.
2589
+ * @param cents
2418
2590
  */
2419
- protected attenuationTarget: number;
2591
+ protected setMasterTuning(cents: number): void;
2592
+ protected getCachedVoice(patch: MIDIPatch, midiNote: number, velocity: number): CachedVoiceList | undefined;
2593
+ protected setCachedVoice(patch: MIDIPatch, midiNote: number, velocity: number, voices: CachedVoiceList): void;
2420
2594
  /**
2421
- * The voice's sustain amount in dB, relative to attenuation.
2595
+ * Assigns priorities to the voices.
2596
+ * Gets the priority of a voice based on its channel and state.
2597
+ * Higher priority means the voice is more important and should be kept longer.
2422
2598
  */
2423
- protected sustainDbRelative: number;
2599
+ private assignVoicePriorities;
2600
+ private updatePresetList;
2601
+ private getDefaultPresets;
2602
+ private getCachedVoiceIndex;
2603
+ }
2604
+
2605
+ /**
2606
+ * This class represents a single MIDI Channel within the synthesizer.
2607
+ */
2608
+ declare class MIDIChannel {
2609
+ readonly midiControllers: Int16Array;
2424
2610
  /**
2425
- * The time in samples to the end of delay stage, relative to the start of the envelope.
2611
+ * An array for the MIDI 2.0 Per-note pitch wheels.
2426
2612
  */
2427
- protected delayEnd: number;
2613
+ readonly pitchWheels: Int16Array<ArrayBuffer>;
2428
2614
  /**
2429
- * The time in samples to the end of attack stage, relative to the start of the envelope.
2615
+ * An array indicating if a controller, at the equivalent index in the midiControllers array, is locked
2616
+ * (i.e., not allowed changing).
2617
+ * A locked controller cannot be modified.
2430
2618
  */
2431
- protected attackEnd: number;
2619
+ lockedControllers: boolean[];
2432
2620
  /**
2433
- * The time in samples to the end of hold stage, relative to the start of the envelope.
2621
+ * An array of custom (non-SF2) control values such as RPN pitch tuning, transpose, modulation depth, etc.
2622
+ * Refer to controller_tables.ts for the index definitions.
2434
2623
  */
2435
- protected holdEnd: number;
2624
+ readonly customControllers: Float32Array;
2436
2625
  /**
2437
- * The time in samples to the end of decay stage, relative to the start of the envelope.
2626
+ * The key shift of the channel (in semitones).
2438
2627
  */
2439
- protected decayEnd: number;
2628
+ channelTransposeKeyShift: number;
2440
2629
  /**
2441
- * If sustain stage is silent,
2442
- * then we can turn off the voice when it is silent.
2443
- * We can't do that with modulated as it can silence the volume and then raise it again, and the voice must keep playing.
2630
+ * An array of octave tuning values for each note on the channel.
2631
+ * Each index corresponds to a note (0 = C, 1 = C#, ..., 11 = B).
2632
+ * Note: Repeated every 12 notes.
2444
2633
  */
2445
- protected canEndOnSilentSustain: boolean;
2634
+ channelOctaveTuning: Int8Array;
2446
2635
  /**
2447
- * @param sampleRate Hz
2448
- * @param initialDecay cb
2636
+ * A system for dynamic modulator assignment for advanced system exclusives.
2449
2637
  */
2450
- constructor(sampleRate: number, initialDecay: number);
2638
+ sysExModulators: DynamicModulatorSystem;
2451
2639
  /**
2452
- * Starts the release phase in the envelope.
2453
- * @param voice the voice this envelope belongs to.
2640
+ * Indicates whether this channel is a drum channel.
2454
2641
  */
2455
- static startRelease(voice: Voice): void;
2642
+ drumChannel: boolean;
2456
2643
  /**
2457
- * Recalculates the envelope
2458
- * @param voice the voice this envelope belongs to
2644
+ * Enables random panning for every note played on this channel.
2459
2645
  */
2460
- static recalculate(voice: Voice): void;
2646
+ randomPan: boolean;
2461
2647
  /**
2462
- * Applies volume envelope gain to the given output buffer.
2463
- * Essentially we use approach of 100dB is silence, 0dB is peak, and always add attenuation to that (which is interpolated).
2464
- * @param voice the voice we're working on
2465
- * @param audioBuffer the audio buffer to modify
2466
- * @param centibelOffset the centibel offset of volume, for modLFOtoVolume
2467
- * @param smoothingFactor the adjusted smoothing factor for the envelope
2648
+ * The current state of the data entry for the channel.
2468
2649
  */
2469
- static apply(voice: Voice, audioBuffer: Float32Array, centibelOffset: number, smoothingFactor: number): void;
2470
- }
2471
-
2472
- declare class ModulationEnvelope {
2650
+ dataEntryState: DataEntryState;
2473
2651
  /**
2474
- * The attack duration, in seconds.
2652
+ * The currently selected MIDI patch of the channel.
2653
+ * Note that the exact matching preset may not be available, but this represents exactly what MIDI asks for.
2475
2654
  */
2476
- protected attackDuration: number;
2655
+ readonly patch: MIDIPatch;
2477
2656
  /**
2478
- * The decay duration, in seconds.
2657
+ * The preset currently assigned to the channel.
2658
+ * Note that this may be undefined in some cases
2659
+ * https://github.com/spessasus/spessasynth_core/issues/48
2479
2660
  */
2480
- protected decayDuration: number;
2661
+ preset?: BasicPreset;
2481
2662
  /**
2482
- * The hold duration, in seconds.
2663
+ * Indicates whether the program on this channel is locked.
2483
2664
  */
2484
- protected holdDuration: number;
2665
+ lockPreset: boolean;
2485
2666
  /**
2486
- * Release duration, in seconds.
2667
+ * Indicates the MIDI system when the preset was locked.
2487
2668
  */
2488
- protected releaseDuration: number;
2669
+ lockedSystem: SynthSystem;
2489
2670
  /**
2490
- * The sustain level 0-1.
2671
+ * Indicates whether the GS NRPN parameters are enabled for this channel.
2491
2672
  */
2492
- protected sustainLevel: number;
2673
+ lockGSNRPNParams: boolean;
2493
2674
  /**
2494
- * Delay phase end time in seconds, absolute (audio context time).
2675
+ * The vibrato settings for the channel.
2676
+ * @property depth - Depth of the vibrato effect in cents.
2677
+ * @property delay - Delay before the vibrato effect starts (in seconds).
2678
+ * @property rate - Rate of the vibrato oscillation (in Hz).
2495
2679
  */
2496
- protected delayEnd: number;
2680
+ channelVibrato: {
2681
+ delay: number;
2682
+ depth: number;
2683
+ rate: number;
2684
+ };
2497
2685
  /**
2498
- * Attack phase end time in seconds, absolute (audio context time).
2686
+ * If the channel is in the poly mode.
2687
+ * True - POLY ON - regular playback.
2688
+ * False - MONO ON - one note per channel, others are killed on note-on
2499
2689
  */
2500
- protected attackEnd: number;
2690
+ polyMode: boolean;
2501
2691
  /**
2502
- * Hold phase end time in seconds, absolute (audio context time).
2692
+ * Channel's current voice count
2503
2693
  */
2504
- protected holdEnd: number;
2694
+ voiceCount: number;
2505
2695
  /**
2506
- * Decay phase end time in seconds, absolute (audio context time).
2696
+ * The channel's number (0-based index)
2507
2697
  */
2508
- protected decayEnd: number;
2698
+ readonly channel: number;
2509
2699
  /**
2510
- * The level of the envelope when the release phase starts.
2700
+ * Core synthesis engine.
2511
2701
  */
2512
- protected releaseStartLevel: number;
2702
+ synthCore: SynthesizerCore;
2513
2703
  /**
2514
- * The current modulation envelope value.
2704
+ * Sends a "MIDI Note on" message and starts a note.
2705
+ * @param midiNote The MIDI note number (0-127).
2706
+ * @param velocity The velocity of the note (0-127). If less than 1, it will send a note off instead.
2515
2707
  */
2516
- protected currentValue: number;
2708
+ noteOn: typeof noteOn;
2517
2709
  /**
2518
- * Starts the release phase in the envelope.
2519
- * @param voice the voice this envelope belongs to.
2710
+ * Releases a note by its MIDI note number.
2711
+ * If the note is in high performance mode and the channel is not a drum channel,
2712
+ * it kills the note instead of releasing it.
2713
+ * @param midiNote The MIDI note number to release (0-127).
2520
2714
  */
2521
- static startRelease(voice: Voice): void;
2715
+ noteOff: typeof noteOff;
2522
2716
  /**
2523
- * @param voice the voice to recalculate.
2717
+ * Changes the program (preset) of the channel.
2718
+ * @param programNumber The program number (0-127) to change to.
2524
2719
  */
2525
- static recalculate(voice: Voice): void;
2720
+ programChange: typeof programChange;
2721
+ controllerChange: typeof controllerChange;
2526
2722
  /**
2527
- * Calculates the current modulation envelope value for the given time and voice.
2528
- * @param voice the voice we are working on.
2529
- * @param currentTime in seconds.
2530
- * @param ignoreRelease if true, it will compute the value as if the voice was not released.
2531
- * @returns mod env value, from 0 to 1.
2723
+ * Reset all controllers for channel.
2724
+ * This will reset all controllers to their default values,
2725
+ * except for the locked controllers.
2532
2726
  */
2533
- static getValue(voice: Voice, currentTime: number, ignoreRelease?: boolean): number;
2534
- }
2535
-
2536
- declare class AudioSample {
2727
+ readonly resetControllers: typeof resetControllers;
2728
+ readonly resetPreset: typeof resetPreset;
2537
2729
  /**
2538
- * The sample's audio data
2730
+ * https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf
2731
+ * Reset controllers according to RP-15 Recommended Practice.
2539
2732
  */
2540
- readonly sampleData: Float32Array;
2733
+ readonly resetControllersRP15Compliant: typeof resetControllersRP15Compliant;
2541
2734
  /**
2542
- * Current playback step (rate)
2735
+ * Reset all parameters to their default values.
2736
+ * This includes NRPN and RPN controllers, data entry state,
2737
+ * and generator overrides and offsets.
2543
2738
  */
2544
- readonly playbackStep: number;
2739
+ resetParameters: typeof resetParameters;
2545
2740
  /**
2546
- * Current position in the sample
2741
+ * Executes a data entry fine (LSB) change for the current channel.
2742
+ * @param dataValue The value to set for the data entry fine controller (0-127).
2547
2743
  */
2548
- cursor: number;
2744
+ dataEntryFine: typeof dataEntryFine;
2549
2745
  /**
2550
- * MIDI root key of the sample
2746
+ * Executes a data entry coarse (MSB) change for the current channel.
2747
+ * @param dataValue The value to set for the data entry coarse controller (0-127).
2551
2748
  */
2552
- readonly rootKey: number;
2749
+ dataEntryCoarse: typeof dataEntryCoarse;
2750
+ readonly renderVoice: (voice: Voice, timeNow: number, outputL: Float32Array<ArrayBufferLike>, outputR: Float32Array<ArrayBufferLike>, reverbL: Float32Array<ArrayBufferLike>, reverbR: Float32Array<ArrayBufferLike>, chorusL: Float32Array<ArrayBufferLike>, chorusR: Float32Array<ArrayBufferLike>, startIndex: number, sampleCount: number) => void;
2553
2751
  /**
2554
- * Start position of the loop
2752
+ * Per-note pitch wheel mode uses the pitchWheels table as source
2753
+ * instead of the regular entry in the midiControllers table.
2555
2754
  */
2556
- loopStart: number;
2755
+ protected perNotePitch: boolean;
2557
2756
  /**
2558
- * End position of the loop
2757
+ * Will be updated every time something tuning-related gets changed.
2758
+ * This is used to avoid a big addition for every voice rendering call.
2559
2759
  */
2560
- loopEnd: number;
2760
+ protected channelTuningCents: number;
2561
2761
  /**
2562
- * End position of the sample
2762
+ * An array of offsets generators for SF2 nrpn support.
2763
+ * A value of 0 means no change; -10 means 10 lower, etc.
2563
2764
  */
2564
- end: number;
2765
+ protected generatorOffsets: Int16Array;
2565
2766
  /**
2566
- * Looping mode of the sample:
2567
- * 0 - no loop
2568
- * 1 - loop
2569
- * 2 - UNOFFICIAL: polyphone 2.4 added start on release
2570
- * 3 - loop then play when released
2767
+ * A small optimization that disables applying offsets until at least one is set.
2571
2768
  */
2572
- loopingMode: SampleLoopingMode;
2769
+ protected generatorOffsetsEnabled: boolean;
2573
2770
  /**
2574
- * Indicates if the sample is currently looping
2771
+ * An array of override generators for AWE32 support.
2772
+ * A value of 32,767 means unchanged, as it is not allowed anywhere.
2575
2773
  */
2576
- isLooping: boolean;
2774
+ protected generatorOverrides: Int16Array;
2577
2775
  /**
2578
- * @param data
2579
- * @param playbackStep the playback step, a single increment
2580
- * @param cursorStart the sample id which starts the playback
2581
- * @param rootKey MIDI root key
2582
- * @param loopStart loop start index
2583
- * @param loopEnd loop end index
2584
- * @param endIndex sample end index (for end offset)
2585
- * @param loopingMode sample looping mode
2776
+ * A small optimization that disables applying overrides until at least one is set.
2586
2777
  */
2587
- constructor(data: Float32Array, playbackStep: number, cursorStart: number, rootKey: number, loopStart: number, loopEnd: number, endIndex: number, loopingMode: SampleLoopingMode);
2588
- }
2589
-
2590
- /**
2591
- * Voice.ts
2592
- * purpose: prepares Voices from sample and generator data
2593
- */
2594
-
2595
- /**
2596
- * Voice represents a single instance of the
2597
- * SoundFont2 synthesis model.
2598
- * That is:
2599
- * A wavetable oscillator (sample)
2600
- * A volume envelope (volumeEnvelope)
2601
- * A modulation envelope (modulationEnvelope)
2602
- * Generators (generators and modulatedGenerators)
2603
- * Modulators (modulators)
2604
- * And MIDI params such as channel, MIDI note, velocity
2605
- */
2606
- declare class Voice {
2778
+ protected generatorOverridesEnabled: boolean;
2779
+ protected readonly computeModulators: (voice: Voice, sourceUsesCC?: 0 | 1 | -1 | undefined, sourceIndex?: number | undefined) => void;
2607
2780
  /**
2608
- * The sample of the voice.
2781
+ * For tracking voice count changes
2782
+ * @private
2609
2783
  */
2610
- sample: AudioSample;
2784
+ private previousVoiceCount;
2611
2785
  /**
2612
- * Lowpass filter applied to the voice.
2786
+ * Constructs a new MIDI channel.
2613
2787
  */
2614
- filter: LowpassFilter;
2788
+ constructor(synthProps: SynthesizerCore, preset: BasicPreset | undefined, channelNumber: number);
2615
2789
  /**
2616
- * Linear gain of the voice. Used with Key Modifiers.
2790
+ * Indicates whether the channel is muted.
2617
2791
  */
2618
- gain: number;
2792
+ protected _isMuted: boolean;
2619
2793
  /**
2620
- * The unmodulated (copied to) generators of the voice.
2794
+ * Indicates whether the channel is muted.
2621
2795
  */
2622
- generators: Int16Array;
2796
+ get isMuted(): boolean;
2797
+ protected get channelSystem(): SynthSystem;
2798
+ clearVoiceCount(): void;
2799
+ updateVoiceCount(): void;
2623
2800
  /**
2624
- * The voice's modulators.
2801
+ * Transposes the channel by given amount of semitones.
2802
+ * @param semitones The number of semitones to transpose the channel by. Can be decimal.
2803
+ * @param force Defaults to false, if true, it will force the transpose even if the channel is a drum channel.
2625
2804
  */
2626
- modulators: Modulator[];
2805
+ transposeChannel(semitones: number, force?: boolean): void;
2627
2806
  /**
2628
- * Resonance offset, it is affected by the default resonant modulator
2807
+ * Sets the octave tuning for a given channel.
2808
+ * @param tuning The tuning array of 12 values, each representing the tuning for a note in the octave.
2809
+ * @remarks
2810
+ * Cent tunings are relative.
2629
2811
  */
2630
- resonanceOffset: number;
2812
+ setOctaveTuning(tuning: Int8Array): void;
2631
2813
  /**
2632
- * The generators in real-time, affected by modulators.
2633
- * This is used during rendering.
2814
+ * Sets the modulation depth for the channel.
2815
+ * @param cents The modulation depth in cents to set.
2816
+ * @remarks
2817
+ * This method sets the modulation depth for the channel by converting the given cents value into a
2818
+ * multiplier. The MIDI specification assumes the default modulation depth is 50 cents,
2819
+ * but it may vary for different sound banks.
2820
+ * For example, if you want a modulation depth of 100 cents,
2821
+ * the multiplier will be 2,
2822
+ * which, for a preset with a depth of 50,
2823
+ * will create a total modulation depth of 100 cents.
2824
+ *
2634
2825
  */
2635
- modulatedGenerators: Int16Array;
2826
+ setModulationDepth(cents: number): void;
2636
2827
  /**
2637
- * Indicates if the voice is finished.
2828
+ * Sets the channel's tuning.
2829
+ * @param cents The tuning in cents to set.
2830
+ * @param log If true, logs the change to the console.
2638
2831
  */
2639
- finished: boolean;
2832
+ setTuning(cents: number, log?: boolean): void;
2640
2833
  /**
2641
- * Indicates if the voice is in the release phase.
2834
+ * Sets the pitch of the given channel.
2835
+ * @param pitch The pitch (0 - 16384)
2836
+ * @param midiNote The MIDI note number, pass -1 for the regular pitch wheel
2642
2837
  */
2643
- isInRelease: boolean;
2838
+ pitchWheel(pitch: number, midiNote?: number): void;
2644
2839
  /**
2645
- * Velocity of the note.
2840
+ * Sets the channel pressure (MIDI Aftertouch).
2841
+ * @param pressure the pressure of the channel.
2646
2842
  */
2647
- velocity: number;
2843
+ channelPressure(pressure: number): void;
2648
2844
  /**
2649
- * MIDI note number.
2845
+ * Sets the pressure of the given note on a specific channel.
2846
+ * This is used for polyphonic pressure (aftertouch).
2847
+ * @param midiNote 0 - 127, the MIDI note number to set the pressure for.
2848
+ * @param pressure 0 - 127, the pressure value to set for the note.
2650
2849
  */
2651
- midiNote: number;
2850
+ polyPressure(midiNote: number, pressure: number): void;
2851
+ setCustomController(type: CustomController, value: number): void;
2852
+ updateChannelTuning(): void;
2652
2853
  /**
2653
- * The pressure of the voice
2854
+ * Locks or unlocks the preset from MIDI program changes.
2855
+ * @param locked If the preset should be locked.
2654
2856
  */
2655
- pressure: number;
2857
+ setPresetLock(locked: boolean): void;
2656
2858
  /**
2657
- * Target key for the note.
2859
+ * Changes the preset to, or from drums.
2860
+ * Note that this executes a program change.
2861
+ * @param isDrum If the channel should be a drum preset or not.
2658
2862
  */
2659
- targetKey: number;
2863
+ setDrums(isDrum: boolean): void;
2660
2864
  /**
2661
- * Modulation envelope.
2865
+ * Sets the channel to a given MIDI patch.
2866
+ * Note that this executes a program change.
2867
+ * @param patch The MIDI patch to set the channel to.
2662
2868
  */
2663
- modulationEnvelope: ModulationEnvelope;
2869
+ setPatch(patch: MIDIPatch): void;
2664
2870
  /**
2665
- * Volume envelope.
2871
+ * Sets the GM/GS drum flag.
2872
+ * @param drums
2666
2873
  */
2667
- volumeEnvelope: VolumeEnvelope;
2874
+ setGSDrums(drums: boolean): void;
2668
2875
  /**
2669
- * Start time of the voice, absolute.
2876
+ * Sets a custom vibrato.
2877
+ * @param depth In cents.
2878
+ * @param rate In Hertz.
2879
+ * @param delay seconds.
2670
2880
  */
2671
- startTime: number;
2881
+ setVibrato(depth: number, rate: number, delay: number): void;
2672
2882
  /**
2673
- * Start time of the release phase, absolute.
2883
+ * Disables and locks all GS NPRN parameters, including the custom vibrato.
2674
2884
  */
2675
- releaseStartTime: number;
2885
+ disableAndLockGSNRPN(): void;
2886
+ resetGeneratorOverrides(): void;
2887
+ setGeneratorOverride(gen: GeneratorType, value: number, realtime?: boolean): void;
2888
+ resetGeneratorOffsets(): void;
2889
+ setGeneratorOffset(gen: GeneratorType, value: number): void;
2676
2890
  /**
2677
- * Current tuning in cents.
2891
+ * Stops a note nearly instantly.
2892
+ * @param midiNote The note to stop.
2893
+ * @param releaseTime in timecents, defaults to -12000 (very short release).
2678
2894
  */
2679
- currentTuningCents: number;
2895
+ killNote(midiNote: number, releaseTime?: number): void;
2680
2896
  /**
2681
- * Current calculated tuning. (as in ratio)
2897
+ * Stops all notes on the channel.
2898
+ * @param force If true, stops all notes immediately, otherwise applies release time.
2682
2899
  */
2683
- currentTuningCalculated: number;
2900
+ stopAllNotes(force?: boolean): void;
2684
2901
  /**
2685
- * From -500 to 500.
2902
+ * Mutes or unmutes a channel.
2903
+ * @param isMuted If the channel should be muted.
2686
2904
  */
2687
- currentPan: number;
2905
+ muteChannel(isMuted: boolean): void;
2688
2906
  /**
2689
- * If MIDI Tuning Standard is already applied (at note-on time),
2690
- * this will be used to take the values at real-time tuning as "midiNote"
2691
- * property contains the tuned number.
2692
- * see SpessaSynth#29 comment by @paulikaro
2907
+ * Sends this channel's property
2693
2908
  */
2694
- realKey: number;
2909
+ sendChannelProperty(): void;
2910
+ protected computeModulatorsAll(sourceUsesCC: -1 | 0 | 1, sourceIndex: number): void;
2911
+ protected setBankMSB(bankMSB: number): void;
2912
+ protected setBankLSB(bankLSB: number): void;
2695
2913
  /**
2696
- * Initial key to glide from, MIDI Note number. If -1, the portamento is OFF.
2914
+ * Sets drums on channel.
2697
2915
  */
2698
- portamentoFromKey: number;
2916
+ protected setDrumFlag(isDrum: boolean): void;
2917
+ }
2918
+
2919
+ /**
2920
+ * Processor.ts
2921
+ * purpose: the core synthesis engine
2922
+ */
2923
+ declare class SpessaSynthProcessor {
2699
2924
  /**
2700
- * Duration of the linear glide, in seconds.
2925
+ * Controls if the processor is fully initialized.
2701
2926
  */
2702
- portamentoDuration: number;
2927
+ readonly processorInitialized: Promise<boolean>;
2703
2928
  /**
2704
- * From -500 to 500, where zero means disabled (use the channel pan). Used for random pan.
2929
+ * Sample rate in Hertz.
2705
2930
  */
2706
- overridePan: number;
2931
+ readonly sampleRate: number;
2707
2932
  /**
2708
- * Exclusive class number for hi-hats etc.
2933
+ * Calls when an event occurs.
2934
+ * @param event The event that occurred.
2709
2935
  */
2710
- exclusiveClass: number;
2936
+ onEventCall?: (event: SynthProcessorEvent) => unknown;
2711
2937
  /**
2712
- * Creates a Voice.
2938
+ * Renders float32 audio data to stereo outputs; buffer size of 128 is recommended.
2939
+ * All float arrays must have the same length.
2940
+ * @param outputs output stereo channels (L, R).
2941
+ * @param reverb reverb stereo channels (L, R).
2942
+ * @param chorus chorus stereo channels (L, R).
2943
+ * @param startIndex start offset of the passed arrays, rendering starts at this index, defaults to 0.
2944
+ * @param sampleCount the length of the rendered buffer, defaults to float32array length - startOffset.
2713
2945
  */
2714
- constructor(sampleRate: number, audioSample: AudioSample, midiNote: number, velocity: number, currentTime: number, targetKey: number, realKey: number, generators: Int16Array, modulators: Modulator[]);
2946
+ readonly renderAudio: (outputs: Float32Array[], reverb: Float32Array[], chorus: Float32Array[], startIndex?: number, sampleCount?: number) => void;
2715
2947
  /**
2716
- * Copies a voice.
2948
+ * Renders the float32 audio data of each channel; buffer size of 128 is recommended.
2949
+ * All float arrays must have the same length.
2950
+ * @param reverbChannels reverb stereo channels (L, R).
2951
+ * @param chorusChannels chorus stereo channels (L, R).
2952
+ * @param separateChannels a total of 16 stereo pairs (L, R) for each MIDI channel.
2953
+ * @param startIndex start offset of the passed arrays, rendering starts at this index, defaults to 0.
2954
+ * @param sampleCount the length of the rendered buffer, defaults to float32array length - startOffset.
2717
2955
  */
2718
- static copyFrom(voice: Voice, currentTime: number, realKey: number): Voice;
2956
+ readonly renderAudioSplit: (reverb: Float32Array[], chorus: Float32Array[], separate: Float32Array[][], startIndex?: number, sampleCount?: number) => void;
2719
2957
  /**
2720
- * Releases the voice as exclusiveClass.
2958
+ * Core synthesis engine.
2721
2959
  */
2722
- exclusiveRelease(currentTime: number): void;
2960
+ private readonly synthCore;
2723
2961
  /**
2724
- * Stops the voice
2725
- * @param currentTime
2726
- * @param minNoteLength minimum note length in seconds
2962
+ * Tor applying the snapshot after an override sound bank too.
2727
2963
  */
2728
- release(currentTime: number, minNoteLength?: number): void;
2729
- }
2730
- /**
2731
- * @param preset the preset to get voices for
2732
- * @param midiNote the MIDI note to use
2733
- * @param velocity the velocity to use
2734
- * @param realKey the real MIDI note if the "midiNote" was changed by MIDI Tuning Standard
2735
- * @returns output is an array of Voices
2736
- */
2737
- declare function getVoicesForPresetInternal(this: SpessaSynthProcessor, preset: BasicPreset, midiNote: number, velocity: number, realKey: number): VoiceList;
2738
-
2739
- declare class ModulatorSource {
2964
+ private savedSnapshot?;
2740
2965
  /**
2741
- * If this field is set to false, the controller should be mapped with a minimum value of 0 and a maximum value of 1. This is also
2742
- * called Unipolar. Thus, it behaves similar to the Modulation Wheel controller of the MIDI specification.
2743
- *
2744
- * If this field is set to true, the controller sound be mapped with a minimum value of -1 and a maximum value of 1. This is also
2745
- * called Bipolar. Thus, it behaves similar to the Pitch Wheel controller of the MIDI specification.
2966
+ * Creates a new synthesizer engine.
2967
+ * @param sampleRate sample rate, in Hertz.
2968
+ * @param opts the processor's options.
2746
2969
  */
2747
- isBipolar: boolean;
2970
+ constructor(sampleRate: number, opts?: Partial<SynthProcessorOptions>);
2748
2971
  /**
2749
- * If this field is set true, the direction of the controller should be from the maximum value to the minimum value. So, for
2750
- * example, if the controller source is Key Number, then a Key Number value of 0 corresponds to the maximum possible
2751
- * controller output, and the Key Number value of 127 corresponds to the minimum possible controller input.
2972
+ * Are the chorus and reverb effects enabled?
2752
2973
  */
2753
- isNegative: boolean;
2974
+ get enableEffects(): boolean;
2754
2975
  /**
2755
- * The index of the source.
2756
- * It can point to one of the MIDI controllers or one of the predefined sources, depending on the 'isCC' flag.
2976
+ * Are the chorus and reverb effects enabled?
2757
2977
  */
2758
- index: ModulatorSourceIndex;
2978
+ set enableEffects(v: boolean);
2759
2979
  /**
2760
- * If this field is set to true, the MIDI Controller Palette is selected. The ‘index’ field value corresponds to one of the 128
2761
- * MIDI Continuous Controller messages as defined in the MIDI specification.
2980
+ * Is the event system enabled?
2762
2981
  */
2763
- isCC: boolean;
2982
+ get enableEventSystem(): boolean;
2764
2983
  /**
2765
- * This field specifies how the minimum value approaches the maximum value.
2984
+ * Is the event system enabled?
2766
2985
  */
2767
- curveType: ModulatorCurveType;
2768
- constructor(index?: ModulatorSourceIndex, curveType?: ModulatorCurveType, isCC?: boolean, isBipolar?: boolean, isNegative?: boolean);
2769
- private get sourceName();
2770
- private get curveTypeName();
2771
- static fromSourceEnum(sourceEnum: number): ModulatorSource;
2986
+ set enableEventSystem(v: boolean);
2772
2987
  /**
2773
- * Copies the modulator source.
2774
- * @param source The source to copy from.
2775
- * @returns the copied source.
2988
+ * All MIDI channels of the synthesizer.
2776
2989
  */
2777
- static copyFrom(source: ModulatorSource): ModulatorSource;
2778
- toString(): string;
2779
- toSourceEnum(): number;
2780
- isIdentical(source: ModulatorSource): boolean;
2990
+ get midiChannels(): MIDIChannel[];
2781
2991
  /**
2782
- * Gets the current value from this source.
2783
- * @param midiControllers The MIDI controller + modulator source array.
2784
- * @param voice The voice to get the data for.
2992
+ * Current total amount of voices that are currently playing.
2785
2993
  */
2786
- getValue(midiControllers: Int16Array, voice: Voice): number;
2787
- }
2788
-
2789
- declare class Modulator {
2994
+ get totalVoicesAmount(): number;
2790
2995
  /**
2791
- * The current computed value of this modulator. Only used in the synthesis engine for local voices.
2996
+ * The current time of the synthesizer, in seconds. You probably should not modify this directly.
2792
2997
  */
2793
- currentValue: number;
2998
+ get currentSynthTime(): number;
2794
2999
  /**
2795
- * The generator destination of this modulator.
3000
+ * The sound bank manager, which manages all sound banks and presets.
2796
3001
  */
2797
- destination: GeneratorType;
3002
+ get soundBankManager(): SoundBankManager;
2798
3003
  /**
2799
- * The transform amount for this modulator.
3004
+ * Handles the custom key overrides: velocity and preset
2800
3005
  */
2801
- transformAmount: number;
3006
+ get keyModifierManager(): KeyModifierManager;
2802
3007
  /**
2803
- * The transform type for this modulator.
3008
+ * A handler for missing presets during program change. By default, it warns to console.
3009
+ * @param patch The MIDI patch that was requested.
3010
+ * @param system The MIDI System for the request.
3011
+ * @returns If a BasicPreset instance is returned, it will be used by the channel.
2804
3012
  */
2805
- transformType: ModulatorTransformType;
3013
+ onMissingPreset: (patch: MIDIPatch, system: SynthSystem) => BasicPreset | undefined;
2806
3014
  /**
2807
- * Indicates if the given modulator is chorus or reverb effects modulator.
2808
- * This is done to simulate BASSMIDI effects behavior:
2809
- * - defaults to 1000 transform amount rather than 200
2810
- * - values can be changed, but anything above 200 is 1000
2811
- * (except for values above 1000, they are copied directly)
2812
- * - all values below are multiplied by 5 (200 * 5 = 1000)
2813
- * - still can be disabled if the soundfont has its own modulator curve
2814
- * - this fixes the very low amount of reverb by default and doesn't break soundfonts
3015
+ * Executes a system exclusive message for the synthesizer.
3016
+ * @param syx The system exclusive message as an array of bytes.
3017
+ * @param channelOffset The channel offset to apply (default is 0).
2815
3018
  */
2816
- readonly isEffectModulator: boolean;
3019
+ systemExclusive(syx: SysExAcceptedArray, channelOffset?: number): void;
2817
3020
  /**
2818
- * The default resonant modulator does not affect the filter gain.
2819
- * Neither XG nor GS responded to cc #74 in that way.
3021
+ * Sets a master parameter of the synthesizer.
3022
+ * @param type The type of the master parameter to set.
3023
+ * @param value The value to set for the master parameter.
2820
3024
  */
2821
- readonly isDefaultResonantModulator: boolean;
3025
+ setMasterParameter<P extends keyof MasterParameterType>(type: P, value: MasterParameterType[P]): void;
2822
3026
  /**
2823
- * The primary source of this modulator.
3027
+ * Gets a master parameter of the synthesizer.
3028
+ * @param type The type of the master parameter to get.
3029
+ * @returns The value of the master parameter.
2824
3030
  */
2825
- readonly primarySource: ModulatorSource;
3031
+ getMasterParameter<P extends keyof MasterParameterType>(type: P): MasterParameterType[P];
2826
3032
  /**
2827
- * The secondary source of this modulator.
3033
+ * Gets all master parameters of the synthesizer.
3034
+ * @returns All the master parameters.
2828
3035
  */
2829
- readonly secondarySource: ModulatorSource;
3036
+ getAllMasterParameters(): MasterParameterType;
2830
3037
  /**
2831
- * Creates a new SF2 Modulator
3038
+ * Executes a full system reset of all controllers.
3039
+ * This will reset all controllers to their default values,
3040
+ * except for the locked controllers.
2832
3041
  */
2833
- constructor(primarySource?: ModulatorSource, secondarySource?: ModulatorSource, destination?: GeneratorType, amount?: number, transformType?: ModulatorTransformType, isEffectModulator?: boolean, isDefaultResonantModulator?: boolean);
2834
- private get destinationName();
3042
+ resetAllControllers(system?: SynthSystem): void;
2835
3043
  /**
2836
- * Checks if the pair of modulators is identical (in SF2 terms)
2837
- * @param mod1 modulator 1
2838
- * @param mod2 modulator 2
2839
- * @param checkAmount if the amount should be checked too.
2840
- * @returns if they are identical
3044
+ * Applies the snapshot to the synth
2841
3045
  */
2842
- static isIdentical(mod1: Modulator, mod2: Modulator, checkAmount?: boolean): boolean;
3046
+ applySynthesizerSnapshot(snapshot: SynthesizerSnapshot): void;
2843
3047
  /**
2844
- * Copies a modulator.
2845
- * @param mod The modulator to copy.
2846
- * @returns The copied modulator.
3048
+ * Gets a synthesizer snapshot from this processor instance.
2847
3049
  */
2848
- static copyFrom(mod: Modulator): Modulator;
2849
- toString(): string;
2850
- write(modData: IndexedByteArray, indexes?: SoundFontWriteIndexes): void;
3050
+ getSnapshot(): SynthesizerSnapshot;
2851
3051
  /**
2852
- * Sums transform and create a NEW modulator
2853
- * @param modulator the modulator to sum with
2854
- * @returns the new modulator
3052
+ * Sets the embedded sound bank.
3053
+ * @param bank The sound bank file to set.
3054
+ * @param offset The bank offset of the embedded sound bank.
2855
3055
  */
2856
- sumTransform(modulator: Modulator): Modulator;
2857
- }
2858
-
2859
- /**
2860
- * Midi_message.ts
2861
- * purpose: contains enums for midi events and controllers and functions to parse them
2862
- */
2863
-
2864
- declare class MIDIMessage {
3056
+ setEmbeddedSoundBank(bank: ArrayBuffer, offset: number): void;
3057
+ clearEmbeddedBank(): void;
3058
+ createMIDIChannel(): void;
2865
3059
  /**
2866
- * Absolute number of MIDI ticks from the start of the track.
3060
+ * Stops all notes on all channels.
3061
+ * @param force if true, all notes are stopped immediately, otherwise they are stopped gracefully.
2867
3062
  */
2868
- ticks: number;
3063
+ stopAllChannels(force?: boolean): void;
2869
3064
  /**
2870
- * The MIDI message status byte. Note that for meta events, it is the second byte. (not 0xFF)
3065
+ * Destroy the synthesizer processor, clearing all channels and voices.
3066
+ * This is irreversible, so use with caution.
2871
3067
  */
2872
- statusByte: MIDIMessageType;
3068
+ destroySynthProcessor(): void;
2873
3069
  /**
2874
- * Message's binary data
3070
+ * Executes a MIDI controller change message on the specified channel.
3071
+ * @param channel The MIDI channel to change the controller on.
3072
+ * @param controllerNumber The MIDI controller number to change.
3073
+ * @param controllerValue The value to set the controller to.
2875
3074
  */
2876
- data: Uint8Array<ArrayBuffer>;
3075
+ controllerChange(channel: number, controllerNumber: MIDIController, controllerValue: number): void;
2877
3076
  /**
2878
- * Creates a new MIDI message
2879
- * @param ticks time of this message in absolute MIDI ticks
2880
- * @param byte the message status byte
2881
- * @param data the message's binary data
3077
+ * Executes a MIDI Note-on message on the specified channel.
3078
+ * @param channel The MIDI channel to send the note on.
3079
+ * @param midiNote The MIDI note number to play.
3080
+ * @param velocity The velocity of the note, from 0 to 127.
3081
+ * @remarks
3082
+ * If the velocity is 0, it will be treated as a Note-off message.
2882
3083
  */
2883
- constructor(ticks: number, byte: MIDIMessageType, data: Uint8Array<ArrayBuffer>);
2884
- }
2885
-
2886
- /**
2887
- * RMIDInfoData type represents metadata for an RMIDI file.
2888
- */
2889
- interface RMIDInfoData {
3084
+ noteOn(channel: number, midiNote: number, velocity: number): void;
2890
3085
  /**
2891
- * The name of the song.
3086
+ * Executes a MIDI Note-off message on the specified channel.
3087
+ * @param channel The MIDI channel to send the note off.
3088
+ * @param midiNote The MIDI note number to stop playing.
2892
3089
  */
2893
- name: string;
3090
+ noteOff(channel: number, midiNote: number): void;
2894
3091
  /**
2895
- * The engineer who worked on the sound bank file.
3092
+ * Executes a MIDI Poly Pressure (Aftertouch) message on the specified channel.
3093
+ * @param channel The MIDI channel to send the poly pressure on.
3094
+ * @param midiNote The MIDI note number to apply the pressure to.
3095
+ * @param pressure The pressure value, from 0 to 127.
2896
3096
  */
2897
- engineer: string;
3097
+ polyPressure(channel: number, midiNote: number, pressure: number): void;
2898
3098
  /**
2899
- * The artist of the MIDI file.
3099
+ * Executes a MIDI Channel Pressure (Aftertouch) message on the specified channel.
3100
+ * @param channel The MIDI channel to send the channel pressure on.
3101
+ * @param pressure The pressure value, from 0 to 127.
2900
3102
  */
2901
- artist: string;
3103
+ channelPressure(channel: number, pressure: number): void;
2902
3104
  /**
2903
- * The album of the song.
3105
+ * Executes a MIDI Pitch Wheel message on the specified channel.
3106
+ * @param channel The MIDI channel to send the pitch wheel on.
3107
+ * @param pitch The new pitch value: 0-16384
3108
+ * @param midiNote The MIDI note number, pass -1 for the regular pitch wheel
2904
3109
  */
2905
- album: string;
3110
+ pitchWheel(channel: number, pitch: number, midiNote?: number): void;
2906
3111
  /**
2907
- * The genre of the song.
3112
+ * Executes a MIDI Program Change message on the specified channel.
3113
+ * @param channel The MIDI channel to send the program change on.
3114
+ * @param programNumber The program number to change to, from 0 to 127.
2908
3115
  */
2909
- genre: string;
3116
+ programChange(channel: number, programNumber: number): void;
2910
3117
  /**
2911
- * The image for the file (album cover).
3118
+ * DEPRECATED, does nothing!
3119
+ * @param amount
3120
+ * @deprecated
2912
3121
  */
2913
- picture: ArrayBuffer;
3122
+ killVoices(amount: number): void;
2914
3123
  /**
2915
- * The comment of the file.
3124
+ * Processes a raw MIDI message.
3125
+ * @param message The message to process.
3126
+ * @param channelOffset The channel offset for the message.
3127
+ * @param force If true, forces the message to be processed.
3128
+ * @param options Additional options for scheduling the message.
2916
3129
  */
2917
- comment: string;
3130
+ processMessage(message: Uint8Array | number[], channelOffset?: number, force?: boolean, options?: SynthMethodOptions): void;
2918
3131
  /**
2919
- * The creation date of the file.
3132
+ * Clears the synthesizer's voice cache.
2920
3133
  */
2921
- creationDate: Date;
3134
+ clearCache(): void;
2922
3135
  /**
2923
- * The copyright of the file.
3136
+ * Gets voices for a preset.
3137
+ * @param preset The preset to get voices for.
3138
+ * @param midiNote The MIDI note to use.
3139
+ * @param velocity The velocity to use.
3140
+ * @returns Output is an array of voices.
3141
+ * @remarks
3142
+ * This is a public method, but it is only intended to be used by the sequencer.
3143
+ * @internal
2924
3144
  */
2925
- copyright: string;
3145
+ getVoicesForPreset(preset: BasicPreset, midiNote: number, velocity: number): CachedVoiceList;
2926
3146
  /**
2927
- * The encoding of the RMIDI info.
3147
+ * Calls synth event
3148
+ * @param eventName the event name
3149
+ * @param eventData the event data
2928
3150
  */
2929
- infoEncoding: string;
3151
+ private callEvent;
3152
+ private missingPreset;
3153
+ }
3154
+
3155
+ /**
3156
+ * Represents a snapshot of a single channel's state in the synthesizer.
3157
+ */
3158
+ declare class ChannelSnapshot {
2930
3159
  /**
2931
- * The encoding of the MIDI file's text messages.
3160
+ * The MIDI patch that the channel is using.
2932
3161
  */
2933
- midiEncoding: string;
3162
+ patch: MIDIPatchNamed;
2934
3163
  /**
2935
- * The software used to write the file.
3164
+ * Indicates whether the channel's program change is disabled.
2936
3165
  */
2937
- software: string;
3166
+ lockPreset: boolean;
2938
3167
  /**
2939
- * The subject of the file.
3168
+ * Indicates the MIDI system when the preset was locked
2940
3169
  */
2941
- subject: string;
2942
- }
2943
- interface TempoChange {
3170
+ lockedSystem: SynthSystem;
2944
3171
  /**
2945
- * MIDI ticks of the change, absolute value from the start of the MIDI file.
3172
+ * The array of all MIDI controllers (in 14-bit values) with the modulator sources at the end.
2946
3173
  */
2947
- ticks: number;
3174
+ midiControllers: Int16Array;
2948
3175
  /**
2949
- * New tempo in BPM.
3176
+ * An array of booleans, indicating if the controller with a current index is locked.
2950
3177
  */
2951
- tempo: number;
2952
- }
2953
- type MIDILoopType = "soft" | "hard";
2954
- interface MIDILoop {
3178
+ lockedControllers: boolean[];
2955
3179
  /**
2956
- * Start of the loop, in MIDI ticks.
3180
+ * Array of custom (not SF2) control values such as RPN pitch tuning, transpose, modulation depth, etc.
2957
3181
  */
2958
- start: number;
3182
+ customControllers: Float32Array;
2959
3183
  /**
2960
- * End of the loop, in MIDI ticks.
3184
+ * Indicates whether the channel vibrato is locked.
2961
3185
  */
2962
- end: number;
3186
+ lockVibrato: boolean;
2963
3187
  /**
2964
- * The type of the loop detected:
2965
- * - Soft - the playback will immediately jump to the loop start pointer without any further processing.
2966
- * - Hard - the playback will quickly process all messages from
2967
- * the start of the file to ensure that synthesizer is in the correct state.
2968
- * This is the default behavior.
2969
- *
2970
- * Soft loop types are enabled for Touhou and GameMaker loop points.
3188
+ * The channel's vibrato settings.
3189
+ * @property depth Vibrato depth, in gain.
3190
+ * @property delay Vibrato delay from note on in seconds.
3191
+ * @property rate Vibrato rate in Hz.
2971
3192
  */
2972
- type: MIDILoopType;
2973
- }
2974
- type MIDIFormat = 0 | 1 | 2;
2975
- interface NoteTime {
3193
+ channelVibrato: {
3194
+ depth: number;
3195
+ delay: number;
3196
+ rate: number;
3197
+ };
2976
3198
  /**
2977
- * The MIDI key number.
3199
+ * Key shift for the channel.
2978
3200
  */
2979
- midiNote: number;
3201
+ channelTransposeKeyShift: number;
2980
3202
  /**
2981
- * Start of the note, in seconds.
3203
+ * The channel's octave tuning in cents.
2982
3204
  */
2983
- start: number;
3205
+ channelOctaveTuning: Int8Array;
2984
3206
  /**
2985
- * Length of the note, in seconds.
3207
+ * Indicates whether the channel is muted.
2986
3208
  */
2987
- length: number;
3209
+ isMuted: boolean;
2988
3210
  /**
2989
- * The MIDI velocity of the note.
3211
+ * Indicates whether the channel is a drum channel.
2990
3212
  */
2991
- velocity: number;
2992
- }
2993
- /**
2994
- * Represents a desired program change for a MIDI channel.
2995
- */
2996
- interface DesiredProgramChange extends MIDIPatch {
3213
+ drumChannel: boolean;
2997
3214
  /**
2998
- * The channel number.
3215
+ * The channel number this snapshot represents.
2999
3216
  */
3000
- channel: number;
3001
- }
3002
- /**
3003
- * Represents a desired controller change for a MIDI channel.
3004
- */
3005
- interface DesiredControllerChange {
3217
+ channelNumber: number;
3218
+ constructor(patch: MIDIPatchNamed, lockPreset: boolean, lockedSystem: SynthSystem, midiControllers: Int16Array, lockedControllers: boolean[], customControllers: Float32Array, lockVibrato: boolean, channelVibrato: {
3219
+ delay: number;
3220
+ depth: number;
3221
+ rate: number;
3222
+ }, channelTransposeKeyShift: number, channelOctaveTuning: Int8Array, isMuted: boolean, drumChannel: boolean, channelNumber: number);
3006
3223
  /**
3007
- * The channel number.
3224
+ * Creates a copy of existing snapshot.
3225
+ * @param snapshot The snapshot to create a copy from.
3008
3226
  */
3009
- channel: number;
3227
+ static copyFrom(snapshot: ChannelSnapshot): ChannelSnapshot;
3010
3228
  /**
3011
- * The MIDI controller number.
3229
+ * Creates a snapshot of the channel's state.
3230
+ * @param spessaSynthProcessor The synthesizer processor containing the channel.
3231
+ * @param channelNumber The channel number to take a snapshot of.
3012
3232
  */
3013
- controllerNumber: number;
3233
+ static create(spessaSynthProcessor: SpessaSynthProcessor, channelNumber: number): ChannelSnapshot;
3014
3234
  /**
3015
- * The new controller value.
3235
+ * Applies the snapshot to the specified channel.
3236
+ * @param spessaSynthProcessor The processor containing the channel.
3016
3237
  */
3017
- controllerValue: number;
3238
+ apply(spessaSynthProcessor: SpessaSynthProcessor): void;
3018
3239
  }
3240
+
3019
3241
  /**
3020
- * Represents a desired channel transpose change.
3242
+ * Represents a snapshot of the synthesizer's state.
3021
3243
  */
3022
- interface DesiredChannelTranspose {
3023
- /**
3024
- * The channel number.
3025
- */
3026
- channel: number;
3244
+ declare class SynthesizerSnapshot {
3027
3245
  /**
3028
- * The number of semitones to transpose.
3029
- * This can use floating point numbers, which will be used to fine-tune the pitch in cents using RPN.
3246
+ * The individual channel snapshots.
3030
3247
  */
3031
- keyShift: number;
3032
- }
3033
- interface RMIDIWriteOptions {
3248
+ channelSnapshots: ChannelSnapshot[];
3034
3249
  /**
3035
- * The bank offset for RMIDI.
3250
+ * Key modifiers.
3036
3251
  */
3037
- bankOffset: number;
3252
+ keyMappings: (KeyModifier | undefined)[][];
3253
+ masterParameters: MasterParameterType;
3254
+ constructor(channelSnapshots: ChannelSnapshot[], masterParameters: MasterParameterType, keyMappings: (KeyModifier | undefined)[][]);
3038
3255
  /**
3039
- * The metadata of the file. Optional.
3256
+ * Creates a new synthesizer snapshot from the given SpessaSynthProcessor.
3257
+ * @param processor the processor to take a snapshot of.
3258
+ * @returns The snapshot.
3040
3259
  */
3041
- metadata: Partial<Omit<RMIDInfoData, "infoEncoding">>;
3260
+ static create(processor: SpessaSynthProcessor): SynthesizerSnapshot;
3042
3261
  /**
3043
- * If the MIDI file should internally be corrected to work with the set bank offset.
3262
+ * Creates a copy of existing snapshot.
3263
+ * @param snapshot The snapshot to create a copy from.
3044
3264
  */
3045
- correctBankOffset: boolean;
3265
+ static copyFrom(snapshot: SynthesizerSnapshot): SynthesizerSnapshot;
3046
3266
  /**
3047
- * The optional sound bank instance used to correct bank offset.
3267
+ * Applies the snapshot to the synthesizer.
3268
+ * @param processor the processor to apply the snapshot to.
3048
3269
  */
3049
- soundBank?: BasicSoundBank;
3270
+ apply(processor: SpessaSynthProcessor): void;
3050
3271
  }
3051
- type RMIDInfoFourCC = "INAM" | "IPRD" | "IALB" | "IART" | "IGNR" | "IPIC" | "ICOP" | "ICRD" | "ICRT" | "ICMT" | "IENG" | "ISFT" | "ISBJ" | "IENC" | "MENC" | "DBNK";
3052
3272
 
3053
3273
  declare class MIDITrack {
3054
3274
  /**
@@ -3212,6 +3432,12 @@ declare class BasicMIDI {
3212
3432
  * @returns The time in seconds.
3213
3433
  */
3214
3434
  midiTicksToSeconds(ticks: number): number;
3435
+ /**
3436
+ * Converts seconds to time in MIDI ticks.
3437
+ * @param seconds The time in seconds.
3438
+ * @returns The time in MIDI ticks.
3439
+ */
3440
+ secondsToMIDITicks(seconds: number): number;
3215
3441
  /**
3216
3442
  * Gets the used programs and keys for this MIDI file with a given sound bank.
3217
3443
  * @param soundbank the sound bank.
@@ -3502,9 +3728,8 @@ interface SoundBankInfoData {
3502
3728
  romVersion?: SF2VersionTag;
3503
3729
  }
3504
3730
  type SoundBankInfoFourCC = keyof SoundBankInfoData;
3505
- interface VoiceSynthesisData {
3506
- instrumentGenerators: Generator[];
3507
- presetGenerators: Generator[];
3731
+ interface VoiceParameters {
3732
+ generators: Int16Array;
3508
3733
  modulators: Modulator[];
3509
3734
  sample: BasicSample;
3510
3735
  }
@@ -3737,20 +3962,6 @@ declare class MIDIBuilder extends BasicMIDI {
3737
3962
  addPitchWheel(ticks: number, track: number, channel: number, MSB: number, LSB: number): void;
3738
3963
  }
3739
3964
 
3740
- /**
3741
- * Processes a single MIDI tick.
3742
- * Call this every rendering quantum to process the sequencer events in real-time.
3743
- */
3744
- declare function processTick(this: SpessaSynthSequencer): void;
3745
-
3746
- /**
3747
- * Plays the MIDI file to a specific time or ticks.
3748
- * @param time in seconds.
3749
- * @param ticks optional MIDI ticks, when given is used instead of time.
3750
- * @returns true if the MIDI file is not finished.
3751
- */
3752
- declare function setTimeToInternal(this: SpessaSynthSequencer, time: number, ticks?: number | undefined): boolean;
3753
-
3754
3965
  interface SequencerEventData {
3755
3966
  /**
3756
3967
  * Called when a MIDI message is sent and externalMIDIPlayback is true.
@@ -3760,6 +3971,11 @@ interface SequencerEventData {
3760
3971
  * The binary MIDI message.
3761
3972
  */
3762
3973
  message: Iterable<number>;
3974
+ /**
3975
+ * The synthesizer's current time when this event was sent.
3976
+ * Use this for scheduling MIDI messages to your external MIDI device.
3977
+ */
3978
+ time: number;
3763
3979
  };
3764
3980
  /**
3765
3981
  * Called when the time is changed.
@@ -3833,6 +4049,20 @@ type SequencerEvent = {
3833
4049
  };
3834
4050
  }[keyof SequencerEventData];
3835
4051
 
4052
+ /**
4053
+ * Processes a single MIDI tick.
4054
+ * Call this every rendering quantum to process the sequencer events in real-time.
4055
+ */
4056
+ declare function processTick(this: SpessaSynthSequencer): void;
4057
+
4058
+ /**
4059
+ * Plays the MIDI file to a specific time or ticks.
4060
+ * @param time in seconds.
4061
+ * @param ticks optional MIDI ticks, when given is used instead of time.
4062
+ * @returns true if the MIDI file is not finished.
4063
+ */
4064
+ declare function setTimeToInternal(this: SpessaSynthSequencer, time: number, ticks?: number | undefined): boolean;
4065
+
3836
4066
  declare class SpessaSynthSequencer {
3837
4067
  /**
3838
4068
  * Sequencer's song list.
@@ -4068,14 +4298,6 @@ declare class SpessaSynthSequencer {
4068
4298
  protected sendMIDIPitchWheel(channel: number, pitch: number): void;
4069
4299
  }
4070
4300
 
4071
- declare const DEFAULT_MASTER_PARAMETERS: MasterParameterType;
4072
-
4073
- /**
4074
- * Default MIDI drum channel.
4075
- */
4076
- declare const DEFAULT_PERCUSSION = 9;
4077
- declare const ALL_CHANNELS_OR_DIFFERENT_ACTION = -1;
4078
-
4079
4301
  declare const NON_CC_INDEX_OFFSET = 128;
4080
4302
  declare const CONTROLLER_TABLE_SIZE = 147;
4081
4303
  /**
@@ -4086,6 +4308,14 @@ declare const setResetValue: (i: MIDIController, v: number) => number;
4086
4308
  declare const CUSTOM_CONTROLLER_TABLE_SIZE: number;
4087
4309
  declare const customResetArray: Float32Array<ArrayBuffer>;
4088
4310
 
4311
+ declare const DEFAULT_MASTER_PARAMETERS: MasterParameterType;
4312
+
4313
+ /**
4314
+ * Default MIDI drum channel.
4315
+ */
4316
+ declare const DEFAULT_PERCUSSION = 9;
4317
+ declare const ALL_CHANNELS_OR_DIFFERENT_ACTION = -1;
4318
+
4089
4319
  declare class SoundBankLoader {
4090
4320
  /**
4091
4321
  * Loads a sound bank from a file buffer.
@@ -4096,4 +4326,4 @@ declare class SoundBankLoader {
4096
4326
  private static loadDLS;
4097
4327
  }
4098
4328
 
4099
- export { ALL_CHANNELS_OR_DIFFERENT_ACTION, BasicGlobalZone, BasicInstrument, BasicInstrumentZone, BasicMIDI, BasicPreset, BasicPresetZone, BasicSample, BasicSoundBank, BasicZone, CONTROLLER_TABLE_SIZE, CUSTOM_CONTROLLER_TABLE_SIZE, type ChannelPressureCallback, type ChannelProperty, type ChannelPropertyChangeCallback, ChannelSnapshot, type ControllerChangeCallback, type CustomController, DEFAULT_MASTER_PARAMETERS, DEFAULT_PERCUSSION, DEFAULT_WAV_WRITE_OPTIONS, type DLSChunkFourCC, type DLSDestination, type DLSInfoFourCC, type DLSLoop, type DLSLoopType, DLSLoopTypes, type DLSSource, type DLSTransform, type DLSWriteOptions, type DataEntryState, type DesiredChannelTranspose, type DesiredControllerChange, type DesiredProgramChange, type DrumChangeCallback, EmptySample, type FourCC, GENERATORS_AMOUNT, Generator, type GeneratorType, type GenericBankInfoFourCC, type GenericRIFFFourCC, type GenericRange, IndexedByteArray, type InterpolationType, KeyModifier, MAX_GENERATOR, MIDIBuilder, type MIDIController, type MIDIFormat, type MIDILoop, type MIDILoopType, MIDIMessage, type MIDIMessageType, type MIDIPatch, type MIDIPatchNamed, MIDIPatchTools, MIDITrack, type MTSNoteTuning, type MTSProgramTuning, type MasterParameterChangeCallback, type MasterParameterType, Modulator, type ModulatorCurveType, ModulatorSource, type ModulatorSourceEnum, type ModulatorSourceIndex, type ModulatorTransformType, type MuteChannelCallback, NON_CC_INDEX_OFFSET, type NoteOffCallback, type NoteOnCallback, type NoteTime, type PitchWheelCallback, type PolyPressureCallback, type PresetList, type PresetListEntry, type ProgramChangeCallback, type ProgressFunction, type RMIDIWriteOptions, type RMIDInfoData, type RMIDInfoFourCC, type SF2ChunkFourCC, type SF2InfoFourCC, type SF2VersionTag, type SampleEncodingFunction, type SampleLoopingMode, type SampleType, type SequencerEvent, type SequencerEventData, type SoundBankErrorCallback, type SoundBankInfoData, type SoundBankInfoFourCC, SoundBankLoader, type SoundBankManagerListEntry, type SoundFont2WriteOptions, SpessaSynthCoreUtils, SpessaSynthLogging, SpessaSynthProcessor, SpessaSynthSequencer, type StopAllCallback, type SynthMethodOptions, type SynthProcessorEvent, type SynthProcessorEventData, type SynthProcessorOptions, type SynthSystem, SynthesizerSnapshot, type TempoChange, type VoiceList, type VoiceSynthesisData, type WaveMetadata, type WaveWriteOptions, audioToWav, customControllers, customResetArray, dataEntryStates, defaultMIDIControllerValues, dlsDestinations, dlsSources, generatorLimits, generatorTypes, interpolationTypes, midiControllers, midiMessageTypes, modulatorCurveTypes, modulatorSources, modulatorTransformTypes, sampleTypes, setResetValue };
4329
+ export { ALL_CHANNELS_OR_DIFFERENT_ACTION, BasicGlobalZone, BasicInstrument, BasicInstrumentZone, BasicMIDI, BasicPreset, BasicPresetZone, BasicSample, BasicSoundBank, BasicZone, CONTROLLER_TABLE_SIZE, CUSTOM_CONTROLLER_TABLE_SIZE, type CachedVoiceList, type ChannelPressureCallback, type ChannelProperty, type ChannelPropertyChangeCallback, ChannelSnapshot, type ControllerChangeCallback, type CustomController, DEFAULT_MASTER_PARAMETERS, DEFAULT_PERCUSSION, DEFAULT_WAV_WRITE_OPTIONS, type DLSChunkFourCC, type DLSDestination, type DLSInfoFourCC, type DLSLoop, type DLSLoopType, DLSLoopTypes, type DLSSource, type DLSTransform, type DLSWriteOptions, type DataEntryState, type DesiredChannelTranspose, type DesiredControllerChange, type DesiredProgramChange, type DrumChangeCallback, EmptySample, type FourCC, GENERATORS_AMOUNT, Generator, type GeneratorType, type GenericBankInfoFourCC, type GenericRIFFFourCC, type GenericRange, IndexedByteArray, type InterpolationType, KeyModifier, MAX_GENERATOR, MIDIBuilder, type MIDIController, type MIDIFormat, type MIDILoop, type MIDILoopType, MIDIMessage, type MIDIMessageType, type MIDIPatch, type MIDIPatchNamed, MIDIPatchTools, MIDITrack, type MasterParameterChangeCallback, type MasterParameterType, Modulator, type ModulatorCurveType, ModulatorSource, type ModulatorSourceEnum, type ModulatorSourceIndex, type ModulatorTransformType, type MuteChannelCallback, NON_CC_INDEX_OFFSET, type NoteOffCallback, type NoteOnCallback, type NoteTime, type PitchWheelCallback, type PolyPressureCallback, type PresetList, type PresetListEntry, type ProgramChangeCallback, type ProgressFunction, type RMIDIWriteOptions, type RMIDInfoData, type RMIDInfoFourCC, type SF2ChunkFourCC, type SF2InfoFourCC, type SF2VersionTag, type SampleEncodingFunction, type SampleLoopingMode, type SampleType, type SequencerEvent, type SequencerEventData, type SoundBankErrorCallback, type SoundBankInfoData, type SoundBankInfoFourCC, SoundBankLoader, type SoundBankManagerListEntry, type SoundFont2WriteOptions, SpessaSynthCoreUtils, SpessaSynthLogging, SpessaSynthProcessor, SpessaSynthSequencer, type StopAllCallback, type SynthMethodOptions, type SynthProcessorEvent, type SynthProcessorEventData, type SynthProcessorOptions, type SynthSystem, SynthesizerSnapshot, type TempoChange, type VoiceParameters, type WaveMetadata, type WaveWriteOptions, audioToWav, customControllers, customResetArray, dataEntryStates, defaultGeneratorValues, defaultMIDIControllerValues, dlsDestinations, dlsSources, generatorLimits, generatorTypes, interpolationTypes, midiControllers, midiMessageTypes, modulatorCurveTypes, modulatorSources, modulatorTransformTypes, sampleTypes, setResetValue };