spessasynth_lib 3.24.3 → 3.24.6

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.
Files changed (99) hide show
  1. package/README.md +14 -4
  2. package/midi_parser/midi_loader.js +51 -28
  3. package/package.json +1 -2
  4. package/sequencer/sequencer.js +3 -3
  5. package/sequencer/worklet_sequencer/worklet_sequencer.js +6 -0
  6. package/synthetizer/synthetizer.js +8 -6
  7. package/synthetizer/worklet_processor.min.js +9 -9
  8. package/synthetizer/worklet_system/main_processor.js +9 -7
  9. package/synthetizer/worklet_system/worklet_methods/note_on.js +2 -1
  10. package/@types/external_midi/midi_handler.d.ts +0 -39
  11. package/@types/external_midi/web_midi_link.d.ts +0 -12
  12. package/@types/externals/stbvorbis_sync/stbvorbis_sync.min.d.ts +0 -1
  13. package/@types/index.d.ts +0 -44
  14. package/@types/midi_parser/basic_midi.d.ts +0 -36
  15. package/@types/midi_parser/midi_builder.d.ts +0 -68
  16. package/@types/midi_parser/midi_data.d.ts +0 -46
  17. package/@types/midi_parser/midi_editor.d.ts +0 -89
  18. package/@types/midi_parser/midi_loader.d.ts +0 -30
  19. package/@types/midi_parser/midi_message.d.ts +0 -155
  20. package/@types/midi_parser/midi_sequence.d.ts +0 -135
  21. package/@types/midi_parser/midi_writer.d.ts +0 -6
  22. package/@types/midi_parser/rmidi_writer.d.ts +0 -85
  23. package/@types/midi_parser/used_keys_loaded.d.ts +0 -10
  24. package/@types/sequencer/sequencer.d.ts +0 -277
  25. package/@types/sequencer/worklet_sequencer/sequencer_message.d.ts +0 -31
  26. package/@types/soundfont/basic_soundfont/basic_instrument.d.ts +0 -29
  27. package/@types/soundfont/basic_soundfont/basic_preset.d.ts +0 -86
  28. package/@types/soundfont/basic_soundfont/basic_sample.d.ts +0 -88
  29. package/@types/soundfont/basic_soundfont/basic_soundfont.d.ts +0 -102
  30. package/@types/soundfont/basic_soundfont/basic_zone.d.ts +0 -58
  31. package/@types/soundfont/basic_soundfont/basic_zones.d.ts +0 -22
  32. package/@types/soundfont/basic_soundfont/generator.d.ts +0 -102
  33. package/@types/soundfont/basic_soundfont/modulator.d.ts +0 -92
  34. package/@types/soundfont/basic_soundfont/riff_chunk.d.ts +0 -45
  35. package/@types/soundfont/basic_soundfont/write_dls/art2.d.ts +0 -6
  36. package/@types/soundfont/basic_soundfont/write_dls/articulator.d.ts +0 -28
  37. package/@types/soundfont/basic_soundfont/write_dls/combine_zones.d.ts +0 -8
  38. package/@types/soundfont/basic_soundfont/write_dls/ins.d.ts +0 -7
  39. package/@types/soundfont/basic_soundfont/write_dls/lins.d.ts +0 -5
  40. package/@types/soundfont/basic_soundfont/write_dls/modulator_converter.d.ts +0 -11
  41. package/@types/soundfont/basic_soundfont/write_dls/rgn2.d.ts +0 -8
  42. package/@types/soundfont/basic_soundfont/write_dls/wave.d.ts +0 -6
  43. package/@types/soundfont/basic_soundfont/write_dls/write_dls.d.ts +0 -6
  44. package/@types/soundfont/basic_soundfont/write_dls/wsmp.d.ts +0 -12
  45. package/@types/soundfont/basic_soundfont/write_dls/wvpl.d.ts +0 -8
  46. package/@types/soundfont/basic_soundfont/write_sf2/ibag.d.ts +0 -6
  47. package/@types/soundfont/basic_soundfont/write_sf2/igen.d.ts +0 -6
  48. package/@types/soundfont/basic_soundfont/write_sf2/imod.d.ts +0 -6
  49. package/@types/soundfont/basic_soundfont/write_sf2/inst.d.ts +0 -6
  50. package/@types/soundfont/basic_soundfont/write_sf2/pbag.d.ts +0 -6
  51. package/@types/soundfont/basic_soundfont/write_sf2/pgen.d.ts +0 -6
  52. package/@types/soundfont/basic_soundfont/write_sf2/phdr.d.ts +0 -6
  53. package/@types/soundfont/basic_soundfont/write_sf2/pmod.d.ts +0 -6
  54. package/@types/soundfont/basic_soundfont/write_sf2/sdta.d.ts +0 -11
  55. package/@types/soundfont/basic_soundfont/write_sf2/shdr.d.ts +0 -8
  56. package/@types/soundfont/basic_soundfont/write_sf2/soundfont_trimmer.d.ts +0 -6
  57. package/@types/soundfont/basic_soundfont/write_sf2/write.d.ts +0 -21
  58. package/@types/soundfont/dls/articulator_converter.d.ts +0 -19
  59. package/@types/soundfont/dls/dls_destinations.d.ts +0 -29
  60. package/@types/soundfont/dls/dls_preset.d.ts +0 -13
  61. package/@types/soundfont/dls/dls_sample.d.ts +0 -19
  62. package/@types/soundfont/dls/dls_soundfont.d.ts +0 -31
  63. package/@types/soundfont/dls/dls_sources.d.ts +0 -27
  64. package/@types/soundfont/dls/dls_zone.d.ts +0 -23
  65. package/@types/soundfont/dls/read_articulation.d.ts +0 -12
  66. package/@types/soundfont/dls/read_instrument.d.ts +0 -5
  67. package/@types/soundfont/dls/read_instrument_list.d.ts +0 -5
  68. package/@types/soundfont/dls/read_lart.d.ts +0 -7
  69. package/@types/soundfont/dls/read_region.d.ts +0 -7
  70. package/@types/soundfont/dls/read_samples.d.ts +0 -5
  71. package/@types/soundfont/load_soundfont.d.ts +0 -6
  72. package/@types/soundfont/read_sf2/generators.d.ts +0 -16
  73. package/@types/soundfont/read_sf2/instruments.d.ts +0 -29
  74. package/@types/soundfont/read_sf2/modulators.d.ts +0 -15
  75. package/@types/soundfont/read_sf2/presets.d.ts +0 -30
  76. package/@types/soundfont/read_sf2/samples.d.ts +0 -55
  77. package/@types/soundfont/read_sf2/soundfont.d.ts +0 -28
  78. package/@types/soundfont/read_sf2/zones.d.ts +0 -99
  79. package/@types/synthetizer/audio_effects/effects_config.d.ts +0 -41
  80. package/@types/synthetizer/audio_effects/fancy_chorus.d.ts +0 -97
  81. package/@types/synthetizer/audio_effects/reverb.d.ts +0 -7
  82. package/@types/synthetizer/key_modifier_manager.d.ts +0 -56
  83. package/@types/synthetizer/synth_event_handler.d.ts +0 -263
  84. package/@types/synthetizer/synth_soundfont_manager.d.ts +0 -52
  85. package/@types/synthetizer/synthetizer.d.ts +0 -358
  86. package/@types/synthetizer/worklet_system/message_protocol/worklet_message.d.ts +0 -98
  87. package/@types/synthetizer/worklet_system/worklet_methods/worklet_key_modifier.d.ts +0 -77
  88. package/@types/synthetizer/worklet_system/worklet_methods/worklet_soundfont_manager/sfman_message.d.ts +0 -7
  89. package/@types/synthetizer/worklet_system/worklet_utilities/controller_tables.d.ts +0 -23
  90. package/@types/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.d.ts +0 -155
  91. package/@types/synthetizer/worklet_url.d.ts +0 -5
  92. package/@types/utils/buffer_to_wav.d.ts +0 -31
  93. package/@types/utils/byte_functions/big_endian.d.ts +0 -13
  94. package/@types/utils/byte_functions/little_endian.d.ts +0 -35
  95. package/@types/utils/byte_functions/string.d.ts +0 -27
  96. package/@types/utils/byte_functions/variable_length_quantity.d.ts +0 -12
  97. package/@types/utils/indexed_array.d.ts +0 -21
  98. package/@types/utils/loggin.d.ts +0 -26
  99. package/@types/utils/other.d.ts +0 -37
