spessasynth_core 4.2.12 → 4.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2626,79 +2626,6 @@ interface RMIDIWriteOptions {
2626
2626
  }
2627
2627
  type RMIDInfoFourCC = "INAM" | "IPRD" | "IALB" | "IART" | "IGNR" | "IPIC" | "ICOP" | "ICRD" | "ICRT" | "ICMT" | "IENG" | "ISFT" | "ISBJ" | "IENC" | "MENC" | "DBNK";
2628
2628
  //#endregion
2629
- //#region src/synthesizer/audio_engine/engine_methods/controller_control/reset_controllers.d.ts
2630
- /**
2631
- * Reset all controllers for channel.
2632
- * This will reset all controllers to their default values,
2633
- * except for the locked controllers.
2634
- */
2635
- declare function resetControllers(this: MIDIChannel, sendCCEvents?: boolean): void;
2636
- declare function resetPreset(this: MIDIChannel): void;
2637
- /**
2638
- * https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf
2639
- * Reset controllers according to RP-15 Recommended Practice.
2640
- */
2641
- declare function resetControllersRP15Compliant(this: MIDIChannel): void;
2642
- /**
2643
- * Reset all parameters to their default values.
2644
- * This includes NRPN and RPN controllers, data entry state,
2645
- * and generator overrides and offsets.
2646
- */
2647
- declare function resetParameters(this: MIDIChannel): void;
2648
- //#endregion
2649
- //#region src/synthesizer/audio_engine/engine_methods/controller_control/data_entry/data_entry_fine.d.ts
2650
- /**
2651
- * Executes a data entry fine (LSB) change for the current channel.
2652
- * @param dataValue The value to set for the data entry fine controller (0-127).
2653
- */
2654
- declare function dataEntryFine(this: MIDIChannel, dataValue: number): void;
2655
- //#endregion
2656
- //#region src/synthesizer/audio_engine/engine_methods/controller_control/controller_change.d.ts
2657
- /**
2658
- * Handles MIDI controller changes for a channel.
2659
- * @param controllerNumber The MIDI controller number (0-127).
2660
- * @param controllerValue The value of the controller (0-127).
2661
- * @param sendEvent If an event should be emitted.
2662
- * @remarks
2663
- * This function processes MIDI controller changes, updating the channel's
2664
- * midiControllers table and handling special cases like bank select,
2665
- * data entry, and sustain pedal. It also computes modulators for all voices
2666
- * in the channel based on the controller change.
2667
- * to allow changes.
2668
- */
2669
- declare function controllerChange(this: MIDIChannel, controllerNumber: MIDIController, controllerValue: number, sendEvent?: boolean): void;
2670
- //#endregion
2671
- //#region src/synthesizer/audio_engine/engine_methods/controller_control/data_entry/data_entry_coarse.d.ts
2672
- /**
2673
- * Executes a data entry coarse (MSB) change for the current channel.
2674
- * @param dataCoarse The value to set for the data entry coarse controller (0-127).
2675
- */
2676
- declare function dataEntryCoarse(this: MIDIChannel, dataCoarse: number): void;
2677
- //#endregion
2678
- //#region src/synthesizer/audio_engine/engine_methods/note_on.d.ts
2679
- /**
2680
- * Sends a "MIDI Note on" message and starts a note.
2681
- * @param midiNote The MIDI note number (0-127).
2682
- * @param velocity The velocity of the note (0-127). If less than 1, it will send a note off instead.
2683
- */
2684
- declare function noteOn(this: MIDIChannel, midiNote: number, velocity: number): void;
2685
- //#endregion
2686
- //#region src/synthesizer/audio_engine/engine_methods/note_off.d.ts
2687
- /**
2688
- * Releases a note by its MIDI note number.
2689
- * If the note is in high performance mode and the channel is not a drum channel,
2690
- * it kills the note instead of releasing it.
2691
- * @param midiNote The MIDI note number to release (0-127).
2692
- */
2693
- declare function noteOff(this: MIDIChannel, midiNote: number): void;
2694
- //#endregion
2695
- //#region src/synthesizer/audio_engine/engine_methods/program_change.d.ts
2696
- /**
2697
- * Changes the program (preset) of the channel.
2698
- * @param program The program number (0-127) to change to.
2699
- */
2700
- declare function programChange(this: MIDIChannel, program: number): void;
2701
- //#endregion
2702
2629
  //#region src/synthesizer/audio_engine/engine_components/dynamic_modulator_system.d.ts
