spessasynth_core 3.27.8 → 4.0.1

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 (157) hide show
  1. package/README.md +85 -51
  2. package/dist/index.d.ts +4057 -0
  3. package/dist/index.js +17178 -0
  4. package/dist/index.js.map +1 -0
  5. package/package.json +24 -6
  6. package/index.js +0 -132
  7. package/src/externals/README.md +0 -6
  8. package/src/externals/fflate/LICENSE +0 -21
  9. package/src/externals/fflate/fflate.min.js +0 -1
  10. package/src/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -12
  11. package/src/externals/stbvorbis_sync/LICENSE +0 -202
  12. package/src/externals/stbvorbis_sync/NOTICE +0 -6
  13. package/src/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -1
  14. package/src/midi/README.md +0 -32
  15. package/src/midi/basic_midi.js +0 -587
  16. package/src/midi/midi_builder.js +0 -203
  17. package/src/midi/midi_loader.js +0 -321
  18. package/src/midi/midi_message.js +0 -254
  19. package/src/midi/midi_sequence.js +0 -230
  20. package/src/midi/midi_tools/get_note_times.js +0 -154
  21. package/src/midi/midi_tools/midi_editor.js +0 -611
  22. package/src/midi/midi_tools/midi_writer.js +0 -105
  23. package/src/midi/midi_tools/rmidi_writer.js +0 -566
  24. package/src/midi/midi_tools/used_keys_loaded.js +0 -256
  25. package/src/midi/xmf_loader.js +0 -454
  26. package/src/sequencer/README.md +0 -9
  27. package/src/sequencer/events.js +0 -81
  28. package/src/sequencer/play.js +0 -362
  29. package/src/sequencer/process_event.js +0 -165
  30. package/src/sequencer/process_tick.js +0 -104
  31. package/src/sequencer/sequencer_engine.js +0 -372
  32. package/src/sequencer/song_control.js +0 -196
  33. package/src/soundfont/README.md +0 -11
  34. package/src/soundfont/basic_soundfont/basic_global_zone.js +0 -6
  35. package/src/soundfont/basic_soundfont/basic_instrument.js +0 -115
  36. package/src/soundfont/basic_soundfont/basic_instrument_zone.js +0 -45
  37. package/src/soundfont/basic_soundfont/basic_preset.js +0 -313
  38. package/src/soundfont/basic_soundfont/basic_preset_zone.js +0 -39
  39. package/src/soundfont/basic_soundfont/basic_sample.js +0 -477
  40. package/src/soundfont/basic_soundfont/basic_soundbank.js +0 -740
  41. package/src/soundfont/basic_soundfont/basic_zone.js +0 -145
  42. package/src/soundfont/basic_soundfont/generator.js +0 -76
  43. package/src/soundfont/basic_soundfont/generator_types.js +0 -151
  44. package/src/soundfont/basic_soundfont/modulator.js +0 -581
  45. package/src/soundfont/basic_soundfont/riff_chunk.js +0 -195
  46. package/src/soundfont/basic_soundfont/write_dls/art2.js +0 -174
  47. package/src/soundfont/basic_soundfont/write_dls/articulator.js +0 -49
  48. package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +0 -374
  49. package/src/soundfont/basic_soundfont/write_dls/ins.js +0 -85
  50. package/src/soundfont/basic_soundfont/write_dls/lins.js +0 -15
  51. package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +0 -330
  52. package/src/soundfont/basic_soundfont/write_dls/rgn2.js +0 -120
  53. package/src/soundfont/basic_soundfont/write_dls/wave.js +0 -71
  54. package/src/soundfont/basic_soundfont/write_dls/write_dls.js +0 -124
  55. package/src/soundfont/basic_soundfont/write_dls/wsmp.js +0 -78
  56. package/src/soundfont/basic_soundfont/write_dls/wvpl.js +0 -35
  57. package/src/soundfont/basic_soundfont/write_sf2/ibag.js +0 -60
  58. package/src/soundfont/basic_soundfont/write_sf2/igen.js +0 -91
  59. package/src/soundfont/basic_soundfont/write_sf2/imod.js +0 -62
  60. package/src/soundfont/basic_soundfont/write_sf2/inst.js +0 -42
  61. package/src/soundfont/basic_soundfont/write_sf2/pbag.js +0 -57
  62. package/src/soundfont/basic_soundfont/write_sf2/pgen.js +0 -92
  63. package/src/soundfont/basic_soundfont/write_sf2/phdr.js +0 -61
  64. package/src/soundfont/basic_soundfont/write_sf2/pmod.js +0 -62
  65. package/src/soundfont/basic_soundfont/write_sf2/sdta.js +0 -131
  66. package/src/soundfont/basic_soundfont/write_sf2/shdr.js +0 -77
  67. package/src/soundfont/basic_soundfont/write_sf2/write.js +0 -287
  68. package/src/soundfont/dls/articulator_converter.js +0 -402
  69. package/src/soundfont/dls/dls_destinations.js +0 -38
  70. package/src/soundfont/dls/dls_instrument.js +0 -20
  71. package/src/soundfont/dls/dls_preset.js +0 -43
  72. package/src/soundfont/dls/dls_sample.js +0 -238
  73. package/src/soundfont/dls/dls_soundfont.js +0 -183
  74. package/src/soundfont/dls/dls_sources.js +0 -63
  75. package/src/soundfont/dls/dls_zone.js +0 -89
  76. package/src/soundfont/dls/read_articulation.js +0 -300
  77. package/src/soundfont/dls/read_instrument.js +0 -118
  78. package/src/soundfont/dls/read_instrument_list.js +0 -17
  79. package/src/soundfont/dls/read_lart.js +0 -35
  80. package/src/soundfont/dls/read_region.js +0 -157
  81. package/src/soundfont/dls/read_samples.js +0 -154
  82. package/src/soundfont/load_soundfont.js +0 -21
  83. package/src/soundfont/read_sf2/generators.js +0 -43
  84. package/src/soundfont/read_sf2/instrument_zones.js +0 -75
  85. package/src/soundfont/read_sf2/instruments.js +0 -71
  86. package/src/soundfont/read_sf2/modulators.js +0 -25
  87. package/src/soundfont/read_sf2/preset_zones.js +0 -79
  88. package/src/soundfont/read_sf2/presets.js +0 -80
  89. package/src/soundfont/read_sf2/samples.js +0 -317
  90. package/src/soundfont/read_sf2/soundfont.js +0 -452
  91. package/src/soundfont/read_sf2/zones.js +0 -28
  92. package/src/synthetizer/README.md +0 -7
  93. package/src/synthetizer/audio_engine/README.md +0 -9
  94. package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +0 -289
  95. package/src/synthetizer/audio_engine/engine_components/controller_tables.js +0 -90
  96. package/src/synthetizer/audio_engine/engine_components/dynamic_modulator_system.js +0 -95
  97. package/src/synthetizer/audio_engine/engine_components/enums.js +0 -18
  98. package/src/synthetizer/audio_engine/engine_components/key_modifier_manager.js +0 -151
  99. package/src/synthetizer/audio_engine/engine_components/lfo.js +0 -26
  100. package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +0 -282
  101. package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +0 -551
  102. package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +0 -181
  103. package/src/synthetizer/audio_engine/engine_components/modulator_curves.js +0 -89
  104. package/src/synthetizer/audio_engine/engine_components/soundfont_manager.js +0 -265
  105. package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -124
  106. package/src/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
  107. package/src/synthetizer/audio_engine/engine_components/voice.js +0 -525
  108. package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -402
  109. package/src/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -274
  110. package/src/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -159
  111. package/src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -53
  112. package/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -254
  113. package/src/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -20
  114. package/src/synthetizer/audio_engine/engine_methods/data_entry/awe32.js +0 -198
  115. package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -281
  116. package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -109
  117. package/src/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
  118. package/src/synthetizer/audio_engine/engine_methods/note_on.js +0 -220
  119. package/src/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
  120. package/src/synthetizer/audio_engine/engine_methods/program_change.js +0 -35
  121. package/src/synthetizer/audio_engine/engine_methods/render_voice.js +0 -214
  122. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/embedded_sound_bank.js +0 -42
  123. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -0
  124. package/src/synthetizer/audio_engine/engine_methods/soundfont_management/update_preset_list.js +0 -19
  125. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -23
  126. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -56
  127. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
  128. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
  129. package/src/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
  130. package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -1058
  131. package/src/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -23
  132. package/src/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -31
  133. package/src/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -29
  134. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
  135. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -26
  136. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
  137. package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
  138. package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
  139. package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
  140. package/src/synthetizer/audio_engine/main_processor.js +0 -817
  141. package/src/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -16
  142. package/src/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
  143. package/src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -116
  144. package/src/synthetizer/audio_engine/synth_processor_options.js +0 -18
  145. package/src/synthetizer/synth_constants.js +0 -26
  146. package/src/utils/README.md +0 -8
  147. package/src/utils/buffer_to_wav.js +0 -197
  148. package/src/utils/byte_functions/big_endian.js +0 -32
  149. package/src/utils/byte_functions/little_endian.js +0 -77
  150. package/src/utils/byte_functions/string.js +0 -92
  151. package/src/utils/byte_functions/variable_length_quantity.js +0 -42
  152. package/src/utils/fill_with_defaults.js +0 -21
  153. package/src/utils/indexed_array.js +0 -34
  154. package/src/utils/loggin.js +0 -71
  155. package/src/utils/other.js +0 -92
  156. package/src/utils/sysex_detector.js +0 -58
  157. package/src/utils/xg_hacks.js +0 -193