package/README.md CHANGED
@@ -43,12 +43,21 @@ document.getElementById("button").onclick = async () =>
43
43
  - **Excellent SoundFont support:**
44
44
  - **Full Generator Support**
45
45
  - **Full Modulator Support:** *First (to my knowledge) JavaScript SoundFont synth with that feature!*
46
- - **GeneralUserGS Certified:** *[See more here!](https://github.com/mrbumpy409/GeneralUser-GS/blob/main/documentation/README.md)*
46
+ - **GeneralUserGS Compatible:** *[See more here!](https://github.com/mrbumpy409/GeneralUser-GS/blob/main/documentation/README.md)*
47
47
  - **SoundFont3 Support:** Play compressed SoundFonts!
48
48
  - **Experimental SF2Pack Support:** Play soundfonts compressed with BASSMIDI! (*Note: only works with vorbis compression*)
49
49
  - **Can load very large SoundFonts:** up to 4GB! *Note: Only Firefox handles this well; Chromium has a hard-coded memory limit*
50
+ - **Great DLS Support:**
51
+ - **DLS Level 1 Support**
52
+ - **DLS Level 2 Support**
53
+ - **Mobile DLS Support**
54
+ - **Correct articulator support:** *Converts articulators to both modulators and generators!*
55
+ - **Tested and working with gm.dls!**
56
+ - **Correct volume:** *Properly translated to SoundFont volume!*
57
+ - **A-Law encoding support**
58
+ - **Both unsigned 8-bit and signed 16-bit sample support (24-bit theoretically supported as well!)**
59
+ - **Detects special articulator combinations:** *Such as vibratoLfoToPitch*
50
60
  - **Soundfont manager:** Stack multiple soundfonts!
51
- - **DLS Level 1 and 2 Support:** *works with gm.dls!*
52
61
  - **Reverb and chorus support:** [customizable!](https://github.com/spessasus/SpessaSynth/wiki/Synthetizer-Class#effects-configuration-object)
53
62
  - **Export audio files** using [OfflineAudioContext](https://developer.mozilla.org/en-US/docs/Web/API/OfflineAudioContext)
54
63
  - **[Custom modulators for additional controllers](https://github.com/spessasus/SpessaSynth/wiki/Modulator-Class#default-modulators):** *Why not?*
@@ -106,15 +115,16 @@ document.getElementById("button").onclick = async () =>
106
115
  - **Variable compression quality:** You choose between file size and quality!
107
116
  - **Compression preserving:** Avoid decompressing and recompressing uncompressed samples for minimal quality loss!
108
117
 
109
- #### Read and write DLS Level 1 or 2 files
118
+ #### Read and write DLS Level One or Two files
110
119
  - Read DLS (DownLoadable Sounds) files as SF2 files!
111
120
  - **Works like a normal soundfont:** *Saving it as sf2 is still [just one function!](https://github.com/spessasus/SpessaSynth/wiki/SoundFont2-Class#write)*
112
121
  - Converts articulators to both **modulators** and **generators**!
113
122
  - Works with both unsigned 8-bit samples and signed 16-bit samples!
123
+ - A-Law encoding support
114
124
  - **Covers special generator cases:** *such as modLfoToPitch*!
115
125
  - **Correct volume:** *looking at you, Viena and gm.sf2!*
116
126
  - Support built right into the synthesizer!
117
- - **Convert SF2 to DLS:** [with limitations](https://github.com/spessasus/SpessaSynth/wiki/DLS-Conversion-Problem);
127
+ - **Convert SF2 to DLS:** [with limitations](https://github.com/spessasus/SpessaSynth/wiki/DLS-Conversion-Problem)
118
128
 
119
129
  ### Export MIDI as WAV
120
130
  - Save the MIDI file as WAV audio!
@@ -12,7 +12,9 @@ import { BasicMIDI, MIDIticksToSeconds } from "./basic_midi.js";
12
12
 
13
13
  /**
14
14
  * midi_loader.js
15
- * purpose: parses a midi file for the seqyencer, including things like marker or CC 2/4 loop detection, copyright detection etc.
15
+ * purpose:
16
+ * parses a midi file for the seqyencer,
17
+ * including things like marker or CC 2/4 loop detection, copyright detection, etc.
16
18
  */
17
19
 
18
20
  /**
@@ -65,7 +67,7 @@ class MIDI extends BasicMIDI
65
67
  SpessaSynthGroupEnd();
66
68
  throw new SyntaxError(`Invalid RMIDI Chunk header! Expected "data", got "${rmid}"`);
67
69
  }
68
- // this is an rmid, load the midi into array for parsing
70
+ // this is a rmid, load the midi into an array for parsing
69
71
  fileByteArray = riff.chunkData;
70
72
 
71
73
  // keep loading chunks until we get sfbk
@@ -87,7 +89,7 @@ class MIDI extends BasicMIDI
87
89
  }
88
90
  if (type === "dls ")
89
91
  {
90
- // assume bank offset of 0 by default. If we find any bank selects, then the offset is 1.
92
+ // Assume bank offset of 0 by default. If we find any bank selects, then the offset is 1.
91
93
  DLSRMID = true;
92
94
  }
93
95
  }
@@ -145,7 +147,13 @@ class MIDI extends BasicMIDI
145
147
 
146
148
  if (DLSRMID)
147
149
  {
148
- // assume bank offset of 0 by default. If we find any bank selects, then the offset is 1.
150
+ // Assume bank offset of 0 by default. If we find any bank selects, then the offset is 1.
151
+ this.bankOffset = 0;
152
+ }
153
+
154
+ // if no embedded bank, assume 0
155
+ if (this.embeddedSoundFont === undefined)
156
+ {
149
157
  this.bankOffset = 0;
150
158
  }
151
159
  }
@@ -198,8 +206,8 @@ class MIDI extends BasicMIDI
198
206
  let loopEnd = null;
199
207
 
200
208
  /**
201
- * For karaoke files, text events starting with @T are considered titles
202
- * usually the first one is the title, and the latter are things such as "sequenced by" etc.
209
+ * For karaoke files, text events starting with @T are considered titles,
210
+ * usually the first one is the title, and the latter is things such as "sequenced by" etc.
203
211
  * @type {boolean}
204
212
  */
205
213
  let karaokeHasTitle = false;
@@ -207,7 +215,7 @@ class MIDI extends BasicMIDI
207
215
  this.lastVoiceEventTick = 0;
208
216
 
209
217
  /**
210
- * Midi port numbers for each tracks
218
+ * Midi port numbers for each one of the tracks
211
219
  * @type {number[]}
212
220
  */
213
221
  this.midiPorts = [];
@@ -274,16 +282,19 @@ class MIDI extends BasicMIDI
274
282
  {
275
283
  statusByte = runningByte;
276
284
  }
277
- else if (!runningByte && statusByteCheck < 0x80)
278
- {
279
- // if we don't have a running byte and the status byte isn't valid, it's an error.
280
- SpessaSynthGroupEnd();
281
- throw new SyntaxError(`Unexpected byte with no running byte. (${statusByteCheck})`);
282
- }
283
285
  else
284
- {
285
- // if the status byte is valid, just use that
286
- statusByte = trackChunk.data[trackChunk.data.currentIndex++];
286
+ { // noinspection PointlessBooleanExpressionJS
287
+ if (!runningByte && statusByteCheck < 0x80)
288
+ {
289
+ // if we don't have a running byte and the status byte isn't valid, it's an error.
290
+ SpessaSynthGroupEnd();
291
+ throw new SyntaxError(`Unexpected byte with no running byte. (${statusByteCheck})`);
292
+ }
293
+ else
294
+ {
295
+ // if the status byte is valid, use that
296
+ statusByte = trackChunk.data[trackChunk.data.currentIndex++];
297
+ }
287
298
  }
288
299
  const statusByteChannel = getChannel(statusByte);
289
300
 
@@ -310,7 +321,7 @@ class MIDI extends BasicMIDI
310
321
 
311
322
  default:
312
323
  // voice message
313
- // get the midi message length
324
+ // gets the midi message length
314
325
  if (totalTicks > this.lastVoiceEventTick)
315
326
  {
316
327
  this.lastVoiceEventTick = totalTicks;
@@ -344,7 +355,7 @@ class MIDI extends BasicMIDI
344
355
  switch (statusByteChannel)
345
356
  {
346
357
  case -2:
347
- // since this is a meta message
358
+ // since this is a meta-message
348
359
  const eventText = readBytesAsString(eventData, eventData.length);
349
360
  switch (statusByte)
350
361
  {
@@ -404,7 +415,7 @@ class MIDI extends BasicMIDI
404
415
  // note here: .kar files sometimes just use...
405
416
  // lyrics instead of text because why not (of course)
406
417
  // perform the same check for @KMIDI KARAOKE FILE
407
- if (eventText.trim() === "@KMIDI KARAOKE FILE")
418
+ if (eventText.trim().startsWith("@KMIDI KARAOKE FILE"))
408
419
  {
409
420
  this.isKaraokeFile = true;
410
421
  SpessaSynthInfo("%cKaraoke MIDI detected!", consoleColors.recognized);
@@ -431,7 +442,7 @@ class MIDI extends BasicMIDI
431
442
  // it has a text event at the start of the file
432
443
  // "@KMIDI KARAOKE FILE"
433
444
  const checkedText = eventText.trim();
434
- if (checkedText === "@KMIDI KARAOKE FILE")
445
+ if (checkedText.startsWith("@KMIDI KARAOKE FILE"))
435
446
  {
436
447
  this.isKaraokeFile = true;
437
448
 
@@ -440,7 +451,8 @@ class MIDI extends BasicMIDI
440
451
  else if (this.isKaraokeFile)
441
452
  {
442
453
  // check for @T (title)
443
- // or @A because it is a title too sometimes??? idk it's weird
454
+ // or @A because it is a title too sometimes?
455
+ // IDK it's strange
444
456
  if (checkedText.startsWith("@T") || checkedText.startsWith("@A"))
445
457
  {
446
458
  if (!karaokeHasTitle)
@@ -477,6 +489,11 @@ class MIDI extends BasicMIDI
477
489
  // since this is a voice message
478
490
  // check for loop (CC 2/4)
479
491
  trackHasVoiceMessages = true;
492
+ // voice messages are 7-bit always
493
+ for (let j = 0; j < eventData.length; j++)
494
+ {
495
+ eventData[j] = Math.min(127, eventData[j]);
496
+ }
480
497
  if ((statusByte & 0xF0) === messageTypes.controllerChange)
481
498
  {
482
499
  switch (eventData[0])
@@ -494,7 +511,9 @@ class MIDI extends BasicMIDI
494
511
  }
495
512
  else
496
513
  {
497
- // this controller has occured more than once, this means that it doesnt indicate the loop
514
+ // this controller has occured more than once;
515
+ // this means
516
+ // that it doesn't indicate the loop
498
517
  loopEnd = 0;
499
518
  }
500
519
  break;
@@ -516,7 +535,7 @@ class MIDI extends BasicMIDI
516
535
  this.tracks.push(track);
517
536
  this.usedChannelsOnTrack.push(usedChannels);
518
537
 
519
- // if the track has no voice messages, its "track name" event (if it has any)
538
+ // If the track has no voice messages, its "track name" event (if it has any)
520
539
  // is some metadata. Add it to copyright
521
540
  if (!trackHasVoiceMessages)
522
541
  {
@@ -602,9 +621,13 @@ class MIDI extends BasicMIDI
602
621
 
603
622
  // fix midi ports:
604
623
  // midi tracks without ports will have a value of -1
605
- // if all ports have a value of -1, set it to 0, otherwise take the first midi port and replace all -1 with it
606
- // why do this? some midis (for some reason) specify all channels to port 1 or else, but leave the conductor track with no port pref.
607
- // this spessasynth to reserve the first 16 channels for the conductor track (which doesn't play anything) and use additional 16 for the actual ports.
624
+ // if all ports have a value of -1, set it to 0,
625
+ // otherwise take the first midi port and replace all -1 with it,
626
+ // why would we do this?
627
+ // some midis (for some reason) specify all channels to port 1 or else,
628
+ // but leave the conductor track with no port pref.
629
+ // this spessasynth to reserve the first 16 channels for the conductor track
630
+ // (which doesn't play anything) and use the additional 16 for the actual ports.
608
631
  let defaultPort = 0;
609
632
  for (let port of this.midiPorts)
610
633
  {
@@ -615,7 +638,7 @@ class MIDI extends BasicMIDI
615
638
  }
616
639
  }
617
640
  this.midiPorts = this.midiPorts.map(port => port === -1 ? defaultPort : port);
618
- // add dummy port if empty
641
+ // add fake port if empty
619
642
  if (this.midiPortChannelOffsets.length === 0)
620
643
  {
621
644
  this.midiPortChannelOffsets = [0];
@@ -723,7 +746,7 @@ class MIDI extends BasicMIDI
723
746
  {
724
747
  this.lyrics = this.lyrics.map(lyric =>
725
748
  {
726
- // one exception: hyphens at the end. Don't add a space to them
749
+ // One exception: hyphens at the end. Don't add a space to them
727
750
  if (lyric[lyric.length - 1] === 45)
728
751
  {
729
752
  return lyric;
package/package.json CHANGED
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "name": "spessasynth_lib",
3
- "version": "3.24.3",
3
+ "version": "3.24.6",
4
4
  "description": "MIDI and SoundFont2/DLS library with no compromises",
5
5
  "browser": "index.js",
6
- "types": "@types/index.d.ts",
7
6
  "type": "module",
8
7
  "scripts": {
9
8
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -149,12 +149,12 @@ export class Sequencer
149
149
  * @type {boolean}
150
150
  * @private
151
151
  */
152
- this._skipToFirstNoteOn = options?.skipToFirstNoteOn || true;
152
+ this._skipToFirstNoteOn = options?.skipToFirstNoteOn ?? true;
153
153
  /**
154
154
  * @type {boolean}
155
155
  * @private
156
156
  */
157
- this._preservePlaybackState = options?.preservePlaybackState || false;
157
+ this._preservePlaybackState = options?.preservePlaybackState ?? false;
158
158
 
159
159
  if (this._skipToFirstNoteOn === false)
160
160
  {
@@ -167,7 +167,7 @@ export class Sequencer
167
167
  this._sendMessage(WorkletSequencerMessageType.setPreservePlaybackState, true);
168
168
  }
169
169
 
170
- this.loadNewSongList(midiBinaries, options?.autoPlay || true);
170
+ this.loadNewSongList(midiBinaries, options?.autoPlay ?? true);
171
171
 
172
172
  window.addEventListener("beforeunload", this.resetMIDIOut.bind(this));
173
173
  }
@@ -161,6 +161,12 @@ class WorkletSequencer
161
161
  const wasPaused = this.paused && this.preservePlaybackState;
162
162
  this.pausedTime = undefined;
163
163
  this.post(WorkletSequencerReturnMessageType.timeChange, currentTime - time);
164
+ if (this.midiData.duration === 0)
165
+ {
166
+ SpessaSynthWarn("No duration!");
167
+ this.post(WorkletSequencerReturnMessageType.pause, true);
168
+ return;
169
+ }
164
170
  this._playTo(time);
165
171
  this._recalculateStartTime(time);
166
172
  if (wasPaused)
@@ -109,7 +109,7 @@ export class Synthetizer
109
109
  this._voicesAmount = 0;
110
110
 
111
111
  /**
112
- * For Black MIDI's - forces release time to 50ms
112
+ * For Black MIDI's - forces release time to 50 ms
113
113
  * @type {boolean}
114
114
  */
115
115
  this._highPerformanceMode = false;
@@ -268,7 +268,7 @@ export class Synthetizer
268
268
  }
269
269
 
270
270
  /**
271
- * For Black MIDI's - forces release time to 50ms
271
+ * For Black MIDI's - forces release time to 50 ms
272
272
  * @param {boolean} value
273
273
  */
274
274
  set highPerformanceMode(value)
@@ -325,8 +325,8 @@ export class Synthetizer
325
325
 
326
326
  /**
327
327
  * Sets the interpolation type for the synthesizer:
328
- * 0 - linear
329
- * 1 - nearest neighbor
328
+ * 0. - linear
329
+ * 1. - nearest neighbor
330
330
  * @param type {interpolationTypes}
331
331
  */
332
332
  setInterpolationType(type)
@@ -663,7 +663,7 @@ export class Synthetizer
663
663
 
664
664
  /**
665
665
  * Sets the master stereo panning
666
- * @param pan {number} -1 to 1, the pan (-1 is left, 0 is midde, 1 is right)
666
+ * @param pan {number} (-1 to 1), the pan (-1 is left, 0 is midde, 1 is right)
667
667
  */
668
668
  setMasterPan(pan)
669
669
  {
@@ -691,7 +691,8 @@ export class Synthetizer
691
691
  * Changes the patch for a given channel
692
692
  * @param channel {number} usually 0-15: the channel to change
693
693
  * @param programNumber {number} 0-127 the MIDI patch number
694
- * @param userChange {boolean} indicates if the program change has been called by user. defaults to false
694
+ * @param userChange {boolean} indicates if user has called the program change.
695
+ * defaults to false
695
696
  */
696
697
  programChange(channel, programNumber, userChange = false)
697
698
  {
@@ -912,6 +913,7 @@ export class Synthetizer
912
913
  for (let i = 0; i < this.channelsAmount; i++)
913
914
  {
914
915
  this.controllerChange(i, midiControllers.reverbDepth, 127);
916
+ this.lockController(i, midiControllers.reverbDepth, true);
915
917
  }
916
918
  return "That's the spirit!";
917
919
  }