2703
2630
  /**
2704
2631
  * A class for dynamic modulators
@@ -3473,48 +3400,48 @@ declare class MIDIChannel {
3473
3400
  * @param midiNote The MIDI note number (0-127).
3474
3401
  * @param velocity The velocity of the note (0-127). If less than 1, it will send a note off instead.
3475
3402
  */
3476
- noteOn: typeof noteOn;
3403
+ noteOn: (midiNote: number, velocity: number) => void;
3477
3404
  /**
3478
3405
  * Releases a note by its MIDI note number.
3479
3406
  * If the note is in high performance mode and the channel is not a drum channel,
3480
3407
  * it kills the note instead of releasing it.
3481
3408
  * @param midiNote The MIDI note number to release (0-127).
3482
3409
  */
3483
- noteOff: typeof noteOff;
3410
+ noteOff: (midiNote: number) => void;
3484
3411
  /**
3485
3412
  * Changes the program (preset) of the channel.
3486
3413
  * @param programNumber The program number (0-127) to change to.
3487
3414
  */
3488
- programChange: typeof programChange;
3489
- controllerChange: typeof controllerChange;
3415
+ programChange: (program: number) => void;
3416
+ controllerChange: (controllerNumber: MIDIController, controllerValue: number, sendEvent?: boolean | undefined) => void;
3490
3417
  /**
3491
3418
  * Reset all controllers for channel.
3492
3419
  * This will reset all controllers to their default values,
3493
3420
  * except for the locked controllers.
3494
3421
  */
3495
- readonly resetControllers: typeof resetControllers;
3496
- readonly resetPreset: typeof resetPreset;
3422
+ readonly resetControllers: (sendCCEvents?: boolean | undefined) => void;
3423
+ readonly resetPreset: () => void;
3497
3424
  /**
3498
3425
  * https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf
3499
3426
  * Reset controllers according to RP-15 Recommended Practice.
3500
3427
  */
3501
- readonly resetControllersRP15Compliant: typeof resetControllersRP15Compliant;
3428
+ readonly resetControllersRP15Compliant: () => void;
3502
3429
  /**
3503
3430
  * Reset all parameters to their default values.
3504
3431
  * This includes NRPN and RPN controllers, data entry state,
3505
3432
  * and generator overrides and offsets.
3506
3433
  */
3507
- resetParameters: typeof resetParameters;
3434
+ resetParameters: () => void;
3508
3435
  /**
3509
3436
  * Executes a data entry fine (LSB) change for the current channel.
3510
3437
  * @param dataValue The value to set for the data entry fine controller (0-127).
3511
3438
  */
3512
- dataEntryFine: typeof dataEntryFine;
3439
+ dataEntryFine: (dataValue: number) => void;
3513
3440
  /**
3514
3441
  * Executes a data entry coarse (MSB) change for the current channel.
3515
3442
  * @param dataValue The value to set for the data entry coarse controller (0-127).
3516
3443
  */
3517
- dataEntryCoarse: typeof dataEntryCoarse;
3444
+ dataEntryCoarse: (dataCoarse: number) => void;
3518
3445
  readonly renderVoice: (voice: Voice, timeNow: number, outputL: Float32Array<ArrayBufferLike>, outputR: Float32Array<ArrayBufferLike>, startIndex: number, sampleCount: number) => void;
3519
3446
  /**
3520
3447
  * Per-note pitch wheel mode uses the pitchWheels table as source
@@ -3696,7 +3623,7 @@ declare class SpessaSynthProcessor {
3696
3623
  */
3697
3624
  onEventCall?: (event: SynthProcessorEvent) => unknown;
3698
3625
  /**
3699
- * Renders float32 audio data to stereo outputs; buffer size must be equal or smaller than `maxBufferSize`
3626
+ * Renders float32 audio data to stereo outputs; buffer size must be equal or smaller than `maxBufferSize`.
3700
3627
  * All float arrays must have the same length.
3701
3628
  * @param left the left output channel.
3702
3629
  * @param right the right output channel.
@@ -3705,7 +3632,7 @@ declare class SpessaSynthProcessor {
3705
3632
  */
3706
3633
  readonly process: (left: Float32Array, right: Float32Array, startIndex?: number, sampleCount?: number) => void;
