spessasynth_core 1.1.3 → 1.1.5

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 (189) hide show
  1. package/LICENSE +3 -26
  2. package/README.md +156 -474
  3. package/index.js +74 -8
  4. package/package.json +21 -8
  5. package/src/externals/fflate/LICENSE +21 -0
  6. package/src/externals/fflate/fflate.min.js +1 -0
  7. package/src/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +12 -0
  8. package/src/externals/stbvorbis_sync/LICENSE +202 -0
  9. package/src/externals/stbvorbis_sync/NOTICE +6 -0
  10. package/src/externals/stbvorbis_sync/stbvorbis_sync.min.js +1 -0
  11. package/src/midi/README.md +32 -0
  12. package/src/midi/basic_midi.js +567 -0
  13. package/src/midi/midi_builder.js +202 -0
  14. package/src/midi/midi_loader.js +324 -0
  15. package/{spessasynth_core/midi_parser → src/midi}/midi_message.js +58 -35
  16. package/src/midi/midi_sequence.js +224 -0
  17. package/src/midi/midi_tools/get_note_times.js +154 -0
  18. package/src/midi/midi_tools/midi_editor.js +611 -0
  19. package/src/midi/midi_tools/midi_writer.js +99 -0
  20. package/src/midi/midi_tools/rmidi_writer.js +567 -0
  21. package/src/midi/midi_tools/used_keys_loaded.js +238 -0
  22. package/src/midi/xmf_loader.js +454 -0
  23. package/src/sequencer/README.md +5 -0
  24. package/src/sequencer/events.js +81 -0
  25. package/src/sequencer/play.js +349 -0
  26. package/src/sequencer/process_event.js +165 -0
  27. package/{spessasynth_core/sequencer/worklet_sequencer → src/sequencer}/process_tick.js +103 -84
  28. package/src/sequencer/sequencer_engine.js +367 -0
  29. package/src/sequencer/song_control.js +201 -0
  30. package/src/soundfont/README.md +13 -0
  31. package/src/soundfont/basic_soundfont/basic_instrument.js +77 -0
  32. package/src/soundfont/basic_soundfont/basic_preset.js +336 -0
  33. package/src/soundfont/basic_soundfont/basic_sample.js +206 -0
  34. package/src/soundfont/basic_soundfont/basic_soundfont.js +565 -0
  35. package/src/soundfont/basic_soundfont/basic_zone.js +64 -0
  36. package/src/soundfont/basic_soundfont/basic_zones.js +43 -0
  37. package/src/soundfont/basic_soundfont/generator.js +220 -0
  38. package/src/soundfont/basic_soundfont/modulator.js +378 -0
  39. package/src/soundfont/basic_soundfont/riff_chunk.js +149 -0
  40. package/src/soundfont/basic_soundfont/write_dls/art2.js +173 -0
  41. package/src/soundfont/basic_soundfont/write_dls/articulator.js +49 -0
  42. package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +400 -0
  43. package/src/soundfont/basic_soundfont/write_dls/ins.js +103 -0
  44. package/src/soundfont/basic_soundfont/write_dls/lins.js +18 -0
  45. package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +330 -0
  46. package/src/soundfont/basic_soundfont/write_dls/rgn2.js +121 -0
  47. package/src/soundfont/basic_soundfont/write_dls/wave.js +94 -0
  48. package/src/soundfont/basic_soundfont/write_dls/write_dls.js +119 -0
  49. package/src/soundfont/basic_soundfont/write_dls/wsmp.js +78 -0
  50. package/src/soundfont/basic_soundfont/write_dls/wvpl.js +32 -0
  51. package/src/soundfont/basic_soundfont/write_sf2/ibag.js +39 -0
  52. package/src/soundfont/basic_soundfont/write_sf2/igen.js +80 -0
  53. package/src/soundfont/basic_soundfont/write_sf2/imod.js +46 -0
  54. package/src/soundfont/basic_soundfont/write_sf2/inst.js +34 -0
  55. package/src/soundfont/basic_soundfont/write_sf2/pbag.js +39 -0
  56. package/src/soundfont/basic_soundfont/write_sf2/pgen.js +82 -0
  57. package/src/soundfont/basic_soundfont/write_sf2/phdr.js +42 -0
  58. package/src/soundfont/basic_soundfont/write_sf2/pmod.js +46 -0
  59. package/src/soundfont/basic_soundfont/write_sf2/sdta.js +80 -0
  60. package/src/soundfont/basic_soundfont/write_sf2/shdr.js +55 -0
  61. package/src/soundfont/basic_soundfont/write_sf2/write.js +222 -0
  62. package/src/soundfont/dls/articulator_converter.js +396 -0
  63. package/src/soundfont/dls/dls_destinations.js +38 -0
  64. package/src/soundfont/dls/dls_preset.js +44 -0
  65. package/src/soundfont/dls/dls_sample.js +75 -0
  66. package/src/soundfont/dls/dls_soundfont.js +186 -0
  67. package/src/soundfont/dls/dls_sources.js +62 -0
  68. package/src/soundfont/dls/dls_zone.js +95 -0
  69. package/src/soundfont/dls/read_articulation.js +299 -0
  70. package/src/soundfont/dls/read_instrument.js +121 -0
  71. package/src/soundfont/dls/read_instrument_list.js +17 -0
  72. package/src/soundfont/dls/read_lart.js +35 -0
  73. package/src/soundfont/dls/read_region.js +152 -0
  74. package/src/soundfont/dls/read_samples.js +270 -0
  75. package/src/soundfont/load_soundfont.js +21 -0
  76. package/src/soundfont/read_sf2/generators.js +46 -0
  77. package/{spessasynth_core/soundfont/chunk → src/soundfont/read_sf2}/instruments.js +20 -14
  78. package/src/soundfont/read_sf2/modulators.js +36 -0
  79. package/src/soundfont/read_sf2/presets.js +80 -0
  80. package/src/soundfont/read_sf2/samples.js +304 -0
  81. package/src/soundfont/read_sf2/soundfont.js +305 -0
  82. package/{spessasynth_core/soundfont/chunk → src/soundfont/read_sf2}/zones.js +68 -69
  83. package/src/synthetizer/README.md +7 -0
  84. package/src/synthetizer/audio_engine/README.md +9 -0
  85. package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +266 -0
  86. package/src/synthetizer/audio_engine/engine_components/controller_tables.js +88 -0
  87. package/src/synthetizer/audio_engine/engine_components/key_modifier_manager.js +150 -0
  88. package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/lfo.js +9 -6
  89. package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +282 -0
  90. package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +467 -0
  91. package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +181 -0
  92. package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/modulator_curves.js +33 -30
  93. package/src/synthetizer/audio_engine/engine_components/soundfont_manager.js +221 -0
  94. package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +120 -0
  95. package/{spessasynth_core/synthetizer/worklet_system/worklet_utilities → src/synthetizer/audio_engine/engine_components}/unit_converter.js +11 -4
  96. package/src/synthetizer/audio_engine/engine_components/voice.js +519 -0
  97. package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +401 -0
  98. package/src/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +263 -0
  99. package/src/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +132 -0
  100. package/src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +48 -0
  101. package/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +241 -0
  102. package/src/synthetizer/audio_engine/engine_methods/create_midi_channel.js +27 -0
  103. package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +253 -0
  104. package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +66 -0
  105. package/src/synthetizer/audio_engine/engine_methods/mute_channel.js +17 -0
  106. package/src/synthetizer/audio_engine/engine_methods/note_on.js +175 -0
  107. package/src/synthetizer/audio_engine/engine_methods/portamento_time.js +92 -0
  108. package/src/synthetizer/audio_engine/engine_methods/program_change.js +61 -0
  109. package/src/synthetizer/audio_engine/engine_methods/render_voice.js +196 -0
  110. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/clear_sound_font.js +30 -0
  111. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +22 -0
  112. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/reload_sound_font.js +28 -0
  113. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/send_preset_list.js +31 -0
  114. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/set_embedded_sound_font.js +21 -0
  115. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +20 -0
  116. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +55 -0
  117. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +16 -0
  118. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +30 -0
  119. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +63 -0
  120. package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +776 -0
  121. package/src/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +24 -0
  122. package/src/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +33 -0
  123. package/src/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +31 -0
  124. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +15 -0
  125. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +27 -0
  126. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +19 -0
  127. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +27 -0
  128. package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +15 -0
  129. package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +34 -0
  130. package/src/synthetizer/audio_engine/main_processor.js +804 -0
  131. package/src/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +15 -0
  132. package/src/synthetizer/audio_engine/snapshot/channel_snapshot.js +175 -0
  133. package/src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +116 -0
  134. package/src/synthetizer/synth_constants.js +22 -0
  135. package/{spessasynth_core → src}/utils/README.md +1 -0
  136. package/src/utils/buffer_to_wav.js +185 -0
  137. package/src/utils/byte_functions/big_endian.js +32 -0
  138. package/src/utils/byte_functions/little_endian.js +77 -0
  139. package/src/utils/byte_functions/string.js +107 -0
  140. package/src/utils/byte_functions/variable_length_quantity.js +42 -0
  141. package/src/utils/fill_with_defaults.js +21 -0
  142. package/src/utils/indexed_array.js +52 -0
  143. package/{spessasynth_core → src}/utils/loggin.js +70 -78
  144. package/src/utils/other.js +92 -0
  145. package/src/utils/sysex_detector.js +58 -0
  146. package/src/utils/xg_hacks.js +193 -0
  147. package/.idea/inspectionProfiles/Project_Default.xml +0 -10
  148. package/.idea/jsLibraryMappings.xml +0 -6
  149. package/.idea/modules.xml +0 -8
  150. package/.idea/spessasynth_core.iml +0 -12
  151. package/.idea/vcs.xml +0 -6
  152. package/spessasynth_core/midi_parser/README.md +0 -3
  153. package/spessasynth_core/midi_parser/midi_loader.js +0 -386
  154. package/spessasynth_core/sequencer/sequencer.js +0 -202
  155. package/spessasynth_core/sequencer/worklet_sequencer/play.js +0 -209
  156. package/spessasynth_core/sequencer/worklet_sequencer/process_event.js +0 -120
  157. package/spessasynth_core/sequencer/worklet_sequencer/song_control.js +0 -112
  158. package/spessasynth_core/soundfont/README.md +0 -4
  159. package/spessasynth_core/soundfont/chunk/generators.js +0 -205
  160. package/spessasynth_core/soundfont/chunk/modulators.js +0 -232
  161. package/spessasynth_core/soundfont/chunk/presets.js +0 -264
  162. package/spessasynth_core/soundfont/chunk/riff_chunk.js +0 -46
  163. package/spessasynth_core/soundfont/chunk/samples.js +0 -250
  164. package/spessasynth_core/soundfont/soundfont_parser.js +0 -301
  165. package/spessasynth_core/synthetizer/README.md +0 -6
  166. package/spessasynth_core/synthetizer/synthesizer.js +0 -313
  167. package/spessasynth_core/synthetizer/worklet_system/README.md +0 -3
  168. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/controller_control.js +0 -290
  169. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/data_entry.js +0 -280
  170. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/note_off.js +0 -102
  171. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/note_on.js +0 -77
  172. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/program_control.js +0 -140
  173. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/system_exclusive.js +0 -266
  174. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/tuning_control.js +0 -104
  175. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/vibrato_control.js +0 -29
  176. package/spessasynth_core/synthetizer/worklet_system/worklet_methods/voice_control.js +0 -223
  177. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/lowpass_filter.js +0 -133
  178. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/modulation_envelope.js +0 -73
  179. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/stereo_panner.js +0 -76
  180. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/volume_envelope.js +0 -272
  181. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/wavetable_oscillator.js +0 -83
  182. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_modulator.js +0 -175
  183. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_processor_channel.js +0 -106
  184. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/worklet_voice.js +0 -285
  185. package/spessasynth_core/utils/buffer_to_wav.js +0 -70
  186. package/spessasynth_core/utils/byte_functions.js +0 -141
  187. package/spessasynth_core/utils/other.js +0 -49
  188. package/spessasynth_core/utils/shiftable_array.js +0 -26
  189. package/spessasynth_core/utils/stbvorbis_sync.js +0 -1877
