spessasynth_core 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/LICENSE +3 -26
  2. package/README.md +156 -474
  3. package/index.js +73 -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 -303
  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 -222
  177. package/spessasynth_core/synthetizer/worklet_system/worklet_utilities/lowpass_filter.js +0 -95
  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 -194
  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 -173
  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 -313
  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
@@ -1,77 +0,0 @@
1
- import { getWorkletVoices } from '../worklet_utilities/worklet_voice.js'
2
- import { generatorTypes } from '../../../soundfont/chunk/generators.js'
3
- import { computeModulators } from '../worklet_utilities/worklet_modulator.js'
4
- import { VOICE_CAP } from "../../synthesizer.js";
5
- import { SpessaSynthWarn } from '../../../utils/loggin.js'
6
-
7
- /**
8
- * Starts playing a MIDI note
9
- * @param channel {number} - The MIDI Channel to use
10
- * @param midiNote {number} - The MIDI key number
11
- * @param velocity {number} - The velocity (how hard is the key pressed)
12
- * @param enableDebugging {boolean} - used internally, ignore
13
- * @this {Synthesizer}
14
- */
15
- export function noteOn(channel, midiNote, velocity, enableDebugging = false)
16
- {
17
- if (velocity === 0) {
18
- this.noteOff(channel, midiNote);
19
- return;
20
- }
21
-
22
- if (
23
- (this.highPerformanceMode && this.totalVoicesAmount > 200 && velocity < 40) ||
24
- (this.highPerformanceMode && velocity < 10) ||
25
- (this.workletProcessorChannels[channel].isMuted)
26
- ) {
27
- return;
28
- }
29
-
30
- if(midiNote > 127 || midiNote < 0)
31
- {
32
- SpessaSynthWarn(`Received a noteOn for note`, midiNote, "Ignoring.");
33
- return;
34
- }
35
-
36
-
37
- // get voices
38
- const voices = getWorkletVoices(
39
- channel,
40
- midiNote,
41
- velocity,
42
- this.workletProcessorChannels[channel].preset,
43
- this.currentTime,
44
- this.sampleRate,
45
- data => this.sampleDump(data.channel, data.sampleID, data.sampleData),
46
- this.workletProcessorChannels[channel].cachedVoices,
47
- enableDebugging);
48
-
49
- // add voices and exclusive class apply
50
- const channelVoices = this.workletProcessorChannels[channel].voices;
51
- voices.forEach(voice => {
52
- const exclusive = voice.generators[generatorTypes.exclusiveClass];
53
- if(exclusive !== 0)
54
- {
55
- channelVoices.forEach(v => {
56
- if(v.generators[generatorTypes.exclusiveClass] === exclusive)
57
- {
58
- this.releaseVoice(v);
59
- v.generators[generatorTypes.releaseVolEnv] = -7200; // make the release nearly instant
60
- computeModulators(v, this.workletProcessorChannels[channel].midiControllers);
61
- }
62
- })
63
- }
64
- computeModulators(voice, this.workletProcessorChannels[channel].midiControllers);
65
- voice.currentAttenuationDb = 100;
66
- // set initial pan to avoid split second changing from middle to the correct value
67
- voice.currentPan = ( (Math.max(-500, Math.min(500, voice.modulatedGenerators[generatorTypes.pan] )) + 500) / 1000) // 0 to 1
68
- });
69
-
70
- this.totalVoicesAmount += voices.length;
71
- // cap the voices
72
- if(this.totalVoicesAmount > VOICE_CAP)
73
- {
74
- this.voiceKilling(voices.length);
75
- }
76
- channelVoices.push(...voices);
77
- }
@@ -1,140 +0,0 @@
1
- import { midiControllers } from '../../../midi_parser/midi_message.js'
2
- import { SoundFont2 } from '../../../soundfont/soundfont_parser.js'
3
- import { clearSamplesList } from '../worklet_utilities/worklet_voice.js'
4
- import { generatorTypes } from '../../../soundfont/chunk/generators.js'
5
-
6
- /**
7
- * executes a program change
8
- * @param channel {number} - The MIDI Channel to use
9
- * @param programNumber {number} - The MIDI program number
10
- * @this {Synthesizer}
11
- */
12
- export function programChange(channel, programNumber)
13
- {
14
- /**
15
- * @type {WorkletProcessorChannel}
16
- */
17
- const channelObject = this.workletProcessorChannels[channel];
18
- if(channelObject.lockPreset)
19
- {
20
- return;
21
- }
22
- // always 128 for percussion
23
- const bank = (channelObject.drumChannel ? 128 : channelObject.midiControllers[midiControllers.bankSelect]);
24
- const preset = this.soundfont.getPreset(bank, programNumber);
25
- this.setPreset(channel, preset);
26
- }
27
-
28
- /**
29
- * @param channel {number}
30
- * @param preset {Preset}
31
- * @this {Synthesizer}
32
- */
33
- export function setPreset(channel, preset)
34
- {
35
- if(this.workletProcessorChannels[channel].lockPreset)
36
- {
37
- return;
38
- }
39
- this.workletProcessorChannels[channel].preset = preset;
40
-
41
- // reset cached voices
42
- this.workletProcessorChannels[channel].cachedVoices = [];
43
- for (let i = 0; i < 128; i++) {
44
- this.workletProcessorChannels[channel].cachedVoices.push([]);
45
- }
46
- }
47
-
48
- /**
49
- * Toggles drums on a given channel
50
- * @param channel {number} - The MIDI Channel to use
51
- * @param isDrum {boolean} - boolean, if the channel should be drums
52
- * @this {Synthesizer}
53
- */
54
- export function setDrums(channel, isDrum)
55
- {
56
- const channelObject = this.workletProcessorChannels[channel];
57
- if(isDrum)
58
- {
59
- channelObject.drumChannel = true;
60
- this.setPreset(channel, this.soundfont.getPreset(128, channelObject.preset.program));
61
- }
62
- else
63
- {
64
- channelObject.percussionChannel = false;
65
- this.setPreset(channel, this.soundfont.getPreset(0, channelObject.preset.program));
66
- }
67
- }
68
-
69
- /**
70
- * Reloads the soundfont, stops all voices
71
- * @param buffer {ArrayBuffer} - the new soundfont buffer
72
- * @this {Synthesizer}
73
- */
74
- export function reloadSoundFont(buffer)
75
- {
76
- this.stopAllChannels(true);
77
- delete this.soundfont;
78
- clearSamplesList();
79
- delete this.workletDumpedSamplesList;
80
- this.workletDumpedSamplesList = [];
81
-
82
-
83
- this.soundfont = new SoundFont2(buffer);
84
- this.defaultPreset = this.soundfont.getPreset(0, 0);
85
- this.drumPreset = this.soundfont.getPreset(128, 0);
86
-
87
- for(let i = 0; i < this.workletProcessorChannels.length; i++)
88
- {
89
- const channelObject = this.workletProcessorChannels[i];
90
- channelObject.cachedVoices = [];
91
- for (let j = 0; j < 128; j++) {
92
- channelObject.cachedVoices.push([]);
93
- }
94
- channelObject.lockPreset = false;
95
- this.programChange(i, channelObject.preset.program);
96
- }
97
- }
98
-
99
- /**
100
- * saves a sample
101
- * @param channel {number}
102
- * @param sampleID {number}
103
- * @param sampleData {Float32Array}
104
- * @this {Synthesizer}
105
- */
106
- export function sampleDump(channel, sampleID, sampleData)
107
- {
108
- this.workletDumpedSamplesList[sampleID] = sampleData;
109
- // the sample maybe was loaded after the voice was sent... adjust the end position!
110
-
111
- // not for all channels because the system tells us for what channel this voice was dumped! yay!
112
- this.workletProcessorChannels[channel].voices.forEach(v => {
113
- if(v.sample.sampleID !== sampleID)
114
- {
115
- return;
116
- }
117
- v.sample.end = sampleData.length - 1 + v.generators[generatorTypes.endAddrOffset] + (v.generators[generatorTypes.endAddrsCoarseOffset] * 32768);
118
- // calculate for how long the sample has been playing and move the cursor there
119
- v.sample.cursor = (v.sample.playbackStep * this.sampleRate) * (this.currentTime - v.startTime);
120
- if(v.sample.loopingMode === 0) // no loop
121
- {
122
- if (v.sample.cursor >= v.sample.end)
123
- {
124
- v.finished = true;
125
- return;
126
- }
127
- }
128
- else
129
- {
130
- // go through modulo (adjust cursor if the sample has looped
131
- if(v.sample.cursor > v.sample.loopEnd)
132
- {
133
- v.sample.cursor = v.sample.cursor % (v.sample.loopEnd - v.sample.loopStart) + v.sample.loopStart - 1;
134
- }
135
- }
136
- // set start time to current!
137
- v.startTime = this.currentTime;
138
- })
139
-
140
- }
@@ -1,266 +0,0 @@
1
- import { arrayToHexString, consoleColors } from '../../../utils/other.js'
2
- import { SpessaSynthInfo, SpessaSynthWarn } from '../../../utils/loggin.js'
3
- /**
4
- * Executes a system exclusive
5
- * @param messageData {number[]} - The binary message data without f0
6
- * @param channelOffset {number} - Channel offset (for midi ports). Defaults to 0.
7
- * @this {Synthesizer}
8
- */
9
-
10
- export function systemExclusive(messageData, channelOffset = 0)
11
- {
12
- const type = messageData[0];
13
- switch (type)
14
- {
15
- default:
16
- SpessaSynthWarn(`%cUnrecognized SysEx: %c${arrayToHexString(messageData)}`,
17
- consoleColors.warn,
18
- consoleColors.unrecognized);
19
- break;
20
-
21
- // non realtime
22
- case 0x7E:
23
- // gm system
24
- if(messageData[2] === 0x09)
25
- {
26
- if(messageData[3] === 0x01)
27
- {
28
- SpessaSynthInfo("%cGM system on", consoleColors.info);
29
- this.system = "gm";
30
- }
31
- else if(messageData[3] === 0x03)
32
- {
33
- SpessaSynthInfo("%cGM2 system on", consoleColors.info);
34
- this.system = "gm2";
35
- }
36
- else
37
- {
38
- SpessaSynthInfo("%cGM system off, defaulting to GS", consoleColors.info);
39
- this.system = "gs";
40
- }
41
- }
42
- break;
43
-
44
- // realtime
45
- case 0x7F:
46
- if(messageData[2] === 0x04 && messageData[3] === 0x01)
47
- {
48
- // main volume
49
- const vol = messageData[5] << 7 | messageData[4];
50
- this.setMainVolume(vol / 16384);
51
- SpessaSynthInfo(`%cMaster Volume. Volume: %c${vol}`,
52
- consoleColors.info,
53
- consoleColors.value);
54
- }
55
- else
56
- if(messageData[2] === 0x04 && messageData[3] === 0x03)
57
- {
58
- // fine tuning
59
- const tuningValue = ((messageData[5] << 7) | messageData[6]) - 8192;
60
- const cents = Math.floor(tuningValue / 81.92); // [-100;+99] cents range
61
- this.setMasterTuning(cents);
62
- SpessaSynthInfo(`%cMaster Fine Tuning. Cents: %c${cents}`,
63
- consoleColors.info,
64
- consoleColors.value)
65
- }
66
- else
67
- if(messageData[2] === 0x04 && messageData[3] === 0x04)
68
- {
69
- // coarse tuning
70
- // lsb is ignored
71
- const semitones = messageData[5] - 64;
72
- const cents = semitones * 100;
73
- this.setMasterTuning(cents);
74
- SpessaSynthInfo(`%cMaster Coarse Tuning. Cents: %c${cents}`,
75
- consoleColors.info,
76
- consoleColors.value)
77
- }
78
- else
79
- {
80
- SpessaSynthWarn(
81
- `%cUnrecognized MIDI Real-time message: %c${arrayToHexString(messageData)}`,
82
- consoleColors.warn,
83
- consoleColors.unrecognized)
84
- }
85
- break;
86
-
87
- // this is a roland sysex
88
- // http://www.bandtrax.com.au/sysex.htm
89
- // https://cdn.roland.com/assets/media/pdf/AT-20R_30R_MI.pdf
90
- case 0x41:
91
- // messagedata[1] is device id (ignore as we're everything >:) )
92
- if(messageData[2] === 0x42 && messageData[3] === 0x12)
93
- {
94
- // this is a GS sysex
95
- // messageData[5] and [6] is the system parameter, messageData[7] is the value
96
- const messageValue = messageData[7];
97
- if(messageData[6] === 0x7F)
98
- {
99
- // GS mode set
100
- if(messageValue === 0x00) {
101
- // this is a GS reset
102
- SpessaSynthInfo("%cGS system on", consoleColors.info);
103
- this.system = "gs";
104
- }
105
- else if(messageValue === 0x7F)
106
- {
107
- // GS mode off
108
- SpessaSynthInfo("%cGS system off, switching to GM2", consoleColors.info);
109
- this.system = "gm2";
110
- }
111
- return;
112
- }
113
- else
114
- if(messageData[4] === 0x40)
115
- {
116
- // this is a system parameter
117
- if((messageData[5] & 0x10) > 0)
118
- {
119
- // this is an individual part (channel) parameter
120
- // determine the channel 0 means channel 10 (default), 1 means 1 etc.
121
- const channel = [9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15][messageData[5] & 0x0F] + channelOffset; // for example 1A means A = 11, which corresponds to channel 12 (counting from 1)
122
- switch (messageData[6])
123
- {
124
- default:
125
- break;
126
-
127
- case 0x15:
128
- // this is the Use for Drum Part sysex (multiple drums)
129
- this.setDrums(channel, messageValue > 0 && messageData[5] >> 4); // if set to other than 0, is a drum channel
130
- SpessaSynthInfo(
131
- `%cChannel %c${channel}%c ${messageValue > 0 && messageData[5] >> 4 ?
132
- "is now a drum channel"
133
- :
134
- "now isn't a drum channel"
135
- }%c via: %c${arrayToHexString(messageData)}`,
136
- consoleColors.info,
137
- consoleColors.value,
138
- consoleColors.recognized,
139
- consoleColors.info,
140
- consoleColors.value);
141
- return;
142
-
143
- case 0x16:
144
- // this is the pitch key shift sysex
145
- const keyShift = messageValue - 64;
146
- this.transposeChannel(channel, keyShift);
147
- SpessaSynthInfo(`%cChannel %c${channel}%c pitch shift. Semitones %c${keyShift}%c, with %c${arrayToHexString(messageData)}`,
148
- consoleColors.info,
149
- consoleColors.recognized,
150
- consoleColors.info,
151
- consoleColors.value,
152
- consoleColors.info,
153
- consoleColors.value);
154
- return;
155
-
156
- case 0x40:
157
- case 0x41:
158
- case 0x42:
159
- case 0x43:
160
- case 0x44:
161
- case 0x45:
162
- case 0x46:
163
- case 0x47:
164
- case 0x48:
165
- case 0x49:
166
- case 0x4A:
167
- case 0x4B:
168
- // scale tuning
169
- const cents = messageValue - 64;
170
- SpessaSynthInfo(`%cChannel %c${channel}%c tuning. Cents %c${cents}%c, with %c${arrayToHexString(messageData)}`,
171
- consoleColors.info,
172
- consoleColors.recognized,
173
- consoleColors.info,
174
- consoleColors.value,
175
- consoleColors.info,
176
- consoleColors.value);
177
- this.setChannelTuning(channel, cents);
178
- }
179
- }
180
- else
181
- // this is a global system parameter
182
- if(messageData[5] === 0x00 && messageData[6] === 0x06)
183
- {
184
- // roland master pan
185
- SpessaSynthInfo(`%cRoland GS Master Pan set to: %c${messageValue}%c with: %c${arrayToHexString(messageData)}`,
186
- consoleColors.info,
187
- consoleColors.value,
188
- consoleColors.info,
189
- consoleColors.value);
190
- this.setMasterPan((messageValue - 64) / 64);
191
- return;
192
- }
193
- else
194
- if(messageData[5] === 0x00 && messageData[6] === 0x05)
195
- {
196
- // roland master key shift (transpose)
197
- const transpose = messageValue - 64;
198
- SpessaSynthInfo(`%cRoland GS Master Key-Shift set to: %c${transpose}%c with: %c${arrayToHexString(messageData)}`,
199
- consoleColors.info,
200
- consoleColors.value,
201
- consoleColors.info,
202
- consoleColors.value);
203
- this.setMasterTuning(transpose * 100);
204
- return;
205
- }
206
- else
207
- if(messageData[5] === 0x00 && messageData[6] === 0x04)
208
- {
209
- // roland GS master volume
210
- SpessaSynthInfo(`%cRoland GS Master Volume set to: %c${messageValue}%c with: %c${arrayToHexString(messageData)}`,
211
- consoleColors.info,
212
- consoleColors.value,
213
- consoleColors.info,
214
- consoleColors.value);
215
- this.setMainVolume(messageValue / 127);
216
- return;
217
- }
218
- }
219
- // this is some other GS sysex...
220
- SpessaSynthWarn(`%cUnrecognized Roland %cGS %cSysEx: %c${arrayToHexString(messageData)}`,
221
- consoleColors.warn,
222
- consoleColors.recognized,
223
- consoleColors.warn,
224
- consoleColors.unrecognized);
225
- return;
226
- }
227
- else
228
- if(messageData[2] === 0x16 && messageData[3] === 0x12 && messageData[4] === 0x10)
229
- {
230
- // this is a roland master volume message
231
- this.setMainVolume(messageData[7] / 100);
232
- SpessaSynthInfo(`%cRoland Master Volume control set to: %c${messageData[7]}%c via: %c${arrayToHexString(messageData)}`,
233
- consoleColors.info,
234
- consoleColors.value,
235
- consoleColors.info,
236
- consoleColors.value);
237
- return;
238
- }
239
- else
240
- {
241
- // this is something else...
242
- SpessaSynthWarn(`%cUnrecognized Roland SysEx: %c${arrayToHexString(messageData)}`,
243
- consoleColors.warn,
244
- consoleColors.unrecognized);
245
- return;
246
- }
247
-
248
- // yamaha
249
- case 0x43:
250
- // XG on
251
- if(messageData[2] === 0x4C && messageData[5] === 0x7E && messageData[6] === 0x00)
252
- {
253
- SpessaSynthInfo("%cXG system on", consoleColors.info);
254
- this.system = "xg";
255
- }
256
- else
257
- {
258
- SpessaSynthWarn(`%cUnrecognized Yamaha SysEx: %c${arrayToHexString(messageData)}`,
259
- consoleColors.warn,
260
- consoleColors.unrecognized);
261
- }
262
- break;
263
-
264
-
265
- }
266
- }
@@ -1,104 +0,0 @@
1
- import {customControllers, NON_CC_INDEX_OFFSET} from '../worklet_utilities/worklet_processor_channel.js'
2
- import {consoleColors} from '../../../utils/other.js'
3
- import {modulatorSources} from '../../../soundfont/chunk/modulators.js'
4
- import {computeModulators} from '../worklet_utilities/worklet_modulator.js'
5
- import {SpessaSynthInfo} from '../../../utils/loggin.js'
6
-
7
- /**
8
- * Transposes all channels by given amount of semitones
9
- * @this {Synthesizer}
10
- * @param semitones {number} Can be float
11
- * @param force {boolean} defaults to false, if true transposes the channel even if it's a drum channel
12
- */
13
- export function transposeAllChannels(semitones, force = false)
14
- {
15
- this.transposition = 0;
16
- for (let i = 0; i < this.workletProcessorChannels.length; i++) {
17
- this.transposeChannel(i, semitones, force);
18
- }
19
- this.transposition = semitones;
20
- }
21
-
22
- /**
23
- * Transposes the channel by given amount of semitones
24
- * @this {Synthesizer}
25
- * @param channel {number} - The MIDI Channel to use
26
- * @param semitones {number} - Can be a float
27
- * @param force {boolean} - defaults to false, if true transposes the channel even if it's a drum channel
28
- */
29
- export function transposeChannel(channel, semitones, force=false)
30
- {
31
- semitones += this.transposition;
32
- const channelObject = this.workletProcessorChannels[channel];
33
- if(channelObject.drumChannel && !force)
34
- {
35
- return;
36
- }
37
- channelObject.customControllers[customControllers.channelTranspose] = semitones * 100;
38
- }
39
-
40
- /**
41
- * Sets the channel's tuning
42
- * @this {Synthesizer}
43
- * @param channel {number}
44
- * @param cents {number}
45
- */
46
- export function setChannelTuning(channel, cents)
47
- {
48
- const channelObject = this.workletProcessorChannels[channel];
49
- cents = Math.round(cents);
50
- channelObject.customControllers[customControllers.channelTuning] = cents;
51
- SpessaSynthInfo(`%cChannel ${channel} tuning. Cents: %c${cents}`,
52
- consoleColors.info,
53
- consoleColors.value);
54
- }
55
-
56
- /**
57
- * Sets the worklet's master tuning
58
- * @this {Synthesizer}
59
- * @param cents {number}
60
- */
61
- export function setMasterTuning(cents)
62
- {
63
- cents = Math.round(cents);
64
- for (let i = 0; i < this.workletProcessorChannels.length; i++) {
65
- this.workletProcessorChannels[i].customControllers[customControllers.masterTuning] = cents;
66
- }
67
- }
68
-
69
- /**
70
- * @this {Synthesizer}
71
- * @param channel {number}
72
- * @param cents {number}
73
- */
74
- export function setModulationDepth(channel, cents)
75
- {
76
- let channelObject = this.workletProcessorChannels[channel];
77
- cents = Math.round(cents);
78
- SpessaSynthInfo(`%cChannel ${channel} modulation depth. Cents: %c${cents}`,
79
- consoleColors.info,
80
- consoleColors.value);
81
- /* ==============
82
- IMPORTANT
83
- here we convert cents into a multiplier.
84
- midi spec assumes the default is 50 cents,
85
- but it might be different for the soundfont,
86
- so we create a multiplier by divinging cents by 50.
87
- for example, if we want 100 cents, then multiplier will be 2,
88
- which for a preset with depth of 50 will create 100.
89
- ================*/
90
- channelObject.customControllers[customControllers.modulationMultiplier] = cents / 50;
91
- }
92
-
93
- /**
94
- * Sets the pitch of the given channel
95
- * @this {Synthesizer}
96
- * @param channel {number} usually 0-15: the channel to change pitch
97
- * @param MSB {number} SECOND byte of the MIDI pitchWheel message
98
- * @param LSB {number} FIRST byte of the MIDI pitchWheel message
99
- */
100
- export function pitchWheel(channel, MSB, LSB)
101
- {
102
- this.workletProcessorChannels[channel].midiControllers[NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel] = (LSB | (MSB << 7));
103
- this.workletProcessorChannels[channel].voices.forEach(v => computeModulators(v, this.workletProcessorChannels[channel].midiControllers));
104
- }
@@ -1,29 +0,0 @@
1
- /**
2
- * @param channel {number}
3
- * @this {Synthesizer}
4
- */
5
- export function disableAndLockVibrato(channel)
6
- {
7
- this.workletProcessorChannels[channel].lockVibrato = true;
8
- this.workletProcessorChannels[channel].channelVibrato.rate = 0;
9
- this.workletProcessorChannels[channel].channelVibrato.delay = 0;
10
- this.workletProcessorChannels[channel].channelVibrato.depth = 0;
11
- }
12
-
13
- /**
14
- * @param channel {number}
15
- * @param depth {number}
16
- * @param rate {number}
17
- * @param delay {number}
18
- * @this {Synthesizer}
19
- */
20
- export function setVibrato(channel, depth, rate, delay)
21
- {
22
- if(this.workletProcessorChannels[channel].lockVibrato)
23
- {
24
- return;
25
- }
26
- this.workletProcessorChannels[channel].vibrato.rate = rate;
27
- this.workletProcessorChannels[channel].vibrato.delay = delay;
28
- this.workletProcessorChannels[channel].vibrato.depth = depth;
29
- }