3707
3634
  /**
3708
- * Renders float32 audio data to stereo outputs; buffer size must be equal or smaller than `maxBufferSize
3635
+ * Renders float32 audio data to stereo outputs; buffer size must be equal or smaller than `maxBufferSize`.
3709
3636
  * All float arrays must have the same length.
3710
3637
  * @param outputs any number stereo pairs (L, R) to render channels separately into.
3711
3638
  * @param effectsLeft the left stereo effect output buffer.
@@ -4596,22 +4523,30 @@ sampleIndex: number,
4596
4523
  */
4597
4524
 
4598
4525
  sampleCount: number) => Promise<unknown>;
4526
+ interface SoundBankWriteOptions {
4527
+ /**
4528
+ * A function to show progress for writing large sound banks. It can be undefined.
4529
+ */
4530
+ progressFunction?: ProgressFunction;
4531
+ /**
4532
+ * The `ISFT` field to set when writing. If unset, "SpessaSynth" is written.
4533
+ * This field indicates the last software that was used to edit this sound bank.
4534
+ */
4535
+ software?: string;
4536
+ }
4599
4537
  /**
4600
4538
  * Options for writing a SoundFont2 file.
4601
4539
  */
4602
- interface SoundFont2WriteOptions {
4540
+ interface SoundFont2WriteOptions extends SoundBankWriteOptions {
4603
4541
  /**
4604
4542
  * If the soundfont should be compressed with a given function.
4543
+ * This changes the version to 3.0.
4605
4544
  */
4606
4545
  compress: boolean;
4607
4546
  /**
4608
4547
  * The function for compressing samples. It can be undefined if not compressed.
4609
4548
  */
4610
4549
  compressionFunction?: SampleEncodingFunction;
4611
- /**
4612
- * A function to show progress for writing large banks. It can be undefined.
4613
- */
4614
- progressFunction?: ProgressFunction;
4615
4550
  /**
4616
4551
  * If the DMOD chunk should be written. Recommended.
4617
4552
  * Note that it will only be written if the modulators are unchanged.
@@ -4624,18 +4559,14 @@ interface SoundFont2WriteOptions {
4624
4559
  writeExtendedLimits: boolean;
4625
4560
  /**
4626
4561
  * If an SF3 bank should be decompressed back to SF2. Not recommended.
4562
+ * This changes the version to 2.4.
4627
4563
  */
4628
4564
  decompress: boolean;
4629
4565
  }
4630
4566
  /**
4631
4567
  * Options for writing a DLS file.
4632
4568
  */
4633
- interface DLSWriteOptions {
4634
- /**
4635
- * A function to show progress for writing large banks. It can be undefined.
4636
- */
4637
- progressFunction?: ProgressFunction;
4638
- }
4569
+ type DLSWriteOptions = SoundBankWriteOptions;
4639
4570
  interface GenericRange {
4640
4571
  min: number;
4641
4572
  max: number;
package/dist/index.js CHANGED
@@ -1813,12 +1813,39 @@ const dataEntryStates = {
1813
1813
  DataFine: 6
1814
1814
  };
1815
1815
  const customControllers = {
1816
+ /**
1817
+ * Cents, RPN for fine-tuning
1818
+ */
1816
1819
  channelTuning: 0,
1820
+ /**
1821
+ * Cents, only the decimal tuning, (e.g., transpose is 4.5,
1822
+ * Then shift by 4 keys + tune by 50 cents)
1823
+ */
1817
1824
  channelTransposeFine: 1,
1825
+ /**
1826
+ * The MIDI specification assumes the default modulation depth is 50 cents,
1827
+ * but it may vary for different sound banks.
1828
+ * For example, if you want a modulation depth of 100 cents,
1829
+ * the multiplier will be 2,
1830
+ * which, for a preset with a depth of 50,
1831
+ * will create a total modulation depth of 100 cents.
1832
+ */
1818
1833
  modulationMultiplier: 2,
1834
+ /**
1835
+ * Cents, set by system exclusive
1836
+ */
1819
1837
  masterTuning: 3,
1838
+ /**
1839
+ * Semitones, for RPN coarse tuning
1840
+ */
1820
1841
  channelTuningSemitones: 4,
1842
+ /**
1843
+ * Key shift: for system exclusive
1844
+ */
1821
1845
  channelKeyShift: 5,
1846
+ /**
1847
+ * Sf2 NPRN LSB for selecting a generator value
1848
+ */
1822
1849
  sf2NPRNGeneratorLSB: 6
1823
1850
  };
1824
1851
  //#endregion
@@ -8334,8 +8361,6 @@ function writeSF2Elements(bank, isPreset = false) {
8334
8361
  //#region src/soundbank/soundfont/write/write.ts
8335
8362
  const DEFAULT_SF2_WRITE_OPTIONS = {
8336
8363
  compress: false,
8337
- compressionFunction: void 0,
8338
- progressFunction: void 0,
8339
8364
  writeDefaultModulators: true,
8340
8365
  writeExtendedLimits: true,
8341
8366
  decompress: false
@@ -8359,65 +8384,40 @@ async function writeSF2Internal(bank, writeOptions = DEFAULT_SF2_WRITE_OPTIONS)
8359
8384
  * Write INFO
8360
8385
  */
8361
8386
  const infoArrays = [];
8362
- bank.soundBankInfo.software = "SpessaSynth";
8387
+ const info = bank.soundBankInfo;
8363
8388
  if (options?.compress || bank.samples.some((s) => s.isCompressed)) {
8364
- bank.soundBankInfo.version.major = 3;
8365
- bank.soundBankInfo.version.minor = 0;
8389
+ info.version.major = 3;
8390
+ info.version.minor = 0;
8366
8391
  }
8367
8392
  if (options?.decompress) {
8368
- bank.soundBankInfo.version.major = 2;
8369
- bank.soundBankInfo.version.minor = 4;
8393
+ info.version.major = 2;
8394
+ info.version.minor = 4;
8370
8395
  }
8371
8396
  const writeSF2Info = (type, data) => {
8397
+ if (!data) return;
8372
8398
  infoArrays.push(RIFFChunk.write(type, getStringBytes(data, true, true)));
8373
8399
  };
8374
- const ifilData = new IndexedByteArray(4);
8375
- writeWord(ifilData, bank.soundBankInfo.version.major);
8376
- writeWord(ifilData, bank.soundBankInfo.version.minor);
8377
- infoArrays.push(RIFFChunk.write("ifil", ifilData));
8378
- if (bank.soundBankInfo.romVersion) {
8400
+ {
8401
+ const ifilData = new IndexedByteArray(4);
8402
+ writeWord(ifilData, info.version.major);
8403
+ writeWord(ifilData, info.version.minor);
8404
+ infoArrays.push(RIFFChunk.write("ifil", ifilData));
8405
+ }
8406
+ writeSF2Info("isng", info.soundEngine);
8407
+ writeSF2Info("INAM", info.name);
8408
+ writeSF2Info("irom", info.romInfo);
8409
+ if (info.romVersion) {
8379
8410
  const ifilData = new IndexedByteArray(4);
8380
- writeWord(ifilData, bank.soundBankInfo.romVersion.major);
8381
- writeWord(ifilData, bank.soundBankInfo.romVersion.minor);
8411
+ writeWord(ifilData, info.romVersion.major);
8412
+ writeWord(ifilData, info.romVersion.minor);
8382
8413
  infoArrays.push(RIFFChunk.write("iver", ifilData));
8383
8414
  }
8384
- const commentText = (bank.soundBankInfo?.comment ?? "") + (bank.soundBankInfo.subject ? `
8385
- ${bank.soundBankInfo.subject}` : "");
8386
- for (const [t, d] of Object.entries(bank.soundBankInfo)) {
8387
- const type = t;
8388
- const data = d;
8389
- if (!data) continue;
8390
- switch (type) {
8391
- case "name":
8392
- writeSF2Info("INAM", data);
8393
- break;
8394
- case "comment":
8395
- writeSF2Info("ICMT", commentText);
8396
- break;
8397
- case "copyright":
8398
- writeSF2Info("ICOP", data);
8399
- break;
8400
- case "creationDate":
8401
- writeSF2Info("ICRD", toISODateString(data));
8402
- break;
8403
- case "engineer":
8404
- writeSF2Info("IENG", data);
8405
- break;
8406
- case "product":
8407
- writeSF2Info("IPRD", data);
8408
- break;
8409
- case "romInfo":
8410
- writeSF2Info("irom", data);
8411
- break;
8412
- case "software":
8413
- writeSF2Info("ISFT", data);
8414
- break;
8415
- case "soundEngine":
8416
- writeSF2Info("isng", data);
8417
- break;
8418
- case "subject": break;
8419
- }
8420
- }
8415
+ writeSF2Info("ICRD", toISODateString(info.creationDate));
8416
+ writeSF2Info("IENG", info.engineer);
8417
+ writeSF2Info("IPRD", info.product);
8418
+ writeSF2Info("ICOP", info.copyright);
8419
+ writeSF2Info("ICMT", info?.subject ? (info?.comment ? info.comment + "\n" : "") + info.subject : info?.comment);
8420
+ writeSF2Info("ISFT", options.software ?? "SpessaSynth");
8421
8421
  if (bank.defaultModulators.some((mod) => !SPESSASYNTH_DEFAULT_MODULATORS.some((m) => Modulator.isIdentical(m, mod, true))) && options?.writeDefaultModulators) {
8422
8422
  const mods = bank.defaultModulators;
8423
8423
  SpessaSynthInfo(`%cWriting %c${mods.length}%c default modulators...`, consoleColors.info, consoleColors.recognized, consoleColors.info);
@@ -8453,9 +8453,8 @@ ${bank.soundBankInfo.subject}` : "");
8453
8453
  ];
8454
8454
  const pdtaChunk = RIFFChunk.writeParts("pdta", chunks.map((c) => c.pdta), true);
8455
8455
  if (options.writeExtendedLimits && (instData.writeXdta || presData.writeXdta || bank.presets.some((p) => p.name.length > 20) || bank.instruments.some((i) => i.name.length > 20) || bank.samples.some((s) => s.name.length > 20))) {
8456
- SpessaSynthInfo(`%cWriting the xdta chunk as writeExendedLimits is enabled and at least one condition was met.`, consoleColors.info, consoleColors.value);
8457
- const xpdtaChunk = RIFFChunk.writeParts("xdta", chunks.map((c) => c.xdta), true);
8458
- infoArrays.push(xpdtaChunk);
8456
+ SpessaSynthInfo(`%cWriting the xdta chunk as writeExtendedLimits is enabled and at least one condition was met.`, consoleColors.info, consoleColors.value);
8457
+ infoArrays.push(RIFFChunk.writeParts("xdta", chunks.map((c) => c.xdta), true));
8459
8458
  }
8460
8459
  const infoChunk = RIFFChunk.writeParts("INFO", infoArrays, true);
8461
8460
  SpessaSynthInfo("%cWriting the output file...", consoleColors.info);
@@ -8465,7 +8464,7 @@ ${bank.soundBankInfo.subject}` : "");
8465
8464
  sdtaChunk,
8466
8465
  pdtaChunk
8467
8466
  ]);
8468
- SpessaSynthInfo(`%cSaved succesfully! Final file size: %c${main.length}`, consoleColors.info, consoleColors.recognized);
8467
+ SpessaSynthInfo(`%cSaved successfully! Final file size: %c${main.length}`, consoleColors.info, consoleColors.recognized);
8469
8468
  SpessaSynthGroupEnd();
8470
8469
  return main.buffer;
8471
8470
  }
@@ -10003,10 +10002,11 @@ var DownloadableSounds = class DownloadableSounds extends DLSVerifier {
10003
10002
  samples = new Array();
10004
10003
  instruments = new Array();
10005
10004
  soundBankInfo = {
10006
- name: "Unnamed",
10005
+ name: "Unnamed DLS sound bank",
10007
10006
  creationDate: /* @__PURE__ */ new Date(),
10008
10007
  software: "SpessaSynth",
10009
10008
  soundEngine: "DLS Level 2.2",
10009
+ product: "SpessaSynth DLS",
10010
10010
  version: {
10011
10011
  major: 2,
10012
10012
  minor: 4
@@ -10025,9 +10025,6 @@ var DownloadableSounds = class DownloadableSounds extends DLSVerifier {
10025
10025
  const chunks = [];
10026
10026
  while (dataArray.currentIndex < dataArray.length) chunks.push(RIFFChunk.read(dataArray));
10027
10027
  const dls = new DownloadableSounds();
10028
- dls.soundBankInfo.name = "Unnamed DLS";
10029
- dls.soundBankInfo.product = "SpessaSynth DLS";
10030
- dls.soundBankInfo.comment = "(no description)";
10031
10028
  const infoChunk = RIFFChunk.findListType(chunks, "INFO");
10032
10029
  if (infoChunk) while (infoChunk.data.currentIndex < infoChunk.data.length) {
10033
10030
  const infoPart = RIFFChunk.read(infoChunk.data);
@@ -10145,7 +10142,6 @@ var DownloadableSounds = class DownloadableSounds extends DLSVerifier {
10145
10142
  SpessaSynthGroupCollapsed("%cSaving SF2 to DLS level 2...", consoleColors.info);
10146
10143
  const dls = new DownloadableSounds();
10147
10144
  dls.soundBankInfo = { ...bank.soundBankInfo };
10148
- dls.soundBankInfo.comment = (dls.soundBankInfo.comment ?? "(No description)") + "\nConverted from SF2 to DLS with SpessaSynth";
10149
10145
  for (const s of bank.samples) dls.samples.push(DownloadableSoundsSample.fromSFSample(s));
10150
10146
  for (const p of bank.presets) dls.instruments.push(DownloadableSoundsInstrument.fromSFPreset(p, bank.samples));
10151
10147
  SpessaSynthInfo("%cConversion complete!", consoleColors.recognized);
@@ -10153,13 +10149,10 @@ var DownloadableSounds = class DownloadableSounds extends DLSVerifier {
10153
10149
  return dls;
10154
10150
  }
10155
10151
  static printInfo(dls) {
10156
- for (const [info, value] of Object.entries(dls.soundBankInfo)) {
10157
- if (typeof value === "object" && "major" in value) {
10158
- const v = value;
10159
- SpessaSynthInfo(`%c${info}: %c"${v.major}.${v.minor}"`, consoleColors.info, consoleColors.recognized);
10160
- }
10161
- SpessaSynthInfo(`%c${info}: %c${value.toLocaleString()}`, consoleColors.info, consoleColors.recognized);
10162
- }
10152
+ for (const [info, value] of Object.entries(dls.soundBankInfo)) if (typeof value === "object" && "major" in value) {
10153
+ const v = value;
10154
+ SpessaSynthInfo(`%c${info}: %c"${v.major}.${v.minor}"`, consoleColors.info, consoleColors.recognized);
10155
+ } else SpessaSynthInfo(`%c${info}: %c${value.toLocaleString()}`, consoleColors.info, consoleColors.recognized);
10163
10156
  }
10164
10157
  /**
10165
10158
  * Writes a DLS file
@@ -10196,43 +10189,19 @@ var DownloadableSounds = class DownloadableSounds extends DLSVerifier {
10196
10189
  const ptbl = RIFFChunk.write("ptbl", ptblData);
10197
10190
  this.soundBankInfo.software = "SpessaSynth";
10198
10191
  const infos = [];
10192
+ const info = this.soundBankInfo;
10199
10193
  const writeDLSInfo = (type, data) => {
10194
+ if (!data) return;
10200
10195
  infos.push(RIFFChunk.write(type, getStringBytes(data, true)));
10201
10196
  };
10202
- for (const [t, d] of Object.entries(this.soundBankInfo)) {
10203
- const type = t;
10204
- const data = d;
10205
- if (!data) continue;
10206
- switch (type) {
10207
- case "name":
10208
- writeDLSInfo("INAM", data);
10209
- break;
10210
- case "comment":
10211
- writeDLSInfo("ICMT", data);
10212
- break;
10213
- case "copyright":
10214
- writeDLSInfo("ICOP", data);
10215
- break;
10216
- case "creationDate":
10217
- writeDLSInfo("ICRD", toISODateString(data));
10218
- break;
10219
- case "engineer":
10220
- writeDLSInfo("IENG", data);
10221
- break;
10222
- case "product":
10223
- writeDLSInfo("IPRD", data);
10224
- break;
10225
- case "romVersion":
10226
- case "version":
10227
- case "soundEngine":
10228
- case "romInfo": break;
10229
- case "software":
10230
- writeDLSInfo("ISFT", data);
10231
- break;
10232
- case "subject": writeDLSInfo("ISBJ", data);
10233
- }
10234
- }
10235
- const info = RIFFChunk.writeParts("INFO", infos, true);
10197
+ writeDLSInfo("INAM", info.name);
10198
+ writeDLSInfo("ICMT", info.comment);
10199
+ writeDLSInfo("ICOP", info.copyright);
10200
+ writeDLSInfo("ICRD", toISODateString(info.creationDate));
10201
+ writeDLSInfo("IENG", info.engineer);
10202
+ writeDLSInfo("IPRD", info.product);
10203
+ writeDLSInfo("ISFT", options.software ?? "SpessaSynth");
10204
+ writeDLSInfo("ISBJ", info.subject);
10236
10205
  SpessaSynthInfo("%cCombining everything...");
10237
10206
  const out = RIFFChunk.writeParts("RIFF", [
10238
10207
  getStringBytes("DLS "),
@@ -10240,7 +10209,7 @@ var DownloadableSounds = class DownloadableSounds extends DLSVerifier {
10240
10209
  lins,
10241
10210
  ptbl,
10242
10211
  wvpl,
10243
- info
10212
+ RIFFChunk.writeParts("INFO", infos, true)
10244
10213
  ]);
10245
10214
  SpessaSynthInfo("%cSaved successfully!", consoleColors.recognized);
10246
10215
  SpessaSynthGroupEnd();
@@ -10255,7 +10224,6 @@ var DownloadableSounds = class DownloadableSounds extends DLSVerifier {
10255
10224
  soundBank.soundBankInfo.version.minor = 4;
10256
10225
  soundBank.soundBankInfo.version.major = 2;
10257
10226
  soundBank.soundBankInfo = { ...this.soundBankInfo };
10258
- soundBank.soundBankInfo.comment = (soundBank.soundBankInfo.comment ?? "(No description)") + "\nConverted from DLS to SF2 with SpessaSynth";
10259
10227
  for (const sample of this.samples) sample.toSFSample(soundBank);
10260
10228
  for (const instrument of this.instruments) instrument.toSFPreset(soundBank);
10261
10229
  soundBank.flush();
@@ -10635,13 +10603,10 @@ var BasicSoundBank = class BasicSoundBank {
10635
10603
  }
10636
10604
  }
10637
10605
  printInfo() {
10638
- for (const [info, value] of Object.entries(this.soundBankInfo)) {
10639
- if (typeof value === "object" && "major" in value) {
10640
- const v = value;
10641
- SpessaSynthInfo(`%c${info}: %c"${v.major}.${v.minor}"`, consoleColors.info, consoleColors.recognized);
10642
- }
10643
- SpessaSynthInfo(`%c${info}: %c${value.toLocaleString()}`, consoleColors.info, consoleColors.recognized);
10644
- }
10606
+ for (const [info, value] of Object.entries(this.soundBankInfo)) if (typeof value === "object" && "major" in value) {
10607
+ const v = value;
10608
+ SpessaSynthInfo(`%c${info}: %c"${v.major}.${v.minor}"`, consoleColors.info, consoleColors.recognized);
10609
+ } else SpessaSynthInfo(`%c${info}: %c${value.toLocaleString()}`, consoleColors.info, consoleColors.recognized);
10645
10610
  }
10646
10611
  };
10647
10612
  //#endregion
@@ -10887,7 +10852,7 @@ var SoundFont2 = class extends BasicSoundBank {
10887
10852
  const infoString = readBinaryStringIndexed(infoChunk.data, 4);
10888
10853
  if (infoString !== "INFO") {
10889
10854
  SpessaSynthGroupEnd();
10890
- throw new SyntaxError(`Invalid soundFont! Expected "INFO" or "${infoString}"`);
10855
+ throw new SyntaxError(`Invalid soundFont! Expected "INFO" got "${infoString}"`);
10891
10856
  }
10892
10857
  let xdtaChunk;
10893
10858
  while (infoChunk.data.length > infoChunk.data.currentIndex) {
@@ -19557,7 +19522,7 @@ var SpessaSynthProcessor = class {
19557
19522
  */
19558
19523
  onEventCall;
19559
19524
  /**
19560
- * Renders float32 audio data to stereo outputs; buffer size must be equal or smaller than `maxBufferSize`
19525
+ * Renders float32 audio data to stereo outputs; buffer size must be equal or smaller than `maxBufferSize`.
19561
19526
  * All float arrays must have the same length.
19562
19527
  * @param left the left output channel.
19563
19528
  * @param right the right output channel.
@@ -19566,7 +19531,7 @@ var SpessaSynthProcessor = class {
19566
19531
  */
19567
19532
  process;
19568
19533
  /**
19569
- * Renders float32 audio data to stereo outputs; buffer size must be equal or smaller than `maxBufferSize
19534
+ * Renders float32 audio data to stereo outputs; buffer size must be equal or smaller than `maxBufferSize`.
19570
19535
  * All float arrays must have the same length.
19571
19536
  * @param outputs any number stereo pairs (L, R) to render channels separately into.
19572
19537
  * @param effectsLeft the left stereo effect output buffer.