@@ -0,0 +1,24 @@
1
+ import { NON_CC_INDEX_OFFSET } from "../../engine_components/controller_tables.js";
2
+ import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulator.js";
3
+ import { computeModulators } from "../../engine_components/compute_modulator.js";
4
+
5
+ /**
6
+ * Sets the pressure of the given channel
7
+ * @this {MidiAudioChannel}
8
+ * @param pressure {number} the pressure of the channel
9
+ */
10
+ export function channelPressure(pressure)
11
+ {
12
+ this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.channelPressure] = pressure << 7;
13
+ this.voices.forEach(v =>
14
+ computeModulators(
15
+ v,
16
+ this.midiControllers,
17
+ 0,
18
+ modulatorSources.channelPressure
19
+ ));
20
+ this.synth.callEvent("channelpressure", {
21
+ channel: this.channelNumber,
22
+ pressure: pressure
23
+ });
24
+ }
@@ -0,0 +1,33 @@
1
+ import { NON_CC_INDEX_OFFSET } from "../../engine_components/controller_tables.js";
2
+ import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulator.js";
3
+ import { computeModulators } from "../../engine_components/compute_modulator.js";
4
+
5
+ /**
6
+ * Sets the pitch of the given channel
7
+ * @this {MidiAudioChannel}
8
+ * @param MSB {number} SECOND byte of the MIDI pitchWheel message
9
+ * @param LSB {number} FIRST byte of the MIDI pitchWheel message
10
+ */
11
+ export function pitchWheel(MSB, LSB)
12
+ {
13
+ if (this.lockedControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel])
14
+ {
15
+ return;
16
+ }
17
+ const bend = (LSB | (MSB << 7));
18
+ this.synth.callEvent("pitchwheel", {
19
+ channel: this.channelNumber,
20
+ MSB: MSB,
21
+ LSB: LSB
22
+ });
23
+ this.midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel] = bend;
24
+ this.voices.forEach(v =>
25
+ // compute pitch modulators
26
+ computeModulators(
27
+ v,
28
+ this.midiControllers,
29
+ 0,
30
+ modulatorSources.pitchWheel
31
+ ));
32
+ this.sendChannelProperty();
33
+ }
@@ -0,0 +1,31 @@
1
+ import { computeModulators } from "../../engine_components/compute_modulator.js";
2
+ import { modulatorSources } from "../../../../soundfont/basic_soundfont/modulator.js";
3
+
4
+ /**
5
+ * Sets the pressure of the given note on a specific channel
6
+ * @this {MidiAudioChannel}
7
+ * @param midiNote {number} 0-127
8
+ * @param pressure {number} the pressure of the note
9
+ */
10
+ export function polyPressure(midiNote, pressure)
11
+ {
12
+ this.voices.forEach(v =>
13
+ {
14
+ if (v.midiNote !== midiNote)
15
+ {
16
+ return;
17
+ }
18
+ v.pressure = pressure;
19
+ computeModulators(
20
+ v,
21
+ this.midiControllers,
22
+ 0,
23
+ modulatorSources.polyPressure
24
+ );
25
+ });
26
+ this.synth.callEvent("polypressure", {
27
+ channel: this.channelNumber,
28
+ midiNote: midiNote,
29
+ pressure: pressure
30
+ });
31
+ }
@@ -0,0 +1,15 @@
1
+ import { customControllers } from "../../engine_components/controller_tables.js";
2
+
3
+ /**
4
+ * Sets the worklet's primary tuning
5
+ * @this {SpessaSynthProcessor}
6
+ * @param cents {number}
7
+ */
8
+ export function setMasterTuning(cents)
9
+ {
10
+ cents = Math.round(cents);
11
+ for (let i = 0; i < this.midiAudioChannels.length; i++)
12
+ {
13
+ this.midiAudioChannels[i].setCustomController(customControllers.masterTuning, cents);
14
+ }
15
+ }
@@ -0,0 +1,27 @@
1
+ import { SpessaSynthInfo } from "../../../../utils/loggin.js";
2
+ import { consoleColors } from "../../../../utils/other.js";
3
+ import { customControllers } from "../../engine_components/controller_tables.js";
4
+
5
+ /**
6
+ * @this {MidiAudioChannel}
7
+ * @param cents {number}
8
+ */
9
+ export function setModulationDepth(cents)
10
+ {
11
+ cents = Math.round(cents);
12
+ SpessaSynthInfo(
13
+ `%cChannel ${this.channelNumber} modulation depth. Cents: %c${cents}`,
14
+ consoleColors.info,
15
+ consoleColors.value
16
+ );
17
+ /* ==============
18
+ IMPORTANT
19
+ here we convert cents into a multiplier.
20
+ midi spec assumes the default is 50 cents,
21
+ but it might be different for the soundfont,
22
+ so we create a multiplier by dividing cents by 50.
23
+ for example, if we want 100 cents, then multiplier will be 2,
24
+ which for a preset with depth of 50 will create 100.
25
+ ================ */
26
+ this.setCustomController(customControllers.modulationMultiplier, cents / 50);
27
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Sets the octave tuning for a given channel
3
+ * @this {MidiAudioChannel}
4
+ * @param tuning {Int8Array} LENGTH of 12!
5
+ * relative cent tuning.
6
+ * min -128 max 127.
7
+ */
8
+ export function setOctaveTuning(tuning)
9
+ {
10
+ if (tuning.length !== 12)
11
+ {
12
+ throw new Error("Tuning is not the length of 12.");
13
+ }
14
+ this.channelOctaveTuning = new Int8Array(128);
15
+ for (let i = 0; i < 128; i++)
16
+ {
17
+ this.channelOctaveTuning[i] = tuning[i % 12];
18
+ }
19
+ }
@@ -0,0 +1,27 @@
1
+ import { customControllers } from "../../engine_components/controller_tables.js";
2
+ import { SpessaSynthInfo } from "../../../../utils/loggin.js";
3
+ import { consoleColors } from "../../../../utils/other.js";
4
+
5
+ /**
6
+ * Sets the channel's tuning
7
+ * @this {MidiAudioChannel}
8
+ * @param cents {number}
9
+ * @param log {boolean}
10
+ */
11
+ export function setTuning(cents, log = true)
12
+ {
13
+ cents = Math.round(cents);
14
+ this.setCustomController(customControllers.channelTuning, cents);
15
+ if (!log)
16
+ {
17
+ return;
18
+ }
19
+ SpessaSynthInfo(
20
+ `%cFine tuning for %c${this.channelNumber}%c is now set to %c${cents}%c cents.`,
21
+ consoleColors.info,
22
+ consoleColors.recognized,
23
+ consoleColors.info,
24
+ consoleColors.value,
25
+ consoleColors.info
26
+ );
27
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Transposes all channels by given amount of semitones
3
+ * @this {SpessaSynthProcessor}
4
+ * @param semitones {number} Can be float
5
+ * @param force {boolean} defaults to false, if true transposes the channel even if it's a drum channel
6
+ */
7
+ export function transposeAllChannels(semitones, force = false)
8
+ {
9
+ this.transposition = 0;
10
+ for (let i = 0; i < this.midiAudioChannels.length; i++)
11
+ {
12
+ this.midiAudioChannels[i].transposeChannel(semitones, force);
13
+ }
14
+ this.transposition = semitones;
15
+ }
@@ -0,0 +1,34 @@
1
+ import { customControllers } from "../../engine_components/controller_tables.js";
2
+ import { midiControllers } from "../../../../midi/midi_message.js";
3
+
4
+ /**
5
+ * Transposes the channel by given amount of semitones
6
+ * @this {MidiAudioChannel}
7
+ * @param semitones {number} Can be float
8
+ * @param force {boolean} defaults to false, if true transposes the channel even if it's a drum channel
9
+ */
10
+ export function transposeChannel(semitones, force = false)
11
+ {
12
+ if (!this.drumChannel)
13
+ {
14
+ semitones += this.synth.transposition;
15
+ }
16
+ const keyShift = Math.trunc(semitones);
17
+ const currentTranspose = this.channelTransposeKeyShift + this.customControllers[customControllers.channelTransposeFine] / 100;
18
+ if (
19
+ (this.drumChannel && !force)
20
+ || semitones === currentTranspose
21
+ )
22
+ {
23
+ return;
24
+ }
25
+ if (keyShift !== this.channelTransposeKeyShift)
26
+ {
27
+ // stop all (and emit cc change)
28
+ this.controllerChange(midiControllers.allNotesOff, 127);
29
+ }
30
+ // apply transpose
31
+ this.channelTransposeKeyShift = keyShift;
32
+ this.setCustomController(customControllers.channelTransposeFine, (semitones - keyShift) * 100);
33
+ this.sendChannelProperty();
34
+ }