@@ -1,16 +0,0 @@
1
- import { SpessaSynthInfo } from "../../../utils/loggin.js";
2
- import { consoleColors } from "../../../utils/other.js";
3
- import { SynthesizerSnapshot } from "./synthesizer_snapshot.js";
4
-
5
- /**
6
- * Applies the snapshot to the synth
7
- * @param snapshot {SynthesizerSnapshot}
8
- * @this {SpessaSynthProcessor}
9
- */
10
- export function applySynthesizerSnapshot(snapshot)
11
- {
12
- this._snapshot = snapshot;
13
- SynthesizerSnapshot.applySnapshot(this, snapshot);
14
- SpessaSynthInfo("%cFinished applying snapshot!", consoleColors.info);
15
- this.resetAllControllers();
16
- }
@@ -1,175 +0,0 @@
1
- /**
2
- * Represents a snapshot of a single channel's state in the synthesizer.
3
- */
4
- export class ChannelSnapshot
5
- {
6
- /**
7
- * The channel's MIDI program number.
8
- * @type {number}
9
- */
10
- program;
11
-
12
- /**
13
- * The channel's bank number.
14
- * @type {number}
15
- */
16
- bank;
17
-
18
- /**
19
- * If the bank is LSB. For restoring.
20
- * @type {boolean}
21
- */
22
- isBankLSB;
23
-
24
- /**
25
- * The name of the patch currently loaded in the channel.
26
- * @type {string}
27
- */
28
- patchName;
29
-
30
- /**
31
- * Indicates whether the channel's program change is disabled.
32
- * @type {boolean}
33
- */
34
- lockPreset;
35
-
36
- /**
37
- * Indicates the MIDI system when the preset was locked
38
- * @type {SynthSystem}
39
- */
40
- lockedSystem;
41
-
42
- /**
43
- * The array of all MIDI controllers (in 14-bit values) with the modulator sources at the end.
44
- * @type {Int16Array}
45
- */
46
- midiControllers;
47
-
48
- /**
49
- * An array of booleans, indicating if the controller with a current index is locked.
50
- * @type {boolean[]}
51
- */
52
- lockedControllers;
53
-
54
- /**
55
- * Array of custom (not SF2) control values such as RPN pitch tuning, transpose, modulation depth, etc.
56
- * @type {Float32Array}
57
- */
58
- customControllers;
59
-
60
- /**
61
- * Indicates whether the channel vibrato is locked.
62
- * @type {boolean}
63
- */
64
- lockVibrato;
65
-
66
- /**
67
- * The channel's vibrato settings.
68
- * @type {Object}
69
- * @property {number} depth - Vibrato depth, in gain.
70
- * @property {number} delay - Vibrato delay from note on in seconds.
71
- * @property {number} rate - Vibrato rate in Hz.
72
- */
73
- channelVibrato;
74
-
75
- /**
76
- * Key shift for the channel.
77
- * @type {number}
78
- */
79
- channelTransposeKeyShift;
80
-
81
- /**
82
- * The channel's octave tuning in cents.
83
- * @type {Int8Array}
84
- */
85
- channelOctaveTuning;
86
-
87
- /**
88
- * Indicates whether the channel is muted.
89
- * @type {boolean}
90
- */
91
- isMuted;
92
-
93
- /**
94
- * Overrides velocity if greater than 0, otherwise disabled.
95
- * @type {number}
96
- */
97
- velocityOverride;
98
-
99
- /**
100
- * Indicates whether the channel is a drum channel.
101
- * @type {boolean}
102
- */
103
- drumChannel;
104
-
105
- /**
106
- * Creates a snapshot of a single channel's state in the synthesizer.
107
- * @param spessaSynthProcessor {SpessaSynthProcessor}
108
- * @param channelNumber {number}
109
- * @returns {ChannelSnapshot}
110
- */
111
- static getChannelSnapshot(spessaSynthProcessor, channelNumber)
112
- {
113
- const channelObject = spessaSynthProcessor.midiAudioChannels[channelNumber];
114
- const channelSnapshot = new ChannelSnapshot();
115
- // program data
116
- channelSnapshot.program = channelObject.preset.program;
117
- channelSnapshot.bank = channelObject.getBankSelect();
118
- channelSnapshot.isBankLSB = channelSnapshot.bank !== channelObject.bank;
119
- channelSnapshot.lockPreset = channelObject.lockPreset;
120
- channelSnapshot.lockedSystem = channelObject.lockedSystem;
121
- channelSnapshot.patchName = channelObject.preset.presetName;
122
-
123
- // controller data
124
- channelSnapshot.midiControllers = channelObject.midiControllers;
125
- channelSnapshot.lockedControllers = channelObject.lockedControllers;
126
- channelSnapshot.customControllers = channelObject.customControllers;
127
-
128
- // vibrato data
129
- channelSnapshot.channelVibrato = channelObject.channelVibrato;
130
- channelSnapshot.lockVibrato = channelObject.lockGSNRPNParams;
131
-
132
- // tuning and transpose data
133
- channelSnapshot.channelTransposeKeyShift = channelObject.channelTransposeKeyShift;
134
- channelSnapshot.channelOctaveTuning = channelObject.channelOctaveTuning;
135
-
136
- // other data
137
- channelSnapshot.isMuted = channelObject.isMuted;
138
- channelSnapshot.velocityOverride = channelObject.velocityOverride;
139
- channelSnapshot.drumChannel = channelObject.drumChannel;
140
- return channelSnapshot;
141
- }
142
-
143
- /**
144
- * Applies the snapshot to the specified channel.
145
- * @param spessaSynthProcessor {SpessaSynthProcessor}
146
- * @param channelNumber {number}
147
- * @param channelSnapshot {ChannelSnapshot}
148
- */
149
- static applyChannelSnapshot(spessaSynthProcessor, channelNumber, channelSnapshot)
150
- {
151
- const channelObject = spessaSynthProcessor.midiAudioChannels[channelNumber];
152
- channelObject.muteChannel(channelSnapshot.isMuted);
153
- channelObject.setDrums(channelSnapshot.drumChannel);
154
-
155
- // restore controllers
156
- channelObject.midiControllers = channelSnapshot.midiControllers;
157
- channelObject.lockedControllers = channelSnapshot.lockedControllers;
158
- channelObject.customControllers = channelSnapshot.customControllers;
159
- channelObject.updateChannelTuning();
160
-
161
- // restore vibrato and transpose
162
- channelObject.channelVibrato = channelSnapshot.channelVibrato;
163
- channelObject.lockGSNRPNParams = channelSnapshot.lockVibrato;
164
- channelObject.channelTransposeKeyShift = channelSnapshot.channelTransposeKeyShift;
165
- channelObject.channelOctaveTuning = channelSnapshot.channelOctaveTuning;
166
- channelObject.velocityOverride = channelSnapshot.velocityOverride;
167
-
168
- // restore preset and lock
169
- channelObject.setPresetLock(false);
170
- channelObject.setBankSelect(channelSnapshot.bank, channelSnapshot.isBankLSB);
171
- channelObject.programChange(channelSnapshot.program);
172
- channelObject.setPresetLock(channelSnapshot.lockPreset);
173
- channelObject.lockedSystem = channelSnapshot.lockedSystem;
174
- }
175
- }
@@ -1,116 +0,0 @@
1
- import { SpessaSynthInfo } from "../../../utils/loggin.js";
2
- import { consoleColors } from "../../../utils/other.js";
3
- import { ChannelSnapshot } from "./channel_snapshot.js";
4
- import { masterParameterType } from "../engine_methods/controller_control/master_parameters.js";
5
-
6
- /**
7
- * Represents a snapshot of the synthesizer's state.
8
- */
9
- export class SynthesizerSnapshot
10
- {
11
- /**
12
- * The individual channel snapshots.
13
- * @type {ChannelSnapshot[]}
14
- */
15
- channelSnapshots;
16
-
17
- /**
18
- * Key modifiers.
19
- * @type {KeyModifier[][]}
20
- */
21
- keyMappings;
22
-
23
- /**
24
- * Main synth volume (set by MIDI), from 0 to 1.
25
- * @type {number}
26
- */
27
- mainVolume;
28
-
29
- /**
30
- * Master stereo panning, from -1 to 1.
31
- * @type {number}
32
- */
33
- pan;
34
-
35
- /**
36
- * The synth's interpolation type.
37
- * @type {interpolationTypes}
38
- */
39
- interpolation;
40
-
41
- /**
42
- * The synth's system. Values can be "gs", "gm", "gm2" or "xg".
43
- * @type {SynthSystem}
44
- */
45
- system;
46
-
47
- /**
48
- * The current synth transposition in semitones. Can be a float.
49
- * @type {number}
50
- */
51
- transposition;
52
-
53
-
54
- /**
55
- * Creates a snapshot of the synthesizer's state.
56
- * @param spessaSynthProcessor {SpessaSynthProcessor}
57
- * @returns {SynthesizerSnapshot}
58
- */
59
- static createSynthesizerSnapshot(spessaSynthProcessor)
60
- {
61
- const snapshot = new SynthesizerSnapshot();
62
- // channel snapshots
63
- snapshot.channelSnapshots =
64
- spessaSynthProcessor.midiAudioChannels.map((_, i) =>
65
- ChannelSnapshot.getChannelSnapshot(spessaSynthProcessor, i));
66
-
67
- // key mappings
68
- snapshot.keyMappings = spessaSynthProcessor.keyModifierManager.getMappings();
69
- // pan and volume
70
- snapshot.mainVolume = spessaSynthProcessor.masterGain;
71
- snapshot.pan = spessaSynthProcessor.pan;
72
-
73
- // others
74
- snapshot.system = spessaSynthProcessor.system;
75
- snapshot.interpolation = spessaSynthProcessor.interpolationType;
76
- snapshot.transposition = spessaSynthProcessor.transposition;
77
-
78
- // effect config is stored on the main thread, leave it empty
79
- snapshot.effectsConfig = {};
80
- return snapshot;
81
-
82
- }
83
-
84
- /**
85
- * Applies the snapshot to the synthesizer.
86
- * @param spessaSynthProcessor {SpessaSynthProcessor}
87
- * @param snapshot {SynthesizerSnapshot}
88
- */
89
- static applySnapshot(spessaSynthProcessor, snapshot)
90
- {
91
- // restore system
92
- spessaSynthProcessor.setSystem(snapshot.system);
93
-
94
- // restore pan and volume
95
- spessaSynthProcessor.setMasterParameter(masterParameterType.mainVolume, snapshot.mainVolume);
96
- spessaSynthProcessor.setMasterParameter(masterParameterType.masterPan, snapshot.pan);
97
- spessaSynthProcessor.transposeAllChannels(snapshot.transposition);
98
- spessaSynthProcessor.interpolationType = snapshot.interpolation;
99
- spessaSynthProcessor.keyModifierManager.setMappings(snapshot.keyMappings);
100
-
101
- // add channels if more needed
102
- while (spessaSynthProcessor.midiAudioChannels.length < snapshot.channelSnapshots.length)
103
- {
104
- spessaSynthProcessor.createMidiChannel();
105
- }
106
-
107
- // restore channels
108
- snapshot.channelSnapshots.forEach((channelSnapshot, index) =>
109
- {
110
- ChannelSnapshot.applyChannelSnapshot(spessaSynthProcessor, index, channelSnapshot);
111
- });
112
-
113
- SpessaSynthInfo("%cFinished restoring controllers!", consoleColors.info);
114
- }
115
- }
116
-
@@ -1,18 +0,0 @@
1
- /**
2
- * @typedef {Object} SynthProcessorOptions
3
- * @property {boolean?} enableEventSystem - if the event system is enabled.
4
- * @property {number?} initialTime - initial synth time, in seconds.
5
- * @property {boolean?} effectsEnabled - if the processor should route audio to the effect channels.
6
- * @property {number?} midiChannels - the default MIDI channel count.
7
- */
8
-
9
-
10
- /**
11
- * @type {SynthProcessorOptions}
12
- */
13
- export const DEFAULT_SYNTH_OPTIONS = {
14
- enableEventSystem: true,
15
- initialTime: 0,
16
- effectsEnabled: true,
17
- midiChannels: 16
18
- };
@@ -1,26 +0,0 @@
1
- /**
2
- * Synthesizer's default voice cap
3
- * @type {number}
4
- */
5
- export const VOICE_CAP = 350;
6
- /**
7
- * Default MIDI drum channel
8
- * @type {number}
9
- */
10
- export const DEFAULT_PERCUSSION = 9;
11
- /**
12
- * MIDI channel count
13
- * @type {number}
14
- */
15
- export const MIDI_CHANNEL_COUNT = 16;
16
- /**
17
- * Default bank select and SysEx mode
18
- * @type {string}
19
- */
20
- export const DEFAULT_SYNTH_MODE = "gs";
21
-
22
- export const ALL_CHANNELS_OR_DIFFERENT_ACTION = -1;
23
-
24
- export const EMBEDDED_SOUND_BANK_ID = `SPESSASYNTH_EMBEDDED_BANK_${Math.random()}`;
25
-
26
- export const GENERATOR_OVERRIDE_NO_CHANGE_VALUE = 32767;
@@ -1,8 +0,0 @@
1
- ## This is the utility folder.
2
-
3
- There are various utilities here used by the SpessaSynth library.
4
-
5
- - `byte_functions` - low-level byte manipulation utilities
6
- - `buffer_to_wav.js` - converts audio buffer to WAV format
7
- - `sysex_detector.js` - detects various System Exclusive messages
8
- - `xg_hacks.js` - XG-specific MIDI handling utilities
@@ -1,197 +0,0 @@
1
- /**
2
- * @typedef {Object} WaveMetadata
3
- * @property {string} title - the song's title
4
- * @property {string} artist - the song's artist
5
- * @property {string} album - the song's album
6
- * @property {string} genre - the song's genre
7
- */
8
-
9
- import { IndexedByteArray } from "./indexed_array.js";
10
- import { writeStringAsBytes } from "./byte_functions/string.js";
11
- import { writeRIFFChunkParts, writeRIFFChunkRaw } from "../soundfont/basic_soundfont/riff_chunk.js";
12
- import { writeLittleEndian } from "./byte_functions/little_endian.js";
13
-
14
- /**
15
- *
16
- * @param audioData {Float32Array[]} channels
17
- * @param sampleRate {number}
18
- * @param normalizeAudio {boolean} find the max sample point and set it to 1, and scale others with it
19
- * @param metadata {Partial<WaveMetadata>}
20
- * @param loop {{start: number, end: number}} loop start and end points in seconds. Undefined if no loop
21
- * @returns {ArrayBuffer}
22
- */
23
- export function audioToWav(audioData, sampleRate, normalizeAudio = true, metadata = {}, loop = undefined)
24
- {
25
- const length = audioData[0].length;
26
- const numChannels = audioData.length;
27
-
28
- const bytesPerSample = 2; // 16-bit PCM
29
-
30
- // prepare INFO chunk
31
- let infoChunk = new IndexedByteArray(0);
32
- const infoOn = Object.keys(metadata).length > 0;
33
- // INFO chunk
34
- if (infoOn)
35
- {
36
- const encoder = new TextEncoder();
37
- const infoChunks = [
38
- writeRIFFChunkRaw("ICMT", encoder.encode("Created with SpessaSynth"), true)
39
- ];
40
- if (metadata.artist)
41
- {
42
- infoChunks.push(
43
- writeRIFFChunkRaw("IART", encoder.encode(metadata.artist), true)
44
- );
45
- }
46
- if (metadata.album)
47
- {
48
- infoChunks.push(
49
- writeRIFFChunkRaw("IPRD", encoder.encode(metadata.album), true)
50
- );
51
- }
52
- if (metadata.genre)
53
- {
54
- infoChunks.push(
55
- writeRIFFChunkRaw("IGNR", encoder.encode(metadata.genre), true)
56
- );
57
- }
58
- if (metadata.title)
59
- {
60
- infoChunks.push(
61
- writeRIFFChunkRaw("INAM", encoder.encode(metadata.title), true)
62
- );
63
- }
64
- infoChunk = writeRIFFChunkParts("INFO", infoChunks, true);
65
- }
66
-
67
- // prepare CUE chunk
68
- let cueChunk = new IndexedByteArray(0);
69
- const cueOn = loop?.end !== undefined && loop?.start !== undefined;
70
- if (cueOn)
71
- {
72
- const loopStartSamples = Math.floor(loop.start * sampleRate);
73
- const loopEndSamples = Math.floor(loop.end * sampleRate);
74
-
75
- const cueStart = new IndexedByteArray(24);
76
- writeLittleEndian(cueStart, 0, 4); // dwIdentifier
77
- writeLittleEndian(cueStart, 0, 4); // dwPosition
78
- writeStringAsBytes(cueStart, "data"); // cue point ID
79
- writeLittleEndian(cueStart, 0, 4); // chunkStart, always 0
80
- writeLittleEndian(cueStart, 0, 4); // BlockStart, always 0
81
- writeLittleEndian(cueStart, loopStartSamples, 4); // sampleOffset
82
-
83
- const cueEnd = new IndexedByteArray(24);
84
- writeLittleEndian(cueEnd, 1, 4); // dwIdentifier
85
- writeLittleEndian(cueEnd, 0, 4); // dwPosition
86
- writeStringAsBytes(cueEnd, "data"); // cue point ID
87
- writeLittleEndian(cueEnd, 0, 4); // chunkStart, always 0
88
- writeLittleEndian(cueEnd, 0, 4); // BlockStart, always 0
89
- writeLittleEndian(cueEnd, loopEndSamples, 4); // sampleOffset
90
-
91
- cueChunk = writeRIFFChunkParts("cue ", [
92
- new IndexedByteArray([2, 0, 0, 0]), // cue points count
93
- cueStart,
94
- cueEnd]);
95
- }
96
-
97
- // Prepare the header
98
- const headerSize = 44;
99
- const dataSize = length * numChannels * bytesPerSample; // 16-bit per channel
100
- const fileSize = headerSize + dataSize + infoChunk.length + cueChunk.length - 8; // total file size minus the first 8 bytes
101
- const header = new Uint8Array(headerSize);
102
-
103
- // 'RIFF'
104
- header.set([82, 73, 70, 70], 0);
105
- // file length
106
- header.set(
107
- new Uint8Array([fileSize & 0xff, (fileSize >> 8) & 0xff, (fileSize >> 16) & 0xff, (fileSize >> 24) & 0xff]),
108
- 4
109
- );
110
- // 'WAVE'
111
- header.set([87, 65, 86, 69], 8);
112
- // 'fmt '
113
- header.set([102, 109, 116, 32], 12);
114
- // fmt chunk length
115
- header.set([16, 0, 0, 0], 16); // 16 for PCM
116
- // audio format (PCM)
117
- header.set([1, 0], 20);
118
- // number of channels (2)
119
- header.set([numChannels & 255, numChannels >> 8], 22);
120
- // sample rate
121
- header.set(
122
- new Uint8Array([sampleRate & 0xff, (sampleRate >> 8) & 0xff, (sampleRate >> 16) & 0xff, (sampleRate >> 24) & 0xff]),
123
- 24
124
- );
125
- // byte rate (sample rate * block align)
126
- const byteRate = sampleRate * numChannels * bytesPerSample; // 16-bit per channel
127
- header.set(
128
- new Uint8Array([byteRate & 0xff, (byteRate >> 8) & 0xff, (byteRate >> 16) & 0xff, (byteRate >> 24) & 0xff]),
129
- 28
130
- );
131
- // block align (channels * bytes per sample)
132
- header.set([numChannels * bytesPerSample, 0], 32); // n channels * 16-bit per channel / 8
133
- // bits per sample
134
- header.set([16, 0], 34); // 16-bit
135
-
136
- // data chunk identifier 'data'
137
- header.set([100, 97, 116, 97], 36);
138
- // data chunk length
139
- header.set(
140
- new Uint8Array([dataSize & 0xff, (dataSize >> 8) & 0xff, (dataSize >> 16) & 0xff, (dataSize >> 24) & 0xff]),
141
- 40
142
- );
143
-
144
- let wavData = new Uint8Array(fileSize + 8);
145
- let offset = headerSize;
146
- wavData.set(header, 0);
147
-
148
- // Interleave audio data (combine channels)
149
- let multiplier = 32767;
150
- if (normalizeAudio)
151
- {
152
- // find min and max values to prevent clipping when converting to 16 bits
153
- const numSamples = audioData[0].length;
154
-
155
- let maxAbsValue = 0;
156
-
157
- for (let ch = 0; ch < numChannels; ch++)
158
- {
159
- const data = audioData[ch];
160
- for (let i = 0; i < numSamples; i++)
161
- {
162
- const sample = Math.abs(data[i]);
163
- if (sample > maxAbsValue)
164
- {
165
- maxAbsValue = sample;
166
- }
167
- }
168
- }
169
-
170
- multiplier = maxAbsValue > 0 ? (32767 / maxAbsValue) : 1;
171
- }
172
- for (let i = 0; i < length; i++)
173
- {
174
- // interleave both channels
175
- audioData.forEach(d =>
176
- {
177
- const sample = Math.min(32767, Math.max(-32768, d[i] * multiplier));
178
- // convert to 16-bit
179
- wavData[offset++] = sample & 0xff;
180
- wavData[offset++] = (sample >> 8) & 0xff;
181
-
182
- });
183
-
184
- }
185
-
186
- if (infoOn)
187
- {
188
- wavData.set(infoChunk, offset);
189
- offset += infoChunk.length;
190
- }
191
- if (cueOn)
192
- {
193
- wavData.set(cueChunk, offset);
194
- }
195
-
196
- return wavData.buffer;
197
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * Reads as Big endian
3
- * @param dataArray {IndexedByteArray}
4
- * @param bytesAmount {number}
5
- * @returns {number}
6
- */
7
- export function readBytesAsUintBigEndian(dataArray, bytesAmount)
8
- {
9
- let out = 0;
10
- for (let i = 8 * (bytesAmount - 1); i >= 0; i -= 8)
11
- {
12
- out |= (dataArray[dataArray.currentIndex++] << i);
13
- }
14
- return out >>> 0;
15
- }
16
-
17
- /**
18
- * @param number {number}
19
- * @param bytesAmount {number}
20
- * @returns {number[]}
21
- */
22
- export function writeBytesAsUintBigEndian(number, bytesAmount)
23
- {
24
- const bytes = new Array(bytesAmount).fill(0);
25
- for (let i = bytesAmount - 1; i >= 0; i--)
26
- {
27
- bytes[i] = number & 0xFF;
28
- number >>= 8;
29
- }
30
-
31
- return bytes;
32
- }
@@ -1,77 +0,0 @@
1
- /**
2
- * Reads as little endian
3
- * @param dataArray {IndexedByteArray}
4
- * @param bytesAmount {number}
5
- * @returns {number}
6
- */
7
- export function readLittleEndian(dataArray, bytesAmount)
8
- {
9
- let out = 0;
10
- for (let i = 0; i < bytesAmount; i++)
11
- {
12
- out |= (dataArray[dataArray.currentIndex++] << i * 8);
13
- }
14
- // make sure it stays unsigned
15
- return out >>> 0;
16
- }
17
-
18
- /**
19
- * Writes a number as little endian seems to also work for negative numbers so yay?
20
- * @param dataArray {IndexedByteArray}
21
- * @param number {number}
22
- * @param byteTarget {number}
23
- */
24
- export function writeLittleEndian(dataArray, number, byteTarget)
25
- {
26
- for (let i = 0; i < byteTarget; i++)
27
- {
28
- dataArray[dataArray.currentIndex++] = (number >> (i * 8)) & 0xFF;
29
- }
30
- }
31
-
32
- /**
33
- * @param dataArray {IndexedByteArray}
34
- * @param word {number}
35
- */
36
- export function writeWord(dataArray, word)
37
- {
38
- dataArray[dataArray.currentIndex++] = word & 0xFF;
39
- dataArray[dataArray.currentIndex++] = word >> 8;
40
- }
41
-
42
- /**
43
- * @param dataArray {IndexedByteArray}
44
- * @param dword {number}
45
- */
46
- export function writeDword(dataArray, dword)
47
- {
48
- writeLittleEndian(dataArray, dword, 4);
49
- }
50
-
51
- /**
52
- * @param byte1 {number}
53
- * @param byte2 {number}
54
- * @returns {number}
55
- */
56
- export function signedInt16(byte1, byte2)
57
- {
58
- let val = (byte2 << 8) | byte1;
59
- if (val > 32767)
60
- {
61
- return val - 65536;
62
- }
63
- return val;
64
- }
65
-
66
- /**
67
- * @param byte {number}
68
- * @returns {number}
69
- */
70
- export function signedInt8(byte)
71
- {
72
- if (byte > 127)
73
- {
74
- return byte - 256;
75
- }
76
- return byte;
77
- }