spessasynth_core 3.27.8 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -51
- package/dist/index.d.ts +4057 -0
- package/dist/index.js +17188 -0
- package/dist/index.js.map +1 -0
- package/package.json +23 -6
- package/index.js +0 -132
- package/src/externals/README.md +0 -6
- package/src/externals/fflate/LICENSE +0 -21
- package/src/externals/fflate/fflate.min.js +0 -1
- package/src/externals/stbvorbis_sync/@types/stbvorbis_sync.d.ts +0 -12
- package/src/externals/stbvorbis_sync/LICENSE +0 -202
- package/src/externals/stbvorbis_sync/NOTICE +0 -6
- package/src/externals/stbvorbis_sync/stbvorbis_sync.min.js +0 -1
- package/src/midi/README.md +0 -32
- package/src/midi/basic_midi.js +0 -587
- package/src/midi/midi_builder.js +0 -203
- package/src/midi/midi_loader.js +0 -321
- package/src/midi/midi_message.js +0 -254
- package/src/midi/midi_sequence.js +0 -230
- package/src/midi/midi_tools/get_note_times.js +0 -154
- package/src/midi/midi_tools/midi_editor.js +0 -611
- package/src/midi/midi_tools/midi_writer.js +0 -105
- package/src/midi/midi_tools/rmidi_writer.js +0 -566
- package/src/midi/midi_tools/used_keys_loaded.js +0 -256
- package/src/midi/xmf_loader.js +0 -454
- package/src/sequencer/README.md +0 -9
- package/src/sequencer/events.js +0 -81
- package/src/sequencer/play.js +0 -362
- package/src/sequencer/process_event.js +0 -165
- package/src/sequencer/process_tick.js +0 -104
- package/src/sequencer/sequencer_engine.js +0 -372
- package/src/sequencer/song_control.js +0 -196
- package/src/soundfont/README.md +0 -11
- package/src/soundfont/basic_soundfont/basic_global_zone.js +0 -6
- package/src/soundfont/basic_soundfont/basic_instrument.js +0 -115
- package/src/soundfont/basic_soundfont/basic_instrument_zone.js +0 -45
- package/src/soundfont/basic_soundfont/basic_preset.js +0 -313
- package/src/soundfont/basic_soundfont/basic_preset_zone.js +0 -39
- package/src/soundfont/basic_soundfont/basic_sample.js +0 -477
- package/src/soundfont/basic_soundfont/basic_soundbank.js +0 -740
- package/src/soundfont/basic_soundfont/basic_zone.js +0 -145
- package/src/soundfont/basic_soundfont/generator.js +0 -76
- package/src/soundfont/basic_soundfont/generator_types.js +0 -151
- package/src/soundfont/basic_soundfont/modulator.js +0 -581
- package/src/soundfont/basic_soundfont/riff_chunk.js +0 -195
- package/src/soundfont/basic_soundfont/write_dls/art2.js +0 -174
- package/src/soundfont/basic_soundfont/write_dls/articulator.js +0 -49
- package/src/soundfont/basic_soundfont/write_dls/combine_zones.js +0 -374
- package/src/soundfont/basic_soundfont/write_dls/ins.js +0 -85
- package/src/soundfont/basic_soundfont/write_dls/lins.js +0 -15
- package/src/soundfont/basic_soundfont/write_dls/modulator_converter.js +0 -330
- package/src/soundfont/basic_soundfont/write_dls/rgn2.js +0 -120
- package/src/soundfont/basic_soundfont/write_dls/wave.js +0 -71
- package/src/soundfont/basic_soundfont/write_dls/write_dls.js +0 -124
- package/src/soundfont/basic_soundfont/write_dls/wsmp.js +0 -78
- package/src/soundfont/basic_soundfont/write_dls/wvpl.js +0 -35
- package/src/soundfont/basic_soundfont/write_sf2/ibag.js +0 -60
- package/src/soundfont/basic_soundfont/write_sf2/igen.js +0 -91
- package/src/soundfont/basic_soundfont/write_sf2/imod.js +0 -62
- package/src/soundfont/basic_soundfont/write_sf2/inst.js +0 -42
- package/src/soundfont/basic_soundfont/write_sf2/pbag.js +0 -57
- package/src/soundfont/basic_soundfont/write_sf2/pgen.js +0 -92
- package/src/soundfont/basic_soundfont/write_sf2/phdr.js +0 -61
- package/src/soundfont/basic_soundfont/write_sf2/pmod.js +0 -62
- package/src/soundfont/basic_soundfont/write_sf2/sdta.js +0 -131
- package/src/soundfont/basic_soundfont/write_sf2/shdr.js +0 -77
- package/src/soundfont/basic_soundfont/write_sf2/write.js +0 -287
- package/src/soundfont/dls/articulator_converter.js +0 -402
- package/src/soundfont/dls/dls_destinations.js +0 -38
- package/src/soundfont/dls/dls_instrument.js +0 -20
- package/src/soundfont/dls/dls_preset.js +0 -43
- package/src/soundfont/dls/dls_sample.js +0 -238
- package/src/soundfont/dls/dls_soundfont.js +0 -183
- package/src/soundfont/dls/dls_sources.js +0 -63
- package/src/soundfont/dls/dls_zone.js +0 -89
- package/src/soundfont/dls/read_articulation.js +0 -300
- package/src/soundfont/dls/read_instrument.js +0 -118
- package/src/soundfont/dls/read_instrument_list.js +0 -17
- package/src/soundfont/dls/read_lart.js +0 -35
- package/src/soundfont/dls/read_region.js +0 -157
- package/src/soundfont/dls/read_samples.js +0 -154
- package/src/soundfont/load_soundfont.js +0 -21
- package/src/soundfont/read_sf2/generators.js +0 -43
- package/src/soundfont/read_sf2/instrument_zones.js +0 -75
- package/src/soundfont/read_sf2/instruments.js +0 -71
- package/src/soundfont/read_sf2/modulators.js +0 -25
- package/src/soundfont/read_sf2/preset_zones.js +0 -79
- package/src/soundfont/read_sf2/presets.js +0 -80
- package/src/soundfont/read_sf2/samples.js +0 -317
- package/src/soundfont/read_sf2/soundfont.js +0 -452
- package/src/soundfont/read_sf2/zones.js +0 -28
- package/src/synthetizer/README.md +0 -7
- package/src/synthetizer/audio_engine/README.md +0 -9
- package/src/synthetizer/audio_engine/engine_components/compute_modulator.js +0 -289
- package/src/synthetizer/audio_engine/engine_components/controller_tables.js +0 -90
- package/src/synthetizer/audio_engine/engine_components/dynamic_modulator_system.js +0 -95
- package/src/synthetizer/audio_engine/engine_components/enums.js +0 -18
- package/src/synthetizer/audio_engine/engine_components/key_modifier_manager.js +0 -151
- package/src/synthetizer/audio_engine/engine_components/lfo.js +0 -26
- package/src/synthetizer/audio_engine/engine_components/lowpass_filter.js +0 -282
- package/src/synthetizer/audio_engine/engine_components/midi_audio_channel.js +0 -551
- package/src/synthetizer/audio_engine/engine_components/modulation_envelope.js +0 -181
- package/src/synthetizer/audio_engine/engine_components/modulator_curves.js +0 -89
- package/src/synthetizer/audio_engine/engine_components/soundfont_manager.js +0 -265
- package/src/synthetizer/audio_engine/engine_components/stereo_panner.js +0 -124
- package/src/synthetizer/audio_engine/engine_components/unit_converter.js +0 -73
- package/src/synthetizer/audio_engine/engine_components/voice.js +0 -525
- package/src/synthetizer/audio_engine/engine_components/volume_envelope.js +0 -402
- package/src/synthetizer/audio_engine/engine_components/wavetable_oscillator.js +0 -274
- package/src/synthetizer/audio_engine/engine_methods/controller_control/controller_change.js +0 -159
- package/src/synthetizer/audio_engine/engine_methods/controller_control/master_parameters.js +0 -53
- package/src/synthetizer/audio_engine/engine_methods/controller_control/reset_controllers.js +0 -254
- package/src/synthetizer/audio_engine/engine_methods/create_midi_channel.js +0 -20
- package/src/synthetizer/audio_engine/engine_methods/data_entry/awe32.js +0 -198
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_coarse.js +0 -281
- package/src/synthetizer/audio_engine/engine_methods/data_entry/data_entry_fine.js +0 -109
- package/src/synthetizer/audio_engine/engine_methods/mute_channel.js +0 -17
- package/src/synthetizer/audio_engine/engine_methods/note_on.js +0 -220
- package/src/synthetizer/audio_engine/engine_methods/portamento_time.js +0 -92
- package/src/synthetizer/audio_engine/engine_methods/program_change.js +0 -35
- package/src/synthetizer/audio_engine/engine_methods/render_voice.js +0 -214
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/embedded_sound_bank.js +0 -42
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/get_preset.js +0 -0
- package/src/synthetizer/audio_engine/engine_methods/soundfont_management/update_preset_list.js +0 -19
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/kill_note.js +0 -23
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/note_off.js +0 -56
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_channels.js +0 -16
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/stop_all_notes.js +0 -30
- package/src/synthetizer/audio_engine/engine_methods/stopping_notes/voice_killing.js +0 -63
- package/src/synthetizer/audio_engine/engine_methods/system_exclusive.js +0 -1058
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/channel_pressure.js +0 -23
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/pitch_wheel.js +0 -31
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/poly_pressure.js +0 -29
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_master_tuning.js +0 -15
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_modulation_depth.js +0 -26
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_octave_tuning.js +0 -19
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/set_tuning.js +0 -27
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_all_channels.js +0 -15
- package/src/synthetizer/audio_engine/engine_methods/tuning_control/transpose_channel.js +0 -34
- package/src/synthetizer/audio_engine/main_processor.js +0 -817
- package/src/synthetizer/audio_engine/snapshot/apply_synthesizer_snapshot.js +0 -16
- package/src/synthetizer/audio_engine/snapshot/channel_snapshot.js +0 -175
- package/src/synthetizer/audio_engine/snapshot/synthesizer_snapshot.js +0 -116
- package/src/synthetizer/audio_engine/synth_processor_options.js +0 -18
- package/src/synthetizer/synth_constants.js +0 -26
- package/src/utils/README.md +0 -8
- package/src/utils/buffer_to_wav.js +0 -197
- package/src/utils/byte_functions/big_endian.js +0 -32
- package/src/utils/byte_functions/little_endian.js +0 -77
- package/src/utils/byte_functions/string.js +0 -92
- package/src/utils/byte_functions/variable_length_quantity.js +0 -42
- package/src/utils/fill_with_defaults.js +0 -21
- package/src/utils/indexed_array.js +0 -34
- package/src/utils/loggin.js +0 -71
- package/src/utils/other.js +0 -92
- package/src/utils/sysex_detector.js +0 -58
- package/src/utils/xg_hacks.js +0 -193
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/indexed_array.ts","../src/utils/byte_functions/string.ts","../src/utils/byte_functions/little_endian.ts","../src/utils/riff_chunk.ts","../src/utils/fill_with_defaults.ts","../src/utils/write_wav.ts","../src/utils/byte_functions/big_endian.ts","../src/utils/byte_functions/variable_length_quantity.ts","../src/utils/other.ts","../src/externals/fflate/fflate.min.js","../src/externals/fflate/fflate_wrapper.ts","../src/utils/loggin.ts","../src/utils/exports.ts","../src/midi/midi_message.ts","../src/midi/enums.ts","../src/midi/midi_tools/midi_writer.ts","../src/synthesizer/audio_engine/engine_components/synth_constants.ts","../src/utils/midi_hacks.ts","../src/utils/sysex_detector.ts","../src/midi/midi_tools/get_gs_on.ts","../src/soundbank/basic_soundbank/midi_patch.ts","../src/midi/midi_tools/rmidi_writer.ts","../src/midi/midi_tools/used_keys_loaded.ts","../src/midi/midi_tools/get_note_times.ts","../src/synthesizer/enums.ts","../src/midi/midi_tools/midi_editor.ts","../src/midi/xmf_loader.ts","../src/midi/midi_track.ts","../src/midi/midi_loader.ts","../src/utils/load_date.ts","../src/midi/basic_midi.ts","../src/midi/midi_tools/midi_builder.ts","../src/sequencer/process_event.ts","../src/sequencer/process_tick.ts","../src/sequencer/song_control.ts","../src/soundbank/basic_soundbank/generator_types.ts","../src/soundbank/enums.ts","../src/synthesizer/audio_engine/engine_components/controller_tables.ts","../src/synthesizer/audio_engine/engine_methods/controller_control/reset_controllers.ts","../src/sequencer/play.ts","../src/sequencer/sequencer.ts","../src/externals/stbvorbis_sync/stbvorbis_sync.min.js","../src/externals/stbvorbis_sync/stbvorbis_wrapper.ts","../src/synthesizer/audio_engine/engine_components/unit_converter.ts","../src/synthesizer/audio_engine/engine_components/dsp_chain/volume_envelope.ts","../src/synthesizer/audio_engine/engine_methods/controller_control/master_parameters.ts","../src/utils/byte_functions/bit_mask.ts","../src/synthesizer/audio_engine/engine_components/modulator_curves.ts","../src/soundbank/basic_soundbank/modulator_source.ts","../src/soundbank/basic_soundbank/modulator.ts","../src/soundbank/basic_soundbank/generator.ts","../src/soundbank/basic_soundbank/basic_zone.ts","../src/soundbank/basic_soundbank/basic_global_zone.ts","../src/soundbank/basic_soundbank/basic_preset_zone.ts","../src/soundbank/basic_soundbank/basic_instrument_zone.ts","../src/soundbank/basic_soundbank/basic_instrument.ts","../src/soundbank/basic_soundbank/basic_preset.ts","../src/soundbank/basic_soundbank/preset_selector.ts","../src/synthesizer/audio_engine/engine_components/sound_bank_manager.ts","../src/synthesizer/audio_engine/engine_components/dsp_chain/stereo_panner.ts","../src/synthesizer/audio_engine/engine_components/dsp_chain/lowpass_filter.ts","../src/synthesizer/audio_engine/engine_components/synth_processor_options.ts","../src/synthesizer/audio_engine/engine_methods/stopping_notes/voice_killing.ts","../src/synthesizer/audio_engine/engine_components/dsp_chain/modulation_envelope.ts","../src/synthesizer/audio_engine/engine_components/audio_sample.ts","../src/synthesizer/audio_engine/engine_components/voice.ts","../src/synthesizer/audio_engine/engine_methods/system_exclusive.ts","../src/synthesizer/audio_engine/snapshot/channel_snapshot.ts","../src/synthesizer/audio_engine/engine_components/key_modifier_manager.ts","../src/synthesizer/audio_engine/snapshot/synthesizer_snapshot.ts","../src/synthesizer/audio_engine/engine_components/master_parameters.ts","../src/synthesizer/audio_engine/engine_components/internal_synth_values.ts","../src/synthesizer/audio_engine/engine_components/dsp_chain/lfo.ts","../src/synthesizer/audio_engine/engine_components/dsp_chain/wavetable_oscillator.ts","../src/synthesizer/audio_engine/engine_components/dsp_chain/render_voice.ts","../src/synthesizer/audio_engine/engine_methods/controller_control/data_entry/data_entry_coarse.ts","../src/synthesizer/audio_engine/engine_methods/controller_control/data_entry/awe32.ts","../src/synthesizer/audio_engine/engine_methods/controller_control/data_entry/data_entry_fine.ts","../src/synthesizer/audio_engine/engine_methods/controller_control/controller_change.ts","../src/synthesizer/audio_engine/engine_methods/portamento_time.ts","../src/synthesizer/audio_engine/engine_methods/note_on.ts","../src/synthesizer/audio_engine/engine_methods/stopping_notes/note_off.ts","../src/synthesizer/audio_engine/engine_methods/program_change.ts","../src/synthesizer/audio_engine/engine_components/dynamic_modulator_system.ts","../src/synthesizer/audio_engine/engine_components/compute_modulator.ts","../src/synthesizer/audio_engine/engine_components/midi_channel.ts","../src/soundbank/soundfont/write/sdta.ts","../src/soundbank/basic_soundbank/basic_sample.ts","../src/soundbank/soundfont/read/samples.ts","../src/soundbank/soundfont/write/shdr.ts","../src/soundbank/soundfont/write/write_sf2_elements.ts","../src/soundbank/soundfont/write/write.ts","../src/soundbank/downloadable_sounds/dls_verifier.ts","../src/soundbank/downloadable_sounds/wave_sample.ts","../src/soundbank/downloadable_sounds/dls_sample.ts","../src/soundbank/downloadable_sounds/sample.ts","../src/soundbank/downloadable_sounds/default_dls_modulators.ts","../src/soundbank/downloadable_sounds/connection_source.ts","../src/soundbank/downloadable_sounds/connection_block.ts","../src/soundbank/downloadable_sounds/articulation.ts","../src/soundbank/downloadable_sounds/wave_link.ts","../src/soundbank/downloadable_sounds/region.ts","../src/soundbank/downloadable_sounds/instrument.ts","../src/soundbank/downloadable_sounds/downloadable_sounds.ts","../src/soundbank/basic_soundbank/basic_soundbank.ts","../src/soundbank/soundfont/read/generators.ts","../src/soundbank/soundfont/read/preset_zones.ts","../src/soundbank/soundfont/read/presets.ts","../src/soundbank/soundfont/read/instrument_zones.ts","../src/soundbank/soundfont/read/instruments.ts","../src/soundbank/soundfont/read/modulators.ts","../src/soundbank/soundfont/read/zones.ts","../src/soundbank/soundfont/read/soundfont.ts","../src/soundbank/sound_bank_loader.ts","../src/synthesizer/processor.ts"],"sourcesContent":["/**\n * Indexed_array.ts\n * purpose: extends Uint8Array with a currentIndex property.\n */\n\nexport class IndexedByteArray extends Uint8Array {\n /**\n * The current index of the array.\n */\n public currentIndex = 0;\n\n /**\n * Returns a section of an array.\n * @param start The beginning of the specified portion of the array.\n * @param end The end of the specified portion of the array. This is exclusive of the element at the index 'end'.\n */\n public slice(start?: number, end?: number): IndexedByteArray {\n const a = super.slice(start, end) as IndexedByteArray;\n a.currentIndex = 0;\n return a;\n }\n}\n","import { IndexedByteArray } from \"../indexed_array\";\n\n/**\n * Reads bytes as an ASCII string. This version works with any numeric array.\n * @param dataArray the array to read from.\n * @param bytes the amount of bytes to read.\n * @param offset the offset in the array to start reading from.\n * @returns the string.\n */\nexport function readBinaryString(\n dataArray: ArrayLike<number>,\n bytes = dataArray.length,\n offset = 0\n) {\n let string = \"\";\n for (let i = 0; i < bytes; i++) {\n const byte = dataArray[offset + i];\n if (byte === 0) {\n return string;\n }\n\n string += String.fromCharCode(byte);\n }\n return string;\n}\n\n/**\n * Reads bytes as an ASCII string from an IndexedByteArray.\n * @param dataArray the IndexedByteArray to read from.\n * @param bytes the amount of bytes to read.\n * @returns the string.\n */\nexport function readBinaryStringIndexed(\n dataArray: IndexedByteArray,\n bytes: number\n) {\n const startIndex = dataArray.currentIndex;\n dataArray.currentIndex += bytes;\n return readBinaryString(dataArray, bytes, startIndex);\n}\n\n/**\n * Gets ASCII bytes from string.\n * @param string the string.\n * @param addZero adds a zero terminator at the end.\n * @param ensureEven ensures even byte count.\n * @returns the binary data.\n */\nexport function getStringBytes(\n string: string,\n addZero = false,\n ensureEven = false\n): IndexedByteArray {\n let len = string.length;\n if (addZero) {\n len++;\n }\n if (ensureEven && len % 2 !== 0) {\n len++;\n }\n const arr = new IndexedByteArray(len);\n writeBinaryStringIndexed(arr, string);\n return arr;\n}\n\n/**\n * Writes ASCII bytes into a specified array.\n * @param string the string.\n * @param outArray the target array\n * @param padLength pad with zeros if the string is shorter\n * @returns modified _in-place_\n */\nexport function writeBinaryStringIndexed(\n outArray: IndexedByteArray,\n string: string,\n padLength = 0\n): IndexedByteArray {\n if (padLength > 0) {\n if (string.length > padLength) {\n string = string.slice(0, padLength);\n }\n }\n for (let i = 0; i < string.length; i++) {\n outArray[outArray.currentIndex++] = string.charCodeAt(i);\n }\n\n // Pad with zeros if needed\n if (padLength > string.length) {\n for (let i = 0; i < padLength - string.length; i++) {\n outArray[outArray.currentIndex++] = 0;\n }\n }\n return outArray;\n}\n","import type { IndexedByteArray } from \"../indexed_array\";\n\n/**\n * Reads the number as little endian from an IndexedByteArray.\n * @param dataArray the array to read from.\n * @param bytesAmount the number of bytes to read.\n * @returns the number.\n */\nexport function readLittleEndianIndexed(\n dataArray: IndexedByteArray,\n bytesAmount: number\n): number {\n const res = readLittleEndian(\n dataArray,\n bytesAmount,\n dataArray.currentIndex\n );\n dataArray.currentIndex += bytesAmount;\n return res;\n}\n\n/**\n * Reads the number as little endian.\n * @param dataArray the array to read from.\n * @param bytesAmount the number of bytes to read.\n * @param offset the offset to start reading at.\n * @returns the number.\n */\nexport function readLittleEndian(\n dataArray: number[] | ArrayLike<number>,\n bytesAmount: number,\n offset = 0\n) {\n let out = 0;\n for (let i = 0; i < bytesAmount; i++) {\n out |= dataArray[offset + i] << (i * 8);\n }\n // Make sure it stays unsigned\n return out >>> 0;\n}\n\n/**\n * Writes a number as little endian seems to also work for negative numbers so yay?\n * @param dataArray the IndexedByteArray to write to.\n * @param number the number to write.\n * @param byteTarget the amount of bytes to use. Excess bytes will be set to zero.\n * @returns the Big endian representation of the number.\n */\nexport function writeLittleEndianIndexed(\n dataArray: IndexedByteArray,\n number: number,\n byteTarget: number\n) {\n for (let i = 0; i < byteTarget; i++) {\n dataArray[dataArray.currentIndex++] = (number >> (i * 8)) & 0xff;\n }\n}\n\n/**\n * Writes a WORD (SHORT)\n */\nexport function writeWord(dataArray: IndexedByteArray, word: number) {\n dataArray[dataArray.currentIndex++] = word & 0xff;\n dataArray[dataArray.currentIndex++] = word >> 8;\n}\n\n/**\n * Writes a DWORD (INT)\n */\nexport function writeDword(dataArray: IndexedByteArray, dword: number) {\n writeLittleEndianIndexed(dataArray, dword, 4);\n}\n\n/**\n * Reads two bytes as a signed short.\n */\nexport function signedInt16(byte1: number, byte2: number): number {\n const val = (byte2 << 8) | byte1;\n if (val > 32767) {\n return val - 65536;\n }\n return val;\n}\n\n/**\n * Reads a byte as a signed char.\n */\nexport function signedInt8(byte: number): number {\n if (byte > 127) {\n return byte - 256;\n }\n return byte;\n}\n","import { IndexedByteArray } from \"./indexed_array\";\nimport {\n readLittleEndianIndexed,\n writeDword\n} from \"./byte_functions/little_endian\";\nimport {\n readBinaryString,\n readBinaryStringIndexed,\n writeBinaryStringIndexed\n} from \"./byte_functions/string\";\nimport type {\n DLSChunkFourCC,\n DLSInfoFourCC,\n SF2ChunkFourCC,\n SF2InfoFourCC,\n SoundBankInfoFourCC\n} from \"../soundbank/types\";\n\nimport type { RMIDInfoFourCC } from \"../midi/types\";\n\nexport type GenericRIFFFourCC = \"RIFF\" | \"LIST\" | \"INFO\";\nexport type WAVFourCC = \"wave\" | \"cue \" | \"fmt \";\nexport type FourCC =\n | GenericRIFFFourCC\n | SoundBankInfoFourCC\n | SF2InfoFourCC\n | SF2ChunkFourCC\n | DLSInfoFourCC\n | DLSChunkFourCC\n | RMIDInfoFourCC\n | WAVFourCC;\n\n/**\n * Riff_chunk.ts\n * reads a riff chunk and stores it as a class\n */\n\nexport class RIFFChunk {\n /**\n * The chunks FourCC code.\n */\n public readonly header: FourCC;\n\n /**\n * Chunk's size, in bytes.\n */\n public readonly size: number;\n\n /**\n * Chunk's binary data. Note that this will have a length of 0 if \"readData\" was set to false.\n */\n public readonly data: IndexedByteArray;\n\n /**\n * Creates a new RIFF chunk.\n */\n public constructor(header: FourCC, size: number, data: IndexedByteArray) {\n this.header = header;\n this.size = size;\n this.data = data;\n }\n}\n\nexport function readRIFFChunk(\n dataArray: IndexedByteArray,\n readData = true,\n forceShift = false\n): RIFFChunk {\n const header = readBinaryStringIndexed(dataArray, 4) as FourCC;\n\n let size = readLittleEndianIndexed(dataArray, 4);\n // @ts-expect-error Not all RIFF files are compliant\n if (header === \"\") {\n // Safeguard against evil DLS files\n // The test case: CrysDLS v1.23.dls\n // https://github.com/spessasus/spessasynth_core/issues/5\n size = 0;\n }\n let chunkData: IndexedByteArray;\n if (readData) {\n chunkData = dataArray.slice(\n dataArray.currentIndex,\n dataArray.currentIndex + size\n );\n } else {\n chunkData = new IndexedByteArray(0);\n }\n if (readData || forceShift) {\n dataArray.currentIndex += size;\n if (size % 2 !== 0) {\n dataArray.currentIndex++;\n }\n }\n\n return new RIFFChunk(header, size, chunkData);\n}\n\n/**\n * Writes a RIFF chunk correctly\n * @param header fourCC\n * @param data chunk data\n * @param addZeroByte add a zero byte into the chunk size\n * @param isList adds \"LIST\" as the chunk type and writes the actual type at the start of the data\n * @returns the binary data\n */\nexport function writeRIFFChunkRaw(\n header: FourCC,\n data: Uint8Array,\n addZeroByte = false,\n isList = false\n): IndexedByteArray {\n if (header.length !== 4) {\n throw new Error(`Invalid header length: ${header}`);\n }\n let dataStartOffset = 8;\n let headerWritten = header;\n let dataLength = data.length;\n if (addZeroByte) {\n dataLength++;\n }\n let writtenSize = dataLength;\n if (isList) {\n // Written header is LIST and the passed header is the first 4 bytes of chunk data\n dataStartOffset += 4;\n writtenSize += 4;\n headerWritten = \"LIST\";\n }\n let finalSize = dataStartOffset + dataLength;\n if (finalSize % 2 !== 0) {\n // Pad byte does not get included in the size\n finalSize++;\n }\n\n const outArray = new IndexedByteArray(finalSize);\n // FourCC (\"RIFF\", \"LIST\", \"pdta\" etc.)\n writeBinaryStringIndexed(outArray, headerWritten);\n // Chunk size\n writeDword(outArray, writtenSize);\n if (isList) {\n // List type (e.g. \"INFO\")\n writeBinaryStringIndexed(outArray, header);\n }\n outArray.set(data, dataStartOffset);\n return outArray;\n}\n\n/**\n * Writes RIFF chunk given binary blobs\n * @param header fourCC\n * @param chunks chunk data parts, it will be combined in order\n * @param isList adds \"LIST\" as the chunk type and writes the actual type at the start of the data\n * @returns the binary data\n */\nexport function writeRIFFChunkParts(\n header: FourCC,\n chunks: Uint8Array[],\n isList = false\n): IndexedByteArray {\n let dataOffset = 8;\n let headerWritten = header;\n const dataLength = chunks.reduce((len, c) => c.length + len, 0);\n let writtenSize = dataLength;\n if (isList) {\n // Written header is LIST and the passed header is the first 4 bytes of chunk data\n dataOffset += 4;\n writtenSize += 4;\n headerWritten = \"LIST\";\n }\n let finalSize = dataOffset + dataLength;\n if (finalSize % 2 !== 0) {\n // Pad byte does not get included in the size\n finalSize++;\n }\n\n const outArray = new IndexedByteArray(finalSize);\n // FourCC (\"RIFF\", \"LIST\", \"pdta\" etc.)\n writeBinaryStringIndexed(outArray, headerWritten);\n // Chunk size\n writeDword(outArray, writtenSize);\n if (isList) {\n // List type (e.g. \"INFO\")\n writeBinaryStringIndexed(outArray, header);\n }\n chunks.forEach((c) => {\n outArray.set(c, dataOffset);\n dataOffset += c.length;\n });\n return outArray;\n}\n\n/**\n * Finds a given type in a list.\n * @remarks\n * Also skips the current index to after the list FourCC.\n */\nexport function findRIFFListType(\n collection: RIFFChunk[],\n type: FourCC\n): RIFFChunk | undefined {\n return collection.find((c) => {\n if (c.header !== \"LIST\") {\n return false;\n }\n c.data.currentIndex = 4;\n return readBinaryString(c.data, 4) === type;\n });\n}\n","/**\n * Fills the object with default values.\n * @param obj object to fill.\n * @param defObj object to fill with.\n */\nexport function fillWithDefaults<T>(obj: Partial<T> | undefined, defObj: T): T {\n return {\n ...defObj,\n ...(obj ?? {})\n };\n}\n","import { IndexedByteArray } from \"./indexed_array\";\nimport { writeBinaryStringIndexed } from \"./byte_functions/string\";\nimport { writeRIFFChunkParts, writeRIFFChunkRaw } from \"./riff_chunk\";\nimport { writeLittleEndianIndexed } from \"./byte_functions/little_endian\";\nimport { DEFAULT_WAV_WRITE_OPTIONS, type WaveWriteOptions } from \"./exports\";\nimport { fillWithDefaults } from \"./fill_with_defaults\";\n\n/**\n * Writes an audio into a valid WAV file.\n * @param audioData the audio data channels.\n * @param sampleRate the sample rate, in Hertz.\n * @param options Additional options for writing the file.\n * @returns the binary file.\n */\nexport function audioToWav(\n audioData: Float32Array[],\n sampleRate: number,\n options: Partial<WaveWriteOptions> = DEFAULT_WAV_WRITE_OPTIONS\n): ArrayBuffer {\n const length = audioData[0].length;\n const numChannels = audioData.length;\n const bytesPerSample = 2; // 16-bit PCM\n\n const fullOptions = fillWithDefaults(options, DEFAULT_WAV_WRITE_OPTIONS);\n const loop = fullOptions.loop;\n const metadata = fullOptions.metadata;\n // Prepare INFO chunk\n let infoChunk = new IndexedByteArray(0);\n const infoOn = Object.keys(metadata).length > 0;\n // INFO chunk\n if (infoOn) {\n const encoder = new TextEncoder();\n const infoChunks = [\n writeRIFFChunkRaw(\n \"ICMT\",\n encoder.encode(\"Created with SpessaSynth\"),\n true\n )\n ];\n if (metadata.artist) {\n infoChunks.push(\n writeRIFFChunkRaw(\"IART\", encoder.encode(metadata.artist), true)\n );\n }\n if (metadata.album) {\n infoChunks.push(\n writeRIFFChunkRaw(\"IPRD\", encoder.encode(metadata.album), true)\n );\n }\n if (metadata.genre) {\n infoChunks.push(\n writeRIFFChunkRaw(\"IGNR\", encoder.encode(metadata.genre), true)\n );\n }\n if (metadata.title) {\n infoChunks.push(\n writeRIFFChunkRaw(\"INAM\", encoder.encode(metadata.title), true)\n );\n }\n infoChunk = writeRIFFChunkParts(\"INFO\", infoChunks, true);\n }\n\n // Prepare CUE chunk\n let cueChunk = new IndexedByteArray(0);\n const cueOn = loop?.end !== undefined && loop?.start !== undefined;\n if (cueOn) {\n const loopStartSamples = Math.floor(loop.start * sampleRate);\n const loopEndSamples = Math.floor(loop.end * sampleRate);\n\n const cueStart = new IndexedByteArray(24);\n writeLittleEndianIndexed(cueStart, 0, 4); // DwIdentifier\n writeLittleEndianIndexed(cueStart, 0, 4); // DwPosition\n writeBinaryStringIndexed(cueStart, \"data\"); // Cue point ID\n writeLittleEndianIndexed(cueStart, 0, 4); // ChunkStart, always 0\n writeLittleEndianIndexed(cueStart, 0, 4); // BlockStart, always 0\n writeLittleEndianIndexed(cueStart, loopStartSamples, 4); // SampleOffset\n\n const cueEnd = new IndexedByteArray(24);\n writeLittleEndianIndexed(cueEnd, 1, 4); // DwIdentifier\n writeLittleEndianIndexed(cueEnd, 0, 4); // DwPosition\n writeBinaryStringIndexed(cueEnd, \"data\"); // Cue point ID\n writeLittleEndianIndexed(cueEnd, 0, 4); // ChunkStart, always 0\n writeLittleEndianIndexed(cueEnd, 0, 4); // BlockStart, always 0\n writeLittleEndianIndexed(cueEnd, loopEndSamples, 4); // SampleOffset\n\n cueChunk = writeRIFFChunkParts(\"cue \", [\n new IndexedByteArray([2, 0, 0, 0]), // Cue points count\n cueStart,\n cueEnd\n ]);\n }\n\n // Prepare the header\n const headerSize = 44;\n const dataSize = length * numChannels * bytesPerSample; // 16-bit per channel\n const fileSize =\n headerSize + dataSize + infoChunk.length + cueChunk.length - 8; // Total file size minus the first 8 bytes\n const header = new Uint8Array(headerSize);\n\n // 'RIFF'\n header.set([82, 73, 70, 70], 0);\n // File length\n header.set(\n new Uint8Array([\n fileSize & 0xff,\n (fileSize >> 8) & 0xff,\n (fileSize >> 16) & 0xff,\n (fileSize >> 24) & 0xff\n ]),\n 4\n );\n // 'WAVE'\n header.set([87, 65, 86, 69], 8);\n // 'fmt '\n header.set([102, 109, 116, 32], 12);\n // Fmt chunk length\n header.set([16, 0, 0, 0], 16); // 16 for PCM\n // Audio format (PCM)\n header.set([1, 0], 20);\n // Number of channels (2)\n header.set([numChannels & 255, numChannels >> 8], 22);\n // Sample rate\n header.set(\n new Uint8Array([\n sampleRate & 0xff,\n (sampleRate >> 8) & 0xff,\n (sampleRate >> 16) & 0xff,\n (sampleRate >> 24) & 0xff\n ]),\n 24\n );\n // Byte rate (sample rate * block align)\n const byteRate = sampleRate * numChannels * bytesPerSample; // 16-bit per channel\n header.set(\n new Uint8Array([\n byteRate & 0xff,\n (byteRate >> 8) & 0xff,\n (byteRate >> 16) & 0xff,\n (byteRate >> 24) & 0xff\n ]),\n 28\n );\n // Block align (channels * bytes per sample)\n header.set([numChannels * bytesPerSample, 0], 32); // N channels * 16-bit per channel / 8\n // Bits per sample\n header.set([16, 0], 34); // 16-bit\n\n // Data chunk identifier 'data'\n header.set([100, 97, 116, 97], 36);\n // Data chunk length\n header.set(\n new Uint8Array([\n dataSize & 0xff,\n (dataSize >> 8) & 0xff,\n (dataSize >> 16) & 0xff,\n (dataSize >> 24) & 0xff\n ]),\n 40\n );\n\n const wavData = new Uint8Array(fileSize + 8);\n let offset = headerSize;\n wavData.set(header, 0);\n\n // Interleave audio data (combine channels)\n let multiplier = 32767;\n if (fullOptions.normalizeAudio) {\n // Find min and max values to prevent clipping when converting to 16 bits\n const numSamples = audioData[0].length;\n\n let maxAbsValue = 0;\n\n for (let ch = 0; ch < numChannels; ch++) {\n const data = audioData[ch];\n for (let i = 0; i < numSamples; i++) {\n const sample = Math.abs(data[i]);\n if (sample > maxAbsValue) {\n maxAbsValue = sample;\n }\n }\n }\n\n multiplier = maxAbsValue > 0 ? 32767 / maxAbsValue : 1;\n }\n for (let i = 0; i < length; i++) {\n // Interleave both channels\n audioData.forEach((d) => {\n const sample = Math.min(32767, Math.max(-32768, d[i] * multiplier));\n // Convert to 16-bit\n wavData[offset++] = sample & 0xff;\n wavData[offset++] = (sample >> 8) & 0xff;\n });\n }\n\n if (infoOn) {\n wavData.set(infoChunk, offset);\n offset += infoChunk.length;\n }\n if (cueOn) {\n wavData.set(cueChunk, offset);\n }\n\n return wavData.buffer;\n}\n","import type { IndexedByteArray } from \"../indexed_array\";\n\n/**\n * Reads number as Big endian.\n * @param dataArray the array to read from.\n * @param bytesAmount the number of bytes to read.\n * @param offset the offset to start reading from.\n * @returns the number.\n */\nexport function readBigEndian(\n dataArray: number[] | ArrayLike<number>,\n bytesAmount: number,\n offset = 0\n) {\n let out = 0;\n for (let i = 0; i < bytesAmount; i++) {\n out = (out << 8) | dataArray[offset + i];\n }\n return out >>> 0;\n}\n\n/**\n * Reads number as Big endian from an IndexedByteArray.\n * @param dataArray the array to read from.\n * @param bytesAmount the number of bytes to read.\n * @returns the number.\n */\nexport function readBigEndianIndexed(\n dataArray: IndexedByteArray,\n bytesAmount: number\n) {\n const res = readBigEndian(dataArray, bytesAmount, dataArray.currentIndex);\n dataArray.currentIndex += bytesAmount;\n return res;\n}\n\n/**\n * Writes a number as Big endian.\n * @param number the number to write.\n * @param bytesAmount the amount of bytes to use. Excess bytes will be set to zero.\n * @returns the Big endian representation of the number.\n */\nexport function writeBigEndian(number: number, bytesAmount: number) {\n const bytes = new Array<number>(bytesAmount).fill(0);\n for (let i = bytesAmount - 1; i >= 0; i--) {\n bytes[i] = number & 0xff;\n number >>= 8;\n }\n\n return bytes;\n}\n","import type { IndexedByteArray } from \"../indexed_array\";\n\n/**\n * Reads VLQ from a MIDI byte array.\n * @param MIDIbyteArray the array to read from.\n * @returns the number.\n */\nexport function readVariableLengthQuantity(\n MIDIbyteArray: IndexedByteArray\n): number {\n let out = 0;\n while (MIDIbyteArray) {\n const byte = MIDIbyteArray[MIDIbyteArray.currentIndex++];\n // Extract the first 7 bytes\n out = (out << 7) | (byte & 127);\n\n // If the last byte isn't 1, stop reading\n if (byte >> 7 !== 1) {\n break;\n }\n }\n return out;\n}\n\n/**\n * Writes a VLQ from a number to a byte array.\n * @param number the number to write.\n * @returns the VLQ representation of the number.\n */\nexport function writeVariableLengthQuantity(number: number): number[] {\n // Add the first byte\n const bytes = [number & 127];\n number >>= 7;\n\n // Continue processing the remaining bytes\n while (number > 0) {\n bytes.unshift((number & 127) | 128);\n number >>= 7;\n }\n return bytes;\n}\n","/**\n * Other.ts\n * purpose: contains some useful functions that don't belong in any specific category\n */\n\n/**\n * Formats the given seconds to nice readable time\n * @param totalSeconds time in seconds\n */\nexport function formatTime(totalSeconds: number): {\n seconds: number;\n minutes: number;\n time: string;\n} {\n totalSeconds = Math.floor(totalSeconds);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = Math.round(totalSeconds - minutes * 60);\n return {\n minutes: minutes,\n seconds: seconds,\n time: `${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`\n };\n}\n\n/**\n * Does what it says\n */\nexport function arrayToHexString(arr: Iterable<number>): string {\n let hexString = \"\";\n\n for (const i of arr) {\n const hex = i.toString(16).padStart(2, \"0\").toUpperCase();\n hexString += hex;\n hexString += \" \";\n }\n\n return hexString;\n}\n\nexport const consoleColors = {\n warn: \"color: orange;\",\n unrecognized: \"color: red;\",\n info: \"color: aqua;\",\n recognized: \"color: lime\",\n value: \"color: yellow; background-color: black;\"\n};\n","let tr;(()=>{var l=Uint8Array,T=Uint16Array,ur=Int32Array,W=new l([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),X=new l([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),wr=new l([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),Y=function(r,a){for(var e=new T(31),f=0;f<31;++f)e[f]=a+=1<<r[f-1];for(var v=new ur(e[30]),f=1;f<30;++f)for(var g=e[f];g<e[f+1];++g)v[g]=g-e[f]<<5|f;return{b:e,r:v}},Z=Y(W,2),$=Z.b,cr=Z.r;$[28]=258,cr[258]=28;var j=Y(X,0),hr=j.b,Fr=j.r,_=new T(32768);for(i=0;i<32768;++i)c=(i&43690)>>1|(i&21845)<<1,c=(c&52428)>>2|(c&13107)<<2,c=(c&61680)>>4|(c&3855)<<4,_[i]=((c&65280)>>8|(c&255)<<8)>>1;var c,i,A=function(r,a,e){for(var f=r.length,v=0,g=new T(a);v<f;++v)r[v]&&++g[r[v]-1];var k=new T(a);for(v=1;v<a;++v)k[v]=k[v-1]+g[v-1]<<1;var b;if(e){b=new T(1<<a);var m=15-a;for(v=0;v<f;++v)if(r[v])for(var U=v<<4|r[v],x=a-r[v],n=k[r[v]-1]++<<x,o=n|(1<<x)-1;n<=o;++n)b[_[n]>>m]=U}else for(b=new T(f),v=0;v<f;++v)r[v]&&(b[v]=_[k[r[v]-1]++]>>15-r[v]);return b},M=new l(288);for(i=0;i<144;++i)M[i]=8;var i;for(i=144;i<256;++i)M[i]=9;var i;for(i=256;i<280;++i)M[i]=7;var i;for(i=280;i<288;++i)M[i]=8;var i,L=new l(32);for(i=0;i<32;++i)L[i]=5;var i,gr=A(M,9,1),br=A(L,5,1),q=function(r){for(var a=r[0],e=1;e<r.length;++e)r[e]>a&&(a=r[e]);return a},u=function(r,a,e){var f=a/8|0;return(r[f]|r[f+1]<<8)>>(a&7)&e},C=function(r,a){var e=a/8|0;return(r[e]|r[e+1]<<8|r[e+2]<<16)>>(a&7)},kr=function(r){return(r+7)/8|0},xr=function(r,a,e){return(a==null||a<0)&&(a=0),(e==null||e>r.length)&&(e=r.length),new l(r.subarray(a,e))},yr=[\"unexpected EOF\",\"invalid block type\",\"invalid length/literal\",\"invalid distance\",\"stream finished\",\"no stream handler\",,\"no callback\",\"invalid UTF-8 data\",\"extra field too long\",\"date not in range 1980-2099\",\"filename too long\",\"stream finishing\",\"invalid zip data\"],h=function(r,a,e){var f=new Error(a||yr[r]);if(f.code=r,Error.captureStackTrace&&Error.captureStackTrace(f,h),!e)throw f;return f},Sr=function(r,a,e,f){var v=r.length,g=f?f.length:0;if(!v||a.f&&!a.l)return e||new l(0);var k=!e,b=k||a.i!=2,m=a.i;k&&(e=new l(v*3));var U=function(fr){var or=e.length;if(fr>or){var lr=new l(Math.max(or*2,fr));lr.set(e),e=lr}},x=a.f||0,n=a.p||0,o=a.b||0,S=a.l,I=a.d,z=a.m,D=a.n,G=v*8;do{if(!S){x=u(r,n,1);var H=u(r,n+1,3);if(n+=3,H)if(H==1)S=gr,I=br,z=9,D=5;else if(H==2){var N=u(r,n,31)+257,s=u(r,n+10,15)+4,d=N+u(r,n+5,31)+1;n+=14;for(var F=new l(d),P=new l(19),t=0;t<s;++t)P[wr[t]]=u(r,n+t*3,7);n+=s*3;for(var rr=q(P),Ar=(1<<rr)-1,Mr=A(P,rr,1),t=0;t<d;){var ar=Mr[u(r,n,Ar)];n+=ar&15;var w=ar>>4;if(w<16)F[t++]=w;else{var E=0,O=0;for(w==16?(O=3+u(r,n,3),n+=2,E=F[t-1]):w==17?(O=3+u(r,n,7),n+=3):w==18&&(O=11+u(r,n,127),n+=7);O--;)F[t++]=E}}var er=F.subarray(0,N),y=F.subarray(N);z=q(er),D=q(y),S=A(er,z,1),I=A(y,D,1)}else h(1);else{var w=kr(n)+4,J=r[w-4]|r[w-3]<<8,K=w+J;if(K>v){m&&h(0);break}b&&U(o+J),e.set(r.subarray(w,K),o),a.b=o+=J,a.p=n=K*8,a.f=x;continue}if(n>G){m&&h(0);break}}b&&U(o+131072);for(var Ur=(1<<z)-1,zr=(1<<D)-1,Q=n;;Q=n){var E=S[C(r,n)&Ur],p=E>>4;if(n+=E&15,n>G){m&&h(0);break}if(E||h(2),p<256)e[o++]=p;else if(p==256){Q=n,S=null;break}else{var nr=p-254;if(p>264){var t=p-257,B=W[t];nr=u(r,n,(1<<B)-1)+$[t],n+=B}var R=I[C(r,n)&zr],V=R>>4;R||h(3),n+=R&15;var y=hr[V];if(V>3){var B=X[V];y+=C(r,n)&(1<<B)-1,n+=B}if(n>G){m&&h(0);break}b&&U(o+131072);var vr=o+nr;if(o<y){var ir=g-y,Dr=Math.min(y,vr);for(ir+o<0&&h(3);o<Dr;++o)e[o]=f[ir+o]}for(;o<vr;++o)e[o]=e[o-y]}}a.l=S,a.p=Q,a.b=o,a.f=x,S&&(x=1,a.m=z,a.d=I,a.n=D)}while(!x);return o!=e.length&&k?xr(e,0,o):e.subarray(0,o)},Tr=new l(0);function mr(r,a){return Sr(r,{i:2},a&&a.out,a&&a.dictionary)}var Er=typeof TextDecoder<\"u\"&&new TextDecoder,pr=0;try{Er.decode(Tr,{stream:!0}),pr=1}catch{}tr=mr})();export{tr as inflateSync};\n","// @ts-expect-error minified lib that I can't move\nimport { inflateSync } from \"./fflate.min\";\n\ntype inflateFunc = (input: Uint8Array) => Uint8Array<ArrayBuffer>;\n\n// @ts-expect-error minified lib that I can't move\nconst inf: inflateFunc = inflateSync as inflateFunc;\n\nexport { inf as inflateSync };\n","let ENABLE_INFO = false;\nlet ENABLE_WARN = true;\nlet ENABLE_GROUP = false;\n\n/**\n * Enables or disables logging.\n * @param enableInfo enables info.\n * @param enableWarn enables warning.\n * @param enableGroup enables groups.\n */\nexport function SpessaSynthLogging(\n enableInfo: boolean,\n enableWarn: boolean,\n enableGroup: boolean\n) {\n ENABLE_INFO = enableInfo;\n ENABLE_WARN = enableWarn;\n ENABLE_GROUP = enableGroup;\n}\n\nexport function SpessaSynthInfo(...message: unknown[]) {\n if (ENABLE_INFO) {\n console.info(...message);\n }\n}\n\nexport function SpessaSynthWarn(...message: unknown[]) {\n if (ENABLE_WARN) {\n console.warn(...message);\n }\n}\n\nexport function SpessaSynthGroup(...message: unknown[]) {\n if (ENABLE_GROUP) {\n console.group(...message);\n }\n}\n\nexport function SpessaSynthGroupCollapsed(...message: unknown[]) {\n if (ENABLE_GROUP) {\n console.groupCollapsed(...message);\n }\n}\n\nexport function SpessaSynthGroupEnd() {\n if (ENABLE_GROUP) {\n console.groupEnd();\n }\n}\n","import { IndexedByteArray } from \"./indexed_array\";\nimport { audioToWav } from \"./write_wav\";\n\nimport { readBigEndian } from \"./byte_functions/big_endian\";\nimport { readLittleEndianIndexed } from \"./byte_functions/little_endian\";\nimport { readBinaryStringIndexed } from \"./byte_functions/string\";\nimport { readVariableLengthQuantity } from \"./byte_functions/variable_length_quantity\";\nimport { consoleColors } from \"./other\";\nimport { inflateSync } from \"../externals/fflate/fflate_wrapper\";\nimport {\n SpessaSynthGroup,\n SpessaSynthGroupCollapsed,\n SpessaSynthGroupEnd,\n SpessaSynthInfo,\n SpessaSynthLogging,\n SpessaSynthWarn\n} from \"./loggin\";\nimport type { MIDILoop } from \"../midi/types\";\n\nimport type { FourCC } from \"./riff_chunk\";\n\n// You shouldn't use these...\nconst SpessaSynthCoreUtils = {\n consoleColors,\n SpessaSynthInfo,\n SpessaSynthWarn,\n SpessaSynthGroupCollapsed,\n // noinspection JSUnusedGlobalSymbols\n SpessaSynthGroup,\n SpessaSynthGroupEnd,\n // noinspection JSUnusedGlobalSymbols\n readBytesAsUintBigEndian: readBigEndian,\n readLittleEndian: readLittleEndianIndexed,\n readBytesAsString: readBinaryStringIndexed,\n // noinspection JSUnusedGlobalSymbols\n readVariableLengthQuantity,\n inflateSync\n};\n\nexport {\n IndexedByteArray,\n audioToWav,\n SpessaSynthLogging,\n SpessaSynthCoreUtils,\n type FourCC\n};\n\nexport const DEFAULT_WAV_WRITE_OPTIONS: WaveWriteOptions = {\n normalizeAudio: true,\n loop: undefined,\n metadata: {}\n};\n\nexport interface WaveWriteOptions {\n /**\n * This will find the max sample point and set it to 1, and scale others with it. Recommended\n */\n normalizeAudio: boolean;\n /**\n * The loop start and end points in seconds. Undefined if no loop should be written.\n */\n loop?: MIDILoop;\n /**\n * The metadata to write into the file.\n */\n metadata: Partial<WaveMetadata>;\n}\n\nexport interface WaveMetadata {\n /**\n * The song's title.\n */\n title: string;\n /**\n * The song's artist.\n */\n artist: string;\n /**\n * The song's album.\n */\n album: string;\n /**\n * The song's genre.\n */\n genre: string;\n}\n","/**\n * Midi_message.ts\n * purpose: contains enums for midi events and controllers and functions to parse them\n */\nimport type { MIDIMessageType } from \"./enums\";\n\nexport class MIDIMessage {\n /**\n * Absolute number of MIDI ticks from the start of the track.\n */\n public ticks: number;\n\n /**\n * The MIDI message status byte. Note that for meta events, it is the second byte. (not 0xFF)\n */\n public statusByte: MIDIMessageType;\n\n /**\n * Message's binary data\n */\n public data: Uint8Array<ArrayBuffer>;\n\n /**\n * Creates a new MIDI message\n * @param ticks time of this message in absolute MIDI ticks\n * @param byte the message status byte\n * @param data the message's binary data\n */\n public constructor(\n ticks: number,\n byte: MIDIMessageType,\n data: Uint8Array<ArrayBuffer>\n ) {\n this.ticks = ticks;\n this.statusByte = byte;\n this.data = data;\n }\n}\n\n/**\n * Gets the status byte's channel\n * @param statusByte the MIDI status byte\n * @returns channel is -1 for system messages -2 for meta and -3 for sysex\n */\nexport function getChannel(statusByte: MIDIMessageType): number {\n const eventType = statusByte & 0xf0;\n const channel = statusByte & 0x0f;\n\n let resultChannel = channel;\n\n switch (eventType) {\n // Midi (and meta and sysex headers)\n case 0x80:\n case 0x90:\n case 0xa0:\n case 0xb0:\n case 0xc0:\n case 0xd0:\n case 0xe0:\n break;\n\n case 0xf0:\n switch (channel) {\n case 0x0:\n resultChannel = -3;\n break;\n\n case 0x1:\n case 0x2:\n case 0x3:\n case 0x4:\n case 0x5:\n case 0x6:\n case 0x7:\n case 0x8:\n case 0x9:\n case 0xa:\n case 0xb:\n case 0xc:\n case 0xd:\n case 0xe:\n resultChannel = -1;\n break;\n\n case 0xf:\n resultChannel = -2;\n break;\n }\n break;\n\n default:\n resultChannel = -1;\n }\n\n return resultChannel;\n}\n\n/**\n * Gets the event's status and channel from the status byte\n * @param statusByte the status byte\n * @returns channel will be -1 for sysex and meta\n */\nexport function getEvent(statusByte: MIDIMessageType): {\n channel: number;\n status: number;\n} {\n const status = statusByte & 0xf0;\n const channel = statusByte & 0x0f;\n\n let eventChannel = -1;\n let eventStatus = statusByte;\n\n if (status >= 0x80 && status <= 0xe0) {\n eventChannel = channel;\n eventStatus = status as MIDIMessageType;\n }\n\n return {\n status: eventStatus,\n channel: eventChannel\n };\n}\n\nexport const dataBytesAmount = {\n 0x8: 2, // Note off\n 0x9: 2, // Note on\n 0xa: 2, // Note at\n 0xb: 2, // Cc change\n 0xc: 1, // Pg change\n 0xd: 1, // Channel after touch\n 0xe: 2 // Pitch wheel\n} as const;\n","// All the midi statuses dictionary\nexport const midiMessageTypes = {\n noteOff: 0x80,\n noteOn: 0x90,\n polyPressure: 0xa0,\n controllerChange: 0xb0,\n programChange: 0xc0,\n channelPressure: 0xd0,\n pitchWheel: 0xe0,\n systemExclusive: 0xf0,\n timecode: 0xf1,\n songPosition: 0xf2,\n songSelect: 0xf3,\n tuneRequest: 0xf6,\n clock: 0xf8,\n start: 0xfa,\n continue: 0xfb,\n stop: 0xfc,\n activeSensing: 0xfe,\n reset: 0xff,\n sequenceNumber: 0x00,\n text: 0x01,\n copyright: 0x02,\n trackName: 0x03,\n instrumentName: 0x04,\n lyric: 0x05,\n marker: 0x06,\n cuePoint: 0x07,\n programName: 0x08,\n midiChannelPrefix: 0x20,\n midiPort: 0x21,\n endOfTrack: 0x2f,\n setTempo: 0x51,\n smpteOffset: 0x54,\n timeSignature: 0x58,\n keySignature: 0x59,\n sequenceSpecific: 0x7f\n} as const;\n\nexport type MIDIMessageType =\n (typeof midiMessageTypes)[keyof typeof midiMessageTypes];\n\n// All midi controllers dictionary\nexport const midiControllers = {\n bankSelect: 0,\n modulationWheel: 1,\n breathController: 2,\n undefinedCC3: 3,\n footController: 4,\n portamentoTime: 5,\n dataEntryMSB: 6,\n mainVolume: 7,\n balance: 8,\n undefinedCC9: 9,\n pan: 10,\n expressionController: 11,\n effectControl1: 12,\n effectControl2: 13,\n undefinedCC14: 14,\n undefinedCC15: 15,\n generalPurposeController1: 16,\n generalPurposeController2: 17,\n generalPurposeController3: 18,\n generalPurposeController4: 19,\n undefinedCC20: 20,\n undefinedCC21: 21,\n undefinedCC22: 22,\n undefinedCC23: 23,\n undefinedCC24: 24,\n undefinedCC25: 25,\n undefinedCC26: 26,\n undefinedCC27: 27,\n undefinedCC28: 28,\n undefinedCC29: 29,\n undefinedCC30: 30,\n undefinedCC31: 31,\n bankSelectLSB: 32,\n modulationWheelLSB: 33,\n breathControllerLSB: 34,\n undefinedCC3LSB: 35,\n footControllerLSB: 36,\n portamentoTimeLSB: 37,\n dataEntryLSB: 38,\n mainVolumeLSB: 39,\n balanceLSB: 40,\n undefinedCC9LSB: 41,\n panLSB: 42,\n expressionControllerLSB: 43,\n effectControl1LSB: 44,\n effectControl2LSB: 45,\n undefinedCC14LSB: 46,\n undefinedCC15LSB: 47,\n undefinedCC16LSB: 48,\n undefinedCC17LSB: 49,\n undefinedCC18LSB: 50,\n undefinedCC19LSB: 51,\n undefinedCC20LSB: 52,\n undefinedCC21LSB: 53,\n undefinedCC22LSB: 54,\n undefinedCC23LSB: 55,\n undefinedCC24LSB: 56,\n undefinedCC25LSB: 57,\n undefinedCC26LSB: 58,\n undefinedCC27LSB: 59,\n undefinedCC28LSB: 60,\n undefinedCC29LSB: 61,\n undefinedCC30LSB: 62,\n undefinedCC31LSB: 63,\n sustainPedal: 64,\n portamentoOnOff: 65,\n sostenutoPedal: 66,\n softPedal: 67,\n legatoFootswitch: 68,\n hold2Pedal: 69,\n soundVariation: 70,\n filterResonance: 71,\n releaseTime: 72,\n attackTime: 73,\n brightness: 74,\n decayTime: 75,\n vibratoRate: 76,\n vibratoDepth: 77,\n vibratoDelay: 78,\n soundController10: 79,\n generalPurposeController5: 80,\n generalPurposeController6: 81,\n generalPurposeController7: 82,\n generalPurposeController8: 83,\n portamentoControl: 84,\n undefinedCC85: 85,\n undefinedCC86: 86,\n undefinedCC87: 87,\n undefinedCC88: 88,\n undefinedCC89: 89,\n undefinedCC90: 90,\n reverbDepth: 91,\n tremoloDepth: 92,\n chorusDepth: 93,\n detuneDepth: 94,\n phaserDepth: 95,\n dataIncrement: 96,\n dataDecrement: 97,\n nonRegisteredParameterLSB: 98,\n nonRegisteredParameterMSB: 99,\n registeredParameterLSB: 100,\n registeredParameterMSB: 101,\n undefinedCC102LSB: 102,\n undefinedCC103LSB: 103,\n undefinedCC104LSB: 104,\n undefinedCC105LSB: 105,\n undefinedCC106LSB: 106,\n undefinedCC107LSB: 107,\n undefinedCC108LSB: 108,\n undefinedCC109LSB: 109,\n undefinedCC110LSB: 110,\n undefinedCC111LSB: 111,\n undefinedCC112LSB: 112,\n undefinedCC113LSB: 113,\n undefinedCC114LSB: 114,\n undefinedCC115LSB: 115,\n undefinedCC116LSB: 116,\n undefinedCC117LSB: 117,\n undefinedCC118LSB: 118,\n undefinedCC119LSB: 119,\n allSoundOff: 120,\n resetAllControllers: 121,\n localControlOnOff: 122,\n allNotesOff: 123,\n omniModeOff: 124,\n omniModeOn: 125,\n monoModeOn: 126,\n polyModeOn: 127\n} as const;\n\nexport type MIDIController =\n (typeof midiControllers)[keyof typeof midiControllers];\n","import { writeVariableLengthQuantity } from \"../../utils/byte_functions/variable_length_quantity\";\nimport { writeBigEndian } from \"../../utils/byte_functions/big_endian\";\nimport type { BasicMIDI } from \"../basic_midi\";\nimport { midiMessageTypes } from \"../enums\";\n\n/**\n * Exports the midi as a standard MIDI file\n * @param midi the MIDI to write\n */\nexport function writeMIDIInternal(midi: BasicMIDI): ArrayBuffer {\n if (!midi.tracks) {\n throw new Error(\"MIDI has no tracks!\");\n }\n const binaryTrackData: Uint8Array[] = [];\n for (const track of midi.tracks) {\n const binaryTrack = [];\n let currentTick = 0;\n let runningByte = undefined;\n for (const event of track.events) {\n // Ticks stored in MIDI are absolute, but SMF wants relative. Convert them here.\n const deltaTicks = Math.max(0, event.ticks - currentTick);\n // EndOfTrack is written automatically.\n if (event.statusByte === midiMessageTypes.endOfTrack) {\n currentTick += deltaTicks;\n continue;\n }\n let messageData: number[];\n // Determine the message\n if (event.statusByte <= midiMessageTypes.sequenceSpecific) {\n // This is a meta-message\n // Syntax is FF<type><length><data>\n messageData = [\n 0xff,\n event.statusByte,\n ...writeVariableLengthQuantity(event.data.length),\n ...event.data\n ];\n // RP-001:\n // Sysex events and meta-events cancel any running status which was in effect.\n runningByte = undefined;\n } else if (event.statusByte === midiMessageTypes.systemExclusive) {\n // This is a system exclusive message\n // Syntax is F0<length><data>\n messageData = [\n 0xf0,\n ...writeVariableLengthQuantity(event.data.length),\n ...event.data\n ];\n // RP-001:\n // Sysex events and meta-events cancel any running status which was in effect.\n runningByte = undefined;\n } else {\n // This is a midi message\n messageData = [];\n if (runningByte !== event.statusByte) {\n // Running byte was not the byte we want. Add the byte here.\n runningByte = event.statusByte;\n // Add the status byte to the midi\n messageData.push(event.statusByte);\n }\n // Add the data\n messageData.push(...event.data);\n }\n // Write VLQ\n binaryTrack.push(...writeVariableLengthQuantity(deltaTicks));\n // Write the message\n binaryTrack.push(...messageData);\n currentTick += deltaTicks;\n }\n // Write endOfTrack\n binaryTrack.push(0);\n binaryTrack.push(0xff);\n binaryTrack.push(midiMessageTypes.endOfTrack);\n binaryTrack.push(0);\n binaryTrackData.push(new Uint8Array(binaryTrack));\n }\n\n const writeText = (text: string, arr: number[]) => {\n for (let i = 0; i < text.length; i++) {\n arr.push(text.charCodeAt(i));\n }\n };\n\n // Write the file\n const binaryData: number[] = [];\n // Write header\n writeText(\"MThd\", binaryData); // MThd\n binaryData.push(...writeBigEndian(6, 4)); // Length\n binaryData.push(0, midi.format); // Format\n binaryData.push(...writeBigEndian(midi.tracks.length, 2)); // Num tracks\n binaryData.push(...writeBigEndian(midi.timeDivision, 2)); // Time division\n\n // Write tracks\n for (const track of binaryTrackData) {\n // Write track header\n writeText(\"MTrk\", binaryData); // MTrk\n binaryData.push(...writeBigEndian(track.length, 4)); // Length\n binaryData.push(...track); // Write data\n }\n return new Uint8Array(binaryData).buffer;\n}\n","import type { SynthMethodOptions, SynthSystem } from \"../../types\";\n\n/**\n * Synthesizer's default voice cap.\n */\nexport const VOICE_CAP = 350;\n/**\n * Default MIDI drum channel.\n */\nexport const DEFAULT_PERCUSSION = 9;\n/**\n * MIDI channel count.\n */\nexport const MIDI_CHANNEL_COUNT = 16;\n/**\n * Default bank select and SysEx mode.\n */\nexport const DEFAULT_SYNTH_MODE: SynthSystem = \"gs\";\n\nexport const ALL_CHANNELS_OR_DIFFERENT_ACTION = -1;\n\n// Used globally to identify the embedded sound bank\n// This is used to prevent the embedded bank from being deleted.\nexport const EMBEDDED_SOUND_BANK_ID = `SPESSASYNTH_EMBEDDED_BANK_${Math.random()}_DO_NOT_DELETE`;\n\nexport const GENERATOR_OVERRIDE_NO_CHANGE_VALUE = 32767;\n\nexport const DEFAULT_SYNTH_METHOD_OPTIONS: SynthMethodOptions = {\n time: 0\n};\n// If the note is released faster than that, it forced to last that long\n// This is used mostly for drum channels, where a lot of midis like to send instant note off after a note on\nexport const MIN_NOTE_LENGTH = 0.03;\n// This sounds way nicer for an instant hi-hat cutoff\nexport const MIN_EXCLUSIVE_LENGTH = 0.07;\nexport const SYNTHESIZER_GAIN = 1.0;\n","import type { SynthSystem } from \"../synthesizer/types\";\n\nexport const XG_SFX_VOICE = 64;\n\nconst GM2_DEFAULT_BANK = 121;\n\n/**\n * A class for handling various ways of selecting patches (GS, XG, GM2)\n */\nexport class BankSelectHacks {\n /**\n * GM2 has a different default bank number\n */\n public static getDefaultBank(sys: SynthSystem): number {\n return sys === \"gm2\" ? GM2_DEFAULT_BANK : 0;\n }\n\n public static getDrumBank(sys: SynthSystem): number {\n switch (sys) {\n default:\n throw new Error(`${sys} doesn't have a bank MSB for drums.`);\n\n case \"gm2\":\n return 120;\n case \"xg\":\n return 127;\n }\n }\n\n /**\n * Checks if this bank number is XG drums\n */\n public static isXGDrums(bankMSB: number): boolean {\n return bankMSB === 120 || bankMSB === 126 || bankMSB === 127;\n }\n\n /**\n * Checks if this MSB is a valid XG MSB\n */\n public static isValidXGMSB(bankMSB: number): boolean {\n return (\n this.isXGDrums(bankMSB) ||\n bankMSB === XG_SFX_VOICE ||\n bankMSB === GM2_DEFAULT_BANK\n );\n }\n\n public static isSystemXG(system: SynthSystem) {\n return system === \"gm2\" || system === \"xg\";\n }\n\n public static addBankOffset(\n bankMSB: number,\n bankOffset: number,\n xgDrums = true\n ) {\n if (this.isXGDrums(bankMSB) && xgDrums) {\n return bankMSB;\n }\n return Math.min(bankMSB + bankOffset, 127);\n }\n\n public static subtrackBankOffset(\n bankMSB: number,\n bankOffset: number,\n xgDrums = true\n ) {\n if (this.isXGDrums(bankMSB) && xgDrums) {\n return bankMSB;\n }\n return Math.max(0, bankMSB - bankOffset);\n }\n}\n","import type { MIDIMessage } from \"../midi/midi_message\";\n\n/**\n * Checks if this is a XG ON system exclusive\n */\nexport function isXGOn(e: MIDIMessage) {\n return (\n e.data[0] === 0x43 && // Yamaha\n e.data[2] === 0x4c && // XG ON\n e.data[5] === 0x7e &&\n e.data[6] === 0x00\n );\n}\n\n/**\n * Checks if this is a GS Drum part system exclusive\n */\nexport function isGSDrumsOn(e: MIDIMessage) {\n return (\n e.data[0] === 0x41 && // Roland\n e.data[2] === 0x42 && // GS\n e.data[3] === 0x12 && // GS\n e.data[4] === 0x40 && // System parameter\n (e.data[5] & 0x10) !== 0 && // Part parameter\n e.data[6] === 0x15\n ); // Drum parts\n}\n\n/**\n * Checks if this is a GS ON system exclusive\n */\nexport function isGSOn(e: MIDIMessage) {\n return (\n e.data[0] === 0x41 && // Roland\n e.data[2] === 0x42 && // GS\n e.data[6] === 0x7f\n ); // Mode set\n}\n\n/**\n * Checks if this is a GM ON system exclusive\n */\nexport function isGMOn(e: MIDIMessage) {\n return (\n e.data[0] === 0x7e && // Non realtime\n e.data[2] === 0x09 && // Gm system\n e.data[3] === 0x01\n ); // Gm1\n}\n\n/**\n * Checks if this is a GM2 ON system exclusive\n */\nexport function isGM2On(e: MIDIMessage) {\n return (\n e.data[0] === 0x7e && // Non realtime\n e.data[2] === 0x09 && // Gm system\n e.data[3] === 0x03\n ); // Gm2\n}\n","import { MIDIMessage } from \"../midi_message\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport { midiMessageTypes } from \"../enums\";\n\nexport function getGsOn(ticks: number): MIDIMessage {\n return new MIDIMessage(\n ticks,\n midiMessageTypes.systemExclusive,\n new IndexedByteArray([\n 0x41, // Roland\n 0x10, // Device ID (defaults to 16 on roland)\n 0x42, // GS\n 0x12, // Command ID (DT1) (whatever that means...)\n 0x40, // System parameter - Address\n 0x00, // Global parameter - Address\n 0x7f, // GS Change - Address\n 0x00, // Turn on - Data\n 0x41, // Checksum\n 0xf7 // End of exclusive\n ])\n );\n}\n","export interface MIDIPatch {\n /**\n * The MIDI program number.\n */\n program: number;\n\n /**\n * The MIDI bank MSB number.\n */\n bankMSB: number;\n\n /**\n * The MIDI bank LSB number.\n */\n bankLSB: number;\n\n /**\n * If the preset is marked as GM/GS drum preset. Note that XG drums do not have this flag.\n */\n isGMGSDrum: boolean;\n}\n\nexport interface MIDIPatchNamed extends MIDIPatch {\n /**\n * The name of the patch.\n */\n name: string;\n}\n\nexport class MIDIPatchTools {\n /**\n * Converts a MIDI patch to a string.\n */\n public static toMIDIString(patch: MIDIPatch) {\n if (patch.isGMGSDrum) {\n return `DRUM:${patch.program}`;\n }\n return `${patch.bankLSB}:${patch.bankMSB}:${patch.program}`;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Gets a MIDI patch from a string.\n * @param string\n */\n public static fromMIDIString(string: string): MIDIPatch {\n const parts = string.split(\":\");\n if (parts.length > 3 || parts.length < 2) {\n throw new Error(\"Invalid MIDI string:\");\n }\n if (string.startsWith(\"DRUM\")) {\n return {\n bankMSB: 0,\n bankLSB: 0,\n program: parseInt(parts[1]),\n isGMGSDrum: true\n };\n } else {\n return {\n bankLSB: parseInt(parts[0]),\n bankMSB: parseInt(parts[1]),\n program: parseInt(parts[2]),\n isGMGSDrum: false\n };\n }\n }\n\n /**\n * Converts a named MIDI patch to string.\n * @param patch\n */\n public static toNamedMIDIString(patch: MIDIPatchNamed) {\n return `${MIDIPatchTools.toMIDIString(patch)} ${patch.name}`;\n }\n\n /**\n * Checks if two MIDI patches match.\n * @param patch1\n * @param patch2\n */\n public static matches(patch1: MIDIPatch, patch2: MIDIPatch) {\n if (patch1.isGMGSDrum || patch2.isGMGSDrum) {\n // For drums only compare programs\n return (\n patch1.isGMGSDrum === patch2.isGMGSDrum &&\n patch1.program === patch2.program\n );\n }\n return (\n patch1.program === patch2.program &&\n patch1.bankLSB === patch2.bankLSB &&\n patch1.bankMSB === patch2.bankMSB\n );\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Gets a named MIDI patch from a string.\n * @param string\n */\n public static fromNamedMIDIString(string: string): MIDIPatchNamed {\n const firstSpace = string.indexOf(\" \");\n if (firstSpace < 0) {\n throw new Error(`Invalid named MIDI string: ${string}`);\n }\n const patch = this.fromMIDIString(string.substring(0, firstSpace));\n const name = string.substring(firstSpace + 1);\n return {\n ...patch,\n name\n };\n }\n\n public static sorter(a: MIDIPatch, b: MIDIPatch): number {\n if (a.program !== b.program) {\n return a.program - b.program;\n }\n\n // Force drum presets to be last\n if (a.isGMGSDrum && !b.isGMGSDrum) return 1;\n if (!a.isGMGSDrum && b.isGMGSDrum) return -1;\n\n if (a.bankMSB !== b.bankMSB) {\n return a.bankMSB - b.bankMSB;\n }\n\n return a.bankLSB - b.bankLSB;\n }\n}\n","import { IndexedByteArray } from \"../../utils/indexed_array\";\nimport { writeRIFFChunkParts, writeRIFFChunkRaw } from \"../../utils/riff_chunk\";\nimport { getStringBytes } from \"../../utils/byte_functions/string\";\nimport { MIDIMessage } from \"../midi_message\";\nimport {\n SpessaSynthGroup,\n SpessaSynthGroupEnd,\n SpessaSynthInfo\n} from \"../../utils/loggin\";\nimport { consoleColors } from \"../../utils/other\";\nimport { writeLittleEndianIndexed } from \"../../utils/byte_functions/little_endian\";\nimport { DEFAULT_PERCUSSION } from \"../../synthesizer/audio_engine/engine_components/synth_constants\";\nimport { BankSelectHacks } from \"../../utils/midi_hacks\";\nimport {\n isGM2On,\n isGMOn,\n isGSDrumsOn,\n isGSOn,\n isXGOn\n} from \"../../utils/sysex_detector\";\nimport {\n midiControllers,\n type MIDIMessageType,\n midiMessageTypes\n} from \"../enums\";\nimport type { BasicSoundBank } from \"../../soundbank/basic_soundbank/basic_soundbank\";\nimport type { RMIDInfoData, RMIDInfoFourCC, RMIDIWriteOptions } from \"../types\";\nimport type { BasicMIDI } from \"../basic_midi\";\nimport { getGsOn } from \"./get_gs_on\";\nimport type { SynthSystem } from \"../../synthesizer/types\";\nimport {\n type MIDIPatch,\n MIDIPatchTools\n} from \"../../soundbank/basic_soundbank/midi_patch\";\n\nconst DEFAULT_COPYRIGHT = \"Created using SpessaSynth\";\n\nfunction correctBankOffsetInternal(\n mid: BasicMIDI,\n bankOffset: number,\n soundBank: BasicSoundBank\n) {\n // Add the offset to the bank.\n // See https://github.com/spessasus/sf2-rmidi-specification#readme\n // Also fix presets that don't exist\n // Since midi player6 doesn't seem to default to 0 when non-existent...\n let system: SynthSystem = \"gm\";\n /**\n * The unwanted system messages such as gm/gm2 on\n */\n const unwantedSystems: { tNum: number; e: MIDIMessage }[] = [];\n /**\n * Indexes for tracks\n */\n const eventIndexes: number[] = Array<number>(mid.tracks.length).fill(0);\n let remainingTracks = mid.tracks.length;\n\n const findFirstEventIndex = () => {\n let index = 0;\n let ticks = Infinity;\n mid.tracks.forEach((track, i) => {\n if (eventIndexes[i] >= track.events.length) {\n return;\n }\n if (track.events[eventIndexes[i]].ticks < ticks) {\n index = i;\n ticks = track.events[eventIndexes[i]].ticks;\n }\n });\n return index;\n };\n\n // It copies midiPorts everywhere else, but here 0 works so DO NOT CHANGE!\n const ports = Array<number>(mid.tracks.length).fill(0);\n const channelsAmount = 16 + Math.max(...mid.portChannelOffsetMap);\n const channelsInfo: {\n program: number;\n drums: boolean;\n lastBank?: MIDIMessage;\n lastBankLSB?: MIDIMessage;\n hasBankSelect: boolean;\n }[] = [];\n for (let i = 0; i < channelsAmount; i++) {\n channelsInfo.push({\n program: 0,\n drums: i % 16 === DEFAULT_PERCUSSION, // Drums appear on 9 every 16 channels,\n lastBank: undefined,\n lastBankLSB: undefined,\n hasBankSelect: false\n });\n }\n while (remainingTracks > 0) {\n const trackNum = findFirstEventIndex();\n const track = mid.tracks[trackNum];\n if (eventIndexes[trackNum] >= track.events.length) {\n remainingTracks--;\n continue;\n }\n const e = track.events[eventIndexes[trackNum]];\n eventIndexes[trackNum]++;\n\n const portOffset = mid.portChannelOffsetMap[ports[trackNum]];\n if (e.statusByte === midiMessageTypes.midiPort) {\n ports[trackNum] = e.data[0];\n continue;\n }\n const status = e.statusByte & 0xf0;\n if (\n status !== midiMessageTypes.controllerChange &&\n status !== midiMessageTypes.programChange &&\n status !== midiMessageTypes.systemExclusive\n ) {\n continue;\n }\n\n if (status === midiMessageTypes.systemExclusive) {\n // Check for drum sysex\n if (!isGSDrumsOn(e)) {\n // Check for XG\n if (isXGOn(e)) {\n system = \"xg\";\n } else if (isGSOn(e)) {\n system = \"gs\";\n } else if (isGMOn(e)) {\n // We do not want gm1\n system = \"gm\";\n unwantedSystems.push({\n tNum: trackNum,\n e: e\n });\n } else if (isGM2On(e)) {\n system = \"gm2\";\n }\n continue;\n }\n const sysexChannel =\n [9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15][\n e.data[5] & 0x0f\n ] + portOffset;\n channelsInfo[sysexChannel].drums = !!(\n e.data[7] > 0 && e.data[5] >> 4\n );\n continue;\n }\n\n // Program change\n const chNum = (e.statusByte & 0xf) + portOffset;\n const channel = channelsInfo[chNum];\n if (status === midiMessageTypes.programChange) {\n const sentProgram = e.data[0];\n const patch: MIDIPatch = {\n program: sentProgram,\n bankLSB: channel.lastBankLSB?.data?.[1] ?? 0,\n // Make sure to take bank offset into account\n bankMSB: BankSelectHacks.subtrackBankOffset(\n channel.lastBank?.data?.[1] ?? 0,\n mid.bankOffset\n ),\n isGMGSDrum: channel.drums\n };\n const targetPreset = soundBank.getPreset(patch, system);\n SpessaSynthInfo(\n `%cInput patch: %c${MIDIPatchTools.toMIDIString(patch)}%c. Channel %c${chNum}%c. Changing patch to ${targetPreset.toString()}.`,\n consoleColors.info,\n consoleColors.unrecognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n // Set the program number\n e.data[0] = targetPreset.program;\n\n if (targetPreset.isGMGSDrum && BankSelectHacks.isSystemXG(system)) {\n // GM/GS drums returned, leave as is\n // (drums are already set since we got GMGS, just the sound bank doesn't have any XG.)\n continue;\n }\n\n if (channel.lastBank === undefined) {\n continue;\n }\n channel.lastBank.data[1] = BankSelectHacks.addBankOffset(\n targetPreset.bankMSB,\n bankOffset,\n targetPreset.isXGDrums\n );\n if (channel.lastBankLSB === undefined) {\n continue;\n }\n channel.lastBankLSB.data[1] = targetPreset.bankLSB;\n continue;\n }\n\n // Controller change\n // We only care about bank-selects\n const isLSB = e.data[0] === midiControllers.bankSelectLSB;\n if (e.data[0] !== midiControllers.bankSelect && !isLSB) {\n continue;\n }\n // Bank select\n channel.hasBankSelect = true;\n // Interpret\n if (isLSB) {\n channel.lastBankLSB = e;\n } else {\n channel.lastBank = e;\n }\n }\n\n // Add missing bank selects\n // Add all bank selects that are missing for this track\n channelsInfo.forEach((has, ch) => {\n if (has.hasBankSelect) {\n return;\n }\n // Find the first program change (for the given channel)\n const midiChannel = ch % 16;\n const status = midiMessageTypes.programChange | midiChannel;\n // Find track with this channel being used\n const portOffset = Math.floor(ch / 16) * 16;\n const port = mid.portChannelOffsetMap.indexOf(portOffset);\n const track = mid.tracks.find(\n (t) => t.port === port && t.channels.has(midiChannel)\n );\n if (track === undefined) {\n // This channel is not used at all\n return;\n }\n let indexToAdd = track.events.findIndex((e) => e.statusByte === status);\n if (indexToAdd === -1) {\n // No program change...\n // Add programs if they are missing from the track\n // (need them to activate bank 1 for the embedded soundfont)\n const programIndex = track.events.findIndex(\n (e) =>\n e.statusByte > 0x80 &&\n e.statusByte < 0xf0 &&\n (e.statusByte & 0xf) === midiChannel\n );\n if (programIndex === -1) {\n // No voices??? skip\n return;\n }\n const programTicks = track.events[programIndex].ticks;\n const targetProgram = soundBank.getPreset(\n {\n bankMSB: 0,\n bankLSB: 0,\n program: 0,\n isGMGSDrum: false\n },\n system\n ).program;\n track.addEvent(\n new MIDIMessage(\n programTicks,\n (midiMessageTypes.programChange |\n midiChannel) as MIDIMessageType,\n new IndexedByteArray([targetProgram])\n ),\n programIndex\n );\n indexToAdd = programIndex;\n }\n SpessaSynthInfo(\n `%cAdding bank select for %c${ch}`,\n consoleColors.info,\n consoleColors.recognized\n );\n const ticks = track.events[indexToAdd].ticks;\n const targetPreset = soundBank.getPreset(\n {\n bankLSB: 0,\n bankMSB: 0,\n program: has.program,\n isGMGSDrum: has.drums\n },\n system\n );\n const targetBank = BankSelectHacks.addBankOffset(\n targetPreset.bankMSB,\n bankOffset,\n targetPreset.isXGDrums\n );\n track.addEvent(\n new MIDIMessage(\n ticks,\n (midiMessageTypes.controllerChange |\n midiChannel) as MIDIMessageType,\n new IndexedByteArray([midiControllers.bankSelect, targetBank])\n ),\n indexToAdd\n );\n });\n\n // Make sure to put xg if gm\n if (system !== \"gs\" && !BankSelectHacks.isSystemXG(system)) {\n for (const m of unwantedSystems) {\n const track = mid.tracks[m.tNum];\n track.deleteEvent(track.events.indexOf(m.e));\n }\n let index = 0;\n if (mid.tracks[0].events[0].statusByte === midiMessageTypes.trackName) {\n index++;\n }\n mid.tracks[0].addEvent(getGsOn(0), index);\n }\n}\n\nexport const DEFAULT_RMIDI_WRITE_OPTIONS: RMIDIWriteOptions = {\n bankOffset: 0,\n metadata: {},\n correctBankOffset: true,\n soundBank: undefined\n};\n\n/**\n * Writes an RMIDI file. Note that this method modifies the MIDI file in-place.\n * @param mid MIDI to modify.\n * @param soundBankBinary The binary sound bank to embed into the file.\n * @param options Extra options for writing the file.\n * @returns the binary data\n */\nexport function writeRMIDIInternal(\n mid: BasicMIDI,\n soundBankBinary: ArrayBuffer,\n options: RMIDIWriteOptions\n): ArrayBuffer {\n const metadata = options.metadata;\n SpessaSynthGroup(\"%cWriting the RMIDI File...\", consoleColors.info);\n SpessaSynthInfo(\"metadata\", metadata);\n SpessaSynthInfo(\"Initial bank offset\", mid.bankOffset);\n if (options.correctBankOffset) {\n if (!options.soundBank) {\n throw new Error(\n \"Sound bank must be provided if correcting bank offset.\"\n );\n }\n correctBankOffsetInternal(mid, options.bankOffset, options.soundBank);\n }\n const newMid = new IndexedByteArray(mid.writeMIDI());\n\n // Apply metadata\n metadata.name ??= mid.getName();\n metadata.creationDate ??= new Date();\n metadata.copyright ??= DEFAULT_COPYRIGHT;\n metadata.software ??= \"SpessaSynth\";\n\n Object.entries(metadata).forEach(\n <K extends keyof RMIDInfoData>(v: unknown[]) => {\n const val = v as [K, RMIDInfoData[K]];\n if (val[1]) {\n mid.setRMIDInfo(val[0], val[1]);\n }\n }\n );\n\n // Info data for RMID\n const infoContent: Uint8Array[] = [];\n\n Object.entries(mid.rmidiInfo).forEach((v) => {\n const type = v[0] as keyof RMIDInfoData;\n const data = v[1];\n const writeInfo = (type: RMIDInfoFourCC) => {\n infoContent.push(writeRIFFChunkRaw(type, data));\n };\n switch (type) {\n case \"album\":\n // Note that there are two album chunks: IPRD and IALB\n // Spessasynth uses IPRD, but writes both\n writeInfo(\"IALB\");\n writeInfo(\"IPRD\");\n break;\n\n case \"software\":\n writeInfo(\"ISFT\");\n break;\n\n case \"infoEncoding\":\n writeInfo(\"IENC\");\n break;\n\n case \"creationDate\":\n writeInfo(\"ICRD\");\n break;\n\n case \"picture\":\n writeInfo(\"IPIC\");\n break;\n\n case \"name\":\n writeInfo(\"INAM\");\n break;\n\n case \"artist\":\n writeInfo(\"IART\");\n break;\n\n case \"genre\":\n writeInfo(\"IGNR\");\n break;\n\n case \"copyright\":\n writeInfo(\"ICOP\");\n break;\n\n case \"comment\":\n writeInfo(\"ICMT\");\n break;\n\n case \"engineer\":\n writeInfo(\"IENG\");\n break;\n\n case \"subject\":\n writeInfo(\"ISBJ\");\n break;\n\n case \"midiEncoding\":\n writeInfo(\"MENC\");\n break;\n }\n });\n\n // Bank offset\n const DBNK = new IndexedByteArray(2);\n writeLittleEndianIndexed(DBNK, options.bankOffset, 2);\n infoContent.push(writeRIFFChunkRaw(\"DBNK\", DBNK));\n\n // Combine and write out\n SpessaSynthInfo(\"%cFinished!\", consoleColors.info);\n SpessaSynthGroupEnd();\n return writeRIFFChunkParts(\"RIFF\", [\n getStringBytes(\"RMID\"),\n writeRIFFChunkRaw(\"data\", newMid),\n writeRIFFChunkParts(\"INFO\", infoContent, true),\n new IndexedByteArray(soundBankBinary)\n ]).buffer;\n}\n","import {\n SpessaSynthGroupCollapsed,\n SpessaSynthGroupEnd,\n SpessaSynthInfo\n} from \"../../utils/loggin\";\nimport { consoleColors } from \"../../utils/other\";\nimport { DEFAULT_PERCUSSION } from \"../../synthesizer/audio_engine/engine_components/synth_constants\";\nimport { isGSDrumsOn, isXGOn } from \"../../utils/sysex_detector\";\nimport type { BasicMIDI } from \"../basic_midi\";\nimport type { BasicSoundBank } from \"../../soundbank/basic_soundbank/basic_soundbank\";\nimport type { BasicPreset } from \"../../soundbank/basic_soundbank/basic_preset\";\nimport type { SynthSystem } from \"../../synthesizer/types\";\nimport {\n type MIDIController,\n midiControllers,\n midiMessageTypes\n} from \"../enums\";\nimport type { SoundBankManager } from \"../../synthesizer/audio_engine/engine_components/sound_bank_manager\";\nimport type { MIDIMessage } from \"../midi_message\";\n\ninterface InternalChannelType {\n preset: BasicPreset;\n bankMSB: number;\n bankLSB: number;\n isDrum: boolean;\n}\n\n/**\n * Gets the used programs and keys for this MIDI file with a given sound bank.\n * @param mid\n * @param soundBank the sound bank.\n * @returns Map<patch, Set<key-velocity>>.\n */\nexport function getUsedProgramsAndKeys(\n mid: BasicMIDI,\n soundBank: BasicSoundBank | SoundBankManager\n): Map<BasicPreset, Set<string>> {\n SpessaSynthGroupCollapsed(\n \"%cSearching for all used programs and keys...\",\n consoleColors.info\n );\n // Find every used preset and every key:velocity for each.\n // Make sure to care about ports and drums.\n const channelsAmount = 16 + Math.max(...mid.portChannelOffsetMap);\n const channelPresets: InternalChannelType[] = [];\n\n // Check for xg\n let system: SynthSystem = \"gs\";\n\n for (let i = 0; i < channelsAmount; i++) {\n const isDrum = i % 16 === DEFAULT_PERCUSSION;\n channelPresets.push({\n preset: soundBank.getPreset(\n {\n bankLSB: 0,\n bankMSB: 0,\n isGMGSDrum: isDrum,\n program: 0\n },\n system\n ),\n bankMSB: 0,\n bankLSB: 0,\n isDrum\n });\n }\n\n /**\n * Find all programs used and key-velocity combos in them\n * bank:program each has a set of midiNote-velocity\n */\n const usedProgramsAndKeys = new Map<BasicPreset, Set<string>>();\n\n /**\n * Indexes for tracks\n */\n const eventIndexes: number[] = Array<number>(mid.tracks.length).fill(0);\n let remainingTracks = mid.tracks.length;\n\n function findFirstEventIndex() {\n let index = 0;\n let ticks = Infinity;\n mid.tracks.forEach(({ events: track }, i) => {\n if (eventIndexes[i] >= track.length) {\n return;\n }\n if (track[eventIndexes[i]].ticks < ticks) {\n index = i;\n ticks = track[eventIndexes[i]].ticks;\n }\n });\n return index;\n }\n\n const ports = mid.tracks.map((t) => t.port);\n // Initialize\n while (remainingTracks > 0) {\n const trackNum = findFirstEventIndex();\n const track = mid.tracks[trackNum].events;\n if (eventIndexes[trackNum] >= track.length) {\n remainingTracks--;\n continue;\n }\n const event: MIDIMessage = track[eventIndexes[trackNum]];\n eventIndexes[trackNum]++;\n\n if (event.statusByte === midiMessageTypes.midiPort) {\n ports[trackNum] = event.data[0];\n continue;\n }\n const status = event.statusByte & 0xf0;\n if (\n status !== midiMessageTypes.noteOn &&\n status !== midiMessageTypes.controllerChange &&\n status !== midiMessageTypes.programChange &&\n status !== midiMessageTypes.systemExclusive\n ) {\n continue;\n }\n const channel =\n (event.statusByte & 0xf) +\n mid.portChannelOffsetMap[ports[trackNum]] || 0;\n let ch = channelPresets[channel];\n switch (status) {\n case midiMessageTypes.programChange:\n ch.preset = soundBank.getPreset(\n {\n bankMSB: ch.bankMSB,\n bankLSB: ch.bankLSB,\n program: event.data[0],\n isGMGSDrum: ch.isDrum\n },\n system\n );\n break;\n\n case midiMessageTypes.controllerChange:\n {\n switch (event.data[0] as MIDIController) {\n default:\n continue;\n\n case midiControllers.bankSelectLSB:\n ch.bankLSB = event.data[1];\n break;\n\n case midiControllers.bankSelect:\n ch.bankMSB = event.data[1];\n }\n }\n break;\n\n case midiMessageTypes.noteOn:\n if (event.data[1] === 0) {\n // That's a note off\n continue;\n }\n\n let combos = usedProgramsAndKeys.get(ch.preset);\n if (!combos) {\n combos = new Set<string>();\n usedProgramsAndKeys.set(ch.preset, combos);\n }\n\n combos.add(`${event.data[0]}-${event.data[1]}`);\n break;\n\n case midiMessageTypes.systemExclusive:\n // Check for drum sysex\n {\n if (!isGSDrumsOn(event)) {\n // Check for XG\n if (isXGOn(event)) {\n system = \"xg\";\n SpessaSynthInfo(\n \"%cXG on detected!\",\n consoleColors.recognized\n );\n }\n continue;\n }\n const sysexChannel =\n [9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15][\n event.data[5] & 0x0f\n ] + mid.portChannelOffsetMap[ports[trackNum]];\n const isDrum = !!(event.data[7] > 0 && event.data[5] >> 4);\n ch = channelPresets[sysexChannel];\n ch.isDrum = isDrum;\n }\n break;\n }\n }\n\n usedProgramsAndKeys.forEach((combos, preset) => {\n if (combos.size === 0) {\n SpessaSynthInfo(\n `%cDetected change but no keys for %c${preset.name}`,\n consoleColors.info,\n consoleColors.value\n );\n usedProgramsAndKeys.delete(preset);\n }\n });\n\n SpessaSynthGroupEnd();\n return usedProgramsAndKeys;\n}\n","import { IndexedByteArray } from \"../../utils/indexed_array\";\nimport { readBigEndian } from \"../../utils/byte_functions/big_endian\";\nimport { DEFAULT_PERCUSSION } from \"../../synthesizer/audio_engine/engine_components/synth_constants\";\nimport type { BasicMIDI } from \"../basic_midi\";\nimport type { MIDIMessage } from \"../midi_message\";\nimport type { NoteTime } from \"../types\";\n\n/**\n * Calculates all note times in seconds.\n * @param midi the midi to use\n * @param minDrumLength the shortest a drum note (channel 10) can be, in seconds.\n * @returns an array of 16 channels, each channel containing its notes,\n * with their key number, velocity, absolute start time and length in seconds.\n */\nexport function getNoteTimesInternal(\n midi: BasicMIDI,\n minDrumLength = 0\n): NoteTime[][] {\n /**\n * Gets tempo from the midi message\n * @param event the midi event\n * @return the tempo in bpm\n */\n const getTempo = (event: MIDIMessage): number => {\n // Simulate IndexedByteArray\n event.data = new IndexedByteArray(event.data.buffer);\n return 60000000 / readBigEndian(event.data, 3);\n };\n\n /**\n * An array of 16 arrays (channels)\n */\n const noteTimes: NoteTime[][] = [];\n // Flatten and sort by ticks\n const trackData = midi.tracks.map((t) => t.events);\n const events = trackData.flat();\n events.sort((e1, e2) => e1.ticks - e2.ticks);\n\n for (let i = 0; i < 16; i++) {\n noteTimes.push([]);\n }\n let elapsedTime = 0;\n let oneTickToSeconds = 60 / (120 * midi.timeDivision);\n let eventIndex = 0;\n let unfinished = 0;\n const unfinishedNotes: NoteTime[][] = [];\n for (let i = 0; i < 16; i++) {\n unfinishedNotes.push([]);\n }\n const noteOff = (midiNote: number, channel: number) => {\n const noteIndex = unfinishedNotes[channel].findIndex(\n (n) => n.midiNote === midiNote\n );\n const note = unfinishedNotes[channel][noteIndex];\n if (note) {\n const time = elapsedTime - note.start;\n note.length = time;\n if (channel === DEFAULT_PERCUSSION) {\n note.length = time < minDrumLength ? minDrumLength : time;\n }\n // Delete from unfinished\n unfinishedNotes[channel].splice(noteIndex, 1);\n }\n unfinished--;\n };\n while (eventIndex < events.length) {\n const event = events[eventIndex];\n\n const status = event.statusByte >> 4;\n const channel = event.statusByte & 0x0f;\n\n // Note off\n if (status === 0x8) {\n noteOff(event.data[0], channel);\n }\n // Note on\n else if (status === 0x9) {\n if (event.data[1] === 0) {\n // Never mind, its note off\n noteOff(event.data[0], channel);\n } else {\n // Stop previous\n noteOff(event.data[0], channel);\n const noteTime = {\n midiNote: event.data[0],\n start: elapsedTime,\n length: -1,\n velocity: event.data[1] / 127\n };\n noteTimes[channel].push(noteTime);\n unfinishedNotes[channel].push(noteTime);\n unfinished++;\n }\n }\n // Set tempo\n else if (event.statusByte === 0x51) {\n oneTickToSeconds = 60 / (getTempo(event) * midi.timeDivision);\n }\n\n if (++eventIndex >= events.length) {\n break;\n }\n\n elapsedTime +=\n oneTickToSeconds * (events[eventIndex].ticks - event.ticks);\n }\n\n // Finish the unfinished notes\n if (unfinished > 0) {\n // For every channel, for every note that is unfinished (has -1 length)\n unfinishedNotes.forEach((channelNotes, channel) => {\n channelNotes.forEach((note) => {\n const time = elapsedTime - note.start;\n note.length = time;\n if (channel === DEFAULT_PERCUSSION) {\n note.length = time < minDrumLength ? minDrumLength : time;\n }\n });\n });\n }\n return noteTimes;\n}\n","export const interpolationTypes = {\n linear: 0,\n nearestNeighbor: 1,\n hermite: 2\n} as const;\nexport type InterpolationType =\n (typeof interpolationTypes)[keyof typeof interpolationTypes];\n// Types of synthesizer message displays.\nexport const synthDisplayTypes = {\n // This message type is used to display text on the SoundCanvas display.\n soundCanvasText: 0,\n // This message type is used to display text on a Yamaha XG synthesizer.\n yamahaXGText: 1,\n // This message type is used to display a dot matrix display (pixelated graphics) on a SoundCanvas synthesizer.\n soundCanvasDotMatrix: 2\n} as const;\nexport type SynthDisplayType =\n (typeof synthDisplayTypes)[keyof typeof synthDisplayTypes];\n\n// Data entry states for the MIDI data entry system.\n// These states are used to track the current state of data entry for MIDI controllers.\nexport const dataEntryStates = {\n Idle: 0,\n RPCoarse: 1,\n RPFine: 2,\n NRPCoarse: 3,\n NRPFine: 4,\n DataCoarse: 5,\n DataFine: 6\n} as const;\n\nexport type DataEntryState =\n (typeof dataEntryStates)[keyof typeof dataEntryStates];\n\nexport const customControllers = {\n channelTuning: 0, // Cents, RPN for fine tuning\n channelTransposeFine: 1, // Cents, only the decimal tuning, (e.g., transpose is 4.5,\n // Then shift by 4 keys + tune by 50 cents)\n modulationMultiplier: 2, // Cents, set by modulation depth RPN\n masterTuning: 3, // Cents, set by system exclusive\n channelTuningSemitones: 4, // Semitones, for RPN coarse tuning\n channelKeyShift: 5, // Key shift: for system exclusive\n sf2NPRNGeneratorLSB: 6 // Sf2 NPRN LSB for selecting a generator value\n} as const;\n\nexport type CustomController =\n (typeof customControllers)[keyof typeof customControllers];\n","import { MIDIMessage } from \"../midi_message\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport {\n SpessaSynthGroupCollapsed,\n SpessaSynthGroupEnd,\n SpessaSynthInfo\n} from \"../../utils/loggin\";\nimport { consoleColors } from \"../../utils/other\";\n\nimport { DEFAULT_PERCUSSION } from \"../../synthesizer/audio_engine/engine_components/synth_constants\";\nimport { isGM2On, isGMOn, isGSOn, isXGOn } from \"../../utils/sysex_detector\";\nimport { BankSelectHacks } from \"../../utils/midi_hacks\";\nimport {\n midiControllers,\n type MIDIMessageType,\n midiMessageTypes\n} from \"../enums\";\nimport { getGsOn } from \"./get_gs_on\";\nimport type {\n DesiredChannelTranspose,\n DesiredControllerChange,\n DesiredProgramChange\n} from \"../types\";\nimport type { BasicMIDI } from \"../basic_midi\";\nimport type { SynthesizerSnapshot } from \"../../synthesizer/audio_engine/snapshot/synthesizer_snapshot\";\nimport type { SynthSystem } from \"../../synthesizer/types\";\nimport { customControllers } from \"../../synthesizer/enums\";\nimport { MIDIPatchTools } from \"../../soundbank/basic_soundbank/midi_patch\";\n\nfunction getControllerChange(\n channel: number,\n cc: number,\n value: number,\n ticks: number\n): MIDIMessage {\n return new MIDIMessage(\n ticks,\n (midiMessageTypes.controllerChange | channel % 16) as MIDIMessageType,\n new IndexedByteArray([cc, value])\n );\n}\n\nfunction getDrumChange(channel: number, ticks: number): MIDIMessage {\n const chanAddress =\n 0x10 |\n [1, 2, 3, 4, 5, 6, 7, 8, 0, 9, 10, 11, 12, 13, 14, 15][channel % 16];\n // Excluding manufacturerID DeviceID and ModelID (and F7)\n const sysexData = [\n 0x41, // Roland\n 0x10, // Device ID (defaults to 16 on roland)\n 0x42, // GS\n 0x12, // Command ID (DT1) (whatever that means...)\n 0x40, // System parameter }\n chanAddress, // Channel parameter } Address\n 0x15, // Drum change }\n 0x01 // Is Drums } Data\n ];\n // Calculate checksum\n // https://cdn.roland.com/assets/media/pdf/F-20_MIDI_Imple_e01_W.pdf section 4\n const sum = 0x40 + chanAddress + 0x15 + 0x01;\n const checksum = 128 - (sum % 128);\n // Add system exclusive to enable drums\n return new MIDIMessage(\n ticks,\n midiMessageTypes.systemExclusive,\n new IndexedByteArray([...sysexData, checksum, 0xf7])\n );\n}\n\n/**\n * Allows easy editing of the file by removing channels, changing programs,\n * changing controllers and transposing channels. Note that this modifies the MIDI in-place.\n *\n * @param midi the midi to change\n * @param desiredProgramChanges - The programs to set on given channels.\n * @param desiredControllerChanges - The controllers to set on given channels.\n * @param desiredChannelsToClear - The channels to remove from the sequence.\n * @param desiredChannelsToTranspose - The channels to transpose.\n */\nexport function modifyMIDIInternal(\n midi: BasicMIDI,\n desiredProgramChanges: DesiredProgramChange[] = [],\n desiredControllerChanges: DesiredControllerChange[] = [],\n desiredChannelsToClear: number[] = [],\n desiredChannelsToTranspose: DesiredChannelTranspose[] = []\n) {\n SpessaSynthGroupCollapsed(\n \"%cApplying changes to the MIDI file...\",\n consoleColors.info\n );\n\n SpessaSynthInfo(\"Desired program changes:\", desiredProgramChanges);\n SpessaSynthInfo(\"Desired CC changes:\", desiredControllerChanges);\n SpessaSynthInfo(\"Desired channels to clear:\", desiredChannelsToClear);\n SpessaSynthInfo(\n \"Desired channels to transpose:\",\n desiredChannelsToTranspose\n );\n\n const channelsToChangeProgram = new Set<number>();\n desiredProgramChanges.forEach((c) => {\n channelsToChangeProgram.add(c.channel);\n });\n\n // Go through all events one by one\n let system: SynthSystem = \"gs\";\n let addedGs = false;\n /**\n * Indexes for tracks\n */\n const eventIndexes: number[] = Array<number>(midi.tracks.length).fill(0);\n let remainingTracks = midi.tracks.length;\n\n function findFirstEventIndex() {\n let index = 0;\n let ticks = Infinity;\n midi.tracks.forEach((track, i) => {\n if (eventIndexes[i] >= track.events.length) {\n return;\n }\n if (track.events[eventIndexes[i]].ticks < ticks) {\n index = i;\n ticks = track.events[eventIndexes[i]].ticks;\n }\n });\n return index;\n }\n\n // It copies midiPorts everywhere else, but here 0 works so DO NOT CHANGE!\n /**\n * Midi port number for the corresponding track\n */\n const midiPorts: number[] = midi.tracks.map((t) => t.port);\n /**\n * Midi port: channel offset\n */\n const midiPortChannelOffsets: Record<number, number> = {};\n let midiPortChannelOffset = 0;\n\n const assignMIDIPort = (trackNum: number, port: number) => {\n // Do not assign ports to empty tracks\n\n if (midi.tracks[trackNum].channels.size === 0) {\n return;\n }\n\n // Assign new 16 channels if the port is not occupied yet\n if (midiPortChannelOffset === 0) {\n midiPortChannelOffset += 16;\n midiPortChannelOffsets[port] = 0;\n }\n\n if (midiPortChannelOffsets[port] === undefined) {\n midiPortChannelOffsets[port] = midiPortChannelOffset;\n midiPortChannelOffset += 16;\n }\n\n midiPorts[trackNum] = port;\n };\n\n // Assign port offsets\n midi.tracks.forEach((track, i) => {\n assignMIDIPort(i, track.port);\n });\n\n const channelsAmount = midiPortChannelOffset;\n /**\n * Tracks if the channel already had its first note on\n */\n const isFirstNoteOn = Array<boolean>(channelsAmount).fill(true);\n\n /**\n * MIDI key transpose\n */\n const coarseTranspose = Array<number>(channelsAmount).fill(0);\n /**\n * RPN fine transpose\n */\n const fineTranspose = Array<number>(channelsAmount).fill(0);\n desiredChannelsToTranspose.forEach((transpose) => {\n const coarse = Math.trunc(transpose.keyShift);\n const fine = transpose.keyShift - coarse;\n coarseTranspose[transpose.channel] = coarse;\n fineTranspose[transpose.channel] = fine;\n });\n\n while (remainingTracks > 0) {\n const trackNum = findFirstEventIndex();\n const track = midi.tracks[trackNum];\n if (eventIndexes[trackNum] >= track.events.length) {\n remainingTracks--;\n continue;\n }\n const index = eventIndexes[trackNum]++;\n const e = track.events[index];\n\n const deleteThisEvent = () => {\n track.deleteEvent(index);\n eventIndexes[trackNum]--;\n };\n\n const addEventBefore = (e: MIDIMessage, offset = 0) => {\n track.addEvent(e, index + offset);\n eventIndexes[trackNum]++;\n };\n\n const portOffset = midiPortChannelOffsets[midiPorts[trackNum]] || 0;\n if (e.statusByte === midiMessageTypes.midiPort) {\n assignMIDIPort(trackNum, e.data[0]);\n continue;\n }\n // Don't clear meta\n if (\n e.statusByte <= midiMessageTypes.sequenceSpecific &&\n e.statusByte >= midiMessageTypes.sequenceNumber\n ) {\n continue;\n }\n const status = e.statusByte & 0xf0;\n const midiChannel = e.statusByte & 0xf;\n const channel = midiChannel + portOffset;\n // Clear channel?\n if (desiredChannelsToClear.includes(channel)) {\n deleteThisEvent();\n continue;\n }\n switch (status) {\n case midiMessageTypes.noteOn:\n // Is it first?\n if (isFirstNoteOn[channel]) {\n isFirstNoteOn[channel] = false;\n // All right, so this is the first note on\n // First: controllers\n // Because FSMP does not like program changes after cc changes in embedded midis\n // And since we use splice,\n // Controllers get added first, then programs before them\n // Now add controllers\n desiredControllerChanges\n .filter((c) => c.channel === channel)\n .forEach((change) => {\n const ccChange = getControllerChange(\n midiChannel,\n change.controllerNumber,\n change.controllerValue,\n e.ticks\n );\n addEventBefore(ccChange);\n });\n const fineTune = fineTranspose[channel];\n\n if (fineTune !== 0) {\n // Add rpn\n // 64 is the center, 96 = 50 cents up\n const centsCoarse = fineTune * 64 + 64;\n const rpnCoarse = getControllerChange(\n midiChannel,\n midiControllers.registeredParameterMSB,\n 0,\n e.ticks\n );\n const rpnFine = getControllerChange(\n midiChannel,\n midiControllers.registeredParameterLSB,\n 1,\n e.ticks\n );\n const dataEntryCoarse = getControllerChange(\n channel,\n midiControllers.dataEntryMSB,\n centsCoarse,\n e.ticks\n );\n const dataEntryFine = getControllerChange(\n midiChannel,\n midiControllers.dataEntryLSB,\n 0,\n e.ticks\n );\n addEventBefore(dataEntryFine);\n addEventBefore(dataEntryCoarse);\n addEventBefore(rpnFine);\n addEventBefore(rpnCoarse);\n }\n\n if (channelsToChangeProgram.has(channel)) {\n const change = desiredProgramChanges.find(\n (c) => c.channel === channel\n );\n if (!change) {\n continue;\n }\n SpessaSynthInfo(\n `%cSetting %c${change.channel}%c to %c${MIDIPatchTools.toMIDIString(change)}%c. Track num: %c${trackNum}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n\n // Note: this is in reverse.\n // The output event order is: drums -> lsb -> msb -> program change\n let desiredBankMSB = change.bankMSB;\n let desiredBankLSB = change.bankLSB;\n const desiredProgram = change.program;\n\n // Add program change\n const programChange = new MIDIMessage(\n e.ticks,\n (midiMessageTypes.programChange |\n midiChannel) as MIDIMessageType,\n new IndexedByteArray([desiredProgram])\n );\n addEventBefore(programChange);\n\n const addBank = (isLSB: boolean, v: number) => {\n const bankChange = getControllerChange(\n midiChannel,\n isLSB\n ? midiControllers.bankSelectLSB\n : midiControllers.bankSelect,\n v,\n e.ticks\n );\n addEventBefore(bankChange);\n };\n\n if (\n BankSelectHacks.isSystemXG(system) &&\n change.isGMGSDrum\n ) {\n // Best I can do is XG drums\n SpessaSynthInfo(\n `%cAdding XG Drum change on track %c${trackNum}`,\n consoleColors.recognized,\n consoleColors.value\n );\n desiredBankMSB =\n BankSelectHacks.getDrumBank(system);\n desiredBankLSB = 0;\n }\n\n // Add bank change\n addBank(false, desiredBankMSB);\n addBank(true, desiredBankLSB);\n\n if (\n change.isGMGSDrum &&\n !BankSelectHacks.isSystemXG(system) &&\n midiChannel !== DEFAULT_PERCUSSION\n ) {\n // Add gs drum change\n SpessaSynthInfo(\n `%cAdding GS Drum change on track %c${trackNum}`,\n consoleColors.recognized,\n consoleColors.value\n );\n addEventBefore(getDrumChange(midiChannel, e.ticks));\n }\n }\n }\n // Transpose key (for zero it won't change anyway)\n e.data[0] += coarseTranspose[channel];\n break;\n\n case midiMessageTypes.noteOff:\n e.data[0] += coarseTranspose[channel];\n break;\n\n case midiMessageTypes.programChange:\n // Do we delete it?\n if (channelsToChangeProgram.has(channel)) {\n // This channel has program change. BEGONE!\n deleteThisEvent();\n continue;\n }\n break;\n\n case midiMessageTypes.controllerChange:\n {\n const ccNum = e.data[0];\n const changes = desiredControllerChanges.find(\n (c) =>\n c.channel === channel &&\n ccNum === c.controllerNumber\n );\n if (changes !== undefined) {\n // This controller is locked, BEGONE CHANGE!\n deleteThisEvent();\n continue;\n }\n // Bank maybe?\n if (\n ccNum === midiControllers.bankSelect ||\n ccNum === midiControllers.bankSelectLSB\n ) {\n if (channelsToChangeProgram.has(channel)) {\n // BEGONE!\n deleteThisEvent();\n }\n }\n }\n break;\n\n case midiMessageTypes.systemExclusive:\n // Check for xg on\n if (isXGOn(e)) {\n SpessaSynthInfo(\n \"%cXG system on detected\",\n consoleColors.info\n );\n system = \"xg\";\n addedGs = true; // Flag as true so gs won't get added\n } else if (\n e.data[0] === 0x43 && // Yamaha\n e.data[2] === 0x4c && // XG\n e.data[3] === 0x08 && // Part parameter\n e.data[5] === 0x03 // Program change\n ) {\n // Check for xg program change\n // Do we delete it?\n if (channelsToChangeProgram.has(e.data[4] + portOffset)) {\n // This channel has program change. BEGONE!\n deleteThisEvent();\n }\n } else if (isGM2On(e)) {\n SpessaSynthInfo(\n \"%cGM2 system on detected\",\n consoleColors.info\n );\n system = \"gm2\";\n addedGs = true; // Flag as true so gs won't get added\n } else if (isGSOn(e)) {\n // Check for GS on\n // That's a GS on, we're done here\n addedGs = true;\n SpessaSynthInfo(\n \"%cGS on detected!\",\n consoleColors.recognized\n );\n break;\n } else if (isGMOn(e)) {\n // Check for GM on\n // That's a GM1 system change, remove it!\n SpessaSynthInfo(\n \"%cGM on detected, removing!\",\n consoleColors.info\n );\n deleteThisEvent();\n addedGs = false;\n }\n }\n }\n // Check for gs\n if (!addedGs && desiredProgramChanges.length > 0) {\n // Gs is not on, add it on the first track at index 0 (or 1 if track name is first)\n let index = 0;\n if (\n midi.tracks[0].events[0].statusByte === midiMessageTypes.trackName\n ) {\n index++;\n }\n midi.tracks[0].addEvent(getGsOn(0), index);\n SpessaSynthInfo(\"%cGS on not detected. Adding it.\", consoleColors.info);\n }\n midi.flush();\n SpessaSynthGroupEnd();\n}\n\n/**\n * Modifies the sequence according to the locked presets and controllers in the given snapshot\n */\nexport function applySnapshotInternal(\n midi: BasicMIDI,\n snapshot: SynthesizerSnapshot\n) {\n const channelsToTranspose: DesiredChannelTranspose[] = [];\n\n const channelsToClear: number[] = [];\n const programChanges: DesiredProgramChange[] = [];\n const controllerChanges: DesiredControllerChange[] = [];\n snapshot.channelSnapshots.forEach((channel, channelNumber) => {\n if (channel.isMuted) {\n channelsToClear.push(channelNumber);\n return;\n }\n const transposeFloat =\n channel.channelTransposeKeyShift +\n channel.customControllers[customControllers.channelTransposeFine] /\n 100;\n if (transposeFloat !== 0) {\n channelsToTranspose.push({\n channel: channelNumber,\n keyShift: transposeFloat\n });\n }\n if (channel.lockPreset) {\n programChanges.push({\n channel: channelNumber,\n ...channel.patch\n });\n }\n // Check for locked controllers and change them appropriately\n channel.lockedControllers.forEach((l, ccNumber) => {\n if (\n !l ||\n ccNumber > 127 ||\n ccNumber === midiControllers.bankSelect\n ) {\n return;\n }\n const targetValue = channel.midiControllers[ccNumber] >> 7; // Channel controllers are stored as 14 bit values\n controllerChanges.push({\n channel: channelNumber,\n controllerNumber: ccNumber,\n controllerValue: targetValue\n });\n });\n });\n midi.modify(\n programChanges,\n controllerChanges,\n channelsToClear,\n channelsToTranspose\n );\n}\n","import {\n getStringBytes,\n readBinaryStringIndexed\n} from \"../utils/byte_functions/string\";\nimport {\n SpessaSynthGroup,\n SpessaSynthGroupEnd,\n SpessaSynthInfo,\n SpessaSynthWarn\n} from \"../utils/loggin\";\nimport { consoleColors } from \"../utils/other\";\nimport { readBigEndianIndexed } from \"../utils/byte_functions/big_endian\";\nimport { readVariableLengthQuantity } from \"../utils/byte_functions/variable_length_quantity\";\nimport { inflateSync } from \"../externals/fflate/fflate_wrapper\";\nimport { IndexedByteArray } from \"../utils/indexed_array\";\nimport type { BasicMIDI } from \"./basic_midi\";\nimport type { RMIDInfoData } from \"./types\";\n\nconst metadataTypes = {\n XMFFileType: 0,\n nodeName: 1,\n nodeIDNumber: 2,\n resourceFormat: 3,\n filenameOnDisk: 4,\n filenameExtensionOnDisk: 5,\n macOSFileTypeAndCreator: 6,\n mimeType: 7,\n title: 8,\n copyrightNotice: 9,\n comment: 10,\n autoStart: 11, // Node Name of the FileNode containing the SMF image to autostart when the XMF file loads\n preload: 12, // Used to preload specific SMF and DLS file images.\n contentDescription: 13, // RP-42a (https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp42.pdf)\n ID3Metadata: 14 // RP-47 (https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp47.pdf)\n} as const;\n\ntype metadataTypes = (typeof metadataTypes)[keyof typeof metadataTypes];\n\nconst referenceTypeIds = {\n inLineResource: 1,\n inFileResource: 2,\n inFileNode: 3,\n externalFile: 4,\n externalXMF: 5,\n XMFFileURIandNodeID: 6\n} as const;\n\ntype referenceTypeIds =\n (typeof referenceTypeIds)[keyof typeof referenceTypeIds];\n\nconst resourceFormatIDs = {\n StandardMIDIFile: 0,\n StandardMIDIFileType1: 1,\n DLS1: 2,\n DLS2: 3,\n DLS22: 4,\n mobileDLS: 5,\n unknown: -1,\n folder: -2\n} as const;\n\ntype resourceFormatStrings = keyof typeof resourceFormatIDs;\ntype resourceFormatIDs =\n (typeof resourceFormatIDs)[keyof typeof resourceFormatIDs];\n\nconst formatTypeIDs = {\n standard: 0,\n MMA: 1,\n registered: 2,\n nonRegistered: 3\n} as const;\n\nconst unpackerIDs = {\n none: 0,\n MMAUnpacker: 1,\n registered: 2,\n nonRegistered: 3\n} as const;\n\ntype unpackerIDs = (typeof unpackerIDs)[keyof typeof unpackerIDs];\n\ntype InternalUnpackerType = Partial<{\n id: unpackerIDs;\n standardID: number;\n manufacturerID: number;\n manufacturerInternalID: number;\n decodedSize: number;\n}>;\n\nclass XMFNode {\n public length: number;\n /**\n * 0 means it's a file node\n */\n public itemCount: number;\n public metadataLength: number;\n\n public metadata: Record<string, string | number[] | IndexedByteArray> = {};\n\n public nodeData: IndexedByteArray;\n\n public innerNodes: XMFNode[] = [];\n\n public packedContent = false;\n\n public nodeUnpackers: InternalUnpackerType[] = [];\n\n public resourceFormat: resourceFormatStrings = \"unknown\";\n\n public referenceTypeID: referenceTypeIds;\n\n public constructor(binaryData: IndexedByteArray) {\n const nodeStartIndex = binaryData.currentIndex;\n this.length = readVariableLengthQuantity(binaryData);\n this.itemCount = readVariableLengthQuantity(binaryData);\n // Header length\n const headerLength = readVariableLengthQuantity(binaryData);\n const readBytes = binaryData.currentIndex - nodeStartIndex;\n\n const remainingHeader = headerLength - readBytes;\n const headerData = binaryData.slice(\n binaryData.currentIndex,\n binaryData.currentIndex + remainingHeader\n );\n binaryData.currentIndex += remainingHeader;\n\n this.metadataLength = readVariableLengthQuantity(headerData);\n\n const metadataChunk = headerData.slice(\n headerData.currentIndex,\n headerData.currentIndex + this.metadataLength\n );\n headerData.currentIndex += this.metadataLength;\n\n let fieldSpecifier: metadataTypes | string;\n let key: string;\n while (metadataChunk.currentIndex < metadataChunk.length) {\n const firstSpecifierByte =\n metadataChunk[metadataChunk.currentIndex];\n if (firstSpecifierByte === 0) {\n metadataChunk.currentIndex++;\n fieldSpecifier = readVariableLengthQuantity(\n metadataChunk\n ) as metadataTypes;\n if (!Object.values(metadataTypes).includes(fieldSpecifier)) {\n SpessaSynthInfo(\n `Unknown field specifier: ${fieldSpecifier}`\n );\n key = `unknown_${fieldSpecifier}`;\n } else {\n key =\n Object.keys(metadataTypes).find(\n (k) =>\n metadataTypes[\n k as keyof typeof metadataTypes\n ] === fieldSpecifier\n ) ?? \"\";\n }\n } else {\n // This is the length of string\n const stringLength = readVariableLengthQuantity(metadataChunk);\n fieldSpecifier = readBinaryStringIndexed(\n metadataChunk,\n stringLength\n );\n key = fieldSpecifier;\n }\n\n const numberOfVersions = readVariableLengthQuantity(metadataChunk);\n if (numberOfVersions === 0) {\n const dataLength = readVariableLengthQuantity(metadataChunk);\n const contentsChunk = metadataChunk.slice(\n metadataChunk.currentIndex,\n metadataChunk.currentIndex + dataLength\n );\n metadataChunk.currentIndex += dataLength;\n const formatID = readVariableLengthQuantity(contentsChunk);\n // Text only\n if (formatID < 4) {\n this.metadata[key] = readBinaryStringIndexed(\n contentsChunk,\n dataLength - 1\n );\n } else {\n this.metadata[key] = contentsChunk.slice(\n contentsChunk.currentIndex\n );\n }\n } else {\n // Throw new Error (\"International content is not supported.\");\n // Skip the number of versions\n SpessaSynthInfo(`International content: ${numberOfVersions}`);\n // Length in bytes\n // Skip the whole thing!\n metadataChunk.currentIndex +=\n readVariableLengthQuantity(metadataChunk);\n }\n }\n\n const unpackersStart = headerData.currentIndex;\n const unpackersLength = readVariableLengthQuantity(headerData);\n const unpackersData = headerData.slice(\n headerData.currentIndex,\n unpackersStart + unpackersLength\n );\n headerData.currentIndex = unpackersStart + unpackersLength;\n if (unpackersLength > 0) {\n this.packedContent = true;\n while (unpackersData.currentIndex < unpackersLength) {\n const unpacker: InternalUnpackerType = {};\n unpacker.id = readVariableLengthQuantity(\n unpackersData\n ) as unpackerIDs;\n switch (unpacker.id) {\n case unpackerIDs.nonRegistered:\n case unpackerIDs.registered:\n SpessaSynthGroupEnd();\n throw new Error(\n `Unsupported unpacker ID: ${unpacker.id}`\n );\n\n default:\n SpessaSynthGroupEnd();\n throw new Error(\n `Unknown unpacker ID: ${unpacker.id as string}`\n );\n\n case unpackerIDs.none:\n unpacker.standardID =\n readVariableLengthQuantity(unpackersData);\n break;\n\n case unpackerIDs.MMAUnpacker:\n {\n let manufacturerID =\n unpackersData[unpackersData.currentIndex++];\n // One or three byte form, depending on if the first byte is zero\n if (manufacturerID === 0) {\n manufacturerID <<= 8;\n manufacturerID |=\n unpackersData[unpackersData.currentIndex++];\n manufacturerID <<= 8;\n manufacturerID |=\n unpackersData[unpackersData.currentIndex++];\n }\n const manufacturerInternalID =\n readVariableLengthQuantity(unpackersData);\n unpacker.manufacturerID = manufacturerID;\n unpacker.manufacturerInternalID =\n manufacturerInternalID;\n }\n break;\n }\n unpacker.decodedSize =\n readVariableLengthQuantity(unpackersData);\n this.nodeUnpackers.push(unpacker);\n }\n }\n binaryData.currentIndex = nodeStartIndex + headerLength;\n this.referenceTypeID = readVariableLengthQuantity(\n binaryData\n ) as referenceTypeIds;\n this.nodeData = binaryData.slice(\n binaryData.currentIndex,\n nodeStartIndex + this.length\n );\n binaryData.currentIndex = nodeStartIndex + this.length;\n switch (this.referenceTypeID) {\n case referenceTypeIds.inLineResource:\n break;\n\n case referenceTypeIds.externalXMF:\n case referenceTypeIds.inFileNode:\n case referenceTypeIds.XMFFileURIandNodeID:\n case referenceTypeIds.externalFile:\n case referenceTypeIds.inFileResource:\n SpessaSynthGroupEnd();\n throw new Error(\n `Unsupported reference type: ${this.referenceTypeID}`\n );\n\n default:\n SpessaSynthGroupEnd();\n throw new Error(\n `Unknown reference type: ${this.referenceTypeID as string}`\n );\n }\n\n // Read the data\n if (this.isFile) {\n if (this.packedContent) {\n const compressed = this.nodeData.slice(2, this.nodeData.length);\n SpessaSynthInfo(\n `%cPacked content. Attempting to deflate. Target size: %c${this.nodeUnpackers[0].decodedSize}`,\n consoleColors.warn,\n consoleColors.value\n );\n try {\n this.nodeData = new IndexedByteArray(\n inflateSync(compressed).buffer\n );\n } catch (e: unknown) {\n SpessaSynthGroupEnd();\n if (e instanceof Error) {\n throw new Error(\n `Error unpacking XMF file contents: ${e.message}.`\n );\n }\n }\n }\n /**\n * Interpret the content\n */\n const resourceFormat = this.metadata.resourceFormat as number[];\n if (resourceFormat === undefined) {\n SpessaSynthWarn(\"No resource format for this file node!\");\n } else {\n const formatTypeID = resourceFormat[0];\n if (formatTypeID !== formatTypeIDs.standard) {\n SpessaSynthInfo(\n `Non-standard formatTypeID: ${resourceFormat.toString()}`\n );\n this.resourceFormat =\n resourceFormat.toString() as resourceFormatStrings;\n }\n const resourceFormatID = resourceFormat[1] as resourceFormatIDs;\n if (\n !Object.values(resourceFormatIDs).includes(resourceFormatID)\n ) {\n SpessaSynthInfo(\n `Unrecognized resource format: ${resourceFormatID}`\n );\n } else {\n this.resourceFormat = Object.keys(resourceFormatIDs).find(\n (k) =>\n resourceFormatIDs[\n k as keyof typeof resourceFormatIDs\n ] === resourceFormatID\n ) as resourceFormatStrings;\n }\n }\n } else {\n // Folder node\n this.resourceFormat = \"folder\";\n while (this.nodeData.currentIndex < this.nodeData.length) {\n const nodeStartIndex = this.nodeData.currentIndex;\n const nodeLength = readVariableLengthQuantity(this.nodeData);\n const nodeData = this.nodeData.slice(\n nodeStartIndex,\n nodeStartIndex + nodeLength\n );\n this.nodeData.currentIndex = nodeStartIndex + nodeLength;\n this.innerNodes.push(new XMFNode(nodeData));\n }\n }\n }\n\n public get isFile() {\n return this.itemCount === 0;\n }\n}\n\n/**\n * Parses an XMF file\n * @param midi {BasicMIDI}\n * @param binaryData {IndexedByteArray}\n * @returns {IndexedByteArray} the file byte array\n */\nexport function loadXMF(\n midi: BasicMIDI,\n binaryData: IndexedByteArray\n): IndexedByteArray {\n midi.bankOffset = 0;\n // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/xmf-v1a.pdf\n // https://wiki.multimedia.cx/index.php?title=Extensible_Music_Format_(XMF)\n const sanityCheck = readBinaryStringIndexed(binaryData, 4);\n if (sanityCheck !== \"XMF_\") {\n SpessaSynthGroupEnd();\n throw new SyntaxError(\n `Invalid XMF Header! Expected \"_XMF\", got \"${sanityCheck}\"`\n );\n }\n\n SpessaSynthGroup(\"%cParsing XMF file...\", consoleColors.info);\n const version = readBinaryStringIndexed(binaryData, 4);\n SpessaSynthInfo(\n `%cXMF version: %c${version}`,\n consoleColors.info,\n consoleColors.recognized\n );\n // https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp43.pdf\n // Version 2.00 has additional bytes\n if (version === \"2.00\") {\n const fileTypeId = readBigEndianIndexed(binaryData, 4);\n const fileTypeRevisionId = readBigEndianIndexed(binaryData, 4);\n SpessaSynthInfo(\n `%cFile Type ID: %c${fileTypeId}%c, File Type Revision ID: %c${fileTypeRevisionId}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n }\n\n // File length\n readVariableLengthQuantity(binaryData);\n\n const metadataTableLength = readVariableLengthQuantity(binaryData);\n // Skip metadata\n binaryData.currentIndex += metadataTableLength;\n\n // Skip to tree root\n binaryData.currentIndex = readVariableLengthQuantity(binaryData);\n const rootNode = new XMFNode(binaryData);\n let midiArray: IndexedByteArray | undefined = undefined;\n /**\n * Find the stuff we care about\n */\n const searchNode = (node: XMFNode) => {\n const checkMeta = (\n xmf: string,\n rmid: keyof Omit<RMIDInfoData, \"picture\" | \"creationDate\">\n ) => {\n if (\n node.metadata[xmf] !== undefined &&\n typeof node.metadata[xmf] === \"string\"\n ) {\n midi.rmidiInfo[rmid] = getStringBytes(node.metadata[xmf]);\n }\n };\n // Meta\n checkMeta(\"nodeName\", \"name\");\n checkMeta(\"title\", \"name\");\n checkMeta(\"copyrightNotice\", \"copyright\");\n checkMeta(\"comment\", \"comment\");\n if (node.isFile) {\n switch (node.resourceFormat) {\n default:\n return;\n case \"DLS1\":\n case \"DLS2\":\n case \"DLS22\":\n case \"mobileDLS\":\n SpessaSynthInfo(\n \"%cFound embedded DLS!\",\n consoleColors.recognized\n );\n midi.embeddedSoundBank = node.nodeData.buffer;\n break;\n\n case \"StandardMIDIFile\":\n case \"StandardMIDIFileType1\":\n SpessaSynthInfo(\n \"%cFound embedded MIDI!\",\n consoleColors.recognized\n );\n midiArray = node.nodeData;\n break;\n }\n } else {\n for (const n of node.innerNodes) {\n searchNode(n);\n }\n }\n };\n searchNode(rootNode);\n SpessaSynthGroupEnd();\n if (!midiArray) {\n throw new Error(\"No MIDI data in the XMF file!\");\n }\n return midiArray;\n}\n","import { MIDIMessage } from \"./midi_message\";\nimport { IndexedByteArray } from \"../utils/indexed_array\";\n\nexport class MIDITrack {\n /**\n * The name of this track.\n */\n public name = \"\";\n /**\n * The MIDI port number used by the track.\n */\n public port = 0;\n /**\n * A set that contains the MIDI channels used by the track in the sequence.\n */\n public channels = new Set<number>();\n /**\n * All the MIDI messages of this track.\n */\n public events: Omit<MIDIMessage[], \"push\" | \"splice\"> = [];\n\n public static copyFrom(track: MIDITrack) {\n const t = new MIDITrack();\n t.copyFrom(track);\n return t;\n }\n\n public copyFrom(track: MIDITrack) {\n this.name = track.name;\n this.port = track.port;\n this.channels = new Set(track.channels);\n this.events = track.events.map(\n (e) =>\n new MIDIMessage(\n e.ticks,\n e.statusByte,\n new IndexedByteArray(e.data)\n )\n );\n }\n\n /**\n * Adds an event to the track.\n * @param event The event to add.\n * @param index The index at which to add this event.\n */\n public addEvent(event: MIDIMessage, index: number) {\n (this.events as MIDIMessage[]).splice(index, 0, event);\n }\n\n /**\n * Removes an event from the track.\n * @param index The index of the event to remove.\n */\n public deleteEvent(index: number) {\n (this.events as MIDIMessage[]).splice(index, 1);\n }\n\n /**\n * Appends an event to the end of the track.\n * @param event The event to add.\n */\n public pushEvent(event: MIDIMessage) {\n (this.events as MIDIMessage[]).push(event);\n }\n}\n","import { dataBytesAmount, getChannel, MIDIMessage } from \"./midi_message\";\nimport { IndexedByteArray } from \"../utils/indexed_array\";\nimport { consoleColors } from \"../utils/other\";\nimport { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo, SpessaSynthWarn } from \"../utils/loggin\";\nimport { readRIFFChunk } from \"../utils/riff_chunk\";\nimport { readVariableLengthQuantity } from \"../utils/byte_functions/variable_length_quantity\";\nimport { readBigEndianIndexed } from \"../utils/byte_functions/big_endian\";\nimport { readBinaryString, readBinaryStringIndexed } from \"../utils/byte_functions/string\";\nimport { readLittleEndian } from \"../utils/byte_functions/little_endian\";\nimport { type MIDIMessageType } from \"./enums\";\nimport { BasicMIDI } from \"./basic_midi\";\nimport { loadXMF } from \"./xmf_loader\";\nimport type { MIDIFormat, RMIDInfoFourCC } from \"./types\";\nimport { MIDITrack } from \"./midi_track\";\n\n/**\n * Midi_loader.ts\n * purpose:\n * parses a midi file for the sequencer,\n * including things like marker or CC 2/4 loop detection, copyright detection, etc.\n */\n\ninterface MIDIChunk {\n type: string;\n size: number;\n data: IndexedByteArray;\n}\n\n/**\n * Loads a MIDI file (SMF, RMIDI, XMF) from a given ArrayBuffer.\n * @param outputMIDI The BasicMIDI instance to populate with the parsed MIDI data.\n * @param arrayBuffer The ArrayBuffer containing the binary file data.\n * @param fileName The optional name of the file, will be used if the MIDI file does not have a name.\n * @remarks\n * This function reads the MIDI file format, extracts the header and track chunks,\n * and populates the BasicMIDI instance with the parsed data.\n * It supports Standard MIDI Files (SMF), RIFF MIDI (RMIDI), and Extensible Music Format (XMF).\n * It also handles embedded soundbanks in RMIDI files.\n * If the file is an RMIDI file, it will extract the embedded soundbank and store\n * it in the `embeddedSoundFont` property of the BasicMIDI instance.\n * If the file is an XMF file, it will parse the XMF structure and extract the MIDI data.\n */\nexport function loadMIDIFromArrayBufferInternal(\n outputMIDI: BasicMIDI,\n arrayBuffer: ArrayBuffer,\n fileName?: string\n) {\n SpessaSynthGroupCollapsed(`%cParsing MIDI File...`, consoleColors.info);\n outputMIDI.fileName = fileName;\n const binaryData = new IndexedByteArray(arrayBuffer);\n let smfFileBinary = binaryData;\n\n const readMIDIChunk = (fileByteArray: IndexedByteArray): MIDIChunk => {\n const type = readBinaryStringIndexed(fileByteArray, 4);\n const size = readBigEndianIndexed(fileByteArray, 4);\n const data = new IndexedByteArray(size);\n const chunk: MIDIChunk = {\n type,\n size,\n data\n };\n\n const dataSlice = fileByteArray.slice(\n fileByteArray.currentIndex,\n fileByteArray.currentIndex + chunk.size\n );\n chunk.data.set(dataSlice, 0);\n fileByteArray.currentIndex += chunk.size;\n return chunk;\n };\n\n // Check for rmid\n const initialString = readBinaryString(binaryData, 4);\n if (initialString === \"RIFF\") {\n // Possibly an RMID file (https://github.com/spessasus/sf2-rmidi-specification#readme)\n // Skip size\n binaryData.currentIndex += 8;\n const rmid = readBinaryStringIndexed(binaryData, 4);\n if (rmid !== \"RMID\") {\n SpessaSynthGroupEnd();\n throw new SyntaxError(\n `Invalid RMIDI Header! Expected \"RMID\", got \"${rmid}\"`\n );\n }\n const riff = readRIFFChunk(binaryData);\n if (riff.header !== \"data\") {\n SpessaSynthGroupEnd();\n throw new SyntaxError(\n `Invalid RMIDI Chunk header! Expected \"data\", got \"${rmid}\"`\n );\n }\n // OutputMIDI is a rmid, load the midi into an array for parsing\n smfFileBinary = riff.data;\n\n let isSF2RMIDI = false;\n let foundDbnk = false;\n // Keep loading chunks until we get the \"SFBK\" header\n while (binaryData.currentIndex <= binaryData.length) {\n const startIndex = binaryData.currentIndex;\n const currentChunk = readRIFFChunk(binaryData, true);\n if (currentChunk.header === \"RIFF\") {\n const type = readBinaryStringIndexed(\n currentChunk.data,\n 4\n ).toLowerCase();\n if (type === \"sfbk\" || type === \"sfpk\" || type === \"dls \") {\n SpessaSynthInfo(\n \"%cFound embedded soundbank!\",\n consoleColors.recognized\n );\n outputMIDI.embeddedSoundBank = binaryData.slice(\n startIndex,\n startIndex + currentChunk.size\n ).buffer;\n } else {\n SpessaSynthWarn(`Unknown RIFF chunk: \"${type}\"`);\n }\n if (type === \"dls \") {\n // Assume bank offset of 0 by default. If we find any bank selects, then the offset is 1.\n outputMIDI.isDLSRMIDI = true;\n } else {\n isSF2RMIDI = true;\n }\n } else if (currentChunk.header === \"LIST\") {\n const type = readBinaryStringIndexed(currentChunk.data, 4);\n if (type === \"INFO\") {\n SpessaSynthInfo(\n \"%cFound RMIDI INFO chunk!\",\n consoleColors.recognized\n );\n while (\n currentChunk.data.currentIndex <= currentChunk.size\n ) {\n const infoChunk = readRIFFChunk(\n currentChunk.data,\n true\n );\n const headerTyped = infoChunk.header as RMIDInfoFourCC;\n const infoData = infoChunk.data;\n switch (headerTyped) {\n default:\n SpessaSynthWarn(\n `Unknown RMIDI Info: ${headerTyped as string}`\n );\n break;\n\n case \"INAM\":\n outputMIDI.rmidiInfo.name = infoData;\n break;\n\n case \"IALB\":\n case \"IPRD\":\n // Note that there are two album chunks: IPRD and IALB\n outputMIDI.rmidiInfo.album = infoData;\n break;\n\n case \"ICRT\":\n case \"ICRD\":\n // Older RMIDIs written by spessasynth erroneously used ICRT instead of ICRD.\n outputMIDI.rmidiInfo.creationDate = infoData;\n break;\n\n case \"IART\":\n outputMIDI.rmidiInfo.artist = infoData;\n break;\n\n case \"IGNR\":\n outputMIDI.rmidiInfo.genre = infoData;\n break;\n\n case \"IPIC\":\n outputMIDI.rmidiInfo.picture = infoData;\n break;\n\n case \"ICOP\":\n outputMIDI.rmidiInfo.copyright = infoData;\n break;\n\n case \"ICMT\":\n outputMIDI.rmidiInfo.comment = infoData;\n break;\n\n case \"IENG\":\n outputMIDI.rmidiInfo.engineer = infoData;\n break;\n\n case \"ISFT\":\n outputMIDI.rmidiInfo.software = infoData;\n break;\n\n case \"ISBJ\":\n outputMIDI.rmidiInfo.subject = infoData;\n break;\n\n case \"IENC\":\n outputMIDI.rmidiInfo.infoEncoding = infoData;\n break;\n\n case \"MENC\":\n outputMIDI.rmidiInfo.midiEncoding = infoData;\n break;\n\n case \"DBNK\":\n outputMIDI.bankOffset = readLittleEndian(\n infoData,\n 2\n );\n foundDbnk = true;\n break;\n }\n }\n }\n }\n }\n\n if (isSF2RMIDI && !foundDbnk) {\n outputMIDI.bankOffset = 1; // Defaults to 1\n }\n\n if (outputMIDI.isDLSRMIDI) {\n // Assume bank offset of 0 by default. If we find any bank selects, then the offset is 1.\n outputMIDI.bankOffset = 0;\n }\n\n // If no embedded bank, assume 0\n if (outputMIDI.embeddedSoundBank === undefined) {\n outputMIDI.bankOffset = 0;\n }\n } else if (initialString === \"XMF_\") {\n // XMF file\n smfFileBinary = loadXMF(outputMIDI, binaryData);\n } else {\n smfFileBinary = binaryData;\n }\n const headerChunk = readMIDIChunk(smfFileBinary);\n if (headerChunk.type !== \"MThd\") {\n SpessaSynthGroupEnd();\n throw new SyntaxError(\n `Invalid MIDI Header! Expected \"MThd\", got \"${headerChunk.type}\"`\n );\n }\n\n if (headerChunk.size !== 6) {\n SpessaSynthGroupEnd();\n throw new RangeError(\n `Invalid MIDI header chunk size! Expected 6, got ${headerChunk.size}`\n );\n }\n\n // Format\n outputMIDI.format = readBigEndianIndexed(headerChunk.data, 2) as MIDIFormat;\n // Tracks count\n const trackCount = readBigEndianIndexed(headerChunk.data, 2);\n // Time division\n outputMIDI.timeDivision = readBigEndianIndexed(headerChunk.data, 2);\n // Read all the tracks\n for (let i = 0; i < trackCount; i++) {\n const track = new MIDITrack();\n const trackChunk = readMIDIChunk(smfFileBinary);\n\n if (trackChunk.type !== \"MTrk\") {\n SpessaSynthGroupEnd();\n throw new SyntaxError(\n `Invalid track header! Expected \"MTrk\" got \"${trackChunk.type}\"`\n );\n }\n\n /**\n * MIDI running byte\n */\n let runningByte: MIDIMessageType | undefined = undefined;\n\n let totalTicks = 0;\n // Format 2 plays sequentially\n if (outputMIDI.format === 2 && i > 0) {\n totalTicks +=\n outputMIDI.tracks[i - 1].events[\n outputMIDI.tracks[i - 1].events.length - 1\n ].ticks;\n }\n // Loop until we reach the end of track\n while (trackChunk.data.currentIndex < trackChunk.size) {\n totalTicks += readVariableLengthQuantity(trackChunk.data);\n\n // Check if the status byte is valid (IE. larger than 127)\n const statusByteCheck =\n trackChunk.data[trackChunk.data.currentIndex];\n\n let statusByte: MIDIMessageType;\n // If we have a running byte and the status byte isn't valid\n if (runningByte !== undefined && statusByteCheck < 0x80) {\n statusByte = runningByte;\n } else {\n if (statusByteCheck < 0x80) {\n // If we don't have a running byte and the status byte isn't valid, it's an error.\n SpessaSynthGroupEnd();\n throw new SyntaxError(\n `Unexpected byte with no running byte. (${statusByteCheck})`\n );\n } else {\n // If the status byte is valid, use that\n statusByte = trackChunk.data[\n trackChunk.data.currentIndex++\n ] as MIDIMessageType;\n }\n }\n const statusByteChannel = getChannel(statusByte);\n\n let eventDataLength;\n\n // Determine the message's length;\n switch (statusByteChannel) {\n case -1:\n // System common/realtime (no length)\n eventDataLength = 0;\n break;\n\n case -2:\n // Meta (the next is the actual status byte)\n statusByte = trackChunk.data[\n trackChunk.data.currentIndex++\n ] as MIDIMessageType;\n eventDataLength = readVariableLengthQuantity(\n trackChunk.data\n );\n break;\n\n case -3:\n // Sysex\n eventDataLength = readVariableLengthQuantity(\n trackChunk.data\n );\n break;\n\n default:\n // Voice message\n // Gets the midi message length\n eventDataLength =\n dataBytesAmount[\n (statusByte >> 4) as keyof typeof dataBytesAmount\n ];\n // Save the status byte\n runningByte = statusByte;\n break;\n }\n\n // Put the event data into the array\n const eventData = new IndexedByteArray(eventDataLength);\n eventData.set(\n trackChunk.data.slice(\n trackChunk.data.currentIndex,\n trackChunk.data.currentIndex + eventDataLength\n ),\n 0\n );\n const event = new MIDIMessage(totalTicks, statusByte, eventData);\n track.pushEvent(event);\n\n // Advance the track chunk\n trackChunk.data.currentIndex += eventDataLength;\n }\n outputMIDI.tracks.push(track);\n\n SpessaSynthInfo(\n `%cParsed %c${outputMIDI.tracks.length}%c / %c${outputMIDI.tracks.length}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n }\n\n SpessaSynthInfo(`%cAll tracks parsed correctly!`, consoleColors.recognized);\n // Parse the events (no need to sort as they are already sorted by the SMF specification)\n outputMIDI.flush(false);\n SpessaSynthGroupEnd();\n SpessaSynthInfo(\n `%cMIDI file parsed. Total tick time: %c${outputMIDI.lastVoiceEventTick}%c, total seconds time: %c${outputMIDI.duration}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n}\n","// Attempt to load a date from string\nimport { SpessaSynthWarn } from \"./loggin\";\n\n// Needed because\n// Invalid date: \"sábado 26 setembro 2020, 16:40:14\". Replacing with the current date!\nconst translationPortuguese = new Map([\n // Weekdays map (Portuguese to English)\n [\"domingo\", \"Sunday\"],\n [\"segunda-feira\", \"Monday\"],\n [\"terça-feira\", \"Tuesday\"],\n [\"quarta-feira\", \"Wednesday\"],\n [\"quinta-feira\", \"Thursday\"],\n [\"sexta-feira\", \"Friday\"],\n [\"sábado\", \"Saturday\"],\n\n // Months map (Portuguese to English)\n [\"janeiro\", \"January\"],\n [\"fevereiro\", \"February\"],\n [\"março\", \"March\"],\n [\"abril\", \"April\"],\n [\"maio\", \"May\"],\n [\"junho\", \"June\"],\n [\"julho\", \"July\"],\n [\"agosto\", \"August\"],\n [\"setembro\", \"September\"],\n [\"outubro\", \"October\"],\n [\"novembro\", \"November\"],\n [\"dezembro\", \"December\"]\n]);\n\nconst translations: Map<string, string>[] = [translationPortuguese];\n\nfunction tryTranslate(dateString: string) {\n // Translating\n for (const translation of translations) {\n let translated = dateString;\n translation.forEach((english, pt) => {\n const regex = new RegExp(pt, \"gi\");\n translated = translated.replace(regex, english);\n });\n const date = new Date(translated);\n if (!isNaN(date.getTime())) {\n return date;\n }\n }\n return undefined;\n}\n\nfunction tryDotted(dateString: string) {\n // Regex to match DD.MM.YYYY format\n const match = /^(\\d{2})\\.(\\d{2})\\.(\\d{4})$/.exec(dateString);\n if (match) {\n const day = parseInt(match[1]);\n const month = parseInt(match[2]) - 1;\n const year = parseInt(match[3]);\n const date = new Date(year, month, day);\n if (!isNaN(date.getTime())) {\n return date;\n }\n }\n return undefined;\n}\n\nfunction tryAWE(dateString: string) {\n // Regex to match a \"DD MM YY\" (testcase: AWE32-MIDI-Conversions, sbk conversion so possibly SFEDT used that)\n // Also \"DD MM YY\" (without double space)\n const match = /^(\\d{1,2})\\s{1,2}(\\d{1,2})\\s{1,2}(\\d{2})$/.exec(dateString);\n if (match) {\n const day = match[1];\n const month = (parseInt(match[2]) + 1).toString(); // Seems 0 indexed for some reason\n const year = match[3];\n // Format like string to let date decide if 2000 or 1900\n const date = new Date(`${month}/${day}/${year}`);\n if (!isNaN(date.getTime())) {\n return date;\n }\n }\n return undefined;\n}\n\nfunction tryYear(dateString: string) {\n // Math exactly 4 numbers\n const regex = /\\b\\d{4}\\b/;\n const match = regex.exec(dateString);\n return match ? new Date(match[0]) : undefined;\n}\n\nexport function parseDateString(dateString: string) {\n // Trim the date. Testcase: \" 4 0 97\"\n dateString = dateString.trim();\n if (dateString.length < 1) {\n return new Date();\n }\n\n // Remove \"st\" , \"nd\" , \"rd\", \"th\", etc.\n const filtered = dateString.replace(/\\b(\\d+)(st|nd|rd|th)\\b/g, \"$1\");\n const date = new Date(filtered);\n if (isNaN(date.getTime())) {\n const translated = tryTranslate(dateString);\n if (translated) {\n return translated;\n }\n const dotted = tryDotted(dateString);\n if (dotted) {\n return dotted;\n }\n const awe = tryAWE(dateString);\n if (awe) {\n return awe;\n }\n\n const year = tryYear(dateString);\n if (year) {\n return year;\n }\n\n SpessaSynthWarn(\n `Invalid date: \"${dateString}\". Replacing with the current date!`\n );\n return new Date();\n }\n return date;\n}\n","import { getStringBytes, readBinaryString } from \"../utils/byte_functions/string\";\nimport { MIDIMessage } from \"./midi_message\";\nimport { readBigEndian } from \"../utils/byte_functions/big_endian\";\nimport { SpessaSynthGroup, SpessaSynthGroupEnd, SpessaSynthInfo, SpessaSynthWarn } from \"../utils/loggin\";\nimport { consoleColors } from \"../utils/other\";\nimport { writeMIDIInternal } from \"./midi_tools/midi_writer\";\nimport { DEFAULT_RMIDI_WRITE_OPTIONS, writeRMIDIInternal } from \"./midi_tools/rmidi_writer\";\nimport { getUsedProgramsAndKeys } from \"./midi_tools/used_keys_loaded\";\nimport { IndexedByteArray } from \"../utils/indexed_array\";\nimport { getNoteTimesInternal } from \"./midi_tools/get_note_times\";\nimport type { BasicSoundBank } from \"../soundbank/basic_soundbank/basic_soundbank\";\nimport type {\n DesiredChannelTranspose,\n DesiredControllerChange,\n DesiredProgramChange,\n MIDIFormat,\n MIDILoop,\n NoteTime,\n RMIDInfoData,\n RMIDIWriteOptions,\n TempoChange\n} from \"./types\";\nimport { applySnapshotInternal, modifyMIDIInternal } from \"./midi_tools/midi_editor\";\nimport type { SynthesizerSnapshot } from \"../synthesizer/audio_engine/snapshot/synthesizer_snapshot\";\nimport { loadMIDIFromArrayBufferInternal } from \"./midi_loader\";\nimport { midiMessageTypes } from \"./enums\";\nimport type { GenericRange } from \"../soundbank/types\";\nimport { MIDITrack } from \"./midi_track\";\nimport { fillWithDefaults } from \"../utils/fill_with_defaults\";\nimport { parseDateString } from \"../utils/load_date\";\nimport type { BasicPreset } from \"../soundbank/basic_soundbank/basic_preset\";\nimport type { SoundBankManager } from \"../synthesizer/audio_engine/engine_components/sound_bank_manager\";\n\n/**\n * BasicMIDI is the base of a complete MIDI file.\n */\nexport class BasicMIDI {\n /**\n * The tracks in the sequence.\n */\n public tracks: MIDITrack[] = [];\n\n /**\n * The time division of the sequence, representing the number of ticks per beat.\n */\n public timeDivision = 0;\n\n /**\n * The duration of the sequence, in seconds.\n */\n public duration = 0;\n\n /**\n * The tempo changes in the sequence, ordered from the last change to the first.\n * Each change is represented by an object with a tick position and a tempo value in beats per minute.\n */\n public tempoChanges: TempoChange[] = [{ ticks: 0, tempo: 120 }];\n\n /**\n * Any extra metadata found in the file.\n * These messages were deemed \"interesting\" by the parsing algorithm\n */\n public extraMetadata: MIDIMessage[] = [];\n\n /**\n * An array containing the lyrics of the sequence.\n */\n public lyrics: MIDIMessage[] = [];\n\n /**\n * The tick position of the first note-on event in the MIDI sequence.\n */\n public firstNoteOn = 0;\n\n /**\n * The MIDI key range used in the sequence, represented by a minimum and maximum note value.\n */\n public keyRange: GenericRange = { min: 0, max: 127 };\n\n /**\n * The tick position of the last voice event (such as note-on, note-off, or control change) in the sequence.\n */\n public lastVoiceEventTick = 0;\n\n /**\n * An array of channel offsets for each MIDI port, using the SpessaSynth method.\n * The index is the port number and the value is the channel offset.\n */\n public portChannelOffsetMap: number[] = [0];\n\n /**\n * The loop points (in ticks) of the sequence, including both start and end points.\n */\n public loop: MIDILoop = { start: 0, end: 0 };\n\n /**\n * The file name of the MIDI sequence, if provided during parsing.\n */\n public fileName?: string;\n\n /**\n * The format of the MIDI file, which can be 0, 1, or 2, indicating the type of the MIDI file.\n */\n public format: MIDIFormat = 0;\n\n /**\n * The RMID (Resource-Interchangeable MIDI) info data, if the file is RMID formatted.\n * Otherwise, this object is empty.\n * Info type: Chunk data as a binary array.\n * Note that text chunks contain a terminal zero byte.\n */\n public rmidiInfo: Partial<\n Record<keyof RMIDInfoData, Uint8Array<ArrayBuffer>>\n > = {};\n\n /**\n * The bank offset used for RMID files.\n */\n public bankOffset = 0;\n\n /**\n * If the MIDI file is a Soft Karaoke file (.kar), this is set to true.\n * https://www.mixagesoftware.com/en/midikit/help/HTML/karaoke_formats.html\n */\n public isKaraokeFile = false;\n\n /**\n * Indicates if this file is a Multi-Port MIDI file.\n */\n public isMultiPort = false;\n\n /**\n * If the MIDI file is a DLS RMIDI file.\n */\n public isDLSRMIDI = false;\n\n /**\n * The embedded sound bank in the MIDI file, represented as an ArrayBuffer, if available.\n */\n public embeddedSoundBank?: ArrayBuffer;\n\n /**\n * The raw, encoded MIDI name, represented as a Uint8Array.\n * Useful when the MIDI file uses a different code page.\n * Undefined if no MIDI name could be found.\n */\n protected binaryName?: Uint8Array;\n\n /**\n * The encoding of the RMIDI info in file, if specified.\n */\n public get infoEncoding() {\n const encodingInfo = this.rmidiInfo.infoEncoding;\n if (!encodingInfo) {\n return undefined;\n }\n let lengthToRead = encodingInfo.byteLength;\n // Some files don't have a terminal zero\n if (encodingInfo[encodingInfo.byteLength - 1] === 0) {\n lengthToRead--;\n }\n return readBinaryString(encodingInfo, lengthToRead);\n }\n\n /**\n * Loads a MIDI file (SMF, RMIDI, XMF) from a given ArrayBuffer.\n * @param arrayBuffer The ArrayBuffer containing the binary file data.\n * @param fileName The optional name of the file, will be used if the MIDI file does not have a name.\n */\n public static fromArrayBuffer(\n arrayBuffer: ArrayBuffer,\n fileName = \"\"\n ): BasicMIDI {\n const mid = new BasicMIDI();\n loadMIDIFromArrayBufferInternal(mid, arrayBuffer, fileName);\n return mid;\n }\n\n /**\n * Loads a MIDI file (SMF, RMIDI, XMF) from a given file.\n * @param file The file to load.\n */\n public static async fromFile(file: File) {\n const mid = new BasicMIDI();\n loadMIDIFromArrayBufferInternal(\n mid,\n await file.arrayBuffer(),\n file.name\n );\n return mid;\n }\n\n /**\n * Copies a MIDI.\n * @param mid The MIDI to copy.\n * @returns The copied MIDI.\n */\n public static copyFrom(mid: BasicMIDI) {\n const m = new BasicMIDI();\n m.copyFrom(mid);\n return m;\n }\n\n /**\n * Copies a MIDI.\n * @param mid The MIDI to copy.\n */\n public copyFrom(mid: BasicMIDI) {\n this.copyMetadataFrom(mid);\n\n this.embeddedSoundBank = mid?.embeddedSoundBank?.slice(0) ?? undefined; // Deep copy\n this.tracks = mid.tracks.map((track) => MIDITrack.copyFrom(track)); // Deep copy of each track array\n }\n\n /**\n * Converts MIDI ticks to time in seconds.\n * @param ticks The time in MIDI ticks.\n * @returns The time in seconds.\n */\n public midiTicksToSeconds(ticks: number): number {\n let totalSeconds = 0;\n\n while (ticks > 0) {\n // Tempo changes are reversed, so the first element is the last tempo change\n // And the last element is the first tempo change\n // (always at tick 0 and tempo 120)\n // Find the last tempo change that has occurred\n const tempo = this.tempoChanges.find((v) => v.ticks < ticks);\n if (!tempo) {\n return totalSeconds;\n }\n\n // Calculate the difference and tempo time\n const timeSinceLastTempo = ticks - tempo.ticks;\n totalSeconds +=\n (timeSinceLastTempo * 60) / (tempo.tempo * this.timeDivision);\n ticks -= timeSinceLastTempo;\n }\n\n return totalSeconds;\n }\n\n /**\n * Gets the used programs and keys for this MIDI file with a given sound bank.\n * @param soundbank the sound bank.\n * @returns The output data is a key-value pair: preset -> Set<\"key-velocity\">\n */\n public getUsedProgramsAndKeys(\n soundbank: BasicSoundBank | SoundBankManager\n ): Map<BasicPreset, Set<string>> {\n return getUsedProgramsAndKeys(this, soundbank);\n }\n\n /**\n * Updates all internal values of the MIDI.\n * @param sortEvents if the events should be sorted by ticks. Recommended to be true.\n */\n public flush(sortEvents = true) {\n if (sortEvents) {\n for (const t of this.tracks) {\n // Sort the track by ticks\n t.events.sort((e1, e2) => e1.ticks - e2.ticks);\n }\n }\n this.parseInternal();\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Calculates all note times in seconds.\n * @param minDrumLength the shortest a drum note (channel 10) can be, in seconds.\n * @returns an array of 16 channels, each channel containing its notes,\n * with their key number, velocity, absolute start time and length in seconds.\n */\n public getNoteTimes(minDrumLength = 0): NoteTime[][] {\n return getNoteTimesInternal(this, minDrumLength);\n }\n\n /**\n * Exports the midi as a standard MIDI file.\n * @returns the binary file data.\n */\n public writeMIDI(): ArrayBuffer {\n return writeMIDIInternal(this);\n }\n\n /**\n * Writes an RMIDI file. Note that this method modifies the MIDI file in-place.\n * @param soundBankBinary the binary sound bank to embed into the file.\n * @param configuration Extra options for writing the file.\n * @returns the binary file data.\n */\n public writeRMIDI(\n soundBankBinary: ArrayBuffer,\n configuration: Partial<RMIDIWriteOptions> = DEFAULT_RMIDI_WRITE_OPTIONS\n ): ArrayBuffer {\n return writeRMIDIInternal(\n this,\n soundBankBinary,\n fillWithDefaults(configuration, DEFAULT_RMIDI_WRITE_OPTIONS)\n );\n }\n\n /**\n * Allows easy editing of the file by removing channels, changing programs,\n * changing controllers and transposing channels. Note that this modifies the MIDI *in-place*.\n * @param desiredProgramChanges - The programs to set on given channels.\n * @param desiredControllerChanges - The controllers to set on given channels.\n * @param desiredChannelsToClear - The channels to remove from the sequence.\n * @param desiredChannelsToTranspose - The channels to transpose.\n */\n public modify(\n desiredProgramChanges: DesiredProgramChange[] = [],\n desiredControllerChanges: DesiredControllerChange[] = [],\n desiredChannelsToClear: number[] = [],\n desiredChannelsToTranspose: DesiredChannelTranspose[] = []\n ) {\n modifyMIDIInternal(\n this,\n desiredProgramChanges,\n desiredControllerChanges,\n desiredChannelsToClear,\n desiredChannelsToTranspose\n );\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Modifies the sequence *in-place* according to the locked presets and controllers in the given snapshot.\n * @param snapshot the snapshot to apply.\n */\n public applySnapshot(snapshot: SynthesizerSnapshot) {\n applySnapshotInternal(this, snapshot);\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Gets the MIDI's decoded name.\n * @param encoding The encoding to use if the MIDI uses an extended code page.\n * @remarks\n * Do not call in audioWorkletGlobalScope as it uses TextDecoder.\n * RMIDI encoding overrides the provided encoding.\n */\n public getName(encoding = \"Shift_JIS\") {\n let rawName = \"\";\n const n = this.getRMIDInfo(\"name\");\n if (n) {\n return n.trim();\n }\n if (this.binaryName) {\n encoding = this.getRMIDInfo(\"midiEncoding\") ?? encoding;\n try {\n const decoder = new TextDecoder(encoding);\n // Trim since \" \"\n // Is not a valid name\n // MIDI file with that name: th07_10.mid\n rawName = decoder.decode(this.binaryName).trim();\n } catch (e) {\n SpessaSynthWarn(`Failed to decode MIDI name: ${e as string}`);\n }\n }\n return rawName || this.fileName;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Gets the decoded extra metadata as text and removes any unneeded characters (such as \"@T\" for karaoke files)\n * @param encoding The encoding to use if the MIDI uses an extended code page.\n * @remarks\n * Do not call in audioWorkletGlobalScope as it uses TextDecoder.\n * RMIDI encoding overrides the provided encoding.\n */\n public getExtraMetadata(encoding = \"Shift_JIS\") {\n encoding = this.infoEncoding ?? encoding;\n const decoder = new TextDecoder(encoding);\n return this.extraMetadata.map((d) => {\n const decoded = decoder.decode(d.data);\n return decoded.replace(/@T|@A/g, \"\").trim();\n });\n }\n\n /**\n * Sets a given RMIDI info value.\n * @param infoType The type to set.\n * @param infoData The value to set it to.\n * @remarks\n * This sets the Info encoding to utf-8.\n */\n public setRMIDInfo<K extends keyof RMIDInfoData>(\n infoType: K,\n infoData: RMIDInfoData[K]\n ) {\n this.rmidiInfo.infoEncoding = getStringBytes(\"utf-8\", true);\n if (infoType === \"picture\") {\n // TS2339: Property buffer does not exist on type string | ArrayBuffer | Date\n // Property buffer does not exist on type string\n this.rmidiInfo.picture = new Uint8Array(infoData as ArrayBuffer);\n } else if (infoType === \"creationDate\") {\n this.rmidiInfo.creationDate = getStringBytes(\n (infoData as Date).toISOString(),\n true\n );\n } else {\n const encoded = new TextEncoder().encode(infoData as string);\n // Add zero byte\n this.rmidiInfo[infoType] = new Uint8Array([...encoded, 0]);\n }\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Gets a given chunk from the RMIDI information, undefined if it does not exist.\n * @param infoType The metadata type.\n * @returns String, Date, ArrayBuffer or undefined.\n */\n public getRMIDInfo<K extends keyof RMIDInfoData>(\n infoType: K\n ): RMIDInfoData[K] | undefined {\n if (!this.rmidiInfo[infoType]) {\n return undefined;\n }\n const encoding = this.infoEncoding ?? \"UTF-8\";\n\n if (infoType === \"picture\") {\n return this.rmidiInfo[infoType].buffer as RMIDInfoData[K];\n } else if (infoType === \"creationDate\") {\n return parseDateString(\n readBinaryString(this.rmidiInfo[infoType])\n ) as RMIDInfoData[K];\n }\n\n try {\n const decoder = new TextDecoder(encoding);\n let infoBuffer = this.rmidiInfo[infoType];\n if (infoBuffer[infoBuffer.length - 1] === 0) {\n // Do not decode the terminal byte\n infoBuffer = infoBuffer?.slice(0, infoBuffer.length - 1);\n }\n return decoder.decode(infoBuffer.buffer).trim() as RMIDInfoData[K];\n } catch (e) {\n SpessaSynthWarn(\n `Failed to decode ${infoType} name: ${e as string}`\n );\n return undefined;\n }\n }\n\n /**\n * INTERNAL USE ONLY!\n */\n protected copyMetadataFrom(mid: BasicMIDI) {\n // Properties can be assigned\n this.fileName = mid.fileName;\n this.timeDivision = mid.timeDivision;\n this.duration = mid.duration;\n this.firstNoteOn = mid.firstNoteOn;\n this.lastVoiceEventTick = mid.lastVoiceEventTick;\n this.format = mid.format;\n this.bankOffset = mid.bankOffset;\n this.isKaraokeFile = mid.isKaraokeFile;\n this.isMultiPort = mid.isMultiPort;\n this.isDLSRMIDI = mid.isDLSRMIDI;\n this.isDLSRMIDI = mid.isDLSRMIDI;\n\n // Copying arrays\n this.tempoChanges = [...mid.tempoChanges];\n this.extraMetadata = mid.extraMetadata.map(\n (m) =>\n new MIDIMessage(\n m.ticks,\n m.statusByte,\n new IndexedByteArray(m.data)\n )\n );\n this.lyrics = mid.lyrics.map(\n (arr) =>\n new MIDIMessage(\n arr.ticks,\n arr.statusByte,\n new IndexedByteArray(arr.data)\n )\n );\n this.portChannelOffsetMap = [...mid.portChannelOffsetMap];\n this.binaryName = mid?.binaryName?.slice();\n\n // Copying objects\n this.loop = { ...mid.loop };\n this.keyRange = { ...mid.keyRange };\n this.rmidiInfo = {};\n Object.entries(mid.rmidiInfo).forEach((v) => {\n const key = v[0];\n const value = v[1];\n this.rmidiInfo[key as keyof RMIDInfoData] = value.slice();\n });\n }\n\n /**\n * Parses internal MIDI values\n */\n protected parseInternal() {\n SpessaSynthGroup(\"%cInterpreting MIDI events...\", consoleColors.info);\n /**\n * For karaoke files, text events starting with @T are considered titles,\n * usually the first one is the title, and the latter is things such as \"sequenced by\" etc.\n */\n let karaokeHasTitle = false;\n\n this.keyRange = { max: 0, min: 127 };\n\n this.extraMetadata = [];\n\n let nameDetected = false;\n if (typeof this.rmidiInfo.name !== \"undefined\") {\n // Name is already provided in RMIDInfo\n nameDetected = true;\n }\n\n // Loop tracking\n let loopStart = null;\n let loopEnd = null;\n\n for (const track of this.tracks) {\n const usedChannels = new Set<number>();\n let trackHasVoiceMessages = false;\n\n for (let i = 0; i < track.events.length; i++) {\n const e = track.events[i];\n // Check if it's a voice message\n if (e.statusByte >= 0x80 && e.statusByte < 0xf0) {\n trackHasVoiceMessages = true;\n // Voice messages are 7-bit always\n for (let j = 0; j < e.data.length; j++) {\n e.data[j] = Math.min(127, e.data[j]);\n }\n // Last voice event tick\n if (e.ticks > this.lastVoiceEventTick) {\n this.lastVoiceEventTick = e.ticks;\n }\n\n // Interpret the voice message\n switch (e.statusByte & 0xf0) {\n // Cc change: loop points\n case midiMessageTypes.controllerChange:\n switch (e.data[0]) {\n case 2:\n case 116:\n loopStart = e.ticks;\n break;\n\n case 4:\n case 117:\n if (loopEnd === null) {\n loopEnd = e.ticks;\n } else {\n // This controller has occurred more than once;\n // This means\n // That it doesn't indicate the loop\n loopEnd = 0;\n }\n break;\n\n case 0:\n // Check RMID\n if (\n this.isDLSRMIDI &&\n e.data[1] !== 0 &&\n e.data[1] !== 127\n ) {\n SpessaSynthInfo(\n \"%cDLS RMIDI with offset 1 detected!\",\n consoleColors.recognized\n );\n this.bankOffset = 1;\n }\n }\n break;\n\n // Note on: used notes tracking and key range\n case midiMessageTypes.noteOn: {\n usedChannels.add(e.statusByte & 0x0f);\n const note = e.data[0];\n this.keyRange.min = Math.min(\n this.keyRange.min,\n note\n );\n this.keyRange.max = Math.max(\n this.keyRange.max,\n note\n );\n break;\n }\n }\n }\n const eventText = readBinaryString(e.data);\n // Interpret the message\n switch (e.statusByte) {\n case midiMessageTypes.endOfTrack:\n if (i !== track.events.length - 1) {\n i--;\n track.deleteEvent(i);\n SpessaSynthWarn(\"Unexpected EndOfTrack. Removing!\");\n }\n break;\n\n case midiMessageTypes.setTempo:\n // Add the tempo change\n this.tempoChanges.push({\n ticks: e.ticks,\n tempo: 60000000 / readBigEndian(e.data, 3)\n });\n break;\n\n case midiMessageTypes.marker:\n // Check for loop markers\n {\n const text = eventText.trim().toLowerCase();\n switch (text) {\n default:\n break;\n\n case \"start\":\n case \"loopstart\":\n loopStart = e.ticks;\n break;\n\n case \"loopend\":\n loopEnd = e.ticks;\n }\n }\n break;\n\n case midiMessageTypes.copyright:\n this.extraMetadata.push(e);\n\n break;\n // Fallthrough\n\n case midiMessageTypes.lyric:\n // Note here: .kar files sometimes just use...\n // Lyrics instead of text because why not (of course)\n // Perform the same check for @KMIDI KARAOKE FILE\n if (\n eventText.trim().startsWith(\"@KMIDI KARAOKE FILE\")\n ) {\n this.isKaraokeFile = true;\n SpessaSynthInfo(\n \"%cKaraoke MIDI detected!\",\n consoleColors.recognized\n );\n }\n\n if (this.isKaraokeFile) {\n // Replace the type of the message with text\n e.statusByte = midiMessageTypes.text;\n } else {\n // Add lyrics like a regular midi file\n this.lyrics.push(e);\n }\n\n // Kar: treat the same as text\n // Fallthrough\n case midiMessageTypes.text: {\n // Possibly Soft Karaoke MIDI file\n // It has a text event at the start of the file\n // \"@KMIDI KARAOKE FILE\"\n const checkedText = eventText.trim();\n if (checkedText.startsWith(\"@KMIDI KARAOKE FILE\")) {\n this.isKaraokeFile = true;\n\n SpessaSynthInfo(\n \"%cKaraoke MIDI detected!\",\n consoleColors.recognized\n );\n } else if (this.isKaraokeFile) {\n // Check for @T (title)\n // Or @A because it is a title too sometimes?\n // IDK it's strange\n if (\n checkedText.startsWith(\"@T\") ||\n checkedText.startsWith(\"@A\")\n ) {\n if (!karaokeHasTitle) {\n this.binaryName = e.data.slice(2);\n karaokeHasTitle = true;\n nameDetected = true;\n } else {\n // Append to metadata\n this.extraMetadata.push(e);\n }\n } else if (!checkedText.startsWith(\"@\")) {\n // Non @: the lyrics\n this.lyrics.push(e);\n }\n }\n break;\n }\n }\n }\n // Add used channels\n track.channels = usedChannels;\n\n // Track name\n track.name = \"\";\n const trackName = track.events.find(\n (e) => e.statusByte === midiMessageTypes.trackName\n );\n // Don't add the first track's name as it's not metadata, it's the name!\n if (trackName && this.tracks.indexOf(track) > 0) {\n track.name = readBinaryString(trackName.data);\n // If the track has no voice messages, its \"track name\" event (if it has any)\n // Is some metadata.\n // Add it to copyright\n if (\n !trackHasVoiceMessages &&\n !track.name.toLowerCase().includes(\"setup\")\n ) {\n this.extraMetadata.push(trackName);\n }\n }\n }\n\n // Reverse the tempo changes\n this.tempoChanges.reverse();\n\n SpessaSynthInfo(\n `%cCorrecting loops, ports and detecting notes...`,\n consoleColors.info\n );\n\n const firstNoteOns = [];\n for (const t of this.tracks) {\n const firstNoteOn = t.events.find(\n (e) => (e.statusByte & 0xf0) === midiMessageTypes.noteOn\n );\n if (firstNoteOn) {\n firstNoteOns.push(firstNoteOn.ticks);\n }\n }\n this.firstNoteOn = Math.min(...firstNoteOns);\n\n SpessaSynthInfo(\n `%cFirst note-on detected at: %c${this.firstNoteOn}%c ticks!`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n\n if (loopStart !== null && loopEnd === null) {\n // Not a loop\n loopStart = this.firstNoteOn;\n loopEnd = this.lastVoiceEventTick;\n } else {\n loopStart ??= this.firstNoteOn;\n\n if (loopEnd === null || loopEnd === 0) {\n loopEnd = this.lastVoiceEventTick;\n }\n }\n\n this.loop = { start: loopStart, end: loopEnd };\n\n SpessaSynthInfo(\n `%cLoop points: start: %c${this.loop.start}%c end: %c${this.loop.end}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n\n // Determine ports\n let portOffset = 0;\n this.portChannelOffsetMap = [];\n for (const track of this.tracks) {\n track.port = -1;\n if (track.channels.size === 0) {\n continue;\n }\n for (const e of track.events) {\n if (e.statusByte !== midiMessageTypes.midiPort) {\n continue;\n }\n const port = e.data[0];\n track.port = port;\n if (this.portChannelOffsetMap[port] === undefined) {\n this.portChannelOffsetMap[port] = portOffset;\n portOffset += 16;\n }\n }\n }\n\n // Fix empty port channel offsets (do a copy to turn empty slots into undefined so the map goes over them)\n this.portChannelOffsetMap = [...this.portChannelOffsetMap].map(\n (o) => o ?? 0\n );\n\n // Fix midi ports:\n // Midi tracks without ports will have a value of -1\n // If all ports have a value of -1, set it to 0,\n // Otherwise take the first midi port and replace all -1 with it,\n // Why would we do this?\n // Some midis (for some reason) specify all channels to port 1 or else,\n // But leave the conductor track with no port pref.\n // This spessasynth to reserve the first 16 channels for the conductor track\n // (which doesn't play anything) and use the additional 16 for the actual ports.\n let defaultPort = Infinity;\n for (const track of this.tracks) {\n if (track.port !== -1) {\n if (defaultPort > track.port) {\n defaultPort = track.port;\n }\n }\n }\n if (defaultPort === Infinity) {\n defaultPort = 0;\n }\n for (const track of this.tracks) {\n if (track.port === -1 || track.port === undefined) {\n track.port = defaultPort;\n }\n }\n // Add fake port if empty\n if (this.portChannelOffsetMap.length === 0) {\n this.portChannelOffsetMap = [0];\n }\n if (this.portChannelOffsetMap.length < 2) {\n SpessaSynthInfo(\n `%cNo additional MIDI Ports detected.`,\n consoleColors.info\n );\n } else {\n this.isMultiPort = true;\n SpessaSynthInfo(`%cMIDI Ports detected!`, consoleColors.recognized);\n }\n\n // Midi name\n if (!nameDetected) {\n if (this.tracks.length > 1) {\n // If more than 1 track and the first track has no notes,\n // Just find the first trackName in the first track.\n if (\n this.tracks[0].events.find(\n (message) =>\n message.statusByte >= midiMessageTypes.noteOn &&\n message.statusByte < midiMessageTypes.polyPressure\n ) === undefined\n ) {\n const name = this.tracks[0].events.find(\n (message) =>\n message.statusByte === midiMessageTypes.trackName\n );\n if (name) {\n this.binaryName = name.data;\n }\n }\n } else {\n // If only 1 track, find the first \"track name\" event\n const name = this.tracks[0].events.find(\n (message) =>\n message.statusByte === midiMessageTypes.trackName\n );\n if (name) {\n this.binaryName = name.data;\n }\n }\n }\n // Remove empty strings\n this.extraMetadata = this.extraMetadata.filter(\n (c) => c.data.length > 0\n );\n\n // Sort lyrics (https://github.com/spessasus/spessasynth_core/issues/10)\n this.lyrics.sort((a, b) => a.ticks - b.ticks);\n\n // If the first event is not at 0 ticks, add a track name\n // https://github.com/spessasus/SpessaSynth/issues/145\n if (!this.tracks.some((t) => t.events[0].ticks === 0)) {\n const track = this.tracks[0];\n // Can copy\n let b = this?.binaryName?.buffer as ArrayBuffer;\n if (!b) {\n b = new Uint8Array(0).buffer;\n }\n track.events.unshift(\n new MIDIMessage(\n 0,\n midiMessageTypes.trackName,\n new IndexedByteArray(b)\n )\n );\n }\n this.duration = this.midiTicksToSeconds(this.lastVoiceEventTick);\n\n // Invalidate raw name if empty\n if (this.binaryName && this.binaryName.length < 1) {\n this.binaryName = undefined;\n }\n\n SpessaSynthInfo(\"%cSuccess!\", consoleColors.recognized);\n SpessaSynthGroupEnd();\n }\n}\n","import { BasicMIDI } from \"../basic_midi\";\nimport { MIDIMessage } from \"../midi_message\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport { type MIDIMessageType, midiMessageTypes } from \"../enums\";\nimport { MIDITrack } from \"../midi_track\";\nimport type { MIDIFormat } from \"../types\";\nimport { fillWithDefaults } from \"../../utils/fill_with_defaults\";\n\ninterface MIDIBuilderOptions {\n /**\n * The MIDI file's tick precision (how many ticks fit in a quarter note).\n */\n timeDivision: number;\n /**\n * The MIDI file's initial tempo in BPM.\n */\n initialTempo: number;\n\n /**\n * The MIDI file's MIDI track format.\n */\n format: MIDIFormat;\n\n /**\n * The MIDI file's name. Will be appended to the conductor track.\n */\n name: string;\n}\n\nconst DEFAULT_MIDI_BUILDER_OPTIONS: MIDIBuilderOptions = {\n name: \"Untitled song\",\n timeDivision: 480,\n initialTempo: 120,\n format: 0\n};\n\n/**\n * A class that helps to build a MIDI file from scratch.\n */\nexport class MIDIBuilder extends BasicMIDI {\n private encoder = new TextEncoder();\n\n /**\n * Creates a new MIDI file.\n * @param options The options for writing the file.\n */\n public constructor(\n options: Partial<MIDIBuilderOptions> = DEFAULT_MIDI_BUILDER_OPTIONS\n ) {\n super();\n this.setRMIDInfo(\"midiEncoding\", \"utf-8\");\n const fullOptions = fillWithDefaults(\n options,\n DEFAULT_MIDI_BUILDER_OPTIONS\n );\n if (fullOptions.format === 2) {\n throw new Error(\n \"MIDI format 2 is not supported in the MIDI builder. Consider using format 1.\"\n );\n }\n this.timeDivision = fullOptions.format;\n this.binaryName = this.encoder.encode(fullOptions.name);\n\n // Create the first (conductor) track with the file name\n this.addNewTrack(fullOptions.name);\n this.addSetTempo(0, fullOptions.initialTempo);\n }\n\n /**\n * Adds a new Set Tempo event.\n * @param ticks the tick number of the event.\n * @param tempo the tempo in beats per minute (BPM).\n */\n public addSetTempo(ticks: number, tempo: number) {\n const array = new IndexedByteArray(3);\n\n tempo = 60000000 / tempo;\n\n // Extract each byte in big-endian order\n array[0] = (tempo >> 16) & 0xff;\n array[1] = (tempo >> 8) & 0xff;\n array[2] = tempo & 0xff;\n\n this.addEvent(ticks, 0, midiMessageTypes.setTempo, array);\n }\n\n /**\n * Adds a new MIDI track.\n * @param name the new track's name.\n * @param port the new track's port.\n */\n public addNewTrack(name: string, port = 0) {\n if (this.format === 0 && this.tracks.length > 0) {\n throw new Error(\n \"Can't add more tracks to MIDI format 0. Consider using format 1.\"\n );\n }\n const track = new MIDITrack();\n track.name = name;\n track.port = port;\n this.tracks.push(track);\n this.addEvent(\n 0,\n this.tracks.length - 1,\n midiMessageTypes.trackName,\n this.encoder.encode(name)\n );\n this.addEvent(0, this.tracks.length - 1, midiMessageTypes.midiPort, [\n port\n ]);\n }\n\n /**\n * Adds a new MIDI Event.\n * @param ticks the tick time of the event (absolute).\n * @param track the track number to use.\n * @param event the MIDI event number.\n * @param eventData {Uint8Array|Iterable<number>} the raw event data.\n */\n public addEvent(\n ticks: number,\n track: number,\n event: MIDIMessageType,\n eventData: Uint8Array | Iterable<number>\n ) {\n if (!this.tracks[track]) {\n throw new Error(\n `Track ${track} does not exist. Add it via addTrack method.`\n );\n }\n if (event < midiMessageTypes.noteOff) {\n // Meta event\n if (track > 0) {\n throw new Error(\n `Meta events must be added to the first track, not track ${track}.`\n );\n }\n } else {\n // Voice event\n if (this.format === 1 && track === 0) {\n throw new Error(\n \"Can't add voice messages to the conductor track (0) in format 1. Consider using format 0 using a different track.\"\n );\n }\n }\n this.tracks[track].pushEvent(\n new MIDIMessage(ticks, event, new IndexedByteArray(eventData))\n );\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Adds a new Note On event.\n * @param ticks the tick time of the event.\n * @param track the track number to use.\n * @param channel the channel to use.\n * @param midiNote the midi note of the keypress.\n * @param velocity the velocity of the keypress.\n */\n public addNoteOn(\n ticks: number,\n track: number,\n channel: number,\n midiNote: number,\n velocity: number\n ) {\n channel %= 16;\n midiNote %= 128;\n velocity %= 128;\n this.addEvent(\n ticks,\n track,\n (midiMessageTypes.noteOn | channel) as MIDIMessageType,\n [midiNote, velocity]\n );\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Adds a new Note Off event.\n * @param ticks the tick time of the event.\n * @param track the track number to use.\n * @param channel the channel to use.\n * @param midiNote the midi note of the key release.\n * @param velocity optional and unsupported by spessasynth.\n */\n public addNoteOff(\n ticks: number,\n track: number,\n channel: number,\n midiNote: number,\n velocity = 64\n ) {\n channel %= 16;\n midiNote %= 128;\n this.addEvent(\n ticks,\n track,\n (midiMessageTypes.noteOff | channel) as MIDIMessageType,\n [midiNote, velocity]\n );\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Adds a new Program Change event.\n * @param ticks the tick time of the event.\n * @param track the track number to use.\n * @param channel the channel to use.\n * @param programNumber the MIDI program to use.\n */\n public addProgramChange(\n ticks: number,\n track: number,\n channel: number,\n programNumber: number\n ) {\n channel %= 16;\n programNumber %= 128;\n this.addEvent(\n ticks,\n track,\n (midiMessageTypes.programChange | channel) as MIDIMessageType,\n [programNumber]\n );\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Adds a new Controller Change event.\n * @param ticks the tick time of the event.\n * @param track the track number to use.\n * @param channel the channel to use.\n * @param controllerNumber the MIDI CC to use.\n * @param controllerValue the new CC value.\n */\n public addControllerChange(\n ticks: number,\n track: number,\n channel: number,\n controllerNumber: number,\n controllerValue: number\n ) {\n channel %= 16;\n controllerNumber %= 128;\n controllerValue %= 128;\n this.addEvent(\n ticks,\n track,\n (midiMessageTypes.controllerChange | channel) as MIDIMessageType,\n [controllerNumber, controllerValue]\n );\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Adds a new Pitch Wheel event.\n * @param ticks the tick time of the event.\n * @param track the track to use.\n * @param channel the channel to use.\n * @param MSB SECOND byte of the MIDI pitchWheel message.\n * @param LSB FIRST byte of the MIDI pitchWheel message.\n */\n public addPitchWheel(\n ticks: number,\n track: number,\n channel: number,\n MSB: number,\n LSB: number\n ) {\n channel %= 16;\n MSB %= 128;\n LSB %= 128;\n this.addEvent(\n ticks,\n track,\n (midiMessageTypes.pitchWheel | channel) as MIDIMessageType,\n [LSB, MSB]\n );\n }\n}\n","import { getEvent, MIDIMessage } from \"../midi/midi_message\";\nimport { consoleColors } from \"../utils/other\";\nimport { SpessaSynthInfo } from \"../utils/loggin\";\nimport { readBigEndian } from \"../utils/byte_functions/big_endian\";\nimport type { SpessaSynthSequencer } from \"./sequencer\";\nimport { type MIDIController, midiMessageTypes } from \"../midi/enums\";\n\n/**\n * Processes a MIDI event.\n * @param event The MIDI event to process.\n * @param trackIndex The index of the track the event belongs to.\n */\nexport function processEventInternal(\n this: SpessaSynthSequencer,\n event: MIDIMessage,\n trackIndex: number\n) {\n if (this.externalMIDIPlayback) {\n // Do not send meta events\n if (event.statusByte >= 0x80) {\n this.sendMIDIMessage([event.statusByte, ...event.data]);\n return;\n }\n }\n const track = this._midiData!.tracks[trackIndex];\n const statusByteData = getEvent(event.statusByte);\n const offset =\n this.midiPortChannelOffsets[this.currentMIDIPorts[trackIndex]] || 0;\n statusByteData.channel += offset;\n // Process the event\n switch (statusByteData.status) {\n case midiMessageTypes.noteOn: {\n const velocity = event.data[1];\n if (velocity > 0) {\n this.synth.noteOn(\n statusByteData.channel,\n event.data[0],\n velocity\n );\n this.playingNotes.push({\n midiNote: event.data[0],\n channel: statusByteData.channel,\n velocity: velocity\n });\n } else {\n this.synth.noteOff(statusByteData.channel, event.data[0]);\n const toDelete = this.playingNotes.findIndex(\n (n) =>\n n.midiNote === event.data[0] &&\n n.channel === statusByteData.channel\n );\n if (toDelete !== -1) {\n this.playingNotes.splice(toDelete, 1);\n }\n }\n break;\n }\n\n case midiMessageTypes.noteOff: {\n this.synth.noteOff(statusByteData.channel, event.data[0]);\n const toDelete = this.playingNotes.findIndex(\n (n) =>\n n.midiNote === event.data[0] &&\n n.channel === statusByteData.channel\n );\n if (toDelete !== -1) {\n this.playingNotes.splice(toDelete, 1);\n }\n break;\n }\n\n case midiMessageTypes.pitchWheel:\n this.synth.pitchWheel(\n statusByteData.channel,\n (event.data[1] << 7) | event.data[0]\n );\n break;\n\n case midiMessageTypes.controllerChange:\n // Empty tracks cannot cc change\n if (this._midiData!.isMultiPort && track.channels.size === 0) {\n return;\n }\n this.synth.controllerChange(\n statusByteData.channel,\n event.data[0] as MIDIController,\n event.data[1]\n );\n break;\n\n case midiMessageTypes.programChange:\n // Empty tracks cannot program change\n if (this._midiData!.isMultiPort && track.channels.size === 0) {\n return;\n }\n this.synth.programChange(statusByteData.channel, event.data[0]);\n break;\n\n case midiMessageTypes.polyPressure:\n this.synth.polyPressure(\n statusByteData.channel,\n event.data[0],\n event.data[1]\n );\n break;\n\n case midiMessageTypes.channelPressure:\n this.synth.channelPressure(statusByteData.channel, event.data[0]);\n break;\n\n case midiMessageTypes.systemExclusive:\n this.synth.systemExclusive(event.data, offset);\n break;\n\n case midiMessageTypes.setTempo: {\n let tempoBPM = 60000000 / readBigEndian(event.data, 3);\n this.oneTickToSeconds =\n 60 / (tempoBPM * this._midiData!.timeDivision);\n if (this.oneTickToSeconds === 0) {\n this.oneTickToSeconds =\n 60 / (120 * this._midiData!.timeDivision);\n SpessaSynthInfo(\"invalid tempo! falling back to 120 BPM\");\n tempoBPM = 120;\n }\n break;\n }\n\n // Recognized but ignored\n case midiMessageTypes.timeSignature:\n case midiMessageTypes.endOfTrack:\n case midiMessageTypes.midiChannelPrefix:\n case midiMessageTypes.songPosition:\n case midiMessageTypes.activeSensing:\n case midiMessageTypes.keySignature:\n case midiMessageTypes.sequenceNumber:\n case midiMessageTypes.sequenceSpecific:\n case midiMessageTypes.text:\n case midiMessageTypes.lyric:\n case midiMessageTypes.copyright:\n case midiMessageTypes.trackName:\n case midiMessageTypes.marker:\n case midiMessageTypes.cuePoint:\n case midiMessageTypes.instrumentName:\n case midiMessageTypes.programName:\n break;\n\n case midiMessageTypes.midiPort:\n this.assignMIDIPort(trackIndex, event.data[0]);\n break;\n\n case midiMessageTypes.reset:\n this.synth.stopAllChannels();\n this.synth.resetAllControllers();\n break;\n\n default:\n SpessaSynthInfo(\n `%cUnrecognized Event: %c${event.statusByte}%c status byte: %c${Object.keys(\n midiMessageTypes\n ).find(\n (k) =>\n midiMessageTypes[k as keyof typeof midiMessageTypes] ===\n statusByteData.status\n )}`,\n consoleColors.warn,\n consoleColors.unrecognized,\n consoleColors.warn,\n consoleColors.value\n );\n break;\n }\n if (statusByteData.status >= 0 && statusByteData.status < 0x80) {\n this.callEvent(\"metaEvent\", {\n event,\n trackIndex\n });\n }\n}\n","import type { SpessaSynthSequencer } from \"./sequencer\";\n\n/**\n * Processes a single MIDI tick.\n * Call this every rendering quantum to process the sequencer events in real-time.\n */\nexport function processTick(this: SpessaSynthSequencer) {\n if (this.paused || !this._midiData) {\n return;\n }\n const currentTime = this.currentTime;\n while (this.playedTime < currentTime) {\n // Find the next event and process it\n const trackIndex = this.findFirstEventIndex();\n const track = this._midiData.tracks[trackIndex];\n const event = track.events[this.eventIndexes[trackIndex]++];\n this.processEvent(event, trackIndex);\n\n // Find the next event\n const nextTrackIndex = this.findFirstEventIndex();\n const nextTrack = this._midiData.tracks[nextTrackIndex];\n // Check for loop\n if (this.loopCount > 0 && this._midiData.loop.end <= event.ticks) {\n if (this.loopCount !== Infinity) {\n this.loopCount--;\n this.callEvent(\"loopCountChange\", {\n newCount: this.loopCount\n });\n }\n this.setTimeTicks(this._midiData.loop.start);\n return;\n }\n // Check for end of track\n if (nextTrack.events.length <= this.eventIndexes[nextTrackIndex]) {\n // Stop the playback\n this.songIsFinished();\n return;\n }\n\n const eventNext = nextTrack.events[this.eventIndexes[nextTrackIndex]];\n this.playedTime +=\n this.oneTickToSeconds * (eventNext.ticks - event.ticks);\n }\n}\n","import { consoleColors, formatTime } from \"../utils/other\";\nimport { SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo, SpessaSynthWarn } from \"../utils/loggin\";\nimport { BasicMIDI } from \"../midi/basic_midi\";\nimport type { SpessaSynthSequencer } from \"./sequencer\";\n\n/**\n * Assigns a MIDI port channel offset to a track.\n * @param trackNum The track number to assign the port to.\n * @param port The MIDI port number to assign.\n */\nexport function assignMIDIPortInternal(\n this: SpessaSynthSequencer,\n trackNum: number,\n port: number\n) {\n // Do not assign ports to empty tracks\n if (this._midiData!.tracks[trackNum].channels.size === 0) {\n return;\n }\n\n // Assign new 16 channels if the port is not occupied yet\n if (this.midiPortChannelOffset === 0) {\n this.midiPortChannelOffset += 16;\n this.midiPortChannelOffsets[port] = 0;\n }\n\n if (this.midiPortChannelOffsets[port] === undefined) {\n if (this.synth.midiChannels.length < this.midiPortChannelOffset + 15) {\n this.addNewMIDIPort();\n }\n this.midiPortChannelOffsets[port] = this.midiPortChannelOffset;\n this.midiPortChannelOffset += 16;\n }\n\n this.currentMIDIPorts[trackNum] = port;\n}\n\n/**\n * Loads a new sequence internally.\n * @param parsedMidi The parsed MIDI data to load.\n */\nexport function loadNewSequenceInternal(\n this: SpessaSynthSequencer,\n parsedMidi: BasicMIDI\n) {\n if (!parsedMidi.tracks) {\n throw new Error(\"This MIDI has no tracks!\");\n }\n\n this.oneTickToSeconds = 60 / (120 * parsedMidi.timeDivision);\n this._midiData = parsedMidi;\n\n // Clear old embedded bank if exists\n this.synth.clearEmbeddedBank();\n\n // Check for embedded soundfont\n if (this._midiData.embeddedSoundBank !== undefined) {\n SpessaSynthInfo(\n \"%cEmbedded soundbank detected! Using it.\",\n consoleColors.recognized\n );\n this.synth.setEmbeddedSoundBank(\n this._midiData.embeddedSoundBank,\n this._midiData.bankOffset\n );\n }\n\n SpessaSynthGroupCollapsed(\"%cPreloading samples...\", consoleColors.info);\n // Smart preloading: load only samples used in the midi!\n const used = this._midiData.getUsedProgramsAndKeys(\n this.synth.soundBankManager\n );\n used.forEach((combos, preset) => {\n SpessaSynthInfo(\n `%cPreloading used samples on %c${preset.name}%c...`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n for (const combo of combos) {\n const [midiNote, velocity] = combo.split(\"-\").map(Number);\n this.synth.getVoicesForPreset(preset, midiNote, velocity, midiNote);\n }\n });\n SpessaSynthGroupEnd();\n\n // Copy over the port data\n this.currentMIDIPorts = this._midiData.tracks.map((t) => t.port);\n\n // Clear last port data\n this.midiPortChannelOffset = 0;\n this.midiPortChannelOffsets = {};\n // Assign port offsets\n this._midiData.tracks.forEach((track, trackIndex) => {\n this.assignMIDIPort(trackIndex, track.port);\n });\n this.firstNoteTime = this._midiData.midiTicksToSeconds(\n this._midiData.firstNoteOn\n );\n SpessaSynthInfo(\n `%cTotal song time: ${formatTime(Math.ceil(this._midiData.duration)).time}`,\n consoleColors.recognized\n );\n this.callEvent(\"songChange\", { songIndex: this._songIndex });\n\n if (this._midiData.duration <= 0.2) {\n SpessaSynthWarn(\n `%cVery short song: (${formatTime(Math.round(this._midiData.duration)).time}). Disabling loop!`,\n consoleColors.warn\n );\n this.loopCount = 0;\n }\n // Reset the time\n this.currentTime = 0;\n}\n","/**\n * All SoundFont2 Generator enumerations.\n */\nexport const generatorTypes = {\n INVALID: -1, // Invalid generator\n startAddrsOffset: 0, // Sample control - moves sample start point\n endAddrOffset: 1, // Sample control - moves sample end point\n startloopAddrsOffset: 2, // Loop control - moves loop start point\n endloopAddrsOffset: 3, // Loop control - moves loop end point\n startAddrsCoarseOffset: 4, // Sample control - moves sample start point in 32,768 increments\n modLfoToPitch: 5, // Pitch modulation - modulation lfo pitch modulation in cents\n vibLfoToPitch: 6, // Pitch modulation - vibrato lfo pitch modulation in cents\n modEnvToPitch: 7, // Pitch modulation - modulation envelope pitch modulation in cents\n initialFilterFc: 8, // Filter - lowpass filter cutoff in cents\n initialFilterQ: 9, // Filter - lowpass filter resonance\n modLfoToFilterFc: 10, // Filter modulation - modulation lfo lowpass filter cutoff in cents\n modEnvToFilterFc: 11, // Filter modulation - modulation envelope lowpass filter cutoff in cents\n endAddrsCoarseOffset: 12, // Ample control - move sample end point in 32,768 increments\n modLfoToVolume: 13, // Modulation lfo - volume (tremolo), where 100 = 10dB\n unused1: 14, // Unused\n chorusEffectsSend: 15, // Effect send - how much is sent to chorus 0 - 1000\n reverbEffectsSend: 16, // Effect send - how much is sent to reverb 0 - 1000\n pan: 17, // Panning - where -500 = left, 0 = center, 500 = right\n unused2: 18, // Unused\n unused3: 19, // Unused\n unused4: 20, // Unused\n delayModLFO: 21, // Mod lfo - delay for mod lfo to start from zero\n freqModLFO: 22, // Mod lfo - frequency of mod lfo, 0 = 8.176 Hz, units: f => 1200log2(f/8.176)\n delayVibLFO: 23, // Vib lfo - delay for vibrato lfo to start from zero\n freqVibLFO: 24, // Vib lfo - frequency of vibrato lfo, 0 = 8.176Hz, unit: f => 1200log2(f/8.176)\n delayModEnv: 25, // Mod env - 0 = 1 s decay till mod env starts\n attackModEnv: 26, // Mod env - attack of mod env\n holdModEnv: 27, // Mod env - hold of mod env\n decayModEnv: 28, // Mod env - decay of mod env\n sustainModEnv: 29, // Mod env - sustain of mod env\n releaseModEnv: 30, // Mod env - release of mod env\n keyNumToModEnvHold: 31, // Mod env - also modulating mod envelope hold with key number\n keyNumToModEnvDecay: 32, // Mod env - also modulating mod envelope decay with key number\n delayVolEnv: 33, // Vol env - delay of envelope from zero (weird scale)\n attackVolEnv: 34, // Vol env - attack of envelope\n holdVolEnv: 35, // Vol env - hold of envelope\n decayVolEnv: 36, // Vol env - decay of envelope\n sustainVolEnv: 37, // Vol env - sustain of envelope\n releaseVolEnv: 38, // Vol env - release of envelope\n keyNumToVolEnvHold: 39, // Vol env - key number to volume envelope hold\n keyNumToVolEnvDecay: 40, // Vol env - key number to volume envelope decay\n instrument: 41, // Zone - instrument index to use for preset zone\n reserved1: 42, // Reserved\n keyRange: 43, // Zone - key range for which preset / instrument zone is active\n velRange: 44, // Zone - velocity range for which preset / instrument zone is active\n startloopAddrsCoarseOffset: 45, // Sample control - moves sample loop start point in 32,768 increments\n keyNum: 46, // Zone - instrument only: always use this midi number (ignore what's pressed)\n velocity: 47, // Zone - instrument only: always use this velocity (ignore what's pressed)\n initialAttenuation: 48, // Zone - allows turning down the volume, 10 = -1dB\n reserved2: 49, // Reserved\n endloopAddrsCoarseOffset: 50, // Sample control - moves sample loop end point in 32,768 increments\n coarseTune: 51, // Tune - pitch offset in semitones\n fineTune: 52, // Tune - pitch offset in cents\n sampleID: 53, // Sample - instrument zone only: which sample to use\n sampleModes: 54, // Sample - 0 = no loop, 1 = loop, 2 = start on release, 3 = loop and play till the end in release phase\n reserved3: 55, // Reserved\n scaleTuning: 56, // Sample - the degree to which MIDI key number influences pitch, 100 = default\n exclusiveClass: 57, // Sample - = cut = choke group\n overridingRootKey: 58, // Sample - can override the sample's original pitch\n unused5: 59, // Unused\n endOper: 60, // End marker\n\n // Additional generators that are used in system exclusives and will not be saved\n vibLfoToVolume: 61,\n vibLfoToFilterFc: 62\n} as const;\n\nexport type GeneratorType =\n (typeof generatorTypes)[keyof typeof generatorTypes];\n\nexport const GENERATORS_AMOUNT = Object.keys(generatorTypes).length;\nexport const MAX_GENERATOR = Math.max(...Object.values(generatorTypes));\n/**\n * Min: minimum value, max: maximum value, def: default value, nrpn: nrpn scale...\n */\nconst generatorLimits: {\n min: number;\n max: number;\n def: number;\n nrpn: number;\n}[] = [];\n// Offsets\ngeneratorLimits[generatorTypes.startAddrsOffset] = {\n min: 0,\n max: 32768,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.endAddrOffset] = {\n min: -32768,\n max: 32768,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.startloopAddrsOffset] = {\n min: -32768,\n max: 32768,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.endloopAddrsOffset] = {\n min: -32768,\n max: 32768,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.startAddrsCoarseOffset] = {\n min: 0,\n max: 32768,\n def: 0,\n nrpn: 1\n};\n\n// Pitch influence\ngeneratorLimits[generatorTypes.modLfoToPitch] = {\n min: -12000,\n max: 12000,\n def: 0,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.vibLfoToPitch] = {\n min: -12000,\n max: 12000,\n def: 0,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.modEnvToPitch] = {\n min: -12000,\n max: 12000,\n def: 0,\n nrpn: 2\n};\n\n// Lowpass\ngeneratorLimits[generatorTypes.initialFilterFc] = {\n min: 1500,\n max: 13500,\n def: 13500,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.initialFilterQ] = {\n min: 0,\n max: 960,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.modLfoToFilterFc] = {\n min: -12000,\n max: 12000,\n def: 0,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.vibLfoToFilterFc] = {\n min: -12000,\n max: 12000,\n def: 0,\n nrpn: 2\n}; // NON-STANDARD\ngeneratorLimits[generatorTypes.modEnvToFilterFc] = {\n min: -12000,\n max: 12000,\n def: 0,\n nrpn: 2\n};\n\ngeneratorLimits[generatorTypes.endAddrsCoarseOffset] = {\n min: -32768,\n max: 32768,\n def: 0,\n nrpn: 1\n};\n\ngeneratorLimits[generatorTypes.modLfoToVolume] = {\n min: -960,\n max: 960,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.vibLfoToVolume] = {\n min: -960,\n max: 960,\n def: 0,\n nrpn: 1\n}; // NON-STANDARD\n\n// Effects, pan\ngeneratorLimits[generatorTypes.chorusEffectsSend] = {\n min: 0,\n max: 1000,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.reverbEffectsSend] = {\n min: 0,\n max: 1000,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.pan] = { min: -500, max: 500, def: 0, nrpn: 1 };\n\n// Lfo\ngeneratorLimits[generatorTypes.delayModLFO] = {\n min: -12000,\n max: 5000,\n def: -12000,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.freqModLFO] = {\n min: -16000,\n max: 4500,\n def: 0,\n nrpn: 4\n};\ngeneratorLimits[generatorTypes.delayVibLFO] = {\n min: -12000,\n max: 5000,\n def: -12000,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.freqVibLFO] = {\n min: -16000,\n max: 4500,\n def: 0,\n nrpn: 4\n};\n\n// Mod env\ngeneratorLimits[generatorTypes.delayModEnv] = {\n min: -32768,\n max: 5000,\n def: -32768,\n nrpn: 2\n}; // -32,768 indicates instant phase,\n// This is done to prevent click at the start of filter modenv\ngeneratorLimits[generatorTypes.attackModEnv] = {\n min: -32768,\n max: 8000,\n def: -32768,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.holdModEnv] = {\n min: -12000,\n max: 5000,\n def: -12000,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.decayModEnv] = {\n min: -12000,\n max: 8000,\n def: -12000,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.sustainModEnv] = {\n min: 0,\n max: 1000,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.releaseModEnv] = {\n min: -12000,\n max: 8000,\n def: -12000,\n nrpn: 2\n};\n// Key num to mod env\ngeneratorLimits[generatorTypes.keyNumToModEnvHold] = {\n min: -1200,\n max: 1200,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.keyNumToModEnvDecay] = {\n min: -1200,\n max: 1200,\n def: 0,\n nrpn: 1\n};\n\n// Vol env\ngeneratorLimits[generatorTypes.delayVolEnv] = {\n min: -12000,\n max: 5000,\n def: -12000,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.attackVolEnv] = {\n min: -12000,\n max: 8000,\n def: -12000,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.holdVolEnv] = {\n min: -12000,\n max: 5000,\n def: -12000,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.decayVolEnv] = {\n min: -12000,\n max: 8000,\n def: -12000,\n nrpn: 2\n};\ngeneratorLimits[generatorTypes.sustainVolEnv] = {\n min: 0,\n max: 1440,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.releaseVolEnv] = {\n min: -12000,\n max: 8000,\n def: -12000,\n nrpn: 2\n};\n// Key num to vol env\ngeneratorLimits[generatorTypes.keyNumToVolEnvHold] = {\n min: -1200,\n max: 1200,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.keyNumToVolEnvDecay] = {\n min: -1200,\n max: 1200,\n def: 0,\n nrpn: 1\n};\n\ngeneratorLimits[generatorTypes.startloopAddrsCoarseOffset] = {\n min: -32768,\n max: 32768,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.keyNum] = {\n min: -1,\n max: 127,\n def: -1,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.velocity] = {\n min: -1,\n max: 127,\n def: -1,\n nrpn: 1\n};\n\ngeneratorLimits[generatorTypes.initialAttenuation] = {\n min: 0,\n max: 1440,\n def: 0,\n nrpn: 1\n};\n\ngeneratorLimits[generatorTypes.endloopAddrsCoarseOffset] = {\n min: -32768,\n max: 32768,\n def: 0,\n nrpn: 1\n};\n\ngeneratorLimits[generatorTypes.coarseTune] = {\n min: -120,\n max: 120,\n def: 0,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.fineTune] = {\n min: -12700,\n max: 12700,\n def: 0,\n nrpn: 1\n}; // This generator is used as initial pitch, hence this range\ngeneratorLimits[generatorTypes.scaleTuning] = {\n min: 0,\n max: 1200,\n def: 100,\n nrpn: 1\n};\ngeneratorLimits[generatorTypes.exclusiveClass] = {\n min: 0,\n max: 99999,\n def: 0,\n nrpn: 0\n};\ngeneratorLimits[generatorTypes.overridingRootKey] = {\n min: 0 - 1,\n max: 127,\n def: -1,\n nrpn: 0\n};\ngeneratorLimits[generatorTypes.sampleModes] = {\n min: 0,\n max: 3,\n def: 0,\n nrpn: 0\n};\nexport { generatorLimits };\n","export * from \"./basic_soundbank/generator_types\";\nexport const sampleTypes = {\n monoSample: 1,\n rightSample: 2,\n leftSample: 4,\n linkedSample: 8,\n romMonoSample: 32769,\n romRightSample: 32770,\n romLeftSample: 32772,\n romLinkedSample: 32776\n} as const;\n\nexport type SampleType = (typeof sampleTypes)[keyof typeof sampleTypes];\n\nexport const modulatorSources = {\n noController: 0,\n noteOnVelocity: 2,\n noteOnKeyNum: 3,\n polyPressure: 10,\n channelPressure: 13,\n pitchWheel: 14,\n pitchWheelRange: 16,\n link: 127\n} as const;\n\nexport type ModulatorSourceEnum =\n (typeof modulatorSources)[keyof typeof modulatorSources];\n\nexport const modulatorCurveTypes = {\n linear: 0,\n concave: 1,\n convex: 2,\n switch: 3\n} as const;\n\nexport type ModulatorCurveType =\n (typeof modulatorCurveTypes)[keyof typeof modulatorCurveTypes];\n\nexport const modulatorTransformTypes = {\n linear: 0,\n absolute: 2\n} as const;\n\nexport type ModulatorTransformType =\n (typeof modulatorTransformTypes)[keyof typeof modulatorTransformTypes];\n\n// Source curve type maps to a soundfont curve type in section 2.10, table 9\nexport type DLSTransform = ModulatorCurveType;\n\nexport const dlsSources = {\n none: 0x0,\n modLfo: 0x1,\n velocity: 0x2,\n keyNum: 0x3,\n volEnv: 0x4,\n modEnv: 0x5,\n pitchWheel: 0x6,\n polyPressure: 0x7,\n channelPressure: 0x8,\n vibratoLfo: 0x9,\n\n modulationWheel: 0x81,\n volume: 0x87,\n pan: 0x8a,\n expression: 0x8b,\n // Note: these are flipped unintentionally in DLS2 table 9. Argh!\n chorus: 0xdd,\n reverb: 0xdb,\n\n pitchWheelRange: 0x100,\n fineTune: 0x101,\n coarseTune: 0x102\n} as const;\n\nexport type DLSSource = (typeof dlsSources)[keyof typeof dlsSources];\n\nexport const dlsDestinations = {\n none: 0x0, // No destination\n gain: 0x1, // Linear gain\n reserved: 0x2, // Reserved\n pitch: 0x3, // Pitch in cents\n pan: 0x4, // Pan 10ths of a percent\n keyNum: 0x5, // MIDI key number\n // Nuh uh, the channel controllers are not supported!\n chorusSend: 0x80, // Chorus send level 10ths of a percent\n reverbSend: 0x81, // Reverb send level 10ths of a percent\n\n modLfoFreq: 0x104, // Modulation LFO frequency\n modLfoDelay: 0x105, // Modulation LFO delay\n\n vibLfoFreq: 0x114, // Vibrato LFO frequency\n vibLfoDelay: 0x115, // Vibrato LFO delay\n\n volEnvAttack: 0x206, // Volume envelope attack\n volEnvDecay: 0x207, // Volume envelope decay\n reservedEG1: 0x208, // Reserved\n volEnvRelease: 0x209, // Volume envelope release\n volEnvSustain: 0x20a, // Volume envelope sustain\n volEnvDelay: 0x20b, // Volume envelope delay\n volEnvHold: 0x20c, // Volume envelope hold\n\n modEnvAttack: 0x30a, // Modulation envelope attack\n modEnvDecay: 0x30b, // Modulation envelope decay\n reservedEG2: 0x30c, // Reserved\n modEnvRelease: 0x30d, // Modulation envelope release\n modEnvSustain: 0x30e, // Modulation envelope sustain\n modEnvDelay: 0x30f, // Modulation envelope delay\n modEnvHold: 0x310, // Modulation envelope hold\n\n filterCutoff: 0x500, // Low pass filter cutoff frequency\n filterQ: 0x501 // Low pass filter resonance\n} as const;\n\nexport type DLSDestination =\n (typeof dlsDestinations)[keyof typeof dlsDestinations];\n\nexport const DLSLoopTypes = {\n forward: 0x0000,\n loopAndRelease: 0x0001\n} as const;\n\nexport type DLSLoopType = (typeof DLSLoopTypes)[keyof typeof DLSLoopTypes];\n","import { type MIDIController, midiControllers } from \"../../../midi/enums\";\nimport { customControllers } from \"../../enums\";\nimport { modulatorSources } from \"../../../soundbank/enums\";\n\n/*\n * A bit of explanation:\n * The controller table is stored as an int16 array, it stores 14-bit values.\n * This controller table is then extended with the modulatorSources section,\n * for example, pitch range and pitch range depth.\n * This allows us for precise control range and supports full pitch-wheel resolution.\n */\nexport const NON_CC_INDEX_OFFSET = 128;\nexport const CONTROLLER_TABLE_SIZE = 147;\n\n/**\n * An array with the default MIDI controller values. Note that these are 14-bit, not 7-bit.\n */\nexport const defaultMIDIControllerValues = new Int16Array(\n CONTROLLER_TABLE_SIZE\n).fill(0);\nexport const setResetValue = (i: MIDIController, v: number) =>\n (defaultMIDIControllerValues[i] = v << 7);\n\n// Values come from Falcosoft MidiPlayer 6\nsetResetValue(midiControllers.mainVolume, 100);\nsetResetValue(midiControllers.balance, 64);\nsetResetValue(midiControllers.expressionController, 127);\nsetResetValue(midiControllers.pan, 64);\n\nsetResetValue(midiControllers.portamentoOnOff, 127);\n\nsetResetValue(midiControllers.filterResonance, 64);\nsetResetValue(midiControllers.releaseTime, 64);\nsetResetValue(midiControllers.attackTime, 64);\nsetResetValue(midiControllers.brightness, 64);\n\nsetResetValue(midiControllers.decayTime, 64);\nsetResetValue(midiControllers.vibratoRate, 64);\nsetResetValue(midiControllers.vibratoDepth, 64);\nsetResetValue(midiControllers.vibratoDelay, 64);\nsetResetValue(midiControllers.generalPurposeController6, 64);\nsetResetValue(midiControllers.generalPurposeController8, 64);\n\nsetResetValue(midiControllers.registeredParameterLSB, 127);\nsetResetValue(midiControllers.registeredParameterMSB, 127);\nsetResetValue(midiControllers.nonRegisteredParameterLSB, 127);\nsetResetValue(midiControllers.nonRegisteredParameterMSB, 127);\n\nexport const PORTAMENTO_CONTROL_UNSET = 1;\n// Special case: portamento control\n// Since it is only 7-bit, only the values at multiple of 128 are allowed.\n// A value of just 1 indicates no key set, hence no portamento.\n// This is the \"initial unset portamento key\" flag.\ndefaultMIDIControllerValues[midiControllers.portamentoControl] =\n PORTAMENTO_CONTROL_UNSET;\n\n// Pitch wheel\nsetResetValue(\n (NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel) as MIDIController,\n 64\n);\nsetResetValue(\n (NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange) as MIDIController,\n 2\n);\n\nexport const CUSTOM_CONTROLLER_TABLE_SIZE =\n Object.keys(customControllers).length;\nexport const customResetArray = new Float32Array(CUSTOM_CONTROLLER_TABLE_SIZE);\ncustomResetArray[customControllers.modulationMultiplier] = 1;\n","import { consoleColors } from \"../../../../utils/other\";\nimport { SpessaSynthInfo } from \"../../../../utils/loggin\";\nimport {\n customResetArray,\n defaultMIDIControllerValues,\n NON_CC_INDEX_OFFSET,\n PORTAMENTO_CONTROL_UNSET\n} from \"../../engine_components/controller_tables\";\nimport { DEFAULT_PERCUSSION, DEFAULT_SYNTH_MODE } from \"../../engine_components/synth_constants\";\nimport { BankSelectHacks } from \"../../../../utils/midi_hacks\";\nimport { type MIDIController, midiControllers } from \"../../../../midi/enums\";\nimport type { MIDIChannel } from \"../../engine_components/midi_channel\";\nimport type { SpessaSynthProcessor } from \"../../../processor\";\nimport { customControllers, dataEntryStates } from \"../../../enums\";\nimport { modulatorSources } from \"../../../../soundbank/enums\";\n\n/**\n * Executes a full system reset of all controllers.\n * This will reset all controllers to their default values,\n * except for the locked controllers.\n */\nexport function resetAllControllersInternal(\n this: SpessaSynthProcessor,\n log = true\n) {\n if (log) {\n SpessaSynthInfo(\"%cResetting all controllers!\", consoleColors.info);\n }\n this.privateProps.callEvent(\"allControllerReset\", undefined);\n this.setMasterParameter(\"midiSystem\", DEFAULT_SYNTH_MODE);\n if (!this.privateProps.drumPreset || !this.privateProps.defaultPreset) {\n return;\n }\n for (\n let channelNumber = 0;\n channelNumber < this.midiChannels.length;\n channelNumber++\n ) {\n const ch: MIDIChannel = this.midiChannels[channelNumber];\n\n // Do not send CC changes as we call allControllerReset\n ch.resetControllers(false);\n ch.resetPreset();\n\n for (let ccNum = 0; ccNum < 128; ccNum++) {\n if (this.midiChannels[channelNumber].lockedControllers[ccNum]) {\n // Was not reset so restore the value\n this.privateProps.callEvent(\"controllerChange\", {\n channel: channelNumber,\n controllerNumber: ccNum,\n controllerValue:\n this.midiChannels[channelNumber].midiControllers[\n ccNum\n ] >> 7\n });\n }\n }\n\n // Restore pitch wheel\n if (\n !this.midiChannels[channelNumber].lockedControllers[\n NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel\n ]\n ) {\n const val =\n this.midiChannels[channelNumber].midiControllers[\n NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel\n ];\n this.privateProps.callEvent(\"pitchWheel\", {\n channel: channelNumber,\n pitch: val\n });\n }\n\n // Restore channel pressure\n if (\n !this.midiChannels[channelNumber].lockedControllers[\n NON_CC_INDEX_OFFSET + modulatorSources.channelPressure\n ]\n ) {\n const val =\n this.midiChannels[channelNumber].midiControllers[\n NON_CC_INDEX_OFFSET + modulatorSources.channelPressure\n ] >> 7;\n this.privateProps.callEvent(\"channelPressure\", {\n channel: channelNumber,\n pressure: val\n });\n }\n }\n this.privateProps.tunings.length = 0;\n this.privateProps.tunings.length = 0;\n for (let i = 0; i < 128; i++) {\n this.privateProps.tunings.push([]);\n }\n\n this.setMIDIVolume(1);\n}\n\n/**\n * Reset all controllers for channel.\n * This will reset all controllers to their default values,\n * except for the locked controllers.\n */\nexport function resetControllers(this: MIDIChannel, sendCCEvents = true) {\n this.channelOctaveTuning.fill(0);\n\n // Reset the array\n for (let i = 0; i < defaultMIDIControllerValues.length; i++) {\n if (this.lockedControllers[i]) {\n continue;\n }\n const resetValue = defaultMIDIControllerValues[i];\n if (this.midiControllers[i] !== resetValue && i < 127) {\n if (i === midiControllers.portamentoControl) {\n this.midiControllers[i] = PORTAMENTO_CONTROL_UNSET;\n } else if (\n i !== midiControllers.portamentoControl &&\n i !== midiControllers.dataEntryMSB &&\n i !== midiControllers.registeredParameterMSB &&\n i !== midiControllers.registeredParameterLSB &&\n i !== midiControllers.nonRegisteredParameterMSB &&\n i !== midiControllers.nonRegisteredParameterLSB\n ) {\n this.controllerChange(\n i as MIDIController,\n resetValue >> 7,\n sendCCEvents\n );\n }\n } else {\n // Out of range, do a regular reset\n this.midiControllers[i] = resetValue;\n }\n }\n this.channelVibrato = { rate: 0, depth: 0, delay: 0 };\n this.randomPan = false;\n\n this.sysExModulators.resetModulators();\n\n // Reset custom controllers\n // Special case: transpose does not get affected\n const transpose =\n this.customControllers[customControllers.channelTransposeFine];\n this.customControllers.set(customResetArray);\n this.setCustomController(customControllers.channelTransposeFine, transpose);\n this.resetParameters();\n}\n\nexport function resetPreset(this: MIDIChannel) {\n this.setBankMSB(BankSelectHacks.getDefaultBank(this.channelSystem));\n this.setBankLSB(0);\n this.setGSDrums(false);\n\n this.setDrums(this.channelNumber % 16 === DEFAULT_PERCUSSION);\n this.programChange(0);\n}\n\nexport const nonResettableCCs = new Set<MIDIController>([\n midiControllers.bankSelect,\n midiControllers.bankSelectLSB,\n midiControllers.mainVolume,\n midiControllers.mainVolumeLSB,\n midiControllers.pan,\n midiControllers.panLSB,\n midiControllers.reverbDepth,\n midiControllers.tremoloDepth,\n midiControllers.chorusDepth,\n midiControllers.detuneDepth,\n midiControllers.phaserDepth,\n midiControllers.soundVariation,\n midiControllers.filterResonance,\n midiControllers.releaseTime,\n midiControllers.attackTime,\n midiControllers.brightness,\n midiControllers.decayTime,\n midiControllers.vibratoRate,\n midiControllers.vibratoDepth,\n midiControllers.vibratoDelay,\n midiControllers.soundController10\n] as const);\n\n/**\n * https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf\n * Reset controllers according to RP-15 Recommended Practice.\n */\nexport function resetControllersRP15Compliant(this: MIDIChannel) {\n // Reset tunings\n this.channelOctaveTuning.fill(0);\n\n // Reset pitch bend\n this.pitchWheel(8192);\n\n this.channelVibrato = { rate: 0, depth: 0, delay: 0 };\n\n for (let i = 0; i < 128; i++) {\n const resetValue = defaultMIDIControllerValues[i];\n if (\n !nonResettableCCs.has(i as MIDIController) &&\n resetValue !== this.midiControllers[i]\n ) {\n if (i === midiControllers.portamentoControl) {\n this.midiControllers[i] = PORTAMENTO_CONTROL_UNSET;\n } else {\n this.controllerChange(i as MIDIController, resetValue >> 7);\n }\n }\n }\n this.resetGeneratorOverrides();\n this.resetGeneratorOffsets();\n}\n\n/**\n * Reset all parameters to their default values.\n * This includes NRPN and RPN controllers, data entry state,\n * and generator overrides and offsets.\n */\nexport function resetParameters(this: MIDIChannel) {\n /**\n * Reset the state machine to idle\n */\n this.dataEntryState = dataEntryStates.Idle;\n this.midiControllers[midiControllers.nonRegisteredParameterLSB] = 127 << 7;\n this.midiControllers[midiControllers.nonRegisteredParameterMSB] = 127 << 7;\n this.midiControllers[midiControllers.registeredParameterLSB] = 127 << 7;\n this.midiControllers[midiControllers.registeredParameterMSB] = 127 << 7;\n this.resetGeneratorOverrides();\n this.resetGeneratorOffsets();\n}\n","import { getEvent } from \"../midi/midi_message\";\nimport { defaultMIDIControllerValues } from \"../synthesizer/audio_engine/engine_components/controller_tables\";\nimport { nonResettableCCs } from \"../synthesizer/audio_engine/engine_methods/controller_control/reset_controllers\";\nimport {\n type MIDIController,\n midiControllers,\n midiMessageTypes\n} from \"../midi/enums\";\nimport type { SpessaSynthSequencer } from \"./sequencer\";\nimport type { MIDITrack } from \"../midi/midi_track\";\n\n// An array with preset default values\nconst defaultControllerArray = defaultMIDIControllerValues.slice(0, 128);\n\n/**\n * Plays the MIDI file to a specific time or ticks.\n * @param time in seconds.\n * @param ticks optional MIDI ticks, when given is used instead of time.\n * @returns true if the MIDI file is not finished.\n */\nexport function setTimeToInternal(\n this: SpessaSynthSequencer,\n time: number,\n ticks: number | undefined = undefined\n): boolean {\n if (!this._midiData) {\n return false;\n }\n this.oneTickToSeconds = 60 / (120 * this._midiData.timeDivision);\n // Reset everything\n if (this.externalMIDIPlayback) {\n this.sendMIDIReset();\n } else {\n this.synth.resetAllControllers();\n this.synth.stopAllChannels(false);\n }\n this.playedTime = 0;\n this.eventIndexes = Array<number>(this._midiData.tracks.length).fill(0);\n\n // We save the pitch bends, programs and controllers here\n // To only send them once after going through the events\n\n const channelsToSave = this.synth.midiChannels.length;\n /**\n * Save pitch bends here and send them only after\n */\n const pitchWheels = Array<number>(channelsToSave).fill(8192);\n\n /**\n * Save programs here and send them only after\n */\n const programs: { program: number; bank: number; actualBank: number }[] =\n [];\n for (let i = 0; i < channelsToSave; i++) {\n programs.push({\n program: -1,\n bank: 0,\n actualBank: 0\n });\n }\n\n const isCCNonSkippable = (cc: MIDIController) =>\n cc === midiControllers.dataDecrement ||\n cc === midiControllers.dataIncrement ||\n cc === midiControllers.dataEntryMSB ||\n cc === midiControllers.dataEntryLSB ||\n cc === midiControllers.registeredParameterLSB ||\n cc === midiControllers.registeredParameterMSB ||\n cc === midiControllers.nonRegisteredParameterLSB ||\n cc === midiControllers.nonRegisteredParameterMSB ||\n cc === midiControllers.bankSelect ||\n cc === midiControllers.bankSelectLSB ||\n cc === midiControllers.resetAllControllers;\n\n /**\n * Save controllers here and send them only after\n */\n const savedControllers: number[][] = [];\n for (let i = 0; i < channelsToSave; i++) {\n savedControllers.push(\n Array.from(defaultControllerArray) as MIDIController[]\n );\n }\n\n /**\n * RP-15 compliant reset\n * https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf\n */\n function resetAllControllers(chan: number) {\n // Reset pitch bend\n pitchWheels[chan] = 8192;\n if (savedControllers?.[chan] === undefined) {\n return;\n }\n for (let i = 0; i < defaultControllerArray.length; i++) {\n if (!nonResettableCCs.has(i as MIDIController)) {\n savedControllers[chan][i] = defaultControllerArray[\n i\n ] as MIDIController;\n }\n }\n }\n\n while (true) {\n // Find the next event\n let trackIndex = this.findFirstEventIndex();\n // Type assertion is required here because tsc is drunk...\n const track: MIDITrack = this._midiData.tracks[trackIndex];\n const event = track.events[this.eventIndexes[trackIndex]];\n if (ticks !== undefined) {\n if (event.ticks >= ticks) {\n break;\n }\n } else {\n if (this.playedTime >= time) {\n break;\n }\n }\n\n // Skip note ons\n const info = getEvent(event.statusByte);\n // Keep in mind midi ports to determine the channel!\n const channel =\n info.channel + (this.midiPortChannelOffsets[track.port] || 0);\n switch (info.status) {\n // Skip note messages\n case midiMessageTypes.noteOn:\n // Track portamento control as last note\n savedControllers[channel] ??= Array.from(\n defaultControllerArray\n ) as MIDIController[];\n savedControllers[channel][midiControllers.portamentoControl] =\n event.data[0] as MIDIController;\n break;\n\n case midiMessageTypes.noteOff:\n break;\n\n // Skip pitch bend\n case midiMessageTypes.pitchWheel:\n pitchWheels[channel] = (event.data[1] << 7) | event.data[0];\n break;\n\n case midiMessageTypes.programChange: {\n // Empty tracks cannot program change\n if (this._midiData.isMultiPort && track.channels.size === 0) {\n break;\n }\n const p = programs[channel];\n p.program = event.data[0];\n p.actualBank = p.bank;\n break;\n }\n\n case midiMessageTypes.controllerChange: {\n // Empty tracks cannot controller change\n if (this._midiData.isMultiPort && track.channels.size === 0) {\n break;\n }\n // Do not skip data entries\n const controllerNumber = event.data[0] as MIDIController;\n if (isCCNonSkippable(controllerNumber)) {\n const ccV = event.data[1];\n if (controllerNumber === midiControllers.bankSelect) {\n // Add the bank to be saved\n programs[channel].bank = ccV;\n break;\n } else if (\n controllerNumber === midiControllers.resetAllControllers\n ) {\n resetAllControllers(channel);\n }\n if (this.externalMIDIPlayback) {\n this.sendMIDICC(channel, controllerNumber, ccV);\n } else {\n this.synth.controllerChange(\n channel,\n controllerNumber,\n ccV\n );\n }\n } else {\n savedControllers[channel] ??= Array.from(\n defaultControllerArray\n ) as MIDIController[];\n savedControllers[channel][controllerNumber] = event\n .data[1] as MIDIController;\n }\n break;\n }\n\n default:\n this.processEvent(event, trackIndex);\n break;\n }\n\n this.eventIndexes[trackIndex]++;\n // Find the next event\n trackIndex = this.findFirstEventIndex();\n\n const nextEvent =\n this._midiData.tracks[trackIndex].events[\n this.eventIndexes[trackIndex]\n ];\n if (nextEvent === undefined) {\n this.stop();\n return false;\n }\n this.playedTime +=\n this.oneTickToSeconds * (nextEvent.ticks - event.ticks);\n }\n\n // Restoring saved controllers\n if (this.externalMIDIPlayback) {\n for (\n let channelNumber = 0;\n channelNumber < channelsToSave;\n channelNumber++\n ) {\n // Restore pitch bends\n if (pitchWheels[channelNumber] !== undefined) {\n this.sendMIDIPitchWheel(\n channelNumber,\n pitchWheels[channelNumber] >> 7,\n pitchWheels[channelNumber] & 0x7f\n );\n }\n if (savedControllers[channelNumber] !== undefined) {\n // Every controller that has changed\n savedControllers[channelNumber].forEach((value, index) => {\n if (\n value !== defaultControllerArray[index] &&\n !isCCNonSkippable(index as MIDIController)\n ) {\n this.sendMIDICC(channelNumber, index, value);\n }\n });\n }\n // Restore programs\n if (\n programs[channelNumber].program >= 0 &&\n programs[channelNumber].actualBank >= 0\n ) {\n const bank = programs[channelNumber].actualBank;\n this.sendMIDICC(\n channelNumber,\n midiControllers.bankSelect,\n bank\n );\n this.sendMIDIProgramChange(\n channelNumber,\n programs[channelNumber].program\n );\n }\n }\n } else {\n // For all synth channels\n for (\n let channelNumber = 0;\n channelNumber < channelsToSave;\n channelNumber++\n ) {\n // Restore pitch bends\n if (pitchWheels[channelNumber] !== undefined) {\n this.synth.pitchWheel(\n channelNumber,\n pitchWheels[channelNumber]\n );\n }\n if (savedControllers[channelNumber] !== undefined) {\n // Every controller that has changed\n savedControllers[channelNumber].forEach((value, index) => {\n if (\n value !== defaultControllerArray[index] &&\n !isCCNonSkippable(index as MIDIController)\n ) {\n this.synth.controllerChange(\n channelNumber,\n index as MIDIController,\n value\n );\n }\n });\n }\n // Restore programs\n if (programs[channelNumber].actualBank >= 0) {\n const p = programs[channelNumber];\n if (p.program !== -1) {\n // A program change has occurred, apply the actual bank when program change was executed\n this.synth.controllerChange(\n channelNumber,\n midiControllers.bankSelect,\n p.actualBank\n );\n this.synth.programChange(channelNumber, p.program);\n } else {\n // No program change, apply the current bank select\n this.synth.controllerChange(\n channelNumber,\n midiControllers.bankSelect,\n p.bank\n );\n }\n }\n }\n }\n\n // Restoring paused time\n\n if (this.paused) {\n this.pausedTime = this.playedTime;\n }\n return true;\n}\n","import { processEventInternal } from \"./process_event\";\nimport { processTick } from \"./process_tick\";\nimport { assignMIDIPortInternal, loadNewSequenceInternal } from \"./song_control\";\nimport { setTimeToInternal } from \"./play\";\nimport { SpessaSynthWarn } from \"../utils/loggin\";\n\nimport { MIDI_CHANNEL_COUNT } from \"../synthesizer/audio_engine/engine_components/synth_constants\";\nimport { BasicMIDI } from \"../midi/basic_midi\";\nimport type { SpessaSynthProcessor } from \"../synthesizer/processor\";\nimport { midiControllers, midiMessageTypes } from \"../midi/enums\";\nimport type { SequencerEvent, SequencerEventData } from \"./types\";\n\nexport class SpessaSynthSequencer {\n /**\n * Sequencer's song list.\n */\n public songs: BasicMIDI[] = [];\n /**\n * The shuffled song indexes.\n * This is used when shuffleMode is enabled.\n */\n public shuffledSongIndexes: number[] = [];\n /**\n * The synthesizer connected to the sequencer.\n */\n public readonly synth: SpessaSynthProcessor;\n /**\n * If the MIDI messages should be sent to an event instead of the synth.\n * This is used by spessasynth_lib to pass them over to Web MIDI API.\n */\n public externalMIDIPlayback = false;\n /**\n * The loop count of the sequencer.\n * If infinite, it will loop forever.\n * If zero, the loop is disabled.\n */\n public loopCount = 0;\n /**\n * Indicates if the sequencer should skip to the first note on event.\n * Defaults to true.\n */\n public skipToFirstNoteOn = true;\n\n /**\n * Called when the sequencer calls an event.\n * @param event The event\n */\n public onEventCall?: (event: SequencerEvent) => unknown;\n /**\n * Processes a single MIDI tick.\n * You should call this every rendering quantum to process the sequencer events in real-time.\n */\n public processTick: typeof processTick = processTick.bind(\n this\n ) as typeof processTick;\n /**\n * The time of the first note in seconds.\n */\n protected firstNoteTime = 0;\n /**\n * How long a single MIDI tick currently lasts in seconds.\n */\n protected oneTickToSeconds = 0;\n /**\n * The current event index for each track.\n * This is used to track which event is currently being processed for each track.\n */\n protected eventIndexes: number[] = [];\n /**\n * The time that has already been played in the current song.\n */\n protected playedTime = 0;\n /**\n * The paused time of the sequencer.\n * If the sequencer is not paused, this is undefined.\n */\n protected pausedTime?: number = -1;\n /**\n * Absolute time of the sequencer when it started playing.\n * It is based on the synth's current time.\n */\n protected absoluteStartTime = 0;\n /**\n * Currently playing notes (for pausing and resuming)\n */\n protected playingNotes: {\n midiNote: number;\n channel: number;\n velocity: number;\n }[] = [];\n /**\n * MIDI Port number for each of the MIDI tracks in the current sequence.\n */\n protected currentMIDIPorts: number[] = [];\n /**\n * This is used to assign new MIDI port offsets to new ports.\n */\n protected midiPortChannelOffset = 0;\n /**\n * Channel offsets for each MIDI port.\n * Stored as:\n * Record<midi port, channel offset>\n */\n protected midiPortChannelOffsets: Record<number, number> = {};\n protected assignMIDIPort = assignMIDIPortInternal.bind(this);\n protected loadNewSequence = loadNewSequenceInternal.bind(this);\n protected processEvent = processEventInternal.bind(this);\n protected setTimeTo: typeof setTimeToInternal =\n setTimeToInternal.bind(this);\n\n /**\n * Initializes a new Sequencer without any songs loaded.\n * @param spessasynthProcessor the synthesizer processor to use with this sequencer.\n */\n public constructor(spessasynthProcessor: SpessaSynthProcessor) {\n this.synth = spessasynthProcessor;\n this.absoluteStartTime = this.synth.currentSynthTime;\n }\n\n protected _midiData?: BasicMIDI;\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * The currently loaded MIDI data.\n */\n public get midiData() {\n return this._midiData;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * The length of the current sequence in seconds.\n */\n public get duration() {\n return this._midiData?.duration ?? 0;\n }\n\n protected _songIndex = 0;\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * The current song index in the song list.\n * If shuffleMode is enabled, this is the index of the shuffled song list.\n */\n public get songIndex(): number {\n return this._songIndex;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * The current song index in the song list.\n * If shuffleMode is enabled, this is the index of the shuffled song list.\n */\n public set songIndex(value: number) {\n this._songIndex = value;\n this._songIndex = Math.max(0, value % this.songs.length);\n this.loadCurrentSong();\n }\n\n protected _shuffleMode = false;\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Controls if the sequencer should shuffle the songs in the song list.\n * If true, the sequencer will play the songs in a random order.\n */\n public get shuffleMode(): boolean {\n return this._shuffleMode;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Controls if the sequencer should shuffle the songs in the song list.\n * If true, the sequencer will play the songs in a random order.\n */\n public set shuffleMode(on: boolean) {\n this._shuffleMode = on;\n if (on) {\n this.shuffleSongIndexes();\n this._songIndex = 0;\n this.loadCurrentSong();\n } else {\n this._songIndex = this.shuffledSongIndexes[this._songIndex];\n }\n }\n\n /**\n * Internal playback rate.\n */\n protected _playbackRate = 1;\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * The sequencer's playback rate.\n * This is the rate at which the sequencer plays back the MIDI data.\n */\n public get playbackRate() {\n return this._playbackRate;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * The sequencer's playback rate.\n * This is the rate at which the sequencer plays back the MIDI data.\n * @param value the playback rate to set.\n */\n public set playbackRate(value: number) {\n const time = this.currentTime;\n this._playbackRate = value;\n this.currentTime = time;\n }\n\n /**\n * The current time of the sequencer.\n * This is the time in seconds since the sequencer started playing.\n */\n public get currentTime() {\n // Return the paused time if it's set to something other than undefined\n if (this.pausedTime !== undefined) {\n return this.pausedTime;\n }\n\n return (\n (this.synth.currentSynthTime - this.absoluteStartTime) *\n this._playbackRate\n );\n }\n\n /**\n * The current time of the sequencer.\n * This is the time in seconds since the sequencer started playing.\n * @param time the time to set in seconds.\n */\n public set currentTime(time) {\n if (!this._midiData) {\n return;\n }\n if (this.paused) {\n this.pausedTime = time;\n }\n if (time > this._midiData.duration || time < 0) {\n // Time is 0\n if (this.skipToFirstNoteOn) {\n this.setTimeTicks(this._midiData.firstNoteOn - 1);\n } else {\n this.setTimeTicks(0);\n }\n } else if (this.skipToFirstNoteOn && time < this.firstNoteTime) {\n this.setTimeTicks(this._midiData.firstNoteOn - 1);\n return;\n } else {\n this.playingNotes = [];\n this.callEvent(\"timeChange\", { newTime: time });\n if (this._midiData.duration === 0) {\n SpessaSynthWarn(\"No duration!\");\n this.callEvent(\"pause\", { isFinished: true });\n return;\n }\n this.setTimeTo(time);\n this.recalculateStartTime(time);\n }\n }\n\n /**\n * True if paused, false if playing or stopped\n */\n public get paused() {\n return this.pausedTime !== undefined;\n }\n\n /**\n * Starts or resumes the playback of the sequencer.\n * If the sequencer is paused, it will resume from the paused time.\n */\n public play() {\n if (!this._midiData) {\n throw new Error(\"No songs loaded in the sequencer!\");\n }\n\n // Reset the time\n if (this.currentTime >= this._midiData.duration) {\n this.currentTime = 0;\n }\n\n // Unpause if paused\n if (this.paused) {\n // Adjust the start time\n this.recalculateStartTime(this.pausedTime ?? 0);\n }\n if (!this.externalMIDIPlayback) {\n this.playingNotes.forEach((n) => {\n this.synth.noteOn(n.channel, n.midiNote, n.velocity);\n });\n }\n this.pausedTime = undefined;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Pauses the playback.\n */\n public pause() {\n this.pauseInternal(false);\n }\n\n /**\n * Loads a new song list into the sequencer.\n * @param midiBuffers the list of songs to load.\n */\n public loadNewSongList(midiBuffers: BasicMIDI[]) {\n /**\n * Parse the MIDIs (only the array buffers, MIDI is unchanged)\n */\n this.songs = midiBuffers;\n if (this.songs.length < 1) {\n return;\n }\n this._songIndex = 0;\n this.shuffleSongIndexes();\n this.callEvent(\"songListChange\", { newSongList: [...this.songs] });\n this.loadCurrentSong();\n }\n\n protected callEvent<K extends keyof SequencerEventData>(\n type: K,\n data: SequencerEventData[K]\n ) {\n this?.onEventCall?.({\n type,\n data\n } as SequencerEvent);\n }\n\n protected pauseInternal(isFinished: boolean) {\n if (this.paused) {\n return;\n }\n this.stop();\n this.callEvent(\"pause\", { isFinished });\n }\n\n protected songIsFinished() {\n if (this.songs.length === 1) {\n this.pauseInternal(true);\n return;\n }\n this._songIndex++;\n this._songIndex %= this.songs.length;\n this.loadCurrentSong();\n }\n\n /**\n * Stops the playback\n */\n protected stop() {\n this.pausedTime = this.currentTime;\n // Disable sustain\n for (let i = 0; i < 16; i++) {\n this.synth.controllerChange(i, midiControllers.sustainPedal, 0);\n }\n this.synth.stopAllChannels();\n if (this.externalMIDIPlayback) {\n for (const note of this.playingNotes) {\n this.sendMIDIMessage([\n midiMessageTypes.noteOff | note.channel % 16,\n note.midiNote\n ]);\n }\n for (let c = 0; c < MIDI_CHANNEL_COUNT; c++) {\n this.sendMIDICC(c, midiControllers.allNotesOff, 0);\n }\n }\n }\n\n /**\n * @returns the index of the first to the current played time\n */\n protected findFirstEventIndex() {\n let index = 0;\n let ticks = Infinity;\n this._midiData!.tracks.forEach((track, i) => {\n if (this.eventIndexes[i] >= track.events.length) {\n return;\n }\n const event = track.events[this.eventIndexes[i]];\n if (event.ticks < ticks) {\n index = i;\n ticks = event.ticks;\n }\n });\n return index;\n }\n\n /**\n * Adds a new port (16 channels) to the synth.\n */\n protected addNewMIDIPort() {\n for (let i = 0; i < 16; i++) {\n this.synth.createMIDIChannel();\n }\n }\n\n protected sendMIDIMessage(message: number[]) {\n if (!this.externalMIDIPlayback) {\n return;\n }\n this.callEvent(\"midiMessage\", { message });\n }\n\n protected sendMIDIReset() {\n this.sendMIDIMessage([midiMessageTypes.reset]);\n for (let ch = 0; ch < MIDI_CHANNEL_COUNT; ch++) {\n this.sendMIDIMessage([\n midiMessageTypes.controllerChange | ch,\n midiControllers.allSoundOff,\n 0\n ]);\n this.sendMIDIMessage([\n midiMessageTypes.controllerChange | ch,\n midiControllers.resetAllControllers,\n 0\n ]);\n }\n }\n\n protected loadCurrentSong() {\n let index = this._songIndex;\n if (this._shuffleMode) {\n index = this.shuffledSongIndexes[this._songIndex];\n }\n this.loadNewSequence(this.songs[index]);\n }\n\n protected shuffleSongIndexes() {\n const indexes = this.songs.map((_, i) => i);\n this.shuffledSongIndexes = [];\n while (indexes.length > 0) {\n const index = indexes[Math.floor(Math.random() * indexes.length)];\n this.shuffledSongIndexes.push(index);\n indexes.splice(indexes.indexOf(index), 1);\n }\n }\n\n protected sendMIDICC(channel: number, type: number, value: number) {\n channel %= 16;\n if (!this.externalMIDIPlayback) {\n return;\n }\n this.sendMIDIMessage([\n midiMessageTypes.controllerChange | channel,\n type,\n value\n ]);\n }\n\n protected sendMIDIProgramChange(channel: number, program: number) {\n channel %= 16;\n if (!this.externalMIDIPlayback) {\n return;\n }\n this.sendMIDIMessage([\n midiMessageTypes.programChange | channel,\n program\n ]);\n }\n\n /**\n * Sets the pitch of the given channel\n * @param channel usually 0-15: the channel to change pitch\n * @param MSB SECOND byte of the MIDI pitchWheel message\n * @param LSB FIRST byte of the MIDI pitchWheel message\n */\n protected sendMIDIPitchWheel(channel: number, MSB: number, LSB: number) {\n channel %= 16;\n if (!this.externalMIDIPlayback) {\n return;\n }\n this.sendMIDIMessage([midiMessageTypes.pitchWheel | channel, LSB, MSB]);\n }\n\n /**\n * Sets the time in MIDI ticks.\n * @param ticks the MIDI ticks to set the time to.\n */\n protected setTimeTicks(ticks: number) {\n if (!this._midiData) {\n return;\n }\n this.playingNotes = [];\n const seconds = this._midiData.midiTicksToSeconds(ticks);\n this.callEvent(\"timeChange\", { newTime: seconds });\n const isNotFinished = this.setTimeTo(0, ticks);\n this.recalculateStartTime(this.playedTime);\n if (!isNotFinished) {\n return;\n }\n }\n\n /**\n * Recalculates the absolute start time of the sequencer.\n * @param time the time in seconds to recalculate the start time for.\n */\n protected recalculateStartTime(time: number) {\n this.absoluteStartTime =\n this.synth.currentSynthTime - time / this._playbackRate;\n }\n}\n","export var stbvorbis=void 0!==stbvorbis?stbvorbis:{};let isReady=!1,readySolver;stbvorbis.isInitialized=new Promise(A=>readySolver=A);var atob=function(A){var I,g,B,E,Q,C,i,h=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\",o=\"\",G=0;A=A.replace(/[^A-Za-z0-9\\+\\/\\=]/g,\"\");do E=h.indexOf(A.charAt(G++)),Q=h.indexOf(A.charAt(G++)),C=h.indexOf(A.charAt(G++)),i=h.indexOf(A.charAt(G++)),I=E<<2|Q>>4,g=(15&Q)<<4|C>>2,B=(3&C)<<6|i,o+=String.fromCharCode(I),64!==C&&(o+=String.fromCharCode(g)),64!==i&&(o+=String.fromCharCode(B));while(G<A.length);return o};!function(){var A,I,g,B,E,Q,C,i,h,o,G,D,a,S,F,R,s,w,y,c,n,U,$=void 0!==$?$:{};$.wasmBinary=Uint8Array.from(atob(\"AGFzbQEAAAABpQEYYAJ/fwF/YAF/AGAAAX9gBH9/f38AYAAAYAN/f38Bf2ABfwF/YAJ/fwBgBn9/f39/fwF/YAR/f39/AX9gBX9/f39/AX9gB39/f39/f38Bf2AGf39/f39/AGAIf39/f39/f38Bf2AFf39/f38AYAd/f39/f39/AGADf39/AGABfwF9YAF9AX1gAnx/AXxgAnx/AX9gA3x8fwF8YAJ8fAF8YAF8AXwCngIPA2VudgZtZW1vcnkCAIACA2VudgV0YWJsZQFwAQQEA2Vudgl0YWJsZUJhc2UDfwADZW52DkRZTkFNSUNUT1BfUFRSA38AA2VudghTVEFDS1RPUAN/AANlbnYJU1RBQ0tfTUFYA38ABmdsb2JhbAhJbmZpbml0eQN8AANlbnYFYWJvcnQAAQNlbnYNZW5sYXJnZU1lbW9yeQACA2Vudg5nZXRUb3RhbE1lbW9yeQACA2VudhdhYm9ydE9uQ2Fubm90R3Jvd01lbW9yeQACA2Vudg5fX19hc3NlcnRfZmFpbAADA2VudgtfX19zZXRFcnJObwABA2VudgZfYWJvcnQABANlbnYWX2Vtc2NyaXB0ZW5fbWVtY3B5X2JpZwAFA3d2BgYCAQcHAQIBAQcBCAcFAAkGCQoHBgYGBgEFBgIBBgYKAAgLAAYGBgYGBgYBAAoMDAMGBQANCAoJAAwODA8OAQAGBgcEABAJEAERAAADBQwAAAMHBxIGAQAABwIFEwMOBw8HBgYQFAoVExYXFxcXFgQFBQYFAAYkB38BIwELfwEjAgt/ASMDC38BQQALfwFBAAt8ASMEC38BQQALB9MCFRBfX2dyb3dXYXNtTWVtb3J5AAgRX19fZXJybm9fbG9jYXRpb24AYwVfZnJlZQBfB19tYWxsb2MAXgdfbWVtY3B5AHkHX21lbXNldAB6BV9zYnJrAHsXX3N0Yl92b3JiaXNfanNfY2hhbm5lbHMAJhRfc3RiX3ZvcmJpc19qc19jbG9zZQAlFV9zdGJfdm9yYmlzX2pzX2RlY29kZQAoE19zdGJfdm9yYmlzX2pzX29wZW4AJBpfc3RiX3ZvcmJpc19qc19zYW1wbGVfcmF0ZQAnC2R5bkNhbGxfaWlpAHwTZXN0YWJsaXNoU3RhY2tTcGFjZQAMC2dldFRlbXBSZXQwAA8LcnVuUG9zdFNldHMAeAtzZXRUZW1wUmV0MAAOCHNldFRocmV3AA0Kc3RhY2tBbGxvYwAJDHN0YWNrUmVzdG9yZQALCXN0YWNrU2F2ZQAKCQoBACMACwR9VFl9Csb2A3YGACAAQAALGwEBfyMGIQEjBiAAaiQGIwZBD2pBcHEkBiABCwQAIwYLBgAgACQGCwoAIAAkBiABJAcLEAAjCEUEQCAAJAggASQJCwsGACAAJAsLBAAjCwsRACAABEAgABARIAAgABASCwvvBwEKfyAAQYADaiEHIAcoAgAhBQJAIAUEQCAAQfwBaiEEIAQoAgAhASABQQBKBEAgAEHwAGohCANAIAUgAkEYbGpBEGohCSAJKAIAIQEgAQRAIAgoAgAhAyAFIAJBGGxqQQ1qIQogCi0AACEGIAZB/wFxIQYgAyAGQbAQbGpBBGohAyADKAIAIQMgA0EASgRAQQAhAwNAIAEgA0ECdGohASABKAIAIQEgACABEBIgA0EBaiEDIAgoAgAhASAKLQAAIQYgBkH/AXEhBiABIAZBsBBsakEEaiEBIAEoAgAhBiAJKAIAIQEgAyAGSA0ACwsgACABEBILIAUgAkEYbGpBFGohASABKAIAIQEgACABEBIgAkEBaiECIAQoAgAhASACIAFODQMgBygCACEFDAAACwALCwsgAEHwAGohAyADKAIAIQEgAQRAIABB7ABqIQUgBSgCACECIAJBAEoEQEEAIQIDQAJAIAEgAkGwEGxqQQhqIQQgBCgCACEEIAAgBBASIAEgAkGwEGxqQRxqIQQgBCgCACEEIAAgBBASIAEgAkGwEGxqQSBqIQQgBCgCACEEIAAgBBASIAEgAkGwEGxqQaQQaiEEIAQoAgAhBCAAIAQQEiABIAJBsBBsakGoEGohASABKAIAIQEgAUUhBCABQXxqIQFBACABIAQbIQEgACABEBIgAkEBaiECIAUoAgAhASACIAFODQAgAygCACEBDAELCyADKAIAIQELIAAgARASCyAAQfgBaiEBIAEoAgAhASAAIAEQEiAHKAIAIQEgACABEBIgAEGIA2ohAyADKAIAIQEgAQRAIABBhANqIQUgBSgCACECIAJBAEoEQEEAIQIDQCABIAJBKGxqQQRqIQEgASgCACEBIAAgARASIAJBAWohAiAFKAIAIQcgAygCACEBIAIgB0gNAAsLIAAgARASCyAAQQRqIQIgAigCACEBIAFBAEoEQEEAIQEDQCAAQZQGaiABQQJ0aiEDIAMoAgAhAyAAIAMQEiAAQZQHaiABQQJ0aiEDIAMoAgAhAyAAIAMQEiAAQdgHaiABQQJ0aiEDIAMoAgAhAyAAIAMQEiABQQFqIQEgAigCACEDIAEgA0ghAyABQRBJIQUgBSADcQ0ACwtBACEBA0AgAEGgCGogAUECdGohAiACKAIAIQIgACACEBIgAEGoCGogAUECdGohAiACKAIAIQIgACACEBIgAEGwCGogAUECdGohAiACKAIAIQIgACACEBIgAEG4CGogAUECdGohAiACKAIAIQIgACACEBIgAEHACGogAUECdGohAiACKAIAIQIgACACEBIgAUEBaiEBIAFBAkcNAAsLGwAgAEHEAGohACAAKAIAIQAgAEUEQCABEF8LC3wBAX8gAEHUB2ohASABQQA2AgAgAEGAC2ohASABQQA2AgAgAEH4CmohASABQQA2AgAgAEGcCGohASABQQA2AgAgAEHVCmohASABQQA6AAAgAEH8CmohASABQQA2AgAgAEHUC2ohASABQQA2AgAgAEHYC2ohACAAQQA2AgAL8AQBB38jBiELIwZBEGokBiALQQhqIQcgC0EEaiEKIAshCCAAQSRqIQYgBiwAACEGAn8gBgR/IABBgAtqIQYgBigCACEGIAZBf0oEQCAFQQA2AgAgACABIAIQFgwCCyAAQRRqIQYgBiABNgIAIAEgAmohAiAAQRxqIQkgCSACNgIAIABB2ABqIQIgAkEANgIAIABBABAXIQkgCUUEQCAFQQA2AgBBAAwCCyAAIAcgCCAKEBghCSAJBEAgBygCACECIAgoAgAhCSAKKAIAIQggACACIAkgCBAaIQogByAKNgIAIABBBGohAiACKAIAIQggCEEASgRAQQAhAgNAIABBlAZqIAJBAnRqIQcgBygCACEHIAcgCUECdGohByAAQdQGaiACQQJ0aiEMIAwgBzYCACACQQFqIQIgAiAISA0ACwsgAwRAIAMgCDYCAAsgBSAKNgIAIABB1AZqIQAgBCAANgIAIAYoAgAhACAAIAFrDAILAkACQAJAAkACQCACKAIAIgNBIGsOBAECAgACCyACQQA2AgAgAEHUAGohAiAAEBkhAwJAIANBf0cEQANAIAIoAgAhAyADDQIgABAZIQMgA0F/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ACECIABBmAhqIQYgBigCACEHIAUgA2shCSAJIAdqIQkgAiAJSSEJIAIgB0khDSACIAdrIQJBACACIA0bIQIgAiADaiECIAIgBUohByAFIAIgBxshAiAJBEAgASACNgIAIAYoAgAhACAAIAJqIQAgBiAANgIAQQEMBgsLCyAAQfQKaiECIAIoAgAhAiADIB9rIQYgBiACaiEGIABBmAhqIQIgAiAGNgIAIAhBATYCAAwBBSAAQZgIaiECIAYNAQsMAQsgBCADayEDIAIoAgAhBCADIARqIQMgAiADNgIACyATKAIAIQIgAgRAIABByABqIQIgAigCACECIABB0ABqIQAgACgCACEAIAIgAEcEQEHTE0HEE0HkGkHnFBAECwsgASAFNgIAQQELIQAgHCQGIAALqAIBBX8gAEHoCmohBSAFKAIAIQICQCACQQBIBEBBACEABSACIAFIBEAgAUEYSgRAIABBGBAsIQIgAUFoaiEBIAAgARAsIQAgAEEYdCEAIAAgAmohACAADwsgAkUEQCAAQeQKaiECIAJBADYCAAsgAEHkCmohAwJAAkACQANAIAAQLiECIAJBf0YNASAFKAIAIQQgAiAEdCECIAMoAgAhBiAGIAJqIQIgAyACNgIAIAUgBEEIaiICNgIAIAIgAUgNAAwCAAsACyAFQX82AgBBACEADAQLIARBeEgEQEEAIQAMBAsLCyAAQeQKaiEEIAQoAgAhA0EBIAF0IQAgAEF/aiEAIAMgAHEhACADIAF2IQMgBCADNgIAIAIgAWshASAFIAE2AgALCyAAC40CAAJAIABBAEgEf0EABSAAQYCAAUgEQCAAQRBIBEAgAEGACGohACAALAAAIQAMAwsgAEGABEgEQCAAQQV2IQAgAEGACGohACAALAAAIQAgAEEFaiEABSAAQQp2IQAgAEGACGohACAALAAAIQAgAEEKaiEACwwCCyAAQYCAgAhIBH8gAEGAgCBIBH8gAEEPdiEAIABBgAhqIQAgACwAACEAIABBD2oFIABBFHYhACAAQYAIaiEAIAAsAAAhACAAQRRqCwUgAEGAgICAAkgEfyAAQRl2IQAgAEGACGohACAALAAAIQAgAEEZagUgAEEediEAIABBgAhqIQAgACwAACEAIABBHmoLCwshAAsgAAuiAQEDfyAAQdQKaiECIAIsAAAhAQJAAkAgAQ0AIABB3ApqIQEgASgCACEBIAEEQEF/IQMFIAAQLyEBIAEEQCACLAAAIQEgAQ0CQaEUQcQTQfYLQbUUEAQFQX8hAwsLDAELIAFBf2pBGHRBGHUhASACIAE6AAAgAEHsCmohASABKAIAIQIgAkEBaiECIAEgAjYCACAAEDAhACAAQf8BcSEDCyADC6wCAQd/IABB3ApqIQIgAigCACEBAkAgAUUEQCAAQdgKaiEEIAQoAgAhASABQX9GBEAgAEHQCGohASABKAIAIQEgAUF/aiEBIABB4ApqIQMgAyABNgIAIAAQMSEBIAFFBEAgAkEBNgIADAMLIABB0wpqIQEgASwAACEBIAFBAXEhASABBH8gBCgCAAUgAEEgEBUMAwshAQsgAUEBaiEHIAQgBzYCACAAQdQIaiABaiEDIAMsAAAhBiAGQf8BcSEDIAZBf0cEQCACQQE2AgAgAEHgCmohAiACIAE2AgALIABB0AhqIQEgASgCACEBIAcgAU4EQCAEQX82AgALIABB1ApqIQAgACwAACEBIAEEQEHFFEHEE0HoC0HaFBAEBSAAIAY6AAAgAyEFCwsLIAULUQEDfyAAQRRqIQMgAygCACEBIABBHGohAiACKAIAIQIgASACSQR/IAFBAWohACADIAA2AgAgASwAAAUgAEHUAGohACAAQQE2AgBBAAshACAACyABAX8gABAyIQEgAQR/IAAQMwUgAEEeEBVBAAshACAAC2ABAX8gABAwIQEgAUH/AXFBzwBGBEAgABAwIQEgAUH/AXFB5wBGBEAgABAwIQEgAUH/AXFB5wBGBEAgABAwIQAgAEH/AXFB0wBGIQAFQQAhAAsFQQAhAAsFQQAhAAsgAAvZAwEGfyAAEDAhAQJ/IAFB/wFxBH8gAEEfEBVBAAUgABAwIQEgAEHTCmohAiACIAE6AAAgABAjIQUgABAjIQIgABAjGiAAECMhASAAQcwIaiEDIAMgATYCACAAECMaIAAQMCEBIAFB/wFxIQEgAEHQCGohAyADIAE2AgAgAEHUCGohBCAAIAQgARAiIQEgAUUEQCAAQQoQFUEADAILIABB8ApqIQQgBEF+NgIAIAIgBXEhAQJAIAFBf0cEQCADKAIAIQEgAUEASgRAA0ACQCABQX9qIQIgAEHUCGogAmohBiAGLAAAIQYgBkF/Rw0AIAFBAUwNBCACIQEMAQsLIAQgAjYCACAAQfQKaiEBIAEgBTYCAAsLCyAAQdUKaiEBIAEsAAAhASABBEAgAygCACEDIANBAEoEf0EAIQJBACEBA0AgAEHUCGogAWohBCAELQAAIQQgBEH/AXEhBCACIARqIQIgAUEBaiEBIAEgA0gNAAsgAkEbagVBGwshASAAQShqIQIgAigCACECIAEgA2ohASABIAJqIQEgAEEsaiEDIAMgAjYCACAAQTBqIQIgAiABNgIAIABBNGohASABIAU2AgALIABB2ApqIQAgAEEANgIAQQELCyEAIAALowEBB38gAEHoCmohAyADKAIAIQECQCABQRlIBEAgAEHkCmohBCABRQRAIARBADYCAAsgAEHUCmohBSAAQdwKaiEGA0AgBigCACEBIAEEQCAFLAAAIQEgAUUNAwsgABAuIQIgAkF/Rg0CIAMoAgAhASACIAF0IQIgBCgCACEHIAcgAmohAiAEIAI2AgAgAUEIaiECIAMgAjYCACABQRFIDQALCwsLrQUBCX8gABA0IAFBIGohAiACKAIAIQUCQAJAIAVFIgNFDQAgAUGkEGohAiACKAIAIQIgAg0AQX8hAQwBCyABQQRqIQIgAigCACECAkACQCACQQhKBEAgAUGkEGohAyADKAIAIQMgAw0BBSADDQELDAELIABB5ApqIQggCCgCACEJIAkQOiEHIAFBrBBqIQIgAigCACECIAJBAUoEQCABQaQQaigCACEKQQAhAwNAIAJBAXYhBSAFIANqIQQgCiAEQQJ0aiEGIAYoAgAhBiAGIAdLIQYgAiAFayECIAMgBCAGGyEDIAUgAiAGGyECIAJBAUoNAAsFQQAhAwsgAUEXaiECIAIsAAAhAiACRQRAIAFBqBBqIQIgAigCACECIAIgA0ECdGohAiACKAIAIQMLIAFBCGohASABKAIAIQEgASADaiEBIAEtAAAhASABQf8BcSEBIABB6ApqIQIgAigCACEAIAAgAUgEf0EAIQBBfwUgACABayEAIAkgAXYhASAIIAE2AgAgAwshASACIAA2AgAMAQsgAUEXaiEDIAMsAAAhAyADBEBBgRVBxBNB6gxBjBUQBAsCQCACQQBKBEAgASgCCCEIIABB5ApqIQlBACEBA0ACQCAIIAFqIQMgAywAACEEIARB/wFxIQMgBEF/RwRAIAUgAUECdGoh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IwZBEGokBiACIQECfCAAvUIgiKdB/////wdxIgNB/MOk/wNJBHwgA0GewZryA0kEfEQAAAAAAADwPwUgAEQAAAAAAAAAABByCwUgACAAoSADQf//v/8HSw0BGgJAAkACQAJAIAAgARBuQQNxDgMAAQIDCyABKwMAIAErAwgQcgwECyABKwMAIAErAwhBARBwmgwDCyABKwMAIAErAwgQcpoMAgsgASsDACABKwMIQQEQcAsLIQAgAiQGIAALywEBA38jBiECIwZBEGokBiACIQECQCAAvUIgiKdB/////wdxIgNB/MOk/wNJBEAgA0GAgMDyA08EQCAARAAAAAAAAAAAQQAQcCEACwUgA0H//7//B0sEQCAAIAChIQAMAgsCQAJAAkACQAJAIAAgARBuQQNxDgMAAQIDCyABKwMAIAErAwhBARBwIQAMBQsgASsDACABKwMIEHIhAAwECyABKwMAIAErAwhBARBwmiEADAMLIAErAwAgASsDCBBymiEACwsLIAIkBiAAC5sDAwJ/AX4CfCAAvSIDQj+IpyEBAnwCfwJAIANCIIinQf////8HcSICQarGmIQESwR8IANC////////////AINCgICAgICAgPj/AFYEQCAADwsgAETvOfr+Qi6GQGQEQCAARAAAAAAAAOB/og8FIABE0rx63SsjhsBjIABEUTAt1RBJh8BjcUUNAkQAAAAAAAAAACIADwsABSACQcLc2P4DSwRAIAJBscXC/wNLDQIgAUEBcyABawwDCyACQYCAwPEDSwR8QQAhASAABSAARAAAAAAAAPA/oA8LCwwCCyAARP6CK2VHFfc/oiABQQN0QYATaisDAKCqCyEBIAAgAbciBEQAAOD+Qi7mP6KhIgAgBER2PHk17znqPaIiBaELIQQgACAEIAQgBCAEoiIAIAAgACAAIABE0KS+cmk3Zj6iRPFr0sVBvbu+oKJELN4lr2pWET+gokSTvb4WbMFmv6CiRD5VVVVVVcU/oKKhIgCiRAAAAAAAAABAIAChoyAFoaBEAAAAAAAA8D+gIQAgAUUEQCAADwsgACABEGULnwMDAn8BfgV8IAC9IgNCIIinIQECfyADQgBTIgIgAUGAgMAASXIEfyADQv///////////wCDQgBRBEBEAAAAAAAA8L8gACAAoqMPCyACRQRAIABEAAAAAAAAUEOi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mgDjqR0AXmGRAAgb5gCFmWUAoBRfAI1AaACA2P8AJ3NNAAYGMQDKVhUAyahzAHviYABrjMAAQcMSC11A+yH5PwAAAAAtRHQ+AAAAgJhG+DwAAABgUcx4OwAAAICDG/A5AAAAQCAlejgAAACAIoLjNgAAAAAd82k1AAAAAAAA4D8AAAAAAADgvwAAAAAAAPA/AAAAAAAA+D8AQagTCwgG0M9D6/1MPgBBuxMLigZAA7jiP09nZ1MuL3N0Yl92b3JiaXMuYwBmLT5hbGxvYy5hbGxvY19idWZmZXJfbGVuZ3RoX2luX2J5dGVzID09IGYtPnRlbXBfb2Zmc2V0AHZvcmJpc19kZWNvZGVfaW5pdGlhbABmLT5ieXRlc19pbl9zZWcgPiAwAGdldDhfcGFja2V0X3JhdwBmLT5ieXRlc19pbl9zZWcgPT0gMABuZXh0X3NlZ21lbnQAdm9yYmlzX2RlY29kZV9wYWNrZXRfcmVzdAAhYy0+c3BhcnNlAGNvZGVib29rX2RlY29kZV9zY2FsYXJfcmF3ACFjLT5zcGFyc2UgfHwgeiA8IGMtPnNvcnRlZF9lbnRyaWVzAGNvZGVib29rX2RlY29kZV9kZWludGVybGVhdmVfcmVwZWF0AHogPCBjLT5zb3J0ZWRfZW50cmllcwBjb2RlYm9va19kZWNvZGVfc3RhcnQAKG4gJiAzKSA9PSAwAGltZGN0X3N0ZXAzX2l0ZXIwX2xvb3AAMABnZXRfd2luZG93AGYtPnRlbXBfb2Zmc2V0ID09IGYtPmFsbG9jLmFsbG9jX2J1ZmZlcl9sZW5ndGhfaW5fYnl0ZXMAc3RhcnRfZGVjb2RlcgB2b3JiaXNjLT5zb3J0ZWRfZW50cmllcyA9PSAwAGNvbXB1dGVfY29kZXdvcmRzAHogPj0gMCAmJiB6IDwgMzIAbGVuW2ldID49IDAgJiYgbGVuW2ldIDwgMzIAYXZhaWxhYmxlW3ldID09IDAAayA9PSBjLT5zb3J0ZWRfZW50cmllcwBjb21wdXRlX3NvcnRlZF9odWZmbWFuAGMtPnNvcnRlZF9jb2Rld29yZHNbeF0gPT0gY29kZQBsZW4gIT0gTk9fQ09ERQBpbmNsdWRlX2luX3NvcnQAcG93KChmbG9hdCkgcisxLCBkaW0pID4gZW50cmllcwBsb29rdXAxX3ZhbHVlcwAoaW50KSBmbG9vcihwb3coKGZsb2F0KSByLCBkaW0pKSA8PSBlbnRyaWVzAOoPBG5hbWUB4g9+AAVhYm9ydAENZW5sYXJnZU1lbW9yeQIOZ2V0VG90YWxNZW1vcnkDF2Fib3J0T25DYW5ub3RHcm93TWVtb3J5BA5fX19hc3NlcnRfZmFpbAULX19fc2V0RXJyTm8GBl9hYm9ydAcWX2Vtc2NyaXB0ZW5fbWVtY3B5X2JpZwgQX19ncm93V2FzbU1lbW9yeQkKc3RhY2tBbGxvYwoJc3RhY2tTYXZlCwxzdGFja1Jlc3RvcmUME2VzdGFibGlzaFN0YWNrU3BhY2UNCHNldFRocmV3DgtzZXRUZW1wUmV0MA8LZ2V0VGVtcFJldDAQEV9zdGJfdm9yYmlzX2Nsb3NlEQ5fdm9yYmlzX2RlaW5pdBILX3NldHVwX2ZyZWUTGl9zdGJfdm9yYmlzX2ZsdXNoX3B1c2hkYXRhFCFfc3RiX3ZvcmJpc19kZWNvZGVfZnJhbWVfcHVzaGRhdGEVBl9lcnJvchYgX3ZvcmJpc19zZWFyY2hfZm9yX3BhZ2VfcHVzaGRhdGEXGF9pc193aG9sZV9wYWNrZXRfcHJlc2VudBgVX3ZvcmJpc19kZWNvZGVfcGFja2V0GQxfZ2V0OF9wYWNrZXQaFF92b3JiaXNfZmluaXNoX2ZyYW1lGxlfc3RiX3ZvcmJpc19vcGVuX3B1c2hkYXRhHAxfdm9yYmlzX2luaXQdDl9zdGFydF9kZWNvZGVyHg1fdm9yYmlzX2FsbG9jHxtfc3RiX3ZvcmJpc19nZXRfZmlsZV9vZmZzZXQgE19tYXliZV9zdGFydF9wYWNrZXQhDV9mbHVzaF9wYWNrZXQiBV9nZXRuIwZfZ2V0MzIkE19zdGJfdm9yYmlzX2pzX29wZW4lFF9zdGJfdm9yYmlzX2pzX2Nsb3NlJhdfc3RiX3ZvcmJpc19qc19jaGFubmVscycaX3N0Yl92b3JiaXNfanNfc2FtcGxlX3JhdGUoFV9zdGJfdm9yYmlzX2pzX2RlY29kZSkNX2NyYzMyX3VwZGF0ZSoWX3ZvcmJpc19kZWNvZGVfaW5pdGlhbCsaX3ZvcmJpc19kZWNvZGVfcGFja2V0X3Jlc3QsCV9nZXRfYml0cy0FX2lsb2cuEF9nZXQ4X3BhY2tldF9yYXcvDV9uZXh0X3NlZ21lbnQwBV9nZXQ4MQtfc3RhcnRfcGFnZTIQX2NhcHR1cmVfcGF0dGVybjMdX3N0YXJ0X3BhZ2Vfbm9fY2FwdHVyZXBhdHRlcm40DV9wcmVwX2h1ZmZtYW41G19jb2RlYm9va19kZWNvZGVfc2NhbGFyX3JhdzYOX3ByZWRpY3RfcG9pbnQ3D19kZWNvZGVfcmVzaWR1ZTgJX2RvX2Zsb29yOQ1faW52ZXJzZV9tZGN0OgxfYml0X3JldmVyc2U7EV9tYWtlX2Jsb2NrX2FycmF5PBJfc2V0dXBfdGVtcF9tYWxsb2M9JF9jb2RlYm9va19kZWNvZGVfZGVpbnRlcmxlYXZlX3JlcGVhdD4PX3Jlc2lkdWVfZGVjb2RlPxVfY29kZWJvb2tfZGVjb2RlX3N0ZXBAEF9jb2RlYm9va19kZWNvZGVBFl9jb2RlYm9va19kZWNvZGVfc3RhcnRCCl9kcmF3X2xpbmVDF19pbWRjdF9zdGVwM19pdGVyMF9sb29wRBlfaW1kY3Rfc3RlcDNfaW5uZXJfcl9sb29wRRlfaW1kY3Rfc3RlcDNfaW5uZXJfc19sb29wRh9faW1kY3Rfc3RlcDNfaW5uZXJfc19sb29wX2xkNjU0RwhfaXRlcl81NEgLX2dldF93aW5kb3dJEF92b3JiaXNfdmFsaWRhdGVKDV9zdGFydF9wYWNrZXRLBV9za2lwTAtfY3JjMzJfaW5pdE0NX3NldHVwX21hbGxvY04QX3NldHVwX3RlbXBfZnJlZU8SX2NvbXB1dGVfY29kZXdvcmRzUBdfY29tcHV0ZV9zb3J0ZWRfaHVmZm1hblEcX2NvbXB1dGVfYWNjZWxlcmF0ZWRfaHVmZm1hblIPX2Zsb2F0MzJfdW5wYWNrUw9fbG9va3VwMV92YWx1ZXNUDl9wb2ludF9jb21wYXJlVQpfbmVpZ2hib3JzVg9faW5pdF9ibG9ja3NpemVXCl9hZGRfZW50cnlYEF9pbmNsdWRlX2luX3NvcnRZD191aW50MzJfY29tcGFyZVoYX2NvbXB1dGVfdHdpZGRsZV9mYWN0b3JzWw9fY29tcHV0ZV93aW5kb3dcE19jb21wdXRlX2JpdHJldmVyc2VdB19zcXVhcmVeB19tYWxsb2NfBV9mcmVlYAhfcmVhbGxvY2ESX3RyeV9yZWFsbG9jX2NodW5rYg5fZGlzcG9zZV9jaHVua2MRX19fZXJybm9fbG9jYXRpb25kB19tZW1jbXBlB19zY2FsYm5mBl9xc29ydGcFX3NpZnRoBF9zaHJpCF90cmlua2xlagRfc2hsawVfcG50emwIX2FfY3R6X2xtBl9jeWNsZW4LX19fcmVtX3BpbzJvEV9fX3JlbV9waW8yX2xhcmdlcAZfX19zaW5xBl9sZGV4cHIGX19fY29zcwRfY29zdARfc2ludQRfZXhwdgRfbG9ndwRfcG93eAtydW5Qb3N0U2V0c3kHX21lbWNweXoHX21lbXNldHsFX3Nicmt8C2R5bkNhbGxfaWlpfQJiMA==\"),function(A){return A.charCodeAt(0)});var $=void 0!==$?$:{},e={};for(A in $)$.hasOwnProperty(A)&&(e[A]=$[A]);$.arguments=[],$.thisProgram=\"./this.program\",$.quit=function(A,I){throw I},$.preRun=[],$.postRun=[];var t=!1,k=!1,N=!1,r=!1;t=\"object\"==typeof window,k=\"function\"==typeof importScripts,N=\"object\"==typeof process&&\"function\"==typeof require&&!t&&!k,r=!t&&!N&&!k;var Y=\"\";function J(A){return $.locateFile?$.locateFile(A,Y):Y+A}N?(Y=\"\"+\"/\",$.read=function A(B,E){var Q;return I||(I=undefined),g||(g=undefined),B=g.normalize(B),Q=I.readFileSync(B),E?Q:Q.toString()},$.readBinary=function A(I){var g=$.read(I,!0);return g.buffer||(g=new Uint8Array(g)),_(g.buffer),g},process.argv.length>1&&($.thisProgram=process.argv[1].replace(/\\\\/g,\"/\")),$.arguments=process.argv.slice(2),\"undefined\"!=typeof module&&(/undefined!=$/),process.on(\"uncaughtException\",function(A){if(!(A instanceof II))throw A}),process.on(\"unhandledRejection\",function(A,I){process.exit(1)}),$.quit=function(A){process.exit(A)},$.inspect=function(){return\"[Emscripten Module object]\"}):r?(\"undefined\"!=typeof read&&($.read=function A(I){return read(I)}),$.readBinary=function A(I){var g;return\"function\"==typeof readbuffer?new Uint8Array(readbuffer(I)):(_(\"object\"==typeof(g=read(I,\"binary\"))),g)},\"undefined\"!=typeof scriptArgs?$.arguments=scriptArgs:\"undefined\"!=typeof arguments&&($.arguments=arguments),\"function\"==typeof quit&&($.quit=function(A){quit(A)})):(t||k)&&(t?document.currentScript&&(Y=document.currentScript.src):Y=self.location.href,Y=0!==Y.indexOf(\"blob:\")?Y.split(\"/\").slice(0,-1).join(\"/\")+\"/\":\"\",$.read=function A(I){var g=new XMLHttpRequest;return g.open(\"GET\",I,!1),g.send(null),g.responseText},k&&($.readBinary=function A(I){var g=new XMLHttpRequest;return g.open(\"GET\",I,!1),g.responseType=\"arraybuffer\",g.send(null),new Uint8Array(g.response)}),$.readAsync=function A(I,g,B){var E=new XMLHttpRequest;E.open(\"GET\",I,!0),E.responseType=\"arraybuffer\",E.onload=function A(){if(200==E.status||0==E.status&&E.response){g(E.response);return}B()},E.onerror=B,E.send(null)},$.setWindowTitle=function(A){document.title=A});var f=$.print||(\"undefined\"!=typeof console?console.log.bind(console):\"undefined\"!=typeof print?print:null),H=$.printErr||(\"undefined\"!=typeof printErr?printErr:\"undefined\"!=typeof console&&console.warn.bind(console)||f);for(A in e)e.hasOwnProperty(A)&&($[A]=e[A]);function L(A){var I=S;return S=S+A+15&-16,I}function M(A){var I=h[c>>2],g=I+A+15&-16;return(h[c>>2]=g,g>=AN&&!Ae())?(h[c>>2]=I,0):I}function d(A,I){return I||(I=16),A=Math.ceil(A/I)*I}function q(A){switch(A){case\"i1\":case\"i8\":return 1;case\"i16\":return 2;case\"i32\":case\"float\":return 4;case\"i64\":case\"double\":return 8;default:if(\"*\"===A[A.length-1])return 4;if(\"i\"!==A[0])return 0;var I=parseInt(A.substr(1));return _(I%8==0),I/8}}function K(A){K.shown||(K.shown={}),K.shown[A]||(K.shown[A]=1,H(A))}e=void 0;var l={\"f64-rem\":function(A,I){return A%I},debugger:function(){}},u=[];function b(A,I){for(var g=0,B=g;B<g+0;B++)if(!u[B])return u[B]=A,1+B;throw\"Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.\"}function X(A){u[A-1]=null}var m={};function Z(A,I){if(A){_(I),m[I]||(m[I]={});var g=m[I];return g[A]||(1===I.length?g[A]=function g(){return V(I,A)}:2===I.length?g[A]=function g(B){return V(I,A,[B])}:g[A]=function g(){return V(I,A,Array.prototype.slice.call(arguments))}),g[A]}}function x(A,I,g){return g?+(A>>>0)+4294967296*+(I>>>0):+(A>>>0)+4294967296*+(0|I)}function V(A,I,g){return g&&g.length?$[\"dynCall_\"+A].apply(null,[I].concat(g)):$[\"dynCall_\"+A].call(null,I)}var p=0,W=0;function _(A,I){A||IE(\"Assertion failed: \"+I)}function T(A){var I=$[\"_\"+A];return _(I,\"Cannot call unknown function \"+A+\", make sure it is exported\"),I}var v={stackSave:function(){IA()},stackRestore:function(){A9()},arrayToC:function(A){var I,g,B=A5(A.length);return I=A,g=B,E.set(I,g),B},stringToC:function(A){var I=0;if(null!=A&&0!==A){var g=(A.length<<2)+1;I=A5(g),Ai(A,I,g)}return I}},O={string:v.stringToC,array:v.arrayToC};function j(A,I,g,B,E){var Q=T(A),C=[],i=0;if(B)for(var h=0;h<B.length;h++){var o=O[g[h]];o?(0===i&&(i=IA()),C[h]=o(B[h])):C[h]=B[h]}var G,D=Q.apply(null,C);return D=(G=D,\"string\"===I?Ag(G):\"boolean\"===I?Boolean(G):G),0!==i&&A9(i),D}function P(A,I,g,B){switch(\"*\"===(g=g||\"i8\").charAt(g.length-1)&&(g=\"i32\"),g){case\"i1\":case\"i8\":E[A>>0]=I;break;case\"i16\":C[A>>1]=I;break;case\"i32\":h[A>>2]=I;break;case\"i64\":tempI64=[I>>>0,+Ax(tempDouble=I)>=1?tempDouble>0?(0|Ap(+A6(tempDouble/4294967296),4294967295))>>>0:~~+AV((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0,],h[A>>2]=tempI64[0],h[A+4>>2]=tempI64[1];break;case\"float\":G[A>>2]=I;break;case\"double\":D[A>>3]=I;break;default:IE(\"invalid type for setValue: \"+g)}}function z(A,I,g){switch(\"*\"===(I=I||\"i8\").charAt(I.length-1)&&(I=\"i32\"),I){case\"i1\":case\"i8\":return E[A>>0];case\"i16\":return C[A>>1];case\"i32\":case\"i64\":return h[A>>2];case\"float\":return G[A>>2];case\"double\":return D[A>>3];default:IE(\"invalid type for getValue: \"+I)}return null}function AA(A,I,g,B){\"number\"==typeof A?(i=!0,o=A):(i=!1,o=A.length);var C=\"string\"==typeof I?I:null;if(G=4==g?B:[\"function\"==typeof A8?A8:L,A5,L,M,][void 0===g?2:g](Math.max(o,C?1:I.length)),i){for(B=G,_((3&G)==0),D=G+(-4&o);B<D;B+=4)h[B>>2]=0;for(D=G+o;B<D;)E[B++>>0]=0;return G}if(\"i8\"===C)return A.subarray||A.slice?Q.set(A,G):Q.set(new Uint8Array(A),G),G;for(var i,o,G,D,a,S,F,R=0;R<o;){var s=A[R];if(0===(a=C||I[R])){R++;continue}\"i64\"==a&&(a=\"i32\"),P(G+R,s,a),F!==a&&(S=q(a),F=a),R+=S}return G}function AI(A){return F?A0?A8(A):M(A):L(A)}function Ag(A,I){if(0===I||!A)return\"\";for(var g,B,E,C=0,i=0;C|=B=Q[A+i>>0],(0!=B||I)&&(i++,!I||i!=I););I||(I=i);var h=\"\";if(C<128){for(;I>0;)E=String.fromCharCode.apply(String,Q.subarray(A,A+Math.min(I,1024))),h=h?h+E:E,A+=1024,I-=1024;return h}return g=A,function A(I,g){for(var B=g;I[B];)++B;if(B-g>16&&I.subarray&&AQ)return AQ.decode(I.subarray(g,B));for(var E,Q,C,i,h,o,G=\"\";;){if(!(E=I[g++]))return G;if(!(128&E)){G+=String.fromCharCode(E);continue}if(Q=63&I[g++],(224&E)==192){G+=String.fromCharCode((31&E)<<6|Q);continue}if(C=63&I[g++],(240&E)==224?E=(15&E)<<12|Q<<6|C:(i=63&I[g++],(248&E)==240?E=(7&E)<<18|Q<<12|C<<6|i:(h=63&I[g++],E=(252&E)==248?(3&E)<<24|Q<<18|C<<12|i<<6|h:(1&E)<<30|Q<<24|C<<18|i<<12|h<<6|(o=63&I[g++]))),E<65536)G+=String.fromCharCode(E);else{var D=E-65536;G+=String.fromCharCode(55296|D>>10,56320|1023&D)}}}(Q,g)}function AB(A){for(var I=\"\";;){var g=E[A++>>0];if(!g)return I;I+=String.fromCharCode(g)}}function AE(A,I){return function A(I,g,B){for(var Q=0;Q<I.length;++Q)E[g++>>0]=I.charCodeAt(Q);B||(E[g>>0]=0)}(A,I,!1)}var AQ=\"undefined\"!=typeof TextDecoder?new TextDecoder(\"utf8\"):void 0;function AC(A,I,g,B){if(!(B>0))return 0;for(var E=g,Q=g+B-1,C=0;C<A.length;++C){var i=A.charCodeAt(C);if(i>=55296&&i<=57343&&(i=65536+((1023&i)<<10)|1023&A.charCodeAt(++C)),i<=127){if(g>=Q)break;I[g++]=i}else if(i<=2047){if(g+1>=Q)break;I[g++]=192|i>>6,I[g++]=128|63&i}else if(i<=65535){if(g+2>=Q)break;I[g++]=224|i>>12,I[g++]=128|i>>6&63,I[g++]=128|63&i}else if(i<=2097151){if(g+3>=Q)break;I[g++]=240|i>>18,I[g++]=128|i>>12&63,I[g++]=128|i>>6&63,I[g++]=128|63&i}else if(i<=67108863){if(g+4>=Q)break;I[g++]=248|i>>24,I[g++]=128|i>>18&63,I[g++]=128|i>>12&63,I[g++]=128|i>>6&63,I[g++]=128|63&i}else{if(g+5>=Q)break;I[g++]=252|i>>30,I[g++]=128|i>>24&63,I[g++]=128|i>>18&63,I[g++]=128|i>>12&63,I[g++]=128|i>>6&63,I[g++]=128|63&i}}return I[g]=0,g-E}function Ai(A,I,g){return AC(A,Q,I,g)}function Ah(A){for(var I=0,g=0;g<A.length;++g){var B=A.charCodeAt(g);B>=55296&&B<=57343&&(B=65536+((1023&B)<<10)|1023&A.charCodeAt(++g)),B<=127?++I:B<=2047?I+=2:B<=65535?I+=3:B<=2097151?I+=4:B<=67108863?I+=5:I+=6}return I}var Ao=\"undefined\"!=typeof TextDecoder?new TextDecoder(\"utf-16le\"):void 0;function AG(A){for(var I=A,g=I>>1;C[g];)++g;if((I=g<<1)-A>32&&Ao)return Ao.decode(Q.subarray(A,I));for(var B=0,E=\"\";;){var i=C[A+2*B>>1];if(0==i)return E;++B,E+=String.fromCharCode(i)}}function AD(A,I,g){if(void 0===g&&(g=2147483647),g<2)return 0;for(var B=I,E=(g-=2)<2*A.length?g/2:A.length,Q=0;Q<E;++Q){var i=A.charCodeAt(Q);C[I>>1]=i,I+=2}return C[I>>1]=0,I-B}function Aa(A){return 2*A.length}function AS(A){for(var I=0,g=\"\";;){var B=h[A+4*I>>2];if(0==B)return g;if(++I,B>=65536){var E=B-65536;g+=String.fromCharCode(55296|E>>10,56320|1023&E)}else g+=String.fromCharCode(B)}}function AF(A,I,g){if(void 0===g&&(g=2147483647),g<4)return 0;for(var B=I,E=B+g-4,Q=0;Q<A.length;++Q){var C=A.charCodeAt(Q);if(C>=55296&&C<=57343&&(C=65536+((1023&C)<<10)|1023&A.charCodeAt(++Q)),h[I>>2]=C,(I+=4)+4>E)break}return h[I>>2]=0,I-B}function AR(A){for(var I=0,g=0;g<A.length;++g){var B=A.charCodeAt(g);B>=55296&&B<=57343&&++g,I+=4}return I}function As(A){var I=Ah(A)+1,g=A8(I);return g&&AC(A,E,g,I),g}function Aw(A){var I=Ah(A)+1,g=A5(I);return AC(A,E,g,I),g}function Ay(A){return A}function Ac(){var A,I=function A(){var I=Error();if(!I.stack){try{throw Error(0)}catch(g){I=g}if(!I.stack)return\"(no stack trace available)\"}return I.stack.toString()}();return $.extraStackTrace&&(I+=\"\\n\"+$.extraStackTrace()),(A=I).replace(/__Z[\\w\\d_]+/g,function(A){var I,g=I=A;return A===g?A:A+\" [\"+g+\"]\"})}function An(A,I){return A%I>0&&(A+=I-A%I),A}function AU(A){$.buffer=B=A}function A$(){$.HEAP8=E=new Int8Array(B),$.HEAP16=C=new Int16Array(B),$.HEAP32=h=new Int32Array(B),$.HEAPU8=Q=new Uint8Array(B),$.HEAPU16=i=new Uint16Array(B),$.HEAPU32=o=new Uint32Array(B),$.HEAPF32=G=new Float32Array(B),$.HEAPF64=D=new Float64Array(B)}function Ae(){var A=$.usingWasm?65536:16777216,I=2147483648-A;if(h[c>>2]>I)return!1;var g=AN;for(AN=Math.max(AN,16777216);AN<h[c>>2];)AN=AN<=536870912?An(2*AN,A):Math.min(An((3*AN+2147483648)/4,A),I);var B=$.reallocBuffer(AN);return B&&B.byteLength==AN?(AU(B),A$(),!0):(AN=g,!1)}a=S=R=s=w=y=c=0,F=!1,$.reallocBuffer||($.reallocBuffer=function(A){try{if(ArrayBuffer.transfer)I=ArrayBuffer.transfer(B,A);else{var I,g=E;I=new ArrayBuffer(A),new Int8Array(I).set(g)}}catch(Q){return!1}return!!Az(I)&&I});try{(n=Function.prototype.call.bind(Object.getOwnPropertyDescriptor(ArrayBuffer.prototype,\"byteLength\").get))(new ArrayBuffer(4))}catch(At){n=function(A){return A.byteLength}}var Ak=$.TOTAL_STACK||5242880,AN=$.TOTAL_MEMORY||16777216;function Ar(){return AN}function AY(A){for(;A.length>0;){var I=A.shift();if(\"function\"==typeof I){I();continue}var g=I.func;\"number\"==typeof g?void 0===I.arg?$.dynCall_v(g):$.dynCall_vi(g,I.arg):g(void 0===I.arg?null:I.arg)}}AN<Ak&&H(\"TOTAL_MEMORY should be larger than TOTAL_STACK, was \"+AN+\"! (TOTAL_STACK=\"+Ak+\")\"),$.buffer?B=$.buffer:(\"object\"==typeof WebAssembly&&\"function\"==typeof WebAssembly.Memory?($.wasmMemory=new WebAssembly.Memory({initial:AN/65536}),B=$.wasmMemory.buffer):B=new ArrayBuffer(AN),$.buffer=B),A$();var AJ=[],Af=[],AH=[],AL=[],AM=[],A0=!1,Ad=!1;function Aq(A){AJ.unshift(A)}function AK(A){Af.unshift(A)}function Al(A){AH.unshift(A)}function Au(A){AL.unshift(A)}function Ab(A){AM.unshift(A)}function AX(A,I,g){var B,Q;K(\"writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!\"),g&&(B=E[Q=I+Ah(A)]),Ai(A,I,1/0),g&&(E[Q]=B)}function Am(A,I,g){return A>=0?A:I<=32?2*Math.abs(1<<I-1)+A:Math.pow(2,I)+A}function AZ(A,I,g){if(A<=0)return A;var B=I<=32?Math.abs(1<<I-1):Math.pow(2,I-1);return A>=B&&(I<=32||A>B)&&(A=-2*B+A),A}var Ax=Math.abs,AV=Math.ceil,A6=Math.floor,Ap=Math.min,A7=0,A1=null,AW=null;function A_(A){return A}$.preloadedImages={},$.preloadedAudios={};var AT=\"data:application/octet-stream;base64,\";function A2(A){return String.prototype.startsWith?A.startsWith(AT):0===A.indexOf(AT)}!function A(){var I=\"main.wast\",g=\"main.wasm\",B=\"main.temp.asm\";A2(I)||(I=J(I)),A2(g)||(g=J(g)),A2(B)||(B=J(B));var E={global:null,env:null,asm2wasm:l,parent:$},Q=null;function C(A){return A}function i(){try{if($.wasmBinary)return new Uint8Array($.wasmBinary);if($.readBinary)return $.readBinary(g);throw\"both async and sync fetching of the wasm failed\"}catch(A){IE(A)}}$.asmPreload=$.asm;var h=$.reallocBuffer,o=function(A){A=An(A,$.usingWasm?65536:16777216);var I=$.buffer.byteLength;if($.usingWasm)try{var g=$.wasmMemory.grow((A-I)/65536);if(-1!==g)return $.buffer=$.wasmMemory.buffer;return null}catch(B){return null}};$.reallocBuffer=function(A){return\"asmjs\"===G?h(A):o(A)};var G=\"\";$.asm=function(A,I,B){var C;if(!(I=C=I).table){var h,o=$.wasmTableSize;void 0===o&&(o=1024);var G=$.wasmMaxTableSize;\"object\"==typeof WebAssembly&&\"function\"==typeof WebAssembly.Table?void 0!==G?I.table=new WebAssembly.Table({initial:o,maximum:G,element:\"anyfunc\"}):I.table=new WebAssembly.Table({initial:o,element:\"anyfunc\"}):I.table=Array(o),$.wasmTable=I.table}return I.memoryBase||(I.memoryBase=$.STATIC_BASE),I.tableBase||(I.tableBase=0),h=function A(I,B,C){if(\"object\"!=typeof WebAssembly)return H(\"no native wasm support detected\"),!1;if(!($.wasmMemory instanceof WebAssembly.Memory))return H(\"no native wasm Memory in use\"),!1;function h(A,I){if((Q=A.exports).memory){var g,B,E;g=Q.memory,B=$.buffer,g.byteLength<B.byteLength&&H(\"the new buffer in mergeMemory is smaller than the previous one. in native wasm, we should grow memory here\"),E=new Int8Array(B),new Int8Array(g).set(E),AU(g),A$()}$.asm=Q,$.usingWasm=!0,function A(I){if(A7--,$.monitorRunDependencies&&$.monitorRunDependencies(A7),0==A7&&(null!==A1&&(clearInterval(A1),A1=null),AW)){var g=AW;AW=null,g()}}(\"wasm-instantiate\")}B.memory=$.wasmMemory,E.global={NaN:NaN,Infinity:1/0},E[\"global.Math\"]=Math,E.env=B;if((A7++,$.monitorRunDependencies&&$.monitorRunDependencies(A7)),$.instantiateWasm)try{return $.instantiateWasm(E,h)}catch(o){return H(\"Module.instantiateWasm callback failed with error: \"+o),!1}function G(A){h(A.instance,A.module)}function D(A){(!$.wasmBinary&&(t||k)&&\"function\"==typeof fetch?fetch(g,{credentials:\"same-origin\"}).then(function(A){if(!A.ok)throw\"failed to load wasm binary file at '\"+g+\"'\";return A.arrayBuffer()}).catch(function(){return i()}):new Promise(function(A,I){A(i())})).then(function(A){return WebAssembly.instantiate(A,E)}).then(A).catch(function(A){H(\"failed to asynchronously prepare wasm: \"+A),IE(A)})}return $.wasmBinary||\"function\"!=typeof WebAssembly.instantiateStreaming||A2(g)||\"function\"!=typeof fetch?D(G):WebAssembly.instantiateStreaming(fetch(g,{credentials:\"same-origin\"}),E).then(G).catch(function(A){H(\"wasm streaming compile failed: \"+A),H(\"falling back to ArrayBuffer instantiation\"),D(G)}),{}}(A,I,B),_(h,\"no binaryen method succeeded.\"),h},$.asm}(),S=(a=1024)+4816,Af.push(),$.STATIC_BASE=a,$.STATIC_BUMP=4816;var Av=S;function AO(A){E[Av]=E[A],E[Av+1]=E[A+1],E[Av+2]=E[A+2],E[Av+3]=E[A+3]}function Aj(A){E[Av]=E[A],E[Av+1]=E[A+1],E[Av+2]=E[A+2],E[Av+3]=E[A+3],E[Av+4]=E[A+4],E[Av+5]=E[A+5],E[Av+6]=E[A+6],E[Av+7]=E[A+7]}function AP(A,I,g){var B=g>0?g:Ah(A)+1,E=Array(B),Q=AC(A,E,0,E.length);return I&&(E.length=Q),E}function A4(A){for(var I=[],g=0;g<A.length;g++){var B=A[g];B>255&&(B&=255),I.push(String.fromCharCode(B))}return I.join(\"\")}S+=16,c=L(4),w=(R=s=d(S))+Ak,y=d(w),h[c>>2]=y,F=!0,$.wasmTableSize=4,$.wasmMaxTableSize=4,$.asmGlobalArg={},$.asmLibraryArg={abort:IE,assert:_,enlargeMemory:Ae,getTotalMemory:Ar,abortOnCannotGrowMemory:function A(){IE(\"Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value \"+AN+\", (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 \")},invoke_iii:function A(I,g,B){var E=IA();try{return $.dynCall_iii(I,g,B)}catch(Q){if(A9(E),\"number\"!=typeof Q&&\"longjmp\"!==Q)throw Q;$.setThrew(1,0)}},___assert_fail:function A(I,g,B,E){IE(\"Assertion failed: \"+Ag(I)+\", at: \"+[g?Ag(g):\"unknown filename\",B,E?Ag(E):\"unknown function\",])},___setErrNo:function A(I){return $.___errno_location&&(h[$.___errno_location()>>2]=I),I},_abort:function A(){$.abort()},_emscripten_memcpy_big:function A(I,g,B){return Q.set(Q.subarray(g,g+B),I),I},_llvm_floor_f64:A6,DYNAMICTOP_PTR:c,tempDoublePtr:Av,ABORT:p,STACKTOP:s,STACK_MAX:w};var A3=$.asm($.asmGlobalArg,$.asmLibraryArg,B);$.asm=A3,$.___errno_location=function(){return $.asm.___errno_location.apply(null,arguments)};var Az=$._emscripten_replace_memory=function(){return $.asm._emscripten_replace_memory.apply(null,arguments)};$._free=function(){return $.asm._free.apply(null,arguments)};var A8=$._malloc=function(){return $.asm._malloc.apply(null,arguments)};$._memcpy=function(){return $.asm._memcpy.apply(null,arguments)},$._memset=function(){return $.asm._memset.apply(null,arguments)},$._sbrk=function(){return $.asm._sbrk.apply(null,arguments)},$._stb_vorbis_js_channels=function(){return $.asm._stb_vorbis_js_channels.apply(null,arguments)},$._stb_vorbis_js_close=function(){return $.asm._stb_vorbis_js_close.apply(null,arguments)},$._stb_vorbis_js_decode=function(){return $.asm._stb_vorbis_js_decode.apply(null,arguments)},$._stb_vorbis_js_open=function(){return $.asm._stb_vorbis_js_open.apply(null,arguments)},$._stb_vorbis_js_sample_rate=function(){return $.asm._stb_vorbis_js_sample_rate.apply(null,arguments)},$.establishStackSpace=function(){return $.asm.establishStackSpace.apply(null,arguments)},$.getTempRet0=function(){return $.asm.getTempRet0.apply(null,arguments)},$.runPostSets=function(){return $.asm.runPostSets.apply(null,arguments)},$.setTempRet0=function(){return $.asm.setTempRet0.apply(null,arguments)},$.setThrew=function(){return $.asm.setThrew.apply(null,arguments)};var A5=$.stackAlloc=function(){return $.asm.stackAlloc.apply(null,arguments)},A9=$.stackRestore=function(){return $.asm.stackRestore.apply(null,arguments)},IA=$.stackSave=function(){return $.asm.stackSave.apply(null,arguments)};function II(A){this.name=\"ExitStatus\",this.message=\"Program terminated with exit(\"+A+\")\",this.status=A}function Ig(A){if(A=A||$.arguments,!(A7>0))!function A(){if($.preRun)for(\"function\"==typeof $.preRun&&($.preRun=[$.preRun]);$.preRun.length;)Aq($.preRun.shift());AY(AJ)}(),!(A7>0)&&($.calledRun||($.setStatus?($.setStatus(\"Running...\"),setTimeout(function(){setTimeout(function(){$.setStatus(\"\")},1),I()},1)):I()));function I(){!$.calledRun&&($.calledRun=!0,p||(A0||(A0=!0,AY(Af)),AY(AH),$.onRuntimeInitialized&&$.onRuntimeInitialized(),function A(){if($.postRun)for(\"function\"==typeof $.postRun&&($.postRun=[$.postRun]);$.postRun.length;)Ab($.postRun.shift());AY(AM)}()))}}function IB(A,I){(!I||!$.noExitRuntime||0!==A)&&($.noExitRuntime||(p=!0,W=A,s=U,AY(AL),Ad=!0,$.onExit&&$.onExit(A)),$.quit(A,new II(A)))}function IE(A){throw $.onAbort&&$.onAbort(A),void 0!==A?(f(A),H(A),A=JSON.stringify(A)):A=\"\",p=!0,W=1,\"abort(\"+A+\"). Build with -s ASSERTIONS=1 for more info.\"}if($.dynCall_iii=function(){return $.asm.dynCall_iii.apply(null,arguments)},$.asm=A3,$.ccall=j,$.cwrap=function A(I,g,B,E){var Q=(B=B||[]).every(function(A){return\"number\"===A});return\"string\"!==g&&Q&&!E?T(I):function(){return j(I,g,B,arguments,E)}},II.prototype=Error(),II.prototype.constructor=II,AW=function A(){$.calledRun||Ig(),$.calledRun||(AW=A)},$.run=Ig,$.abort=IE,$.preInit)for(\"function\"==typeof $.preInit&&($.preInit=[$.preInit]);$.preInit.length>0;)$.preInit.pop()();$.noExitRuntime=!0,Ig(),$.onRuntimeInitialized=()=>{isReady=!0,readySolver()},stbvorbis.decode=function(A){return function A(I){if(!isReady)throw Error(\"SF3 decoder has not been initialized yet. Did you await synth.isReady?\");var g={};function B(A){return new Int32Array($.HEAPU8.buffer,A,1)[0]}function E(A,I){var g=new ArrayBuffer(I*Float32Array.BYTES_PER_ELEMENT),B=new Float32Array(g);return B.set(new Float32Array($.HEAPU8.buffer,A,I)),B}g.open=$.cwrap(\"stb_vorbis_js_open\",\"number\",[]),g.close=$.cwrap(\"stb_vorbis_js_close\",\"void\",[\"number\"]),g.channels=$.cwrap(\"stb_vorbis_js_channels\",\"number\",[\"number\"]),g.sampleRate=$.cwrap(\"stb_vorbis_js_sample_rate\",\"number\",[\"number\"]),g.decode=$.cwrap(\"stb_vorbis_js_decode\",\"number\",[\"number\",\"number\",\"number\",\"number\",\"number\"]);var Q,C,i,h,o=g.open(),G=(Q=I,C=I.byteLength,i=$._malloc(C),(h=new Uint8Array($.HEAPU8.buffer,i,C)).set(new Uint8Array(Q,0,C)),h),D=$._malloc(4),a=$._malloc(4),S=g.decode(o,G.byteOffset,G.byteLength,D,a);if($._free(G.byteOffset),S<0)throw g.close(o),$._free(D),Error(\"stbvorbis decode failed: \"+S);for(var F=g.channels(o),R=Array(F),s=new Int32Array($.HEAPU32.buffer,B(D),F),w=0;w<F;w++)R[w]=E(s[w],S),$._free(s[w]);var y=g.sampleRate(o);return g.close(o),$._free(B(D)),$._free(D),{data:R,sampleRate:y,eof:!0,error:null}}(A)}}();","import { stbvorbis } from \"./stbvorbis_sync.min\";\n\ninterface DecodedData {\n data: Float32Array[];\n error: string | null;\n sampleRate: number;\n eof: boolean;\n}\n\ninterface stbvorbisType {\n decode: (buffer: Uint8Array | ArrayBuffer) => DecodedData;\n isInitialized: Promise<boolean>;\n}\n\nconst stb: stbvorbisType = stbvorbis as stbvorbisType;\n\nexport { stb as stbvorbis };\n","/**\n * Unit_converter.ts\n * purpose: converts soundfont units into more usable values with the use of lookup tables to improve performance\n */\n\n// Timecent lookup table\nconst MIN_TIMECENT = -15000;\nconst MAX_TIMECENT = 15000;\nconst timecentLookupTable = new Float32Array(MAX_TIMECENT - MIN_TIMECENT + 1);\nfor (let i = 0; i < timecentLookupTable.length; i++) {\n const timecents = MIN_TIMECENT + i;\n timecentLookupTable[i] = Math.pow(2, timecents / 1200);\n}\n\n/**\n * Converts timecents to seconds.\n * @param timecents The timecents value.\n * @returns The time in seconds.\n */\nexport function timecentsToSeconds(timecents: number): number {\n if (timecents <= -32767) {\n return 0;\n }\n return timecentLookupTable[timecents - MIN_TIMECENT];\n}\n\n// Abs cent lookup table\nconst MIN_ABS_CENT = -20000; // FreqVibLfo\nconst MAX_ABS_CENT = 16500; // FilterFc\nconst absoluteCentLookupTable = new Float32Array(\n MAX_ABS_CENT - MIN_ABS_CENT + 1\n);\nfor (let i = 0; i < absoluteCentLookupTable.length; i++) {\n const absoluteCents = MIN_ABS_CENT + i;\n absoluteCentLookupTable[i] =\n 440 * Math.pow(2, (absoluteCents - 6900) / 1200);\n}\n\n/**\n * Converts absolute cents to frequency in Hz.\n * @param cents The absolute cents value.\n * @returns The frequency in Hz.\n */\nexport function absCentsToHz(cents: number): number {\n if (cents < MIN_ABS_CENT || cents > MAX_ABS_CENT) {\n return 440 * Math.pow(2, (cents - 6900) / 1200);\n }\n return absoluteCentLookupTable[~~cents - MIN_ABS_CENT];\n}\n\n// Decibel lookup table (2 points of precision)\nconst MIN_DECIBELS = -1660;\nconst MAX_DECIBELS = 1600;\nconst decibelLookUpTable = new Float32Array(\n (MAX_DECIBELS - MIN_DECIBELS) * 100 + 1\n);\nfor (let i = 0; i < decibelLookUpTable.length; i++) {\n const decibels = (MIN_DECIBELS * 100 + i) / 100;\n decibelLookUpTable[i] = Math.pow(10, -decibels / 20);\n}\n\n/**\n * Converts decibel attenuation to gain.\n * @param decibels The decibel value.\n * @return The gain value.\n */\nexport function decibelAttenuationToGain(decibels: number): number {\n return decibelLookUpTable[Math.floor((decibels - MIN_DECIBELS) * 100)];\n}\n","import { decibelAttenuationToGain, timecentsToSeconds } from \"../unit_converter\";\nimport type { Voice } from \"../voice\";\nimport { generatorTypes } from \"../../../../soundbank/basic_soundbank/generator_types\";\n\n/**\n * Volume_envelope.ts\n * purpose: applies a volume envelope for a given voice\n */\n\nexport const VOLUME_ENVELOPE_SMOOTHING_FACTOR = 0.01;\n\nconst DB_SILENCE = 100;\nconst PERCEIVED_DB_SILENCE = 90;\n// Around 96 dB of attenuation\nconst PERCEIVED_GAIN_SILENCE = 0.000015; // Can't go lower than that (see #50)\n\n/**\n * VOL ENV STATES:\n * 0 - delay\n * 1 - attack\n * 2 - hold/peak\n * 3 - decay\n * 4 - sustain\n * release indicates by isInRelease property\n */\ntype VolumeEnvelopeState = 0 | 1 | 2 | 3 | 4;\n\nexport class VolumeEnvelope {\n /**\n * The sample rate in Hz.\n */\n public sampleRate: number;\n /**\n * The current attenuation of the envelope in dB.\n */\n public currentAttenuationDb: number = DB_SILENCE;\n /**\n * The current stage of the volume envelope.\n */\n public state: VolumeEnvelopeState = 0;\n /**\n * The voice's absolute attenuation as linear gain.\n */\n public attenuation = 0;\n /**\n * The attenuation target, which the \"attenuation\" property is linearly interpolated towards (gain).\n */\n public attenuationTargetGain = 0;\n /**\n * The envelope's current time in samples.\n */\n protected currentSampleTime = 0;\n /**\n * The dB attenuation of the envelope when it entered the release stage.\n */\n protected releaseStartDb: number = DB_SILENCE;\n /**\n * The time in samples relative to the start of the envelope.\n */\n protected releaseStartTimeSamples = 0;\n /**\n * The current gain applied to the voice in the release stage.\n */\n protected currentReleaseGain = 1;\n /**\n * The attack duration in samples.\n */\n protected attackDuration = 0;\n /**\n * The decay duration in samples.\n */\n protected decayDuration = 0;\n /**\n * The release duration in samples.\n */\n protected releaseDuration = 0;\n /**\n * The attenuation target, which the \"attenuation\" property is linearly interpolated towards (dB).\n */\n protected attenuationTarget = 0;\n /**\n * The voice's sustain amount in dB, relative to attenuation.\n */\n protected sustainDbRelative = 0;\n /**\n * The time in samples to the end of delay stage, relative to the start of the envelope.\n */\n protected delayEnd = 0;\n /**\n * The time in samples to the end of attack stage, relative to the start of the envelope.\n */\n protected attackEnd = 0;\n /**\n * The time in samples to the end of hold stage, relative to the start of the envelope.\n */\n protected holdEnd = 0;\n /**\n * The time in samples to the end of decay stage, relative to the start of the envelope.\n */\n protected decayEnd = 0;\n\n /**\n * If sustain stage is silent,\n * then we can turn off the voice when it is silent.\n * We can't do that with modulated as it can silence the volume and then raise it again, and the voice must keep playing.\n */\n protected canEndOnSilentSustain: boolean;\n\n /**\n * @param sampleRate Hz\n * @param initialDecay cb\n */\n public constructor(sampleRate: number, initialDecay: number) {\n this.sampleRate = sampleRate;\n this.canEndOnSilentSustain = initialDecay / 10 >= PERCEIVED_DB_SILENCE;\n }\n\n /**\n * Starts the release phase in the envelope.\n * @param voice the voice this envelope belongs to.\n */\n public static startRelease(voice: Voice) {\n voice.volumeEnvelope.releaseStartTimeSamples =\n voice.volumeEnvelope.currentSampleTime;\n voice.volumeEnvelope.currentReleaseGain = decibelAttenuationToGain(\n voice.volumeEnvelope.currentAttenuationDb\n );\n VolumeEnvelope.recalculate(voice);\n }\n\n /**\n * Recalculates the envelope\n * @param voice the voice this envelope belongs to\n */\n public static recalculate(voice: Voice) {\n const env = voice.volumeEnvelope;\n const timecentsToSamples = (tc: number) => {\n return Math.max(\n 0,\n Math.floor(timecentsToSeconds(tc) * env.sampleRate)\n );\n };\n // Calculate absolute times (they can change so we have to recalculate every time\n env.attenuationTarget =\n Math.max(\n 0,\n Math.min(\n voice.modulatedGenerators[\n generatorTypes.initialAttenuation\n ],\n 1440\n )\n ) / 10; // Divide by ten to get decibels\n env.attenuationTargetGain = decibelAttenuationToGain(\n env.attenuationTarget\n );\n env.sustainDbRelative = Math.min(\n DB_SILENCE,\n voice.modulatedGenerators[generatorTypes.sustainVolEnv] / 10\n );\n const sustainDb = Math.min(DB_SILENCE, env.sustainDbRelative);\n\n // Calculate durations\n env.attackDuration = timecentsToSamples(\n voice.modulatedGenerators[generatorTypes.attackVolEnv]\n );\n\n // Decay: sf spec page 35: the time is for change from attenuation to -100dB,\n // Therefore, we need to calculate the real time\n // (changing from attenuation to sustain instead of -100dB)\n const fullChange =\n voice.modulatedGenerators[generatorTypes.decayVolEnv];\n const keyNumAddition =\n (60 - voice.targetKey) *\n voice.modulatedGenerators[generatorTypes.keyNumToVolEnvDecay];\n const fraction = sustainDb / DB_SILENCE;\n env.decayDuration =\n timecentsToSamples(fullChange + keyNumAddition) * fraction;\n\n // Min is set to -7200 prevent clicks\n env.releaseDuration = timecentsToSamples(\n Math.max(\n -7200,\n voice.modulatedGenerators[generatorTypes.releaseVolEnv]\n )\n );\n\n // Calculate absolute end times for the values\n env.delayEnd = timecentsToSamples(\n voice.modulatedGenerators[generatorTypes.delayVolEnv]\n );\n env.attackEnd = env.attackDuration + env.delayEnd;\n\n // Make sure to take keyNumToVolEnvHold into account!\n const holdExcursion =\n (60 - voice.targetKey) *\n voice.modulatedGenerators[generatorTypes.keyNumToVolEnvHold];\n env.holdEnd =\n timecentsToSamples(\n voice.modulatedGenerators[generatorTypes.holdVolEnv] +\n holdExcursion\n ) + env.attackEnd;\n\n env.decayEnd = env.decayDuration + env.holdEnd;\n\n // If this is the first recalculation and the voice has no attack or delay time, set current db to peak\n if (env.state === 0 && env.attackEnd === 0) {\n // Env.currentAttenuationDb = env.attenuationTarget;\n env.state = 2;\n }\n\n // Check if voice is in release\n if (voice.isInRelease) {\n // No interpolation this time: force update to actual attenuation and calculate release start from there\n //Env.attenuation = Math.min(DB_SILENCE, env.attenuationTarget);\n const sustainDb = Math.max(\n 0,\n Math.min(DB_SILENCE, env.sustainDbRelative)\n );\n const fraction = sustainDb / DB_SILENCE;\n env.decayDuration =\n timecentsToSamples(fullChange + keyNumAddition) * fraction;\n\n switch (env.state) {\n case 0:\n env.releaseStartDb = DB_SILENCE;\n break;\n\n case 1: {\n // Attack phase: get linear gain of the attack phase when release started\n // And turn it into db as we're ramping the db up linearly\n // (to make volume go down exponentially)\n // Attack is linear (in gain) so we need to do get db from that\n const elapsed =\n 1 -\n (env.attackEnd - env.releaseStartTimeSamples) /\n env.attackDuration;\n // Calculate the gain that the attack would have, so\n // Turn that into db\n env.releaseStartDb = 20 * Math.log10(elapsed) * -1;\n break;\n }\n\n case 2:\n env.releaseStartDb = 0;\n break;\n\n case 3:\n env.releaseStartDb =\n (1 -\n (env.decayEnd - env.releaseStartTimeSamples) /\n env.decayDuration) *\n sustainDb;\n break;\n\n case 4:\n env.releaseStartDb = sustainDb;\n break;\n }\n env.releaseStartDb = Math.max(\n 0,\n Math.min(env.releaseStartDb, DB_SILENCE)\n );\n if (env.releaseStartDb >= PERCEIVED_DB_SILENCE) {\n voice.finished = true;\n }\n env.currentReleaseGain = decibelAttenuationToGain(\n env.releaseStartDb\n );\n\n // Release: sf spec page 35: the time is for change from attenuation to -100dB,\n // Therefore, we need to calculate the real time\n // (changing from release start to -100dB instead of from peak to -100dB)\n const releaseFraction =\n (DB_SILENCE - env.releaseStartDb) / DB_SILENCE;\n env.releaseDuration *= releaseFraction;\n }\n }\n\n /**\n * Applies volume envelope gain to the given output buffer.\n * Essentially we use approach of 100dB is silence, 0dB is peak, and always add attenuation to that (which is interpolated).\n * @param voice the voice we're working on\n * @param audioBuffer the audio buffer to modify\n * @param centibelOffset the centibel offset of volume, for modLFOtoVolume\n * @param smoothingFactor the adjusted smoothing factor for the envelope\n */\n public static apply(\n voice: Voice,\n audioBuffer: Float32Array,\n centibelOffset: number,\n smoothingFactor: number\n ) {\n const env = voice.volumeEnvelope;\n const decibelOffset = centibelOffset / 10;\n\n const attenuationSmoothing = smoothingFactor;\n\n // RELEASE PHASE\n if (voice.isInRelease) {\n let elapsedRelease =\n env.currentSampleTime - env.releaseStartTimeSamples;\n if (elapsedRelease >= env.releaseDuration) {\n for (let i = 0; i < audioBuffer.length; i++) {\n audioBuffer[i] = 0;\n }\n voice.finished = true;\n return;\n }\n const dbDifference = DB_SILENCE - env.releaseStartDb;\n for (let i = 0; i < audioBuffer.length; i++) {\n // Attenuation interpolation\n env.attenuation +=\n (env.attenuationTargetGain - env.attenuation) *\n attenuationSmoothing;\n const db =\n (elapsedRelease / env.releaseDuration) * dbDifference +\n env.releaseStartDb;\n env.currentReleaseGain =\n env.attenuation *\n decibelAttenuationToGain(db + decibelOffset);\n audioBuffer[i] *= env.currentReleaseGain;\n env.currentSampleTime++;\n elapsedRelease++;\n }\n\n if (env.currentReleaseGain <= PERCEIVED_GAIN_SILENCE) {\n voice.finished = true;\n }\n return;\n }\n\n let filledBuffer = 0;\n switch (env.state) {\n case 0:\n // Delay phase, no sound is produced\n while (env.currentSampleTime < env.delayEnd) {\n env.currentAttenuationDb = DB_SILENCE;\n audioBuffer[filledBuffer] = 0;\n\n env.currentSampleTime++;\n if (++filledBuffer >= audioBuffer.length) {\n return;\n }\n }\n env.state++;\n // Fallthrough\n\n case 1:\n // Attack phase: ramp from 0 to attenuation\n while (env.currentSampleTime < env.attackEnd) {\n // Attenuation interpolation\n env.attenuation +=\n (env.attenuationTargetGain - env.attenuation) *\n attenuationSmoothing;\n\n // Special case: linear gain ramp instead of linear db ramp\n const linearAttenuation =\n 1 -\n (env.attackEnd - env.currentSampleTime) /\n env.attackDuration; // 0 to 1\n audioBuffer[filledBuffer] *=\n linearAttenuation *\n env.attenuation *\n decibelAttenuationToGain(decibelOffset);\n // Set current attenuation to peak as its invalid during this phase\n env.currentAttenuationDb = 0;\n\n env.currentSampleTime++;\n if (++filledBuffer >= audioBuffer.length) {\n return;\n }\n }\n env.state++;\n // Fallthrough\n\n case 2:\n // Hold/peak phase: stay at attenuation\n while (env.currentSampleTime < env.holdEnd) {\n // Attenuation interpolation\n env.attenuation +=\n (env.attenuationTargetGain - env.attenuation) *\n attenuationSmoothing;\n\n audioBuffer[filledBuffer] *=\n env.attenuation *\n decibelAttenuationToGain(decibelOffset);\n env.currentAttenuationDb = 0;\n\n env.currentSampleTime++;\n if (++filledBuffer >= audioBuffer.length) {\n return;\n }\n }\n env.state++;\n // Fallthrough\n\n case 3:\n // Decay phase: linear ramp from attenuation to sustain\n while (env.currentSampleTime < env.decayEnd) {\n // Attenuation interpolation\n env.attenuation +=\n (env.attenuationTargetGain - env.attenuation) *\n attenuationSmoothing;\n\n env.currentAttenuationDb =\n (1 -\n (env.decayEnd - env.currentSampleTime) /\n env.decayDuration) *\n env.sustainDbRelative;\n audioBuffer[filledBuffer] *=\n env.attenuation *\n decibelAttenuationToGain(\n env.currentAttenuationDb + decibelOffset\n );\n\n env.currentSampleTime++;\n if (++filledBuffer >= audioBuffer.length) {\n return;\n }\n }\n env.state++;\n // Fallthrough\n\n case 4:\n if (\n env.canEndOnSilentSustain &&\n env.sustainDbRelative >= PERCEIVED_DB_SILENCE\n ) {\n voice.finished = true;\n }\n // Sustain phase: stay at sustain\n while (true) {\n // Attenuation interpolation\n env.attenuation +=\n (env.attenuationTargetGain - env.attenuation) *\n attenuationSmoothing;\n\n audioBuffer[filledBuffer] *=\n env.attenuation *\n decibelAttenuationToGain(\n env.sustainDbRelative + decibelOffset\n );\n env.currentAttenuationDb = env.sustainDbRelative;\n env.currentSampleTime++;\n if (++filledBuffer >= audioBuffer.length) {\n return;\n }\n }\n }\n }\n}\n","import { SpessaSynthProcessor } from \"../../../processor\";\nimport type { MasterParameterChangeCallback, MasterParameterType } from \"../../../types\";\n\n/**\n * Sets a master parameter of the synthesizer.\n * @param parameter The type of the master parameter to set.\n * @param value The value to set for the master parameter.\n */\nexport function setMasterParameterInternal<P extends keyof MasterParameterType>(\n this: SpessaSynthProcessor,\n parameter: P,\n value: MasterParameterType[P]\n) {\n this.privateProps.masterParameters[parameter] = value;\n // Additional handling for specific parameters\n switch (parameter) {\n case \"masterPan\": {\n let pan = value as number;\n // Clamp to 0-1 (0 is left)\n pan = pan / 2 + 0.5;\n this.privateProps.panLeft = 1 - pan;\n this.privateProps.panRight = pan;\n break;\n }\n\n case \"masterGain\":\n break;\n\n case \"voiceCap\":\n break;\n\n case \"interpolationType\":\n break;\n\n case \"midiSystem\":\n break;\n\n case \"monophonicRetriggerMode\":\n break;\n\n case \"transposition\": {\n const semitones = value as number;\n // Reset transposition temporarily\n this.privateProps.masterParameters.transposition = 0;\n for (const item of this.midiChannels) {\n item.transposeChannel(semitones);\n }\n this.privateProps.masterParameters.transposition = semitones;\n }\n }\n this.callEvent(\"masterParameterChange\", {\n parameter,\n value\n } as MasterParameterChangeCallback);\n}\n\n/**\n * Gets a master parameter of the synthesizer.\n * @param type The type of the master parameter to get.\n * @returns The value of the master parameter.\n */\nexport function getMasterParameterInternal<P extends keyof MasterParameterType>(\n this: SpessaSynthProcessor,\n type: P\n): MasterParameterType[P] {\n return this.privateProps.masterParameters[type];\n}\n\n/**\n * Gets all master parameters of the synthesizer.\n * @returns All the master parameters.\n */\nexport function getAllMasterParametersInternal(\n this: SpessaSynthProcessor\n): MasterParameterType {\n return { ...this.privateProps.masterParameters };\n}\n","/**\n * Converts a given bit to boolean.\n * @param num The input number.\n * @param bit The index of the bit to convert into bool.\n */\nexport function bitMaskToBool(num: number, bit: number) {\n return ((num >> bit) & 1) > 0;\n}\n\nexport function toNumericBool(bool: boolean) {\n return bool ? 1 : 0;\n}\n","/**\n * Modulator_curves.ts\n * precomputes modulator concave and convex curves and calculates a curve value for a given polarity, direction and type\n */\nimport {\n type ModulatorCurveType,\n modulatorCurveTypes\n} from \"../../../soundbank/enums\";\n\n// The length of the precomputed curve tables\nexport const MODULATOR_RESOLUTION = 16384;\n\nexport const MOD_CURVE_TYPES_AMOUNT = Object.keys(modulatorCurveTypes).length;\n/**\n * Unipolar positive\n * unipolar negative\n * bipolar positive\n * bipolar negative\n * that's 4\n */\nexport const MOD_SOURCE_TRANSFORM_POSSIBILITIES = 4;\n\n// Precalculate lookup tables for concave and convex curves\nconst concave = new Float32Array(MODULATOR_RESOLUTION + 1);\nconst convex = new Float32Array(MODULATOR_RESOLUTION + 1);\n// The equation is taken from FluidSynth as it's the standard for soundFonts\n// More precisely, the gen_conv.c file\nconcave[0] = 0;\nconcave[concave.length - 1] = 1;\n\nconvex[0] = 0;\nconvex[convex.length - 1] = 1;\nfor (let i = 1; i < MODULATOR_RESOLUTION - 1; i++) {\n const x =\n (((-200 * 2) / 960) * Math.log(i / (concave.length - 1))) / Math.LN10;\n convex[i] = 1 - x;\n concave[concave.length - 1 - i] = x;\n}\n\n/**\n * Transforms a value with a given curve type\n * @param transformType the bipolar and negative flags as a 2-bit number: 0bPD (polarity MSB, direction LSB)\n * @param curveType enumeration of curve types\n * @param value the linear value, 0 to 1\n * @returns the transformed value, 0 to 1, or -1 to 1\n */\nexport function getModulatorCurveValue(\n transformType: number,\n curveType: ModulatorCurveType,\n value: number\n): number {\n const isBipolar = !!(transformType & 0b10);\n const isNegative = !!(transformType & 1);\n\n // Inverse the value if needed\n if (isNegative) {\n value = 1 - value;\n }\n switch (curveType) {\n case modulatorCurveTypes.linear:\n if (isBipolar) {\n // Bipolar curve\n return value * 2 - 1;\n }\n return value;\n\n case modulatorCurveTypes.switch:\n // Switch\n value = value > 0.5 ? 1 : 0;\n if (isBipolar) {\n // Multiply\n return value * 2 - 1;\n }\n return value;\n\n case modulatorCurveTypes.concave:\n // Look up the value\n if (isBipolar) {\n value = value * 2 - 1;\n if (value < 0) {\n return -concave[~~(value * -MODULATOR_RESOLUTION)];\n }\n return concave[~~(value * MODULATOR_RESOLUTION)];\n }\n return concave[~~(value * MODULATOR_RESOLUTION)];\n\n case modulatorCurveTypes.convex:\n // Look up the value\n if (isBipolar) {\n value = value * 2 - 1;\n if (value < 0) {\n return -convex[~~(value * -MODULATOR_RESOLUTION)];\n }\n return convex[~~(value * MODULATOR_RESOLUTION)];\n }\n return convex[~~(value * MODULATOR_RESOLUTION)];\n }\n}\n","import type { ModulatorSourceIndex } from \"../types\";\nimport {\n type ModulatorCurveType,\n modulatorCurveTypes,\n modulatorSources\n} from \"../enums\";\nimport {\n bitMaskToBool,\n toNumericBool\n} from \"../../utils/byte_functions/bit_mask\";\nimport {\n getModulatorCurveValue,\n MOD_CURVE_TYPES_AMOUNT,\n MOD_SOURCE_TRANSFORM_POSSIBILITIES,\n MODULATOR_RESOLUTION\n} from \"../../synthesizer/audio_engine/engine_components/modulator_curves\";\nimport type { Voice } from \"../../synthesizer/audio_engine/engine_components/voice\";\nimport { NON_CC_INDEX_OFFSET } from \"../../synthesizer/audio_engine/engine_components/controller_tables\";\nimport { midiControllers } from \"../../midi/enums\";\n\nexport class ModulatorSource {\n /**\n * If this field is set to false, the controller should be mapped with a minimum value of 0 and a maximum value of 1. This is also\n * called Unipolar. Thus, it behaves similar to the Modulation Wheel controller of the MIDI specification.\n *\n * If this field is set to true, the controller sound be mapped with a minimum value of -1 and a maximum value of 1. This is also\n * called Bipolar. Thus, it behaves similar to the Pitch Wheel controller of the MIDI specification.\n */\n public isBipolar;\n /**\n * If this field is set true, the direction of the controller should be from the maximum value to the minimum value. So, for\n * example, if the controller source is Key Number, then a Key Number value of 0 corresponds to the maximum possible\n * controller output, and the Key Number value of 127 corresponds to the minimum possible controller input.\n */\n public isNegative;\n\n /**\n * The index of the source.\n * It can point to one of the MIDI controllers or one of the predefined sources, depending on the 'isCC' flag.\n */\n public index: ModulatorSourceIndex;\n\n /**\n * If this field is set to true, the MIDI Controller Palette is selected. The ‘index’ field value corresponds to one of the 128\n * MIDI Continuous Controller messages as defined in the MIDI specification.\n */\n public isCC;\n\n /**\n * This field specifies how the minimum value approaches the maximum value.\n */\n public curveType: ModulatorCurveType;\n\n public constructor(\n index: ModulatorSourceIndex = modulatorSources.noController,\n curveType: ModulatorCurveType = modulatorCurveTypes.linear,\n isCC = false,\n isBipolar = false,\n isNegative = false\n ) {\n this.isBipolar = isBipolar;\n this.isNegative = isNegative;\n this.index = index;\n this.isCC = isCC;\n this.curveType = curveType;\n }\n\n private get sourceName() {\n return this.isCC\n ? (Object.keys(midiControllers).find(\n (k) =>\n midiControllers[k as keyof typeof midiControllers] ===\n this.index\n ) ?? this.index.toString())\n : (Object.keys(modulatorSources).find(\n (k) =>\n modulatorSources[k as keyof typeof modulatorSources] ===\n this.index\n ) ?? this.index.toString());\n }\n\n private get curveTypeName() {\n return (\n Object.keys(modulatorCurveTypes).find(\n (k) =>\n modulatorCurveTypes[\n k as keyof typeof modulatorCurveTypes\n ] === this.curveType\n ) ?? this.curveType.toString()\n );\n }\n\n public static fromSourceEnum(sourceEnum: number) {\n const isBipolar = bitMaskToBool(sourceEnum, 9);\n const isNegative = bitMaskToBool(sourceEnum, 8);\n const isCC = bitMaskToBool(sourceEnum, 7);\n const index = (sourceEnum & 127) as ModulatorSourceIndex;\n const curveType = ((sourceEnum >> 10) & 0x3) as ModulatorCurveType;\n return new ModulatorSource(\n index,\n curveType,\n isCC,\n isBipolar,\n isNegative\n );\n }\n\n /**\n * Copies the modulator source.\n * @param source The source to copy from.\n * @returns the copied source.\n */\n public static copyFrom(source: ModulatorSource) {\n return new ModulatorSource(\n source.index,\n source.curveType,\n source.isCC,\n source.isBipolar,\n source.isNegative\n );\n }\n\n public toString() {\n return `${this.sourceName} ${this.curveTypeName} ${this.isBipolar ? \"bipolar\" : \"unipolar\"} ${this.isNegative ? \"negative\" : \"positive\"}`;\n }\n\n public toSourceEnum() {\n return (\n (this.curveType << 10) |\n (toNumericBool(this.isBipolar) << 9) |\n (toNumericBool(this.isNegative) << 8) |\n (toNumericBool(this.isCC) << 7) |\n this.index\n );\n }\n\n public isIdentical(source: ModulatorSource) {\n return (\n this.index === source.index &&\n this.isNegative === source.isNegative &&\n this.isCC === source.isCC &&\n this.isBipolar === source.isBipolar &&\n this.curveType === source.curveType\n );\n }\n\n /**\n * Gets the current value from this source.\n * @param midiControllers The MIDI controller + modulator source array.\n * @param voice The voice to get the data for.\n */\n public getValue(midiControllers: Int16Array, voice: Voice) {\n // The raw 14-bit value (0 - 16,383)\n let rawValue;\n if (this.isCC) {\n rawValue = midiControllers[this.index];\n } else {\n switch (this.index) {\n case modulatorSources.noController:\n rawValue = 16383; // Equals to 1\n break;\n\n case modulatorSources.noteOnKeyNum:\n rawValue = voice.midiNote << 7;\n break;\n\n case modulatorSources.noteOnVelocity:\n rawValue = voice.velocity << 7;\n break;\n\n case modulatorSources.polyPressure:\n rawValue = voice.pressure << 7;\n break;\n\n default:\n rawValue =\n midiControllers[this.index + NON_CC_INDEX_OFFSET]; // Pitch wheel and range are stored in the cc table\n break;\n }\n }\n\n // Transform the value\n // 2-bit number as in 0bPD\n const transformType =\n (this.isBipolar ? 0b10 : 0b00) | (this.isNegative ? 1 : 0);\n\n return precomputedTransforms[\n MODULATOR_RESOLUTION *\n (this.curveType * MOD_CURVE_TYPES_AMOUNT + transformType) +\n rawValue\n ];\n }\n}\n\n/**\n * To get the value, you do\n * MODULATOR_RESOLUTION * (MOD_CURVE_TYPES_AMOUNT * curveType + transformType) + your raw value as 14-bit number (0 - 16,383)\n */\nconst precomputedTransforms = new Float32Array(\n MODULATOR_RESOLUTION *\n MOD_SOURCE_TRANSFORM_POSSIBILITIES *\n MOD_CURVE_TYPES_AMOUNT\n);\n\nfor (let curveType = 0; curveType < MOD_CURVE_TYPES_AMOUNT; curveType++) {\n for (\n let transformType = 0;\n transformType < MOD_SOURCE_TRANSFORM_POSSIBILITIES;\n transformType++\n ) {\n const tableIndex =\n MODULATOR_RESOLUTION *\n (curveType * MOD_CURVE_TYPES_AMOUNT + transformType);\n for (let value = 0; value < MODULATOR_RESOLUTION; value++) {\n precomputedTransforms[tableIndex + value] = getModulatorCurveValue(\n transformType,\n curveType as ModulatorCurveType,\n value / MODULATOR_RESOLUTION\n );\n }\n }\n}\n","import { type GeneratorType, generatorTypes, MAX_GENERATOR } from \"./generator_types\";\nimport type { ModulatorSourceIndex } from \"../types\";\nimport { type ModulatorCurveType, modulatorCurveTypes, modulatorSources, type ModulatorTransformType } from \"../enums\";\nimport { midiControllers } from \"../../midi/enums\";\nimport { writeWord } from \"../../utils/byte_functions/little_endian\";\nimport type { IndexedByteArray } from \"../../utils/indexed_array\";\nimport { ModulatorSource } from \"./modulator_source\";\nimport type { SoundFontWriteIndexes } from \"../soundfont/write/types\";\n\n/**\n * Modulators.ts\n * purpose: parses soundfont modulators and the source enums, also includes the default modulators list\n **/\n\nexport const MOD_BYTE_SIZE = 10;\n\nexport function getModSourceEnum(\n curveType: ModulatorCurveType,\n isBipolar: boolean,\n isNegative: boolean,\n isCC: boolean,\n index: ModulatorSourceIndex\n): number {\n return new ModulatorSource(\n index,\n curveType,\n isCC,\n isBipolar,\n isNegative\n ).toSourceEnum();\n}\n\nconst defaultResonantModSource = getModSourceEnum(\n modulatorCurveTypes.linear,\n true,\n false,\n true,\n midiControllers.filterResonance\n); // Linear forwards bipolar cc 74\n\nexport class Modulator {\n /**\n * The current computed value of this modulator. Only used in the synthesis engine for local voices.\n */\n public currentValue = 0;\n\n /**\n * The generator destination of this modulator.\n */\n public destination: GeneratorType = generatorTypes.initialAttenuation;\n\n /**\n * The transform amount for this modulator.\n */\n public transformAmount = 0;\n\n /**\n * The transform type for this modulator.\n */\n public transformType: ModulatorTransformType = 0;\n\n /**\n * Indicates if the given modulator is chorus or reverb effects modulator.\n * This is done to simulate BASSMIDI effects behavior:\n * - defaults to 1000 transform amount rather than 200\n * - values can be changed, but anything above 200 is 1000\n * (except for values above 1000, they are copied directly)\n * - all values below are multiplied by 5 (200 * 5 = 1000)\n * - still can be disabled if the soundfont has its own modulator curve\n * - this fixes the very low amount of reverb by default and doesn't break soundfonts\n */\n public readonly isEffectModulator: boolean = false;\n\n /**\n * The default resonant modulator does not affect the filter gain.\n * Neither XG nor GS responded to cc #74 in that way.\n */\n public readonly isDefaultResonantModulator: boolean = false;\n\n /**\n * The primary source of this modulator.\n */\n public readonly primarySource: ModulatorSource;\n\n /**\n * The secondary source of this modulator.\n */\n public readonly secondarySource: ModulatorSource;\n\n /**\n * Creates a new SF2 Modulator\n */\n public constructor(\n primarySource = new ModulatorSource(),\n secondarySource = new ModulatorSource(),\n destination: GeneratorType = generatorTypes.INVALID,\n amount = 0,\n transformType: ModulatorTransformType = 0,\n isEffectModulator = false,\n isDefaultResonantModulator = false\n ) {\n this.primarySource = primarySource;\n this.secondarySource = secondarySource;\n\n this.destination = destination;\n this.transformAmount = amount;\n this.transformType = transformType;\n this.isEffectModulator = isEffectModulator;\n this.isDefaultResonantModulator = isDefaultResonantModulator;\n }\n\n private get destinationName() {\n return Object.keys(generatorTypes).find(\n (k) =>\n generatorTypes[k as keyof typeof generatorTypes] ===\n this.destination\n );\n }\n\n /**\n * Checks if the pair of modulators is identical (in SF2 terms)\n * @param mod1 modulator 1\n * @param mod2 modulator 2\n * @param checkAmount if the amount should be checked too.\n * @returns if they are identical\n */\n public static isIdentical(\n mod1: Modulator,\n mod2: Modulator,\n checkAmount = false\n ): boolean {\n return (\n mod1.primarySource.isIdentical(mod2.primarySource) &&\n mod1.secondarySource.isIdentical(mod2.secondarySource) &&\n mod1.destination === mod2.destination &&\n mod1.transformType === mod2.transformType &&\n (!checkAmount || mod1.transformAmount === mod2.transformAmount)\n );\n }\n\n /**\n * Copies a modulator.\n * @param mod The modulator to copy.\n * @returns The copied modulator.\n */\n public static copyFrom(mod: Modulator) {\n return new Modulator(\n ModulatorSource.copyFrom(mod.primarySource),\n ModulatorSource.copyFrom(mod.secondarySource),\n mod.destination,\n mod.transformAmount,\n mod.transformType,\n mod.isEffectModulator,\n mod.isDefaultResonantModulator\n );\n }\n\n public toString() {\n return (\n `Source: ${this.primarySource.toString()}\\n` +\n `Secondary source: ${this.secondarySource.toString()}\\n` +\n `to: ${this.destinationName}\\n` +\n `amount: ${this.transformAmount}` +\n (this.transformType === 2 ? \"absolute value\" : \"\")\n );\n }\n\n public write(modData: IndexedByteArray, indexes?: SoundFontWriteIndexes) {\n writeWord(modData, this.primarySource.toSourceEnum());\n writeWord(modData, this.destination);\n writeWord(modData, this.transformAmount);\n writeWord(modData, this.secondarySource.toSourceEnum());\n writeWord(modData, this.transformType);\n if (!indexes) {\n return;\n }\n indexes.mod++;\n }\n\n /**\n * Sums transform and create a NEW modulator\n * @param modulator the modulator to sum with\n * @returns the new modulator\n */\n public sumTransform(modulator: Modulator): Modulator {\n const m = Modulator.copyFrom(this);\n m.transformAmount += modulator.transformAmount;\n return m;\n }\n}\n\nexport class DecodedModulator extends Modulator {\n /**\n * Reads an SF2 modulator\n * @param sourceEnum SF2 source enum\n * @param secondarySourceEnum SF2 secondary source enum\n * @param destination destination\n * @param amount amount\n * @param transformType transform type\n */\n public constructor(\n sourceEnum: number,\n secondarySourceEnum: number,\n destination: GeneratorType,\n amount: number,\n transformType: number\n ) {\n const isEffectModulator =\n (sourceEnum === 0x00db || sourceEnum === 0x00dd) &&\n secondarySourceEnum === 0x0 &&\n (destination === generatorTypes.reverbEffectsSend ||\n destination === generatorTypes.chorusEffectsSend);\n\n const isDefaultResonantModulator =\n sourceEnum === defaultResonantModSource &&\n secondarySourceEnum === 0x0 &&\n destination === generatorTypes.initialFilterQ;\n\n super(\n ModulatorSource.fromSourceEnum(sourceEnum),\n ModulatorSource.fromSourceEnum(secondarySourceEnum),\n destination,\n amount,\n transformType as ModulatorTransformType,\n isEffectModulator,\n isDefaultResonantModulator\n );\n\n if (this.destination > MAX_GENERATOR) {\n this.destination = generatorTypes.INVALID; // Flag as invalid (for linked ones)\n }\n }\n}\n\nexport const DEFAULT_ATTENUATION_MOD_AMOUNT = 960;\nexport const DEFAULT_ATTENUATION_MOD_CURVE_TYPE = modulatorCurveTypes.concave;\n\nconst defaultSoundFont2Modulators = [\n // Vel to attenuation\n new DecodedModulator(\n getModSourceEnum(\n DEFAULT_ATTENUATION_MOD_CURVE_TYPE,\n false,\n true,\n false,\n modulatorSources.noteOnVelocity\n ),\n 0x0,\n generatorTypes.initialAttenuation,\n DEFAULT_ATTENUATION_MOD_AMOUNT,\n 0\n ),\n\n // Mod wheel to vibrato\n new DecodedModulator(0x0081, 0x0, generatorTypes.vibLfoToPitch, 50, 0),\n\n // Vol to attenuation\n new DecodedModulator(\n getModSourceEnum(\n DEFAULT_ATTENUATION_MOD_CURVE_TYPE,\n false,\n true,\n true,\n midiControllers.mainVolume\n ),\n 0x0,\n generatorTypes.initialAttenuation,\n DEFAULT_ATTENUATION_MOD_AMOUNT,\n 0\n ),\n\n // Channel pressure to vibrato\n new DecodedModulator(0x000d, 0x0, generatorTypes.vibLfoToPitch, 50, 0),\n\n // Pitch wheel to tuning\n new DecodedModulator(0x020e, 0x0010, generatorTypes.fineTune, 12700, 0),\n\n // Pan to uhh, pan\n // Amount is 500 instead of 1000, see #59\n new DecodedModulator(0x028a, 0x0, generatorTypes.pan, 500, 0),\n\n // Expression to attenuation\n new DecodedModulator(\n getModSourceEnum(\n DEFAULT_ATTENUATION_MOD_CURVE_TYPE,\n false,\n true,\n true,\n midiControllers.expressionController\n ),\n 0x0,\n generatorTypes.initialAttenuation,\n DEFAULT_ATTENUATION_MOD_AMOUNT,\n 0\n ),\n\n // Reverb effects to send\n new DecodedModulator(0x00db, 0x0, generatorTypes.reverbEffectsSend, 200, 0),\n\n // Chorus effects to send\n new DecodedModulator(0x00dd, 0x0, generatorTypes.chorusEffectsSend, 200, 0)\n];\n\nconst defaultSpessaSynthModulators = [\n // Custom modulators heck yeah\n // Poly pressure to vibrato\n new DecodedModulator(\n getModSourceEnum(\n modulatorCurveTypes.linear,\n false,\n false,\n false,\n modulatorSources.polyPressure\n ),\n 0x0,\n generatorTypes.vibLfoToPitch,\n 50,\n 0\n ),\n\n // Cc 92 (tremolo) to modLFO volume\n new DecodedModulator(\n getModSourceEnum(\n modulatorCurveTypes.linear,\n false,\n false,\n true,\n midiControllers.tremoloDepth\n ) /*Linear forward unipolar cc 92 */,\n 0x0, // No controller\n generatorTypes.modLfoToVolume,\n 24,\n 0\n ),\n\n // Cc 73 (attack time) to volEnv attack\n new DecodedModulator(\n getModSourceEnum(\n modulatorCurveTypes.convex,\n true,\n false,\n true,\n midiControllers.attackTime\n ), // Linear forward bipolar cc 72\n 0x0, // No controller\n generatorTypes.attackVolEnv,\n 6000,\n 0\n ),\n\n // Cc 72 (release time) to volEnv release\n new DecodedModulator(\n getModSourceEnum(\n modulatorCurveTypes.linear,\n true,\n false,\n true,\n midiControllers.releaseTime\n ), // Linear forward bipolar cc 72\n 0x0, // No controller\n generatorTypes.releaseVolEnv,\n 3600,\n 0\n ),\n\n // Cc 74 (brightness) to filterFc\n new DecodedModulator(\n getModSourceEnum(\n modulatorCurveTypes.linear,\n true,\n false,\n true,\n midiControllers.brightness\n ), // Linear forwards bipolar cc 74\n 0x0, // No controller\n generatorTypes.initialFilterFc,\n 6000,\n 0\n ),\n\n // Cc 71 (filter Q) to filter Q (default resonant modulator)\n new DecodedModulator(\n defaultResonantModSource,\n 0x0, // No controller\n generatorTypes.initialFilterQ,\n 250,\n 0\n )\n];\n\nexport const SPESSASYNTH_DEFAULT_MODULATORS: Modulator[] =\n defaultSoundFont2Modulators.concat(defaultSpessaSynthModulators);\n","import {\n generatorLimits,\n type GeneratorType,\n generatorTypes\n} from \"./generator_types\";\nimport type { IndexedByteArray } from \"../../utils/indexed_array\";\nimport { writeWord } from \"../../utils/byte_functions/little_endian\";\nimport type { SoundFontWriteIndexes } from \"../soundfont/write/types\";\n\nexport const GEN_BYTE_SIZE = 4;\n\nexport class Generator {\n /**\n * The generator's SF2 type.\n */\n public generatorType: GeneratorType;\n /**\n * The generator's 16-bit value.\n */\n public generatorValue = 0;\n\n /**\n * Constructs a new generator\n * @param type generator type\n * @param value generator value\n * @param validate if the limits should be validated\n */\n public constructor(type: GeneratorType, value: number, validate = true) {\n this.generatorType = type;\n if (value === undefined) {\n throw new Error(\"No value provided.\");\n }\n this.generatorValue = Math.round(value);\n if (validate) {\n const lim = generatorLimits[type];\n\n if (lim !== undefined) {\n this.generatorValue = Math.max(\n lim.min,\n Math.min(lim.max, this.generatorValue)\n );\n }\n }\n }\n\n public write(genData: IndexedByteArray, indexes: SoundFontWriteIndexes) {\n // Name is deceptive, it works on negatives\n writeWord(genData, this.generatorType);\n writeWord(genData, this.generatorValue);\n indexes.gen++;\n }\n\n public toString() {\n return `${Object.keys(generatorTypes).find((k) => generatorTypes[k as keyof typeof generatorTypes] === this.generatorType)}: ${this.generatorValue}`;\n }\n}\n\n/**\n * Generator.ts\n * purpose: contains enums for generators,\n * and their limits parses reads soundfont generators, sums them and applies limits\n */\n/**\n * Adds and clamps generators\n */\nexport function addAndClampGenerator(\n generatorType: number,\n presetGens: Generator[],\n instrumentGens: Generator[]\n) {\n const limits = generatorLimits[generatorType] || {\n min: 0,\n max: 32768,\n def: 0\n };\n const presetGen = presetGens.find((g) => g.generatorType === generatorType);\n let presetValue = 0;\n if (presetGen) {\n presetValue = presetGen.generatorValue;\n }\n\n const instrGen = instrumentGens.find(\n (g) => g.generatorType === generatorType\n );\n let instValue = limits.def;\n if (instrGen) {\n instValue = instrGen.generatorValue;\n }\n\n // Limits are applied in the compute_modulator function\n // Clamp to prevent short from overflowing\n // Testcase: Sega Genesis soundfont (spessasynth/#169) adds 20,999 and the default 13,500 to initialFilterFc\n // Which is more than 32k\n return Math.max(-32767, Math.min(32767, instValue + presetValue));\n}\n","import {\n generatorLimits,\n type GeneratorType,\n generatorTypes\n} from \"./generator_types\";\nimport { Generator } from \"./generator\";\nimport { Modulator } from \"./modulator\";\n\nimport type { GenericRange } from \"../types\";\nimport type { IndexedByteArray } from \"../../utils/indexed_array\";\nimport type {\n ExtendedSF2Chunks,\n SoundFontWriteIndexes\n} from \"../soundfont/write/types\";\nimport type { BasicSoundBank } from \"./basic_soundbank\";\nimport { writeWord } from \"../../utils/byte_functions/little_endian\";\n\nexport const BAG_BYTE_SIZE = 4;\n\nexport class BasicZone {\n /**\n * The zone's velocity range.\n * min -1 means that it is a default value\n */\n public velRange: GenericRange = { min: -1, max: 127 };\n\n /**\n * The zone's key range.\n * min -1 means that it is a default value.\n */\n public keyRange: GenericRange = { min: -1, max: 127 };\n\n /**\n * The zone's generators.\n */\n public generators: Generator[] = [];\n /**\n * The zone's modulators.\n */\n public modulators: Modulator[] = [];\n\n public get hasKeyRange(): boolean {\n return this.keyRange.min !== -1;\n }\n\n public get hasVelRange(): boolean {\n return this.velRange.min !== -1;\n }\n\n /**\n * The current tuning in cents, taking in both coarse and fine generators.\n */\n public get fineTuning() {\n const currentCoarse = this.getGenerator(generatorTypes.coarseTune, 0);\n const currentFine = this.getGenerator(generatorTypes.fineTune, 0);\n return currentCoarse * 100 + currentFine;\n }\n\n /**\n * The current tuning in cents, taking in both coarse and fine generators.\n */\n public set fineTuning(tuningCents: number) {\n const coarse = Math.trunc(tuningCents / 100);\n const fine = tuningCents % 100;\n this.setGenerator(generatorTypes.coarseTune, coarse);\n this.setGenerator(generatorTypes.fineTune, fine);\n }\n\n /**\n * Adds to a given generator, or its default value.\n */\n public addToGenerator(type: GeneratorType, value: number, validate = true) {\n const genValue = this.getGenerator(type, generatorLimits[type].def);\n this.setGenerator(type, value + genValue, validate);\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Sets a generator to a given value if preset, otherwise adds a new one.\n */\n public setGenerator(\n type: GeneratorType,\n value: number | undefined,\n validate = true\n ) {\n switch (type) {\n case generatorTypes.sampleID:\n throw new Error(\"Use setSample()\");\n case generatorTypes.instrument:\n throw new Error(\"Use setInstrument()\");\n\n case generatorTypes.velRange:\n case generatorTypes.keyRange:\n throw new Error(\"Set the range manually\");\n }\n if (value === undefined) {\n this.generators = this.generators.filter(\n (g) => g.generatorType !== type\n );\n return;\n }\n const index = this.generators.findIndex(\n (g) => g.generatorType === type\n );\n if (index > 0) {\n this.generators[index] = new Generator(type, value, validate);\n } else {\n this.addGenerators(new Generator(type, value, validate));\n }\n }\n\n /**\n * Adds generators to the zone.\n * @param generators\n */\n public addGenerators(...generators: Generator[]) {\n generators.forEach((g) => {\n switch (g.generatorType) {\n default:\n this.generators.push(g);\n break;\n\n case generatorTypes.sampleID:\n case generatorTypes.instrument:\n // Don't add these, they already have their own properties\n break;\n\n case generatorTypes.velRange:\n this.velRange.min = g.generatorValue & 0x7f;\n this.velRange.max = (g.generatorValue >> 8) & 0x7f;\n break;\n\n case generatorTypes.keyRange:\n this.keyRange.min = g.generatorValue & 0x7f;\n this.keyRange.max = (g.generatorValue >> 8) & 0x7f;\n }\n });\n }\n\n public addModulators(...modulators: Modulator[]) {\n this.modulators.push(...modulators);\n }\n\n public getGenerator<K>(\n generatorType: GeneratorType,\n notFoundValue: number | K\n ): number | K {\n return (\n this.generators.find((g) => g.generatorType === generatorType)\n ?.generatorValue ?? notFoundValue\n );\n }\n\n public copyFrom(zone: BasicZone) {\n this.generators = zone.generators.map(\n (g) => new Generator(g.generatorType, g.generatorValue, false)\n );\n this.modulators = zone.modulators.map(\n Modulator.copyFrom.bind(Modulator)\n );\n this.velRange = { ...zone.velRange };\n this.keyRange = { ...zone.keyRange };\n }\n\n public getGenCount() {\n let count = this.generators.filter(\n (g) =>\n g.generatorType !== generatorTypes.sampleID &&\n g.generatorType !== generatorTypes.instrument &&\n g.generatorType !== generatorTypes.keyRange &&\n g.generatorType !== generatorTypes.velRange\n ).length;\n if (this.hasVelRange) {\n count++;\n }\n if (this.hasKeyRange) {\n count++;\n }\n return count;\n }\n\n public write(\n genData: IndexedByteArray,\n modData: IndexedByteArray,\n bagData: ExtendedSF2Chunks,\n indexes: SoundFontWriteIndexes,\n bank: BasicSoundBank\n ) {\n const generatorIndex = indexes.gen;\n const modulatorIndex = indexes.mod;\n // Bottom WORD: regular ibag\n writeWord(bagData.pdta, generatorIndex & 0xffff);\n writeWord(bagData.pdta, modulatorIndex & 0xffff);\n // Top WORD: extended ibag\n writeWord(bagData.xdta, generatorIndex >> 16);\n writeWord(bagData.xdta, modulatorIndex >> 16);\n indexes.bag++;\n\n // Write generators and modulators\n const gens = this.getWriteGenerators(bank);\n gens.forEach((g) => g.write(genData, indexes));\n this.modulators.forEach((m) => m.write(modData, indexes));\n }\n\n /**\n * Filters the generators and prepends the range generators.\n */\n protected getWriteGenerators(bank: BasicSoundBank) {\n const generators = this.generators.filter(\n (g) =>\n g.generatorType !== generatorTypes.sampleID &&\n g.generatorType !== generatorTypes.instrument &&\n g.generatorType !== generatorTypes.keyRange &&\n g.generatorType !== generatorTypes.velRange\n );\n\n // Instrument and preset zones use this parameter!\n // So \"use\" it here to please eslint\n if (!bank) {\n throw new Error(\"No bank provided! \");\n }\n void bank;\n\n // Unshift vel then key (to make key first)\n if (this.hasVelRange) {\n generators.unshift(\n new Generator(\n generatorTypes.velRange,\n (this.velRange.max << 8) | Math.max(this.velRange.min, 0),\n false\n )\n );\n }\n if (this.hasKeyRange) {\n generators.unshift(\n new Generator(\n generatorTypes.keyRange,\n (this.keyRange.max << 8) | Math.max(this.keyRange.min, 0),\n false\n )\n );\n }\n return generators;\n }\n}\n","import { BasicZone } from \"./basic_zone\";\n\n// Represents a global zone within an instrument or a preset.\nexport class BasicGlobalZone extends BasicZone {\n // Nothing here, just a different instance...\n}\n","import { BasicZone } from \"./basic_zone\";\nimport type { BasicPreset } from \"./basic_preset\";\nimport type { BasicInstrument } from \"./basic_instrument\";\nimport type { BasicSoundBank } from \"./basic_soundbank\";\nimport { Generator } from \"./generator\";\nimport { generatorTypes } from \"./generator_types\";\n\nexport class BasicPresetZone extends BasicZone {\n /**\n * The preset this zone belongs to.\n */\n public readonly parentPreset: BasicPreset;\n\n /**\n * Creates a new preset zone.\n * @param preset the preset this zone belongs to.\n * @param instrument the instrument to use in this zone.\n */\n public constructor(preset: BasicPreset, instrument: BasicInstrument) {\n super();\n this.parentPreset = preset;\n this._instrument = instrument;\n this._instrument.linkTo(this.parentPreset);\n }\n\n /**\n * Zone's instrument.\n */\n private _instrument: BasicInstrument;\n\n /**\n * Zone's instrument.\n */\n public get instrument() {\n return this._instrument;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Zone's instrument.\n */\n public set instrument(instrument: BasicInstrument) {\n if (this._instrument) {\n this._instrument.unlinkFrom(this.parentPreset);\n }\n this._instrument = instrument;\n this._instrument.linkTo(this.parentPreset);\n }\n\n public getGenCount(): number {\n return super.getGenCount() + 1; // Instrument generator\n }\n\n public getWriteGenerators(bank: BasicSoundBank): Generator[] {\n const gens = super.getWriteGenerators(bank);\n if (!bank) {\n throw new Error(\n \"Instrument ID cannot be determined without the sound bank itself.\"\n );\n }\n gens.push(\n new Generator(\n generatorTypes.instrument,\n bank.instruments.indexOf(this.instrument),\n false\n )\n );\n return gens;\n }\n}\n","import { BasicZone } from \"./basic_zone\";\nimport type { BasicInstrument } from \"./basic_instrument\";\nimport type { BasicSample } from \"./basic_sample\";\nimport { Generator } from \"./generator\";\nimport type { BasicSoundBank } from \"./basic_soundbank\";\nimport { generatorTypes } from \"./generator_types\";\n\nexport class BasicInstrumentZone extends BasicZone {\n /**\n * The instrument this zone belongs to.\n */\n public readonly parentInstrument: BasicInstrument;\n /**\n * For tracking on the individual zone level, since multiple presets can refer to the same instrument.\n */\n public useCount: number;\n\n /**\n * Creates a new instrument zone.\n * @param instrument The parent instrument.\n * @param sample The sample to use in this zone.\n */\n public constructor(instrument: BasicInstrument, sample: BasicSample) {\n super();\n this.parentInstrument = instrument;\n this._sample = sample;\n sample.linkTo(this.parentInstrument);\n this.useCount = instrument.useCount;\n }\n\n /**\n * Zone's sample.\n */\n private _sample: BasicSample;\n\n /**\n * Zone's sample.\n */\n public get sample() {\n return this._sample;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Sets a sample for this zone.\n * @param sample the sample to set.\n */\n public set sample(sample: BasicSample) {\n if (this._sample) {\n this._sample.unlinkFrom(this.parentInstrument);\n }\n this._sample = sample;\n sample.linkTo(this.parentInstrument);\n }\n\n public getGenCount(): number {\n return super.getGenCount() + 1; // SampleID generator\n }\n\n public getWriteGenerators(bank: BasicSoundBank): Generator[] {\n const gens = super.getWriteGenerators(bank);\n gens.push(\n new Generator(\n generatorTypes.sampleID,\n bank.samples.indexOf(this.sample),\n false\n )\n );\n return gens;\n }\n}\n","import { BasicGlobalZone } from \"./basic_global_zone\";\nimport { BasicInstrumentZone } from \"./basic_instrument_zone\";\nimport { SpessaSynthInfo, SpessaSynthWarn } from \"../../utils/loggin\";\nimport { type BasicPreset } from \"./basic_preset\";\nimport type { BasicSample } from \"./basic_sample\";\nimport {\n generatorLimits,\n type GeneratorType,\n generatorTypes\n} from \"./generator_types\";\nimport { MOD_BYTE_SIZE, Modulator } from \"./modulator\";\nimport type { IndexedByteArray } from \"../../utils/indexed_array\";\nimport type {\n ExtendedSF2Chunks,\n SoundFontWriteIndexes\n} from \"../soundfont/write/types\";\nimport { writeBinaryStringIndexed } from \"../../utils/byte_functions/string\";\nimport { writeWord } from \"../../utils/byte_functions/little_endian\";\nimport type { BasicSoundBank } from \"./basic_soundbank\";\nimport { consoleColors } from \"../../utils/other\";\nimport { BAG_BYTE_SIZE } from \"./basic_zone\";\nimport { GEN_BYTE_SIZE } from \"./generator\";\n\nexport const INST_BYTE_SIZE = 22;\n\nconst notGlobalizedTypes = new Set([\n generatorTypes.velRange,\n generatorTypes.keyRange,\n generatorTypes.instrument,\n generatorTypes.sampleID,\n generatorTypes.exclusiveClass,\n generatorTypes.endOper,\n generatorTypes.sampleModes,\n generatorTypes.startloopAddrsOffset,\n generatorTypes.startloopAddrsCoarseOffset,\n generatorTypes.endloopAddrsOffset,\n generatorTypes.endloopAddrsCoarseOffset,\n generatorTypes.startAddrsOffset,\n generatorTypes.startAddrsCoarseOffset,\n generatorTypes.endAddrOffset,\n generatorTypes.endAddrsCoarseOffset,\n generatorTypes.initialAttenuation, // Written into wsmp, there's no global wsmp\n generatorTypes.fineTune, // Written into wsmp, there's no global wsmp\n generatorTypes.coarseTune, // Written into wsmp, there's no global wsmp\n generatorTypes.keyNumToVolEnvHold, // KEY TO SOMETHING:\n generatorTypes.keyNumToVolEnvDecay, // Cannot be globalized as they modify their respective generators\n generatorTypes.keyNumToModEnvHold, // (for example, keyNumToVolEnvDecay modifies VolEnvDecay)\n generatorTypes.keyNumToModEnvDecay\n] as const);\ntype notGlobalizedTypes =\n typeof notGlobalizedTypes extends Set<infer T> ? T : never;\n\n// noinspection JSUnusedGlobalSymbols\n/**\n * Represents a single instrument\n */\nexport class BasicInstrument {\n /**\n * The instrument's name\n */\n public name = \"\";\n /**\n * The instrument's zones\n */\n public zones: BasicInstrumentZone[] = [];\n /**\n * Instrument's global zone\n */\n public readonly globalZone: BasicGlobalZone = new BasicGlobalZone();\n /**\n * Instrument's linked presets (the presets that use it)\n * note that duplicates are allowed since one preset can use the same instrument multiple times.\n */\n public readonly linkedTo: BasicPreset[] = [];\n\n /**\n * How many presets is this instrument used by\n */\n public get useCount(): number {\n return this.linkedTo.length;\n }\n\n /**\n * Creates a new instrument zone and returns it.\n * @param sample The sample to use in the zone.\n */\n public createZone(sample: BasicSample): BasicInstrumentZone {\n const zone = new BasicInstrumentZone(this, sample);\n this.zones.push(zone);\n return zone;\n }\n\n /**\n * Links the instrument ta a given preset\n * @param preset the preset to link to\n */\n public linkTo(preset: BasicPreset) {\n this.linkedTo.push(preset);\n this.zones.forEach((z) => z.useCount++);\n }\n\n /**\n * Unlinks the instrument from a given preset\n * @param preset the preset to unlink from\n */\n public unlinkFrom(preset: BasicPreset) {\n const index = this.linkedTo.indexOf(preset);\n if (index < 0) {\n SpessaSynthWarn(\n `Cannot unlink ${preset.name} from ${this.name}: not linked.`\n );\n return;\n }\n this.linkedTo.splice(index, 1);\n this.zones.forEach((z) => z.useCount--);\n }\n\n // Deletes unused zones of the instrument\n public deleteUnusedZones() {\n this.zones = this.zones.filter((z) => {\n const stays = z.useCount > 0;\n if (!stays) {\n z.sample.unlinkFrom(this);\n }\n return stays;\n });\n }\n\n // Unlinks everything from this instrument\n public delete() {\n if (this.useCount > 0) {\n throw new Error(\n `Cannot delete an instrument that is used by: ${this.linkedTo.map((p) => p.name).toString()}.`\n );\n }\n this.zones.forEach((z) => z.sample.unlinkFrom(this));\n }\n\n /**\n * Deletes a given instrument zone if it has no uses\n * @param index the index of the zone to delete\n * @param force ignores the use count and deletes forcibly\n * @returns if the zone has been deleted\n */\n public deleteZone(index: number, force = false): boolean {\n const zone = this.zones[index];\n zone.useCount -= 1;\n if (zone.useCount < 1 || force) {\n zone.sample.unlinkFrom(this);\n this.zones.splice(index, 1);\n return true;\n }\n return false;\n }\n\n /**\n * Globalizes the instrument *in-place.*\n * This means trying to move as many generators and modulators\n * to the global zone as possible to reduce clutter and the count of parameters.\n */\n public globalize() {\n const globalZone = this.globalZone;\n\n // Create a global zone and add repeating generators to it\n // Also modulators\n // Iterate over every type of generator\n for (\n let checkedType: GeneratorType = 0;\n checkedType < 58;\n checkedType++\n ) {\n // Not these though\n if (notGlobalizedTypes.has(checkedType as notGlobalizedTypes)) {\n continue;\n }\n checkedType = checkedType as GeneratorType;\n let occurrencesForValues: Record<number, number> = {};\n const defaultForChecked = generatorLimits[checkedType]?.def || 0;\n occurrencesForValues[defaultForChecked] = 0;\n for (const zone of this.zones) {\n const value = zone.getGenerator(checkedType, undefined);\n if (value !== undefined) {\n if (occurrencesForValues[value] === undefined) {\n occurrencesForValues[value] = 1;\n } else {\n occurrencesForValues[value]++;\n }\n } else {\n occurrencesForValues[defaultForChecked]++;\n }\n\n // If the checked type has the keyNumTo something generator set, it cannot be globalized.\n let relativeCounterpart;\n switch (checkedType) {\n default:\n continue;\n\n case generatorTypes.decayVolEnv:\n relativeCounterpart =\n generatorTypes.keyNumToVolEnvDecay;\n break;\n case generatorTypes.holdVolEnv:\n relativeCounterpart = generatorTypes.keyNumToVolEnvHold;\n break;\n case generatorTypes.decayModEnv:\n relativeCounterpart =\n generatorTypes.keyNumToModEnvDecay;\n break;\n case generatorTypes.holdModEnv:\n relativeCounterpart = generatorTypes.keyNumToModEnvHold;\n }\n const relative = zone.getGenerator(\n relativeCounterpart,\n undefined\n );\n if (relative !== undefined) {\n occurrencesForValues = {};\n break;\n }\n }\n // If at least one occurrence, find the most used one and add it to global\n if (Object.keys(occurrencesForValues).length > 0) {\n const entries = Object.entries(occurrencesForValues);\n // [value, occurrences]\n const valueToGlobalize = entries.reduce(\n (max, curr) => {\n if (max[1] < curr[1]) {\n return curr;\n }\n return max;\n },\n [\"0\", 0]\n );\n const targetValue = parseInt(valueToGlobalize[0]);\n\n // If the global value is the default value just remove it, no need to add it\n if (targetValue !== defaultForChecked) {\n globalZone.setGenerator(checkedType, targetValue, false);\n }\n // Remove from the zones\n this.zones.forEach((z) => {\n const genValue = z.getGenerator(checkedType, undefined);\n if (genValue !== undefined) {\n if (genValue === targetValue) {\n // That exact value exists. Since it's global now, remove it\n z.setGenerator(checkedType, undefined);\n }\n } else {\n // That type does not exist at all here.\n // Since we're globalizing, we need to add the default here.\n if (targetValue !== defaultForChecked) {\n z.setGenerator(checkedType, defaultForChecked);\n }\n }\n });\n }\n }\n\n // Globalize only modulators that exist in all zones\n const firstZone = this.zones[0];\n const modulators = firstZone.modulators.map((m) =>\n Modulator.copyFrom(m)\n );\n for (const checkedModulator of modulators) {\n let existsForAllZones = true;\n for (const zone of this.zones) {\n if (!existsForAllZones) {\n continue;\n }\n // Check if that zone has an existing modulator\n const mod = zone.modulators.find((m) =>\n Modulator.isIdentical(m, checkedModulator)\n );\n if (!mod) {\n // Does not exist for this zone, so it's not global.\n existsForAllZones = false;\n }\n // Exists.\n }\n if (existsForAllZones) {\n globalZone.addModulators(Modulator.copyFrom(checkedModulator));\n // Delete it from local zones.\n for (const zone of this.zones) {\n const modulator = zone.modulators.find((m) =>\n Modulator.isIdentical(m, checkedModulator)\n );\n if (!modulator) {\n continue;\n }\n // Check if the amount is correct.\n // If so, delete it since it's global.\n // If not, then it will simply override global as it's identical.\n if (\n modulator.transformAmount ===\n checkedModulator.transformAmount\n ) {\n zone.modulators.splice(\n zone.modulators.indexOf(modulator),\n 1\n );\n }\n }\n }\n }\n }\n\n public getSize() {\n const modCount =\n this.zones.reduce(\n (count, zone) => zone.modulators.length + count,\n 0\n ) + this.globalZone.modulators.length;\n const genCount =\n this.zones.reduce((count, zone) => zone.getGenCount() + count, 0) +\n this.globalZone.getGenCount();\n return {\n mod: modCount * MOD_BYTE_SIZE,\n bag: (this.zones.length + 1) * BAG_BYTE_SIZE, // global zone\n gen: genCount * GEN_BYTE_SIZE,\n hdr: INST_BYTE_SIZE\n };\n }\n\n public write(\n genData: IndexedByteArray,\n modData: IndexedByteArray,\n bagData: ExtendedSF2Chunks,\n instData: ExtendedSF2Chunks,\n indexes: SoundFontWriteIndexes,\n bank: BasicSoundBank\n ) {\n SpessaSynthInfo(`%cWriting ${this.name}...`, consoleColors.info);\n // Split up the name\n writeBinaryStringIndexed(instData.pdta, this.name.substring(0, 20), 20);\n writeBinaryStringIndexed(instData.xdta, this.name.substring(20), 20);\n // Inst start index\n writeWord(instData.pdta, indexes.hdr & 0xffff);\n writeWord(instData.xdta, indexes.hdr >>> 16);\n indexes.hdr += this.zones.length + 1; // + global zone\n\n this.globalZone.write(genData, modData, bagData, indexes, bank);\n this.zones.forEach((z) =>\n z.write(genData, modData, bagData, indexes, bank)\n );\n }\n}\n","import { MOD_BYTE_SIZE, Modulator } from \"./modulator\";\nimport { BankSelectHacks } from \"../../utils/midi_hacks\";\n\nimport { BasicGlobalZone } from \"./basic_global_zone\";\nimport { BasicPresetZone } from \"./basic_preset_zone\";\nimport type { BasicSoundBank } from \"./basic_soundbank\";\nimport { GEN_BYTE_SIZE, Generator } from \"./generator\";\nimport type { GenericRange, VoiceSynthesisData } from \"../types\";\nimport { BasicInstrument } from \"./basic_instrument\";\nimport {\n type MIDIPatch,\n type MIDIPatchNamed,\n MIDIPatchTools\n} from \"./midi_patch\";\nimport { generatorLimits, generatorTypes } from \"./generator_types\";\nimport { BAG_BYTE_SIZE } from \"./basic_zone\";\nimport type { IndexedByteArray } from \"../../utils/indexed_array\";\nimport type {\n ExtendedSF2Chunks,\n SoundFontWriteIndexes\n} from \"../soundfont/write/types\";\nimport { SpessaSynthInfo } from \"../../utils/loggin\";\nimport { consoleColors } from \"../../utils/other\";\nimport { writeBinaryStringIndexed } from \"../../utils/byte_functions/string\";\nimport {\n writeDword,\n writeWord\n} from \"../../utils/byte_functions/little_endian\";\n\nexport const PHDR_BYTE_SIZE = 38;\n\nexport class BasicPreset implements MIDIPatchNamed {\n /**\n * The parent soundbank instance\n * Currently used for determining default modulators and XG status\n */\n public readonly parentSoundBank: BasicSoundBank;\n\n /**\n * The preset's name\n */\n public name = \"\";\n\n public program = 0;\n\n public bankMSB = 0;\n\n public bankLSB = 0;\n\n public isGMGSDrum = false;\n\n /**\n * The preset's zones\n */\n public zones: BasicPresetZone[] = [];\n\n /**\n * Preset's global zone\n */\n public readonly globalZone: BasicGlobalZone;\n\n /**\n * Unused metadata\n */\n public library = 0;\n /**\n * Unused metadata\n */\n public genre = 0;\n /**\n * Unused metadata\n */\n public morphology = 0;\n\n /**\n * Creates a new preset representation.\n * @param parentSoundBank the sound bank this preset belongs to.\n * @param globalZone optional, a global zone to use.\n */\n public constructor(\n parentSoundBank: BasicSoundBank,\n globalZone = new BasicGlobalZone()\n ) {\n this.parentSoundBank = parentSoundBank;\n this.globalZone = globalZone;\n }\n\n public get isXGDrums() {\n return (\n this.parentSoundBank.isXGBank &&\n BankSelectHacks.isXGDrums(this.bankMSB)\n );\n }\n\n /**\n * Checks if this preset is a drum preset\n */\n public get isAnyDrums(): boolean {\n const xg = this.parentSoundBank.isXGBank;\n\n return (\n this.isGMGSDrum ||\n (xg &&\n BankSelectHacks.isXGDrums(this.bankMSB) &&\n // SFX is not a drum preset, only for exact match\n this.bankMSB !== 126)\n );\n }\n\n /**\n * Unlinks everything from this preset.\n */\n public delete() {\n this.zones.forEach((z) => z.instrument?.unlinkFrom(this));\n }\n\n /**\n * Deletes an instrument zone from this preset.\n * @param index the zone's index to delete.\n */\n public deleteZone(index: number) {\n this.zones[index]?.instrument?.unlinkFrom(this);\n this.zones.splice(index, 1);\n }\n\n /**\n * Creates a new preset zone and returns it.\n * @param instrument the instrument to use in the zone.\n */\n public createZone(instrument: BasicInstrument): BasicPresetZone {\n const z = new BasicPresetZone(this, instrument);\n this.zones.push(z);\n return z;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Preloads (loads and caches synthesis data) for a given key range.\n */\n public preload(keyMin: number, keyMax: number) {\n for (let key = keyMin; key < keyMax + 1; key++) {\n for (let velocity = 0; velocity < 128; velocity++) {\n this.getSynthesisData(key, velocity).forEach(\n (synthesisData) => {\n synthesisData.sample.getAudioData();\n }\n );\n }\n }\n }\n\n /**\n * Checks if the bank and program numbers are the same for the given preset as this one.\n * @param preset The preset to check.\n */\n public matches(preset: MIDIPatch) {\n return MIDIPatchTools.matches(this, preset);\n }\n\n public getSize() {\n const modCount =\n this.zones.reduce(\n (count, zone) => zone.modulators.length + count,\n 0\n ) + this.globalZone.modulators.length;\n const genCount =\n this.zones.reduce((count, zone) => zone.getGenCount() + count, 0) +\n this.globalZone.getGenCount();\n return {\n mod: modCount * MOD_BYTE_SIZE,\n bag: (this.zones.length + 1) * BAG_BYTE_SIZE, // global zone\n gen: genCount * GEN_BYTE_SIZE,\n hdr: PHDR_BYTE_SIZE\n };\n }\n\n /**\n * Returns the synthesis data from this preset\n * @param midiNote the MIDI note number\n * @param velocity the MIDI velocity\n * @returns the returned sound data\n */\n public getSynthesisData(\n midiNote: number,\n velocity: number\n ): VoiceSynthesisData[] {\n if (this.zones.length < 1) {\n return [];\n }\n\n function isInRange(range: GenericRange, number: number): boolean {\n return number >= range.min && number <= range.max;\n }\n\n function addUnique(main: Generator[], adder: Generator[]) {\n main.push(\n ...adder.filter(\n (g) =>\n !main.find((mg) => mg.generatorType === g.generatorType)\n )\n );\n }\n\n function addUniqueMods(main: Modulator[], adder: Modulator[]) {\n main.push(\n ...adder.filter(\n (m) => !main.find((mm) => Modulator.isIdentical(m, mm))\n )\n );\n }\n\n const parsedGeneratorsAndSamples: VoiceSynthesisData[] = [];\n\n /**\n * Global zone is always first, so it or nothing\n */\n const globalPresetGenerators: Generator[] = [\n ...this.globalZone.generators\n ];\n\n const globalPresetModulators: Modulator[] = [\n ...this.globalZone.modulators\n ];\n const globalKeyRange = this.globalZone.keyRange;\n const globalVelRange = this.globalZone.velRange;\n\n // Find the preset zones in range\n const presetZonesInRange = this.zones.filter(\n (currentZone) =>\n isInRange(\n currentZone.hasKeyRange\n ? currentZone.keyRange\n : globalKeyRange,\n midiNote\n ) &&\n isInRange(\n currentZone.hasVelRange\n ? currentZone.velRange\n : globalVelRange,\n velocity\n )\n );\n\n presetZonesInRange.forEach((presetZone) => {\n const instrument = presetZone.instrument;\n // The global zone is already taken into account earlier\n if (!instrument || instrument.zones.length < 1) {\n return;\n }\n const presetGenerators = presetZone.generators;\n const presetModulators = presetZone.modulators;\n /**\n * Global zone is always first, so it or nothing\n */\n const globalInstrumentGenerators: Generator[] = [\n ...instrument.globalZone.generators\n ];\n const globalInstrumentModulators = [\n ...instrument.globalZone.modulators\n ];\n const globalKeyRange = instrument.globalZone.keyRange;\n const globalVelRange = instrument.globalZone.velRange;\n\n const instrumentZonesInRange = instrument.zones.filter(\n (currentZone) =>\n isInRange(\n currentZone.hasKeyRange\n ? currentZone.keyRange\n : globalKeyRange,\n midiNote\n ) &&\n isInRange(\n currentZone.hasVelRange\n ? currentZone.velRange\n : globalVelRange,\n velocity\n )\n );\n\n instrumentZonesInRange.forEach((instrumentZone) => {\n const instrumentGenerators = [...instrumentZone.generators];\n const instrumentModulators = [...instrumentZone.modulators];\n\n addUnique(presetGenerators, globalPresetGenerators);\n // Add the unique global preset generators (local replace global(\n\n // Add the unique global instrument generators (local replace global)\n addUnique(instrumentGenerators, globalInstrumentGenerators);\n\n addUniqueMods(presetModulators, globalPresetModulators);\n addUniqueMods(instrumentModulators, globalInstrumentModulators);\n\n // Default mods\n addUniqueMods(\n instrumentModulators,\n this.parentSoundBank.defaultModulators\n );\n\n /**\n * Sum preset modulators to instruments (amount) sf spec page 54\n */\n const finalModulatorList: Modulator[] = [\n ...instrumentModulators\n ];\n for (const mod of presetModulators) {\n const identicalInstrumentModulator =\n finalModulatorList.findIndex((m) =>\n Modulator.isIdentical(mod, m)\n );\n if (identicalInstrumentModulator !== -1) {\n // Sum the amounts\n // This makes a new modulator\n // Because otherwise it would overwrite the one in the sound bank!\n finalModulatorList[identicalInstrumentModulator] =\n finalModulatorList[\n identicalInstrumentModulator\n ].sumTransform(mod);\n } else {\n finalModulatorList.push(mod);\n }\n }\n\n if (instrumentZone.sample) {\n // Combine both generators and add to the final result\n parsedGeneratorsAndSamples.push({\n instrumentGenerators: instrumentGenerators,\n presetGenerators: presetGenerators,\n modulators: finalModulatorList,\n sample: instrumentZone.sample\n });\n }\n });\n });\n return parsedGeneratorsAndSamples;\n }\n\n /**\n * BankMSB:bankLSB:program:isGMGSDrum\n */\n public toMIDIString() {\n return MIDIPatchTools.toMIDIString(this);\n }\n\n public toString() {\n return MIDIPatchTools.toNamedMIDIString(this);\n }\n\n /**\n * Combines preset into an instrument, flattening the preset zones into instrument zones.\n * This is a really complex function that attempts to work around the DLS limitations of only having the instrument layer.\n * @returns The instrument containing the flattened zones. In theory, it should exactly the same as this preset.\n */\n public toFlattenedInstrument(): BasicInstrument {\n const addUnique = (main: Generator[], adder: Generator[]) => {\n main.push(\n ...adder.filter(\n (g) =>\n !main.find((mg) => mg.generatorType === g.generatorType)\n )\n );\n };\n\n const subtractRanges = (\n r1: GenericRange,\n r2: GenericRange\n ): GenericRange => {\n return {\n min: Math.max(r1.min, r2.min),\n max: Math.min(r1.max, r2.max)\n };\n };\n\n const addUniqueMods = (main: Modulator[], adder: Modulator[]) => {\n main.push(\n ...adder.filter(\n (m) => !main.find((mm) => Modulator.isIdentical(m, mm))\n )\n );\n };\n\n const outputInstrument = new BasicInstrument();\n outputInstrument.name = this.name;\n\n const globalPresetGenerators: Generator[] = [];\n const globalPresetModulators: Modulator[] = [];\n // Find the global zone and apply ranges, generators, and modulators\n const globalPresetZone = this.globalZone;\n globalPresetGenerators.push(...globalPresetZone.generators);\n globalPresetModulators.push(...globalPresetZone.modulators);\n const globalPresetKeyRange = globalPresetZone.keyRange;\n const globalPresetVelRange = globalPresetZone.velRange;\n // For each non-global preset zone\n for (const presetZone of this.zones) {\n if (!presetZone.instrument) {\n throw new Error(\"No instrument in a preset zone.\");\n }\n // Use global ranges if not provided\n let presetZoneKeyRange = presetZone.keyRange;\n if (!presetZone.hasKeyRange) {\n presetZoneKeyRange = globalPresetKeyRange;\n }\n let presetZoneVelRange = presetZone.velRange;\n if (!presetZone.hasVelRange) {\n presetZoneVelRange = globalPresetVelRange;\n }\n // Add unique generators and modulators from the global zone\n const presetGenerators = presetZone.generators.map(\n (g) => new Generator(g.generatorType, g.generatorValue)\n );\n addUnique(presetGenerators, globalPresetGenerators);\n const presetModulators = [...presetZone.modulators];\n addUniqueMods(presetModulators, globalPresetModulators);\n const instrument = presetZone.instrument;\n const iZones = instrument.zones;\n\n const globalInstGenerators: Generator[] = [];\n const globalInstModulators: Modulator[] = [];\n const globalInstZone = instrument.globalZone;\n globalInstGenerators.push(...globalInstZone.generators);\n globalInstModulators.push(...globalInstZone.modulators);\n const globalInstKeyRange = globalInstZone.keyRange;\n const globalInstVelRange = globalInstZone.velRange;\n // For each non-global instrument zone\n for (const instZone of iZones) {\n if (!instZone.sample) {\n throw new Error(\"No sample in an instrument zone.\");\n }\n // Use global ranges if not provided\n let instZoneKeyRange = instZone.keyRange;\n if (!instZone.hasKeyRange) {\n instZoneKeyRange = globalInstKeyRange;\n }\n let instZoneVelRange = instZone.velRange;\n if (!instZone.hasVelRange) {\n instZoneVelRange = globalInstVelRange;\n }\n instZoneKeyRange = subtractRanges(\n instZoneKeyRange,\n presetZoneKeyRange\n );\n instZoneVelRange = subtractRanges(\n instZoneVelRange,\n presetZoneVelRange\n );\n\n // If either of the zones is out of range (i.e.m min larger than the max),\n // Then we discard that zone\n if (\n instZoneKeyRange.max < instZoneKeyRange.min ||\n instZoneVelRange.max < instZoneVelRange.min\n ) {\n continue;\n }\n\n // Add unique generators and modulators from the global zone\n const instGenerators = instZone.generators.map(\n (g) => new Generator(g.generatorType, g.generatorValue)\n );\n addUnique(instGenerators, globalInstGenerators);\n const instModulators = [...instZone.modulators];\n addUniqueMods(instModulators, globalInstModulators);\n\n /**\n * Sum preset modulators to instruments (amount) sf spec page 54\n */\n const finalModList: Modulator[] = [...instModulators];\n for (const mod of presetModulators) {\n const identicalInstMod = finalModList.findIndex((m) =>\n Modulator.isIdentical(mod, m)\n );\n if (identicalInstMod !== -1) {\n // Sum the amounts\n // (this makes a new modulator)\n // Because otherwise it would overwrite the one in the soundfont!\n finalModList[identicalInstMod] =\n finalModList[identicalInstMod].sumTransform(mod);\n } else {\n finalModList.push(mod);\n }\n }\n\n // Clone the generators as the values are modified during DLS conversion (keyNumToSomething)\n let finalGenList = instGenerators.map(\n (g) => new Generator(g.generatorType, g.generatorValue)\n );\n for (const gen of presetGenerators) {\n if (\n gen.generatorType === generatorTypes.velRange ||\n gen.generatorType === generatorTypes.keyRange ||\n gen.generatorType === generatorTypes.instrument ||\n gen.generatorType === generatorTypes.endOper ||\n gen.generatorType === generatorTypes.sampleModes\n ) {\n continue;\n }\n const identicalInstGen = instGenerators.findIndex(\n (g) => g.generatorType === gen.generatorType\n );\n if (identicalInstGen !== -1) {\n // If exists, sum to that generator\n const newAmount =\n finalGenList[identicalInstGen].generatorValue +\n gen.generatorValue;\n finalGenList[identicalInstGen] = new Generator(\n gen.generatorType,\n newAmount\n );\n } else {\n // If not, sum to the default generator\n const newAmount =\n generatorLimits[gen.generatorType].def +\n gen.generatorValue;\n finalGenList.push(\n new Generator(gen.generatorType, newAmount)\n );\n }\n }\n\n // Remove unwanted\n finalGenList = finalGenList.filter(\n (g) =>\n g.generatorType !== generatorTypes.sampleID &&\n g.generatorType !== generatorTypes.keyRange &&\n g.generatorType !== generatorTypes.velRange &&\n g.generatorType !== generatorTypes.endOper &&\n g.generatorType !== generatorTypes.instrument &&\n g.generatorValue !==\n generatorLimits[g.generatorType].def\n );\n\n // Create the zone and copy over values\n const zone = outputInstrument.createZone(instZone.sample);\n zone.keyRange = instZoneKeyRange;\n zone.velRange = instZoneVelRange;\n if (zone.keyRange.min === 0 && zone.keyRange.max === 127) {\n zone.keyRange.min = -1;\n }\n if (zone.velRange.min === 0 && zone.velRange.max === 127) {\n zone.velRange.min = -1;\n }\n zone.addGenerators(...finalGenList);\n zone.addModulators(...finalModList);\n }\n }\n return outputInstrument;\n }\n\n public write(\n genData: IndexedByteArray,\n modData: IndexedByteArray,\n bagData: ExtendedSF2Chunks,\n phdrData: ExtendedSF2Chunks,\n indexes: SoundFontWriteIndexes,\n bank: BasicSoundBank\n ) {\n SpessaSynthInfo(`%cWriting ${this.name}...`, consoleColors.info);\n // Split up the name\n writeBinaryStringIndexed(phdrData.pdta, this.name.substring(0, 20), 20);\n writeBinaryStringIndexed(phdrData.xdta, this.name.substring(20), 20);\n\n writeWord(phdrData.pdta, this.program);\n let wBank = this.bankMSB;\n if (this.isGMGSDrum) {\n // Drum flag\n wBank = 0x80;\n } else if (this.bankMSB === 0) {\n // If bank MSB is zero, write bank LSB (XG)\n wBank = this.bankLSB;\n }\n writeWord(phdrData.pdta, wBank);\n // Skip wBank and wProgram\n phdrData.xdta.currentIndex += 4;\n\n writeWord(phdrData.pdta, indexes.hdr & 0xffff);\n writeWord(phdrData.xdta, indexes.hdr >> 16);\n\n // 3 unused dword, spec says to keep em so we do\n writeDword(phdrData.pdta, this.library);\n writeDword(phdrData.pdta, this.genre);\n writeDword(phdrData.pdta, this.morphology);\n phdrData.xdta.currentIndex += 12;\n\n indexes.hdr += this.zones.length + 1; // + global zone\n\n this.globalZone.write(genData, modData, bagData, indexes, bank);\n this.zones.forEach((z) =>\n z.write(genData, modData, bagData, indexes, bank)\n );\n }\n}\n","import type { SynthSystem } from \"../../synthesizer/types\";\nimport { BankSelectHacks } from \"../../utils/midi_hacks\";\nimport type { BasicPreset } from \"./basic_preset\";\nimport { type MIDIPatch, MIDIPatchTools } from \"./midi_patch\";\nimport { SpessaSynthInfo } from \"../../utils/loggin\";\nimport { consoleColors } from \"../../utils/other\";\n\nfunction getAnyDrums<T extends BasicPreset>(\n presets: T[],\n preferXG: boolean\n): T {\n let p: T | undefined;\n if (preferXG) {\n // Get any XG drums\n p = presets.find((p) => p.isXGDrums);\n } else {\n // Get any GM/GS drums\n p = presets.find((p) => p.isGMGSDrum);\n }\n if (p) {\n // Return the found preset\n return p;\n }\n // Return any drum preset\n return (\n presets.find((p) => p.isAnyDrums) ?? // ...no?\n // Then just return any preset\n presets[0]\n );\n}\n\nexport function selectPreset<T extends BasicPreset>(\n presets: T[],\n patch: MIDIPatch,\n system: SynthSystem\n): T {\n if (presets.length < 1) {\n throw new Error(\"No presets!\");\n }\n if (patch.isGMGSDrum && BankSelectHacks.isSystemXG(system)) {\n // GM/GS drums with XG. This shouldn't happen. Force XG drums.\n patch = {\n ...patch,\n isGMGSDrum: false,\n bankLSB: 0,\n bankMSB: BankSelectHacks.getDrumBank(system)\n };\n }\n const { isGMGSDrum, bankLSB, bankMSB, program } = patch;\n const isXG = BankSelectHacks.isSystemXG(system);\n const xgDrums = BankSelectHacks.isXGDrums(bankMSB) && isXG;\n\n // Check for exact match\n let p = presets.find((p) => p.matches(patch));\n if (p) {\n // Special case:\n // Non XG banks sometimes specify melodic \"MT\" presets at bank 127,\n // Which matches XG banks.\n // Testcase: 4gmgsmt-sf2_04-compat.sf2\n // Only match if the preset declares itself as drums\n if (!xgDrums || (xgDrums && p.isXGDrums)) {\n return p;\n }\n }\n\n // Helper to log failed exact matches\n const returnReplacement = (pres: T) => {\n SpessaSynthInfo(\n `%cPreset %c${MIDIPatchTools.toMIDIString(patch)}%c not found. (${system}) Replaced with %c${pres.toString()}`,\n consoleColors.warn,\n consoleColors.unrecognized,\n consoleColors.warn,\n consoleColors.value\n );\n };\n\n // No exact match...\n if (isGMGSDrum) {\n // GM/GS drums: check for the exact program match\n let p = presets.find((p) => p.isGMGSDrum && p.program === program);\n if (p) {\n returnReplacement(p);\n return p;\n }\n\n // No match, pick any matching drum\n p = presets.find((p) => p.isAnyDrums && p.program === program);\n if (p) {\n returnReplacement(p);\n return p;\n }\n\n // No match, pick the first drum preset, preferring GM/GS\n p = getAnyDrums(presets, false);\n returnReplacement(p);\n return p;\n }\n if (xgDrums) {\n // XG drums: Look for exact bank and program match\n let p = presets.find((p) => p.program === program && p.isXGDrums);\n if (p) {\n returnReplacement(p);\n return p;\n }\n\n // No match, pick any matching drum\n p = presets.find((p) => p.isAnyDrums && p.program === program);\n if (p) {\n returnReplacement(p);\n return p;\n }\n\n // Pick any drums, preferring XG\n p = getAnyDrums(presets, true);\n returnReplacement(p);\n return p;\n }\n // Melodic preset\n const matchingPrograms = presets.filter(\n (p) => p.program === program && !p.isAnyDrums\n );\n if (matchingPrograms.length < 1) {\n returnReplacement(presets[0]);\n return presets[0];\n }\n if (isXG) {\n // XG uses LSB so search for that.\n p = matchingPrograms.find((p) => p.bankLSB === bankLSB);\n } else {\n // GS uses MSB so search for that.\n p = matchingPrograms.find((p) => p.bankMSB === bankMSB);\n }\n if (p) {\n returnReplacement(p);\n return p;\n }\n // Any matching bank\n p = matchingPrograms.find(\n (p) => p.bankLSB === bankLSB || p.bankMSB === bankMSB\n );\n if (p) {\n returnReplacement(p);\n return p;\n }\n // The first matching program\n returnReplacement(matchingPrograms[0]);\n return matchingPrograms[0];\n}\n","import { SpessaSynthWarn } from \"../../../utils/loggin\";\n\nimport type { SoundBankManagerListEntry } from \"../../../soundbank/types\";\nimport type { BasicSoundBank } from \"../../../soundbank/basic_soundbank/basic_soundbank\";\nimport { BasicPreset } from \"../../../soundbank/basic_soundbank/basic_preset\";\nimport type { PresetListEntry, SynthSystem } from \"../../types\";\nimport { selectPreset } from \"../../../soundbank/basic_soundbank/preset_selector\";\nimport {\n type MIDIPatch,\n MIDIPatchTools\n} from \"../../../soundbank/basic_soundbank/midi_patch\";\nimport { BankSelectHacks } from \"../../../utils/midi_hacks\";\n\nclass SoundBankManagerPreset extends BasicPreset {\n public constructor(p: BasicPreset, offset: number) {\n super(p.parentSoundBank, p.globalZone);\n this.bankMSB = BankSelectHacks.addBankOffset(\n p.bankMSB,\n offset,\n p.isXGDrums\n );\n\n this.name = p.name;\n this.bankLSB = p.bankLSB;\n this.isGMGSDrum = p.isGMGSDrum;\n this.program = p.program;\n\n this.genre = p.genre;\n this.morphology = p.morphology;\n this.library = p.library;\n this.zones = p.zones;\n }\n}\n\nexport class SoundBankManager {\n /**\n * All the sound banks, ordered from the most important to the least.\n */\n public soundBankList: SoundBankManagerListEntry[] = [];\n private readonly presetListChangeCallback: () => unknown;\n\n private selectablePresetList: SoundBankManagerPreset[] = [];\n\n /**\n * @param presetListChangeCallback Supplied by the parent synthesizer class,\n * this is called whenever the preset list changes.\n */\n public constructor(presetListChangeCallback: () => unknown) {\n this.presetListChangeCallback = presetListChangeCallback;\n }\n\n private _presetList: PresetListEntry[] = [];\n\n /**\n * The list of all presets in the sound bank stack.\n */\n public get presetList() {\n return [...this._presetList];\n }\n\n /**\n * The current sound bank priority order.\n * @returns The IDs of the sound banks in the current order.\n */\n public get priorityOrder() {\n return this.soundBankList.map((s) => s.id);\n }\n\n /**\n * The current sound bank priority order.\n * @param newList The new order of sound bank IDs.\n */\n public set priorityOrder(newList: string[]) {\n this.soundBankList.sort(\n (a, b) => newList.indexOf(a.id) - newList.indexOf(b.id)\n );\n this.generatePresetList();\n }\n\n /**\n * Deletes a given sound bank by its ID.\n * @param id the ID of the sound bank to delete.\n */\n public deleteSoundBank(id: string) {\n if (this.soundBankList.length === 0) {\n SpessaSynthWarn(\"1 soundbank left. Aborting!\");\n return;\n }\n const index = this.soundBankList.findIndex((s) => s.id === id);\n if (index === -1) {\n throw new Error(`No sound bank with id \"${id}\"`);\n }\n this.soundBankList.splice(index, 1);\n this.generatePresetList();\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Adds a new sound bank with a given ID, or replaces an existing one.\n * @param font the sound bank to add.\n * @param id the ID of the sound bank.\n * @param bankOffset the bank offset of the sound bank.\n */\n public addSoundBank(font: BasicSoundBank, id: string, bankOffset = 0) {\n const foundBank = this.soundBankList.find((s) => s.id === id);\n if (foundBank !== undefined) {\n // Replace\n foundBank.soundBank = font;\n foundBank.bankOffset = bankOffset;\n } else {\n this.soundBankList.push({\n id: id,\n soundBank: font,\n bankOffset: bankOffset\n });\n }\n this.generatePresetList();\n }\n\n /**\n * Gets a given preset from the sound bank stack.\n * @param patch The MIDI patch to search for.\n * @param system The MIDI system to select the preset for.\n * @returns An object containing the preset and its bank offset.\n */\n public getPreset(patch: MIDIPatch, system: SynthSystem): BasicPreset {\n if (this.soundBankList.length < 1) {\n throw new Error(\"No sound banks! Did you forget to add one?\");\n }\n\n return selectPreset(this.selectablePresetList, patch, system);\n }\n\n // Clears the sound bank list and destroys all sound banks.\n public destroy() {\n this.soundBankList.forEach((s) => {\n s.soundBank.destroySoundBank();\n });\n this.soundBankList = [];\n }\n\n private generatePresetList() {\n const presetList = new Array<SoundBankManagerPreset>();\n\n const addedPresets = new Set<string>();\n this.soundBankList.forEach((s) => {\n const bank = s.soundBank;\n const bankOffset = s.bankOffset;\n bank.presets.forEach((p) => {\n const selectablePreset = new SoundBankManagerPreset(\n p,\n bankOffset\n );\n if (!addedPresets.has(selectablePreset.toMIDIString())) {\n addedPresets.add(selectablePreset.toMIDIString());\n presetList.push(selectablePreset);\n }\n });\n });\n presetList.sort(MIDIPatchTools.sorter.bind(MIDIPatchTools));\n this.selectablePresetList = presetList;\n this._presetList = presetList.map((p) => {\n return {\n bankMSB: p.bankMSB,\n bankLSB: p.bankLSB,\n program: p.program,\n isGMGSDrum: p.isGMGSDrum,\n name: p.name,\n isAnyDrums: p.isAnyDrums\n };\n });\n this.presetListChangeCallback();\n }\n}\n","import type { MIDIChannel } from \"../midi_channel\";\nimport type { Voice } from \"../voice\";\nimport { generatorTypes } from \"../../../../soundbank/basic_soundbank/generator_types\";\n\n/**\n * Stereo_panner.ts\n * purpose: pans a given voice out to the stereo output and to the effects' outputs\n */\n\nexport const PAN_SMOOTHING_FACTOR = 0.05;\n\n// Optimized for spessasynth_lib's effects\nexport const REVERB_DIVIDER = 3070;\nexport const CHORUS_DIVIDER = 2000;\nconst HALF_PI = Math.PI / 2;\n\nconst MIN_PAN = -500;\nconst MAX_PAN = 500;\nconst PAN_RESOLUTION = MAX_PAN - MIN_PAN;\n\n// Initialize pan lookup tables\nconst panTableLeft = new Float32Array(PAN_RESOLUTION + 1);\nconst panTableRight = new Float32Array(PAN_RESOLUTION + 1);\nfor (let pan = MIN_PAN; pan <= MAX_PAN; pan++) {\n // Clamp to 0-1\n const realPan = (pan - MIN_PAN) / PAN_RESOLUTION;\n const tableIndex = pan - MIN_PAN;\n panTableLeft[tableIndex] = Math.cos(HALF_PI * realPan);\n panTableRight[tableIndex] = Math.sin(HALF_PI * realPan);\n}\n\n/**\n * Pans the voice to the given output buffers\n * @param voice The voice to pan.\n * @param inputBuffer The input buffer containing the audio data for the voice (mono).\n * @param outputLeft The left output buffer to mix the voice into.\n * @param outputRight The right output buffer to mix the voice into.\n * @param reverbLeft The left reverb output buffer.\n * @param reverbRight The right reverb output buffer.\n * @param chorusLeft The left chorus output buffer.\n * @param chorusRight The right chorus output buffer.\n * @param startIndex The start index offset in the output buffers where the voice's audio data should be mixed in.\n */\nexport function panAndMixVoice(\n this: MIDIChannel,\n voice: Voice,\n inputBuffer: Float32Array,\n outputLeft: Float32Array,\n outputRight: Float32Array,\n reverbLeft: Float32Array,\n reverbRight: Float32Array,\n chorusLeft: Float32Array,\n chorusRight: Float32Array,\n startIndex: number\n) {\n if (isNaN(inputBuffer[0])) {\n return;\n }\n /**\n * Clamp -500 to 500\n */\n let pan: number;\n if (voice.overridePan) {\n pan = voice.overridePan;\n } else {\n // Smooth out pan to prevent clicking\n voice.currentPan +=\n (voice.modulatedGenerators[generatorTypes.pan] - voice.currentPan) *\n this.synthProps.panSmoothingFactor;\n pan = voice.currentPan;\n }\n\n const gain =\n this.synthProps.masterParameters.masterGain *\n this.synthProps.midiVolume *\n voice.gain;\n const index = ~~(pan + 500);\n // Get voice's gain levels for each channel\n const gainLeft = panTableLeft[index] * gain * this.synthProps.panLeft;\n const gainRight = panTableRight[index] * gain * this.synthProps.panRight;\n\n // Disable reverb and chorus if necessary\n if (this.synth.enableEffects) {\n const reverbSend =\n voice.modulatedGenerators[generatorTypes.reverbEffectsSend];\n if (reverbSend > 0) {\n // Reverb is mono so we need to multiply by gain\n const reverbGain =\n this.synthProps.masterParameters.reverbGain *\n this.synthProps.reverbSend *\n gain *\n (reverbSend / REVERB_DIVIDER);\n for (let i = 0; i < inputBuffer.length; i++) {\n const idx = i + startIndex;\n reverbLeft[idx] += reverbGain * inputBuffer[i];\n reverbRight[idx] += reverbGain * inputBuffer[i];\n }\n }\n\n const chorusSend =\n voice.modulatedGenerators[generatorTypes.chorusEffectsSend];\n if (chorusSend > 0) {\n // Chorus is stereo so we do not need to\n const chorusGain =\n this.synthProps.masterParameters.chorusGain *\n this.synthProps.chorusSend *\n (chorusSend / CHORUS_DIVIDER);\n const chorusLeftGain = gainLeft * chorusGain;\n const chorusRightGain = gainRight * chorusGain;\n for (let i = 0; i < inputBuffer.length; i++) {\n const idx = i + startIndex;\n chorusLeft[idx] += chorusLeftGain * inputBuffer[i];\n chorusRight[idx] += chorusRightGain * inputBuffer[i];\n }\n }\n }\n\n // Mix down the audio data\n if (gainLeft > 0) {\n for (let i = 0; i < inputBuffer.length; i++) {\n outputLeft[i + startIndex] += gainLeft * inputBuffer[i];\n }\n }\n if (gainRight > 0) {\n for (let i = 0; i < inputBuffer.length; i++) {\n outputRight[i + startIndex] += gainRight * inputBuffer[i];\n }\n }\n}\n","import { absCentsToHz, decibelAttenuationToGain } from \"../unit_converter\";\nimport type { Voice } from \"../voice\";\nimport { generatorTypes } from \"../../../../soundbank/basic_soundbank/generator_types\";\n\n/**\n * Lowpass_filter.ts\n * purpose: applies a low pass filter to a voice\n * note to self: a lot of tricks and come from fluidsynth.\n * They are the real smart guys.\n * Shoutout to them!\n * Give their repo a star over at:\n * https://github.com/FluidSynth/fluidsynth\n */\n\nexport const FILTER_SMOOTHING_FACTOR = 0.1;\n\n// Represents a single cached coefficient.\ninterface CachedCoefficient {\n // Filter coefficient 1.\n a0: number;\n // Filter coefficient 2.\n a1: number;\n // Filter coefficient 3.\n a2: number;\n // Filter coefficient 4.\n a3: number;\n // Filter coefficient 5.\n a4: number;\n}\n\nexport class LowpassFilter {\n /**\n * Cached coefficient calculations.\n * stored as cachedCoefficients[resonanceCb][currentInitialFc].\n */\n private static cachedCoefficients: CachedCoefficient[][] = [];\n /**\n * Resonance in centibels.\n */\n public resonanceCb = 0;\n /**\n * Current cutoff frequency in absolute cents.\n */\n public currentInitialFc = 13500;\n /**\n * Filter coefficient 1.\n */\n private a0 = 0;\n /**\n * Filter coefficient 2.\n */\n private a1 = 0;\n /**\n * Filter coefficient 3.\n */\n private a2 = 0;\n /**\n * Filter coefficient 4.\n */\n private a3 = 0;\n /**\n * Filter coefficient 5.\n */\n private a4 = 0;\n /**\n * Input history 1.\n */\n private x1 = 0;\n /**\n * Input history 2.\n */\n private x2 = 0;\n /**\n * Output history 1.\n */\n private y1 = 0;\n /**\n * Output history 2.\n */\n private y2 = 0;\n /**\n * For tracking the last cutoff frequency in the apply method, absolute cents.\n * Set to infinity to force recalculation.\n */\n private lastTargetCutoff = Infinity;\n\n /**\n * Used for tracking if the filter has been initialized.\n */\n private initialized = false;\n /**\n * Filter's sample rate in Hz.\n */\n private sampleRate;\n\n /**\n * Maximum cutoff frequency in Hz.\n * This is used to prevent aliasing and ensure the filter operates within the valid frequency range.\n */\n private maxCutoff: number;\n\n /**\n * Initializes a new instance of the filter.\n * @param sampleRate the sample rate of the audio engine in Hz.\n */\n public constructor(sampleRate: number) {\n this.sampleRate = sampleRate;\n this.maxCutoff = sampleRate * 0.45;\n }\n\n /**\n * Applies the lowpass filter to the output buffer of a voice.\n * @param voice The voice to apply the filter to.\n * @param outputBuffer The output buffer to filter.\n * @param fcExcursion The frequency excursion in cents to apply to the filter.\n * @param smoothingFactor The smoothing factor for the filter as determined by the parent synthesizer.\n */\n public static apply(\n voice: Voice,\n outputBuffer: Float32Array,\n fcExcursion: number,\n smoothingFactor: number\n ) {\n const initialFc =\n voice.modulatedGenerators[generatorTypes.initialFilterFc];\n const filter: LowpassFilter = voice.filter;\n\n if (!filter.initialized) {\n // Filter initialization, set the current fc to target\n filter.initialized = true;\n filter.currentInitialFc = initialFc;\n } else {\n /* Note:\n * We only smooth out the initialFc part,\n * the modulation envelope and LFO excursions are not smoothed.\n */\n filter.currentInitialFc +=\n (initialFc - filter.currentInitialFc) * smoothingFactor;\n }\n\n // The final cutoff for this calculation\n const targetCutoff = filter.currentInitialFc + fcExcursion;\n const modulatedResonance =\n voice.modulatedGenerators[generatorTypes.initialFilterQ];\n /* Note:\n * the check for initialFC is because of the filter optimization\n * (if cents are the maximum then the filter is open)\n * filter cannot use this optimization if it's dynamic (see #53), and\n * the filter can only be dynamic if the initial filter is not open\n */\n if (\n filter.currentInitialFc > 13499 &&\n targetCutoff > 13499 &&\n modulatedResonance === 0\n ) {\n filter.currentInitialFc = 13500;\n return; // Filter is open\n }\n\n // Check if the frequency has changed. if so, calculate new coefficients\n if (\n Math.abs(filter.lastTargetCutoff - targetCutoff) > 1 ||\n filter.resonanceCb !== modulatedResonance\n ) {\n filter.lastTargetCutoff = targetCutoff;\n filter.resonanceCb = modulatedResonance;\n LowpassFilter.calculateCoefficients(filter, targetCutoff);\n }\n\n // Filter the input\n // Initial filtering code was ported from meltysynth created by sinshu.\n for (let i = 0; i < outputBuffer.length; i++) {\n const input = outputBuffer[i];\n const filtered =\n filter.a0 * input +\n filter.a1 * filter.x1 +\n filter.a2 * filter.x2 -\n filter.a3 * filter.y1 -\n filter.a4 * filter.y2;\n\n // Set buffer\n filter.x2 = filter.x1;\n filter.x1 = input;\n filter.y2 = filter.y1;\n filter.y1 = filtered;\n\n outputBuffer[i] = filtered;\n }\n }\n\n /**\n * Calculates the filter coefficients based on the current resonance and cutoff frequency and caches them.\n * @param filter The lowpass filter instance to calculate coefficients for.\n * @param cutoffCents The cutoff frequency in cents.\n */\n public static calculateCoefficients(\n filter: LowpassFilter,\n cutoffCents: number\n ) {\n cutoffCents = ~~cutoffCents; // Math.floor\n const qCb = filter.resonanceCb;\n // Check if these coefficients were already cached\n const cached = LowpassFilter.cachedCoefficients?.[qCb]?.[cutoffCents];\n if (cached !== undefined) {\n filter.a0 = cached.a0;\n filter.a1 = cached.a1;\n filter.a2 = cached.a2;\n filter.a3 = cached.a3;\n filter.a4 = cached.a4;\n return;\n }\n let cutoffHz = absCentsToHz(cutoffCents);\n\n // Fix cutoff on low sample rates\n cutoffHz = Math.min(cutoffHz, filter.maxCutoff);\n\n // The coefficient calculation code was originally ported from meltysynth by sinshu.\n // Turn resonance to gain, -3.01 so it gives a non-resonant peak\n const qDb = qCb / 10;\n // -1 because it's attenuation, and we don't want attenuation\n const resonanceGain = decibelAttenuationToGain(-(qDb - 3.01));\n\n // The sf spec asks for a reduction in gain based on the Q value.\n // Note that we calculate it again,\n // Without the 3.01-peak offset as it only applies to the coefficients, not the gain.\n const qGain = 1 / Math.sqrt(decibelAttenuationToGain(-qDb));\n\n // Note: no sin or cos tables are used here as the coefficients are cached\n const w = (2 * Math.PI * cutoffHz) / filter.sampleRate;\n const cosw = Math.cos(w);\n const alpha = Math.sin(w) / (2 * resonanceGain);\n\n const b1 = (1 - cosw) * qGain;\n const b0 = b1 / 2;\n const b2 = b0;\n const a0 = 1 + alpha;\n const a1 = -2 * cosw;\n const a2 = 1 - alpha;\n\n const toCache: CachedCoefficient = {\n a0: b0 / a0,\n a1: b1 / a0,\n a2: b2 / a0,\n a3: a1 / a0,\n a4: a2 / a0\n };\n filter.a0 = toCache.a0;\n filter.a1 = toCache.a1;\n filter.a2 = toCache.a2;\n filter.a3 = toCache.a3;\n filter.a4 = toCache.a4;\n\n LowpassFilter.cachedCoefficients[qCb] ??= [];\n // Cache the coefficients\n LowpassFilter.cachedCoefficients[qCb][cutoffCents] = toCache;\n }\n}\n\n// Precompute all the cutoffs for 0q (most common)\nconst dummy = new LowpassFilter(44100);\ndummy.resonanceCb = 0;\n// Sf spec section 8.1.3: initialFilterFc ranges from 1500 to 13,500 cents\nfor (let i = 1500; i < 13500; i++) {\n dummy.currentInitialFc = i;\n LowpassFilter.calculateCoefficients(dummy, i);\n}\n","import type { SynthProcessorOptions } from \"../../types\";\n\nexport const DEFAULT_SYNTH_OPTIONS: SynthProcessorOptions = {\n enableEventSystem: true,\n initialTime: 0,\n enableEffects: true\n};\n","import type { MIDIChannel } from \"../../engine_components/midi_channel\";\nimport type { Voice } from \"../../engine_components/voice\";\nimport type { SpessaSynthProcessor } from \"../../../processor\";\n\n/**\n * Gets the priority of a voice based on its channel and state.\n * Higher priority means the voice is more important and should be kept longer.\n * @param channel The MIDI audio channel of the voice.\n * @param voice The voice to evaluate.\n * @returns The priority score of the voice.\n */\nfunction getPriority(channel: MIDIChannel, voice: Voice): number {\n let priority = 0;\n if (channel.drumChannel) {\n // Important\n priority += 5;\n }\n if (voice.isInRelease) {\n // Not important\n priority -= 5;\n }\n // Less velocity = less important\n priority += voice.velocity / 25; // Map to 0-5\n // The newer, more important\n priority -= voice.volumeEnvelope.state;\n if (voice.isInRelease) {\n priority -= 5;\n }\n priority -= voice.volumeEnvelope.currentAttenuationDb / 50;\n return priority;\n}\n\n/**\n * Kills the specified number of voices based on their priority.\n * This function will remove the least important voices from all channels.\n * @param amount The number of voices to remove.\n */\nexport function killVoicesIntenral(this: SpessaSynthProcessor, amount: number) {\n const allVoices: {\n channel: MIDIChannel;\n voice: Voice;\n priority: number;\n }[] = [];\n for (const channel of this.midiChannels) {\n for (const voice of channel.voices) {\n if (!voice.finished) {\n const priority = getPriority(channel, voice);\n allVoices.push({ channel, voice, priority });\n }\n }\n }\n\n // Step 2: Sort voices by priority (ascending order)\n allVoices.sort((a, b) => a.priority - b.priority);\n const voicesToRemove = allVoices.slice(0, amount);\n\n for (const { channel, voice } of voicesToRemove) {\n const index = channel.voices.indexOf(voice);\n if (index > -1) {\n channel.voices.splice(index, 1);\n }\n }\n}\n","import { timecentsToSeconds } from \"../unit_converter\";\nimport { getModulatorCurveValue } from \"../modulator_curves\";\nimport type { Voice } from \"../voice\";\nimport { generatorTypes } from \"../../../../soundbank/basic_soundbank/generator_types\";\nimport { modulatorCurveTypes } from \"../../../../soundbank/enums\";\n\n/**\n * Modulation_envelope.ts\n * purpose: calculates the modulation envelope for the given voice\n */\nconst MODENV_PEAK = 1;\n\n// 1000 should be precise enough\nconst CONVEX_ATTACK = new Float32Array(1000);\nfor (let i = 0; i < CONVEX_ATTACK.length; i++) {\n // This makes the db linear (I think)\n CONVEX_ATTACK[i] = getModulatorCurveValue(\n 0,\n modulatorCurveTypes.convex,\n i / 1000\n );\n}\n\nexport class ModulationEnvelope {\n /**\n * The attack duration, in seconds.\n */\n protected attackDuration = 0;\n /**\n * The decay duration, in seconds.\n */\n protected decayDuration = 0;\n\n /**\n * The hold duration, in seconds.\n */\n protected holdDuration = 0;\n\n /**\n * Release duration, in seconds.\n */\n protected releaseDuration = 0;\n\n /**\n * The sustain level 0-1.\n */\n protected sustainLevel = 0;\n\n /**\n * Delay phase end time in seconds, absolute (audio context time).\n */\n protected delayEnd = 0;\n /**\n * Attack phase end time in seconds, absolute (audio context time).\n */\n protected attackEnd = 0;\n /**\n * Hold phase end time in seconds, absolute (audio context time).\n */\n protected holdEnd = 0;\n /**\n * Decay phase end time in seconds, absolute (audio context time).\n */\n protected decayEnd = 0;\n\n /**\n * The level of the envelope when the release phase starts.\n */\n protected releaseStartLevel = 0;\n\n /**\n * The current modulation envelope value.\n */\n protected currentValue = 0;\n\n /**\n * Starts the release phase in the envelope.\n * @param voice the voice this envelope belongs to.\n */\n public static startRelease(voice: Voice) {\n ModulationEnvelope.recalculate(voice);\n }\n\n /**\n * @param voice the voice to recalculate.\n */\n public static recalculate(voice: Voice) {\n const env = voice.modulationEnvelope;\n\n // In release? Might need to recalculate the value as it can be modulated\n if (voice.isInRelease) {\n env.releaseStartLevel = ModulationEnvelope.getValue(\n voice,\n voice.releaseStartTime,\n true\n );\n }\n\n env.sustainLevel =\n 1 - voice.modulatedGenerators[generatorTypes.sustainModEnv] / 1000;\n\n env.attackDuration = timecentsToSeconds(\n voice.modulatedGenerators[generatorTypes.attackModEnv]\n );\n\n const decayKeyExcursionCents =\n (60 - voice.midiNote) *\n voice.modulatedGenerators[generatorTypes.keyNumToModEnvDecay];\n const decayTime = timecentsToSeconds(\n voice.modulatedGenerators[generatorTypes.decayModEnv] +\n decayKeyExcursionCents\n );\n // According to the specification, the decay time is the time it takes to reach 0% from 100%.\n // Calculate the time to reach actual sustain level,\n // For example, sustain 0.6 will be 0.4 of the decay time\n env.decayDuration = decayTime * (1 - env.sustainLevel);\n\n const holdKeyExcursionCents =\n (60 - voice.midiNote) *\n voice.modulatedGenerators[generatorTypes.keyNumToModEnvHold];\n env.holdDuration = timecentsToSeconds(\n holdKeyExcursionCents +\n voice.modulatedGenerators[generatorTypes.holdModEnv]\n );\n\n // Min is set to -7200 to prevent lowpass clicks\n const releaseTime = timecentsToSeconds(\n Math.max(\n voice.modulatedGenerators[generatorTypes.releaseModEnv],\n -7200\n )\n );\n // Release time is from the full level to 0%\n // To get the actual time, multiply by the release start level\n env.releaseDuration = releaseTime * env.releaseStartLevel;\n\n env.delayEnd =\n voice.startTime +\n timecentsToSeconds(\n voice.modulatedGenerators[generatorTypes.delayModEnv]\n );\n env.attackEnd = env.delayEnd + env.attackDuration;\n env.holdEnd = env.attackEnd + env.holdDuration;\n env.decayEnd = env.holdEnd + env.decayDuration;\n }\n\n /**\n * Calculates the current modulation envelope value for the given time and voice.\n * @param voice the voice we are working on.\n * @param currentTime in seconds.\n * @param ignoreRelease if true, it will compute the value as if the voice was not released.\n * @returns mod env value, from 0 to 1.\n */\n public static getValue(\n voice: Voice,\n currentTime: number,\n ignoreRelease = false\n ): number {\n const env = voice.modulationEnvelope;\n if (voice.isInRelease && !ignoreRelease) {\n // If the voice is still in the delay phase,\n // Start level will be 0 that will result in divide by zero\n if (env.releaseStartLevel === 0) {\n return 0;\n }\n return Math.max(\n 0,\n (1 -\n (currentTime - voice.releaseStartTime) /\n env.releaseDuration) *\n env.releaseStartLevel\n );\n }\n\n if (currentTime < env.delayEnd) {\n env.currentValue = 0; // Delay\n } else if (currentTime < env.attackEnd) {\n // Modulation envelope uses convex curve for attack\n env.currentValue =\n CONVEX_ATTACK[\n ~~(\n (1 -\n (env.attackEnd - currentTime) /\n env.attackDuration) *\n 1000\n )\n ];\n } else if (currentTime < env.holdEnd) {\n // Hold: stay at 1\n env.currentValue = MODENV_PEAK;\n } else if (currentTime < env.decayEnd) {\n // Decay: linear ramp from 1 to sustain level\n env.currentValue =\n (1 - (env.decayEnd - currentTime) / env.decayDuration) *\n (env.sustainLevel - MODENV_PEAK) +\n MODENV_PEAK;\n } else {\n // Sustain: stay at sustain level\n env.currentValue = env.sustainLevel;\n }\n return env.currentValue;\n }\n}\n","import type { SampleLoopingMode } from \"../../types\";\n\nexport class AudioSample {\n /**\n * The sample's audio data\n */\n public readonly sampleData: Float32Array;\n /**\n * Current playback step (rate)\n */\n public readonly playbackStep: number = 0;\n /**\n * Current position in the sample\n */\n public cursor = 0;\n /**\n * MIDI root key of the sample\n */\n public readonly rootKey: number = 0;\n /**\n * Start position of the loop\n */\n public loopStart = 0;\n /**\n * End position of the loop\n */\n public loopEnd = 0;\n /**\n * End position of the sample\n */\n public end = 0;\n /**\n * Looping mode of the sample:\n * 0 - no loop\n * 1 - loop\n * 2 - UNOFFICIAL: polyphone 2.4 added start on release\n * 3 - loop then play when released\n */\n public loopingMode: SampleLoopingMode = 0;\n /**\n * Indicates if the sample is currently looping\n */\n public isLooping = false;\n\n /**\n * @param data\n * @param playbackStep the playback step, a single increment\n * @param cursorStart the sample id which starts the playback\n * @param rootKey MIDI root key\n * @param loopStart loop start index\n * @param loopEnd loop end index\n * @param endIndex sample end index (for end offset)\n * @param loopingMode sample looping mode\n */\n public constructor(\n data: Float32Array,\n playbackStep: number,\n cursorStart: number,\n rootKey: number,\n loopStart: number,\n loopEnd: number,\n endIndex: number,\n loopingMode: SampleLoopingMode\n ) {\n this.sampleData = data;\n this.playbackStep = playbackStep;\n this.cursor = cursorStart;\n this.rootKey = rootKey;\n this.loopStart = loopStart;\n this.loopEnd = loopEnd;\n this.end = endIndex;\n this.loopingMode = loopingMode;\n this.isLooping = this.loopingMode === 1 || this.loopingMode === 3;\n }\n}","/**\n * Voice.ts\n * purpose: prepares Voices from sample and generator data\n */\nimport { SpessaSynthProcessor } from \"../../processor\";\nimport { SpessaSynthWarn } from \"../../../utils/loggin\";\nimport { LowpassFilter } from \"./dsp_chain/lowpass_filter\";\nimport { VolumeEnvelope } from \"./dsp_chain/volume_envelope\";\nimport { ModulationEnvelope } from \"./dsp_chain/modulation_envelope\";\nimport { addAndClampGenerator } from \"../../../soundbank/basic_soundbank/generator\";\nimport { Modulator } from \"../../../soundbank/basic_soundbank/modulator\";\nimport {\n GENERATORS_AMOUNT,\n generatorTypes\n} from \"../../../soundbank/basic_soundbank/generator_types\";\nimport type { SampleLoopingMode, VoiceList } from \"../../types\";\nimport type { BasicPreset } from \"../../../soundbank/basic_soundbank/basic_preset\";\nimport { AudioSample } from \"./audio_sample\";\nimport { MIN_EXCLUSIVE_LENGTH, MIN_NOTE_LENGTH } from \"./synth_constants\";\nimport type { MIDIPatch } from \"../../../soundbank/basic_soundbank/midi_patch\";\n\nconst EXCLUSIVE_CUTOFF_TIME = -2320;\nconst EXCLUSIVE_MOD_CUTOFF_TIME = -1130; // Less because filter shenanigans\n\n/**\n * Voice represents a single instance of the\n * SoundFont2 synthesis model.\n * That is:\n * A wavetable oscillator (sample)\n * A volume envelope (volumeEnvelope)\n * A modulation envelope (modulationEnvelope)\n * Generators (generators and modulatedGenerators)\n * Modulators (modulators)\n * And MIDI params such as channel, MIDI note, velocity\n */\nexport class Voice {\n /**\n * The sample of the voice.\n */\n public sample: AudioSample;\n\n /**\n * Lowpass filter applied to the voice.\n */\n public filter: LowpassFilter;\n\n /**\n * Linear gain of the voice. Used with Key Modifiers.\n */\n public gain = 1;\n\n /**\n * The unmodulated (copied to) generators of the voice.\n */\n public generators: Int16Array;\n\n /**\n * The voice's modulators.\n */\n public modulators: Modulator[] = [];\n\n /**\n * Resonance offset, it is affected by the default resonant modulator\n */\n public resonanceOffset = 0;\n\n /**\n * The generators in real-time, affected by modulators.\n * This is used during rendering.\n */\n public modulatedGenerators: Int16Array;\n\n /**\n * Indicates if the voice is finished.\n */\n public finished = false;\n\n /**\n * Indicates if the voice is in the release phase.\n */\n public isInRelease = false;\n\n /**\n * Velocity of the note.\n */\n public velocity = 0;\n\n /**\n * MIDI note number.\n */\n public midiNote = 0;\n\n /**\n * The pressure of the voice\n */\n public pressure = 0;\n\n /**\n * Target key for the note.\n */\n public targetKey = 0;\n\n /**\n * Modulation envelope.\n */\n public modulationEnvelope: ModulationEnvelope = new ModulationEnvelope();\n\n /**\n * Volume envelope.\n */\n public volumeEnvelope: VolumeEnvelope;\n\n /**\n * Start time of the voice, absolute.\n */\n public startTime = 0;\n\n /**\n * Start time of the release phase, absolute.\n */\n public releaseStartTime = Infinity;\n\n /**\n * Current tuning in cents.\n */\n public currentTuningCents = 0;\n\n /**\n * Current calculated tuning. (as in ratio)\n */\n public currentTuningCalculated = 1;\n\n /**\n * From -500 to 500.\n */\n public currentPan = 0;\n\n /**\n * If MIDI Tuning Standard is already applied (at note-on time),\n * this will be used to take the values at real-time tuning as \"midiNote\"\n * property contains the tuned number.\n * see SpessaSynth#29 comment by @paulikaro\n */\n public realKey: number;\n\n /**\n * Initial key to glide from, MIDI Note number. If -1, the portamento is OFF.\n */\n public portamentoFromKey = -1;\n\n /**\n * Duration of the linear glide, in seconds.\n */\n public portamentoDuration = 0;\n\n /**\n * From -500 to 500, where zero means disabled (use the channel pan). Used for random pan.\n */\n public overridePan = 0;\n\n /**\n * Exclusive class number for hi-hats etc.\n */\n public exclusiveClass = 0;\n\n /**\n * Creates a Voice.\n */\n public constructor(\n sampleRate: number,\n audioSample: AudioSample,\n midiNote: number,\n velocity: number,\n currentTime: number,\n targetKey: number,\n realKey: number,\n generators: Int16Array,\n modulators: Modulator[]\n ) {\n this.sample = audioSample;\n this.generators = generators;\n this.exclusiveClass = this.generators[generatorTypes.exclusiveClass];\n this.modulatedGenerators = new Int16Array(generators);\n this.modulators = modulators;\n this.filter = new LowpassFilter(sampleRate);\n this.velocity = velocity;\n this.midiNote = midiNote;\n this.startTime = currentTime;\n this.targetKey = targetKey;\n this.realKey = realKey;\n this.volumeEnvelope = new VolumeEnvelope(\n sampleRate,\n generators[generatorTypes.sustainVolEnv]\n );\n }\n\n /**\n * Copies a voice.\n */\n public static copyFrom(voice: Voice, currentTime: number, realKey: number) {\n const sampleToCopy = voice.sample;\n const sample = new AudioSample(\n sampleToCopy.sampleData,\n sampleToCopy.playbackStep,\n sampleToCopy.cursor,\n sampleToCopy.rootKey,\n sampleToCopy.loopStart,\n sampleToCopy.loopEnd,\n sampleToCopy.end,\n sampleToCopy.loopingMode\n );\n return new Voice(\n voice.volumeEnvelope.sampleRate,\n sample,\n voice.midiNote,\n voice.velocity,\n currentTime,\n voice.targetKey,\n realKey,\n new Int16Array(voice.generators),\n voice.modulators.map(Modulator.copyFrom.bind(Modulator))\n );\n }\n\n /**\n * Releases the voice as exclusiveClass.\n */\n public exclusiveRelease(currentTime: number) {\n this.release(currentTime, MIN_EXCLUSIVE_LENGTH);\n this.modulatedGenerators[generatorTypes.releaseVolEnv] =\n EXCLUSIVE_CUTOFF_TIME; // Make the release nearly instant\n this.modulatedGenerators[generatorTypes.releaseModEnv] =\n EXCLUSIVE_MOD_CUTOFF_TIME;\n VolumeEnvelope.recalculate(this);\n ModulationEnvelope.recalculate(this);\n }\n\n /**\n * Stops the voice\n * @param currentTime\n * @param minNoteLength minimum note length in seconds\n */\n public release(currentTime: number, minNoteLength = MIN_NOTE_LENGTH) {\n this.releaseStartTime = currentTime;\n // Check if the note is shorter than the min note time, if so, extend it\n if (this.releaseStartTime - this.startTime < minNoteLength) {\n this.releaseStartTime = this.startTime + minNoteLength;\n }\n }\n}\n\n/**\n * @param preset the preset to get voices for\n * @param midiNote the MIDI note to use\n * @param velocity the velocity to use\n * @param realKey the real MIDI note if the \"midiNote\" was changed by MIDI Tuning Standard\n * @returns output is an array of Voices\n */\nexport function getVoicesForPresetInternal(\n this: SpessaSynthProcessor,\n preset: BasicPreset,\n midiNote: number,\n velocity: number,\n realKey: number\n): VoiceList {\n const voices: VoiceList = preset\n .getSynthesisData(midiNote, velocity)\n .reduce((voices: VoiceList, synthesisData) => {\n if (synthesisData.sample.getAudioData() === undefined) {\n SpessaSynthWarn(\n `Discarding invalid sample: ${synthesisData.sample.name}`\n );\n return voices;\n }\n\n // Create the generator list\n const generators = new Int16Array(GENERATORS_AMOUNT);\n // Apply and sum the gens\n for (let i = 0; i < 60; i++) {\n generators[i] = addAndClampGenerator(\n i,\n synthesisData.presetGenerators,\n synthesisData.instrumentGenerators\n );\n }\n\n // EMU initial attenuation correction, multiply initial attenuation by 0.4!\n // All EMU sound cards have this quirk, and all sf2 editors and players emulate it too\n generators[generatorTypes.initialAttenuation] = Math.floor(\n generators[generatorTypes.initialAttenuation] * 0.4\n );\n\n // Key override\n let rootKey = synthesisData.sample.originalKey;\n if (generators[generatorTypes.overridingRootKey] > -1) {\n rootKey = generators[generatorTypes.overridingRootKey];\n }\n\n let targetKey = midiNote;\n if (generators[generatorTypes.keyNum] > -1) {\n targetKey = generators[generatorTypes.keyNum];\n }\n\n // Determine looping mode now. if the loop is too small, disable\n const loopStart = synthesisData.sample.loopStart;\n const loopEnd = synthesisData.sample.loopEnd;\n const loopingMode = generators[\n generatorTypes.sampleModes\n ] as SampleLoopingMode;\n /**\n * Create the sample\n * offsets are calculated at note on time (to allow for modulation of them)\n */\n const sampleData = synthesisData.sample.getAudioData();\n const audioSample: AudioSample = new AudioSample(\n sampleData,\n (synthesisData.sample.sampleRate / this.sampleRate) *\n Math.pow(2, synthesisData.sample.pitchCorrection / 1200), // Cent tuning\n 0,\n rootKey,\n loopStart,\n loopEnd,\n Math.floor(sampleData.length) - 1,\n loopingMode\n );\n // Velocity override\n if (generators[generatorTypes.velocity] > -1) {\n velocity = generators[generatorTypes.velocity];\n }\n\n // Uncomment to print debug info\n voices.push(\n new Voice(\n this.sampleRate,\n audioSample,\n midiNote,\n velocity,\n this.currentSynthTime,\n targetKey,\n realKey,\n generators,\n synthesisData.modulators.map(\n Modulator.copyFrom.bind(Modulator)\n )\n )\n );\n return voices;\n }, []);\n // Cache the voice\n this.setCachedVoice(preset, midiNote, velocity, voices);\n return voices.map((v) => Voice.copyFrom(v, this.currentSynthTime, realKey));\n}\n\n/**\n * @param channel channel to get voices for\n * @param midiNote the MIDI note to use\n * @param velocity the velocity to use\n * @param realKey the real MIDI note if the \"midiNote\" was changed by MIDI Tuning Standard\n * @returns output is an array of Voices\n */\nexport function getVoicesInternal(\n this: SpessaSynthProcessor,\n channel: number,\n midiNote: number,\n velocity: number,\n realKey: number\n): VoiceList {\n const channelObject = this.midiChannels[channel];\n\n // Override patch\n const overridePatch = this.keyModifierManager.hasOverridePatch(\n channel,\n midiNote\n );\n\n let preset = channelObject.preset;\n if (!preset) {\n SpessaSynthWarn(`No preset for channel ${channel}!`);\n return [];\n }\n let patch: MIDIPatch = {\n ...preset\n };\n if (overridePatch) {\n patch = this.keyModifierManager.getPatch(channel, midiNote);\n }\n\n const cached = this.getCachedVoice(patch, midiNote, velocity);\n // If cached, return it!\n if (cached !== undefined) {\n return cached.map((v) =>\n Voice.copyFrom(v, this.currentSynthTime, realKey)\n );\n }\n\n // Not cached...\n if (overridePatch) {\n preset = this.soundBankManager.getPreset(\n patch,\n this.privateProps.masterParameters.midiSystem\n );\n }\n return this.getVoicesForPreset(preset, midiNote, velocity, realKey);\n}\n","import { arrayToHexString, consoleColors } from \"../../../utils/other\";\nimport { SpessaSynthInfo, SpessaSynthWarn } from \"../../../utils/loggin\";\nimport { ALL_CHANNELS_OR_DIFFERENT_ACTION } from \"../engine_components/synth_constants\";\nimport { BankSelectHacks } from \"../../../utils/midi_hacks\";\nimport { readBinaryString } from \"../../../utils/byte_functions/string\";\nimport { NON_CC_INDEX_OFFSET } from \"../engine_components/controller_tables\";\nimport { generatorTypes, type ModulatorSourceEnum, modulatorSources } from \"../../../soundbank/enums\";\nimport type { SpessaSynthProcessor } from \"../../processor\";\nimport type { IndexedByteArray } from \"../../../utils/indexed_array\";\nimport { midiControllers } from \"../../../midi/enums\";\nimport { customControllers, synthDisplayTypes } from \"../../enums\";\n\n/**\n * Calculates frequency for MIDI Tuning Standard.\n * @param byte1 The first byte (midi note).\n * @param byte2 The second byte (most significant bits).\n * @param byte3 The third byte (the least significant bits).\n * @return An object containing the MIDI note and the cent tuning value.\n */\nfunction getTuning(\n byte1: number,\n byte2: number,\n byte3: number\n): { midiNote: number; centTuning: number | null } {\n const midiNote = byte1;\n const fraction = (byte2 << 7) | byte3; // Combine byte2 and byte3 into a 14-bit number\n\n // No change\n if (byte1 === 0x7f && byte2 === 0x7f && byte3 === 0x7f) {\n return { midiNote: -1, centTuning: null };\n }\n\n // Calculate cent tuning\n return { midiNote: midiNote, centTuning: fraction * 0.0061 };\n}\n\ntype TypedArray =\n | Uint8Array\n | Int8Array\n | Uint16Array\n | Int16Array\n | Uint32Array\n | Int32Array\n | Uint8ClampedArray\n | Float32Array\n | Float64Array;\n\n/**\n * Executes a system exclusive message for the synthesizer.\n * @param syx The system exclusive message as an array of bytes.\n * @param channelOffset The channel offset to apply (default is 0).\n * @remarks\n * This is a rather extensive method that handles various system exclusive messages,\n * including Roland GS, MIDI Tuning Standard, and other non-realtime messages.\n */\nexport function systemExclusiveInternal(\n this: SpessaSynthProcessor,\n syx: number[] | IndexedByteArray | TypedArray,\n channelOffset = 0\n) {\n const type = syx[0];\n if (\n this.privateProps.masterParameters.deviceID !==\n ALL_CHANNELS_OR_DIFFERENT_ACTION &&\n syx[1] !== 0x7f\n ) {\n if (this.privateProps.masterParameters.deviceID !== syx[1]) {\n // Not our device ID\n return;\n }\n }\n\n // A helper function to log nicely\n function niceLogging(\n channel: number,\n value: number | string,\n what: string,\n units: string\n ) {\n SpessaSynthInfo(\n `%cChannel %c${channel}%c ${what}. %c${value} ${units}%c, with %c${arrayToHexString(syx)}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n }\n\n function notRecognized() {\n // This is some other GS sysex...\n SpessaSynthInfo(\n `%cUnrecognized Roland %cGS %cSysEx: %c${arrayToHexString(syx)}`,\n consoleColors.warn,\n consoleColors.recognized,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n }\n\n switch (type) {\n default:\n SpessaSynthInfo(\n `%cUnrecognized SysEx: %c${arrayToHexString(syx)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n break;\n\n // Non realtime\n case 0x7e:\n case 0x7f:\n switch (syx[2]) {\n case 0x04: {\n let cents;\n // Device control\n switch (syx[3]) {\n case 0x01: {\n // Main volume\n const vol = (syx[5] << 7) | syx[4];\n this.setMIDIVolume(vol / 16384);\n SpessaSynthInfo(\n `%cMaster Volume. Volume: %c${vol}`,\n consoleColors.info,\n consoleColors.value\n );\n break;\n }\n\n case 0x02: {\n // Main balance\n // Midi spec page 62\n const balance = (syx[5] << 7) | syx[4];\n const pan = (balance - 8192) / 8192;\n this.setMasterParameter(\"masterPan\", pan);\n SpessaSynthInfo(\n `%cMaster Pan. Pan: %c${pan}`,\n consoleColors.info,\n consoleColors.value\n );\n break;\n }\n\n case 0x03: {\n // Fine-tuning\n const tuningValue = ((syx[5] << 7) | syx[6]) - 8192;\n cents = Math.floor(tuningValue / 81.92); // [-100;+99] cents range\n this.setMasterTuning(cents);\n SpessaSynthInfo(\n `%cMaster Fine Tuning. Cents: %c${cents}`,\n consoleColors.info,\n consoleColors.value\n );\n break;\n }\n\n case 0x04: {\n // Coarse tuning\n // Lsb is ignored\n const semitones = syx[5] - 64;\n cents = semitones * 100;\n this.setMasterTuning(cents);\n SpessaSynthInfo(\n `%cMaster Coarse Tuning. Cents: %c${cents}`,\n consoleColors.info,\n consoleColors.value\n );\n break;\n }\n\n default:\n SpessaSynthInfo(\n `%cUnrecognized MIDI Device Control Real-time message: %c${arrayToHexString(syx)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n }\n break;\n }\n\n case 0x09:\n // Gm system related\n if (syx[3] === 0x01) {\n SpessaSynthInfo(\"%cGM1 system on\", consoleColors.info);\n this.setMasterParameter(\"midiSystem\", \"gm\");\n } else if (syx[3] === 0x03) {\n SpessaSynthInfo(\"%cGM2 system on\", consoleColors.info);\n this.setMasterParameter(\"midiSystem\", \"gm2\");\n } else {\n SpessaSynthInfo(\n \"%cGM system off, defaulting to GS\",\n consoleColors.info\n );\n this.setMasterParameter(\"midiSystem\", \"gs\");\n }\n break;\n\n // MIDI Tuning standard\n // https://midi.org/midi-tuning-updated-specification\n case 0x08: {\n let currentMessageIndex = 4;\n switch (syx[3]) {\n // Bulk tuning dump: all 128 notes\n case 0x01: {\n const program = syx[currentMessageIndex++];\n // Read the name\n const tuningName = readBinaryString(\n syx,\n 16,\n currentMessageIndex\n );\n currentMessageIndex += 16;\n if (syx.length < 384) {\n SpessaSynthWarn(\n `The Bulk Tuning Dump is too short! (${syx.length} bytes, at least 384 are expected)`\n );\n return;\n }\n // 128 frequencies follow\n for (let i = 0; i < 128; i++) {\n // Set the given tuning to the program\n this.privateProps.tunings[program][i] =\n getTuning(\n syx[currentMessageIndex++],\n syx[currentMessageIndex++],\n syx[currentMessageIndex++]\n );\n }\n SpessaSynthInfo(\n `%cBulk Tuning Dump %c${tuningName}%c Program: %c${program}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.recognized\n );\n break;\n }\n\n // Single note change\n // Single note change bank\n case 0x02:\n case 0x07: {\n if (syx[3] === 0x07) {\n // Skip the bank\n currentMessageIndex++;\n }\n // Get program and number of changes\n const tuningProgram = syx[currentMessageIndex++];\n const numberOfChanges = syx[currentMessageIndex++];\n for (let i = 0; i < numberOfChanges; i++) {\n // Set the given tuning to the program\n this.privateProps.tunings[tuningProgram][\n syx[currentMessageIndex++]\n ] = getTuning(\n syx[currentMessageIndex++],\n syx[currentMessageIndex++],\n syx[currentMessageIndex++]\n );\n }\n SpessaSynthInfo(\n `%cSingle Note Tuning. Program: %c${tuningProgram}%c Keys affected: %c${numberOfChanges}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n break;\n }\n\n // Octave tuning (1 byte)\n // And octave tuning (2 bytes)\n case 0x09:\n case 0x08: {\n // Get tuning:\n const newOctaveTuning = new Int8Array(12);\n // Start from bit 7\n if (syx[3] === 0x08) {\n // 1 byte tuning: 0 is -64 cents, 64 is 0, 127 is +63\n for (let i = 0; i < 12; i++) {\n newOctaveTuning[i] = syx[7 + i] - 64;\n }\n } else {\n // 2 byte tuning. Like fine tune: 0 is -100 cents, 8192 is 0 cents, 16,383 is +100 cents\n for (let i = 0; i < 24; i += 2) {\n const tuning =\n ((syx[7 + i] << 7) | syx[8 + i]) - 8192;\n newOctaveTuning[i / 2] = Math.floor(\n tuning / 81.92\n ); // Map to [-100;+99] cents\n }\n }\n // Apply to channels (ordered from 0)\n // Bit 1: 14 and 15\n if ((syx[4] & 1) === 1) {\n this.midiChannels[\n 14 + channelOffset\n ].setOctaveTuning(newOctaveTuning);\n }\n if (((syx[4] >> 1) & 1) === 1) {\n this.midiChannels[\n 15 + channelOffset\n ].setOctaveTuning(newOctaveTuning);\n }\n\n // Bit 2: channels 7 to 13\n for (let i = 0; i < 7; i++) {\n const bit = (syx[5] >> i) & 1;\n if (bit === 1) {\n this.midiChannels[\n 7 + i + channelOffset\n ].setOctaveTuning(newOctaveTuning);\n }\n }\n\n // Bit 3: channels 0 to 16\n for (let i = 0; i < 7; i++) {\n const bit = (syx[6] >> i) & 1;\n if (bit === 1) {\n this.midiChannels[\n i + channelOffset\n ].setOctaveTuning(newOctaveTuning);\n }\n }\n\n SpessaSynthInfo(\n `%cMIDI Octave Scale ${\n syx[3] === 0x08 ? \"(1 byte)\" : \"(2 bytes)\"\n } tuning via Tuning: %c${newOctaveTuning.join(\" \")}`,\n consoleColors.info,\n consoleColors.value\n );\n break;\n }\n\n default:\n SpessaSynthInfo(\n `%cUnrecognized MIDI Tuning standard message: %c${arrayToHexString(syx)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n break;\n }\n break;\n }\n\n default:\n SpessaSynthInfo(\n `%cUnrecognized MIDI Realtime/non realtime message: %c${arrayToHexString(syx)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n }\n break;\n\n // This is a roland sysex\n // http://www.bandtrax.com.au/sysex.htm\n // https://cdn.roland.com/assets/media/pdf/AT-20R_30R_MI.pdf\n case 0x41:\n if (syx[2] === 0x42 && syx[3] === 0x12) {\n // This is a GS sysex\n const messageValue = syx[7];\n // Syx[5] and [6] is the system parameter, syx[7] is the value\n // Either patch common or SC-88 mode set\n if (syx[4] === 0x40 || (syx[4] === 0x00 && syx[6] === 0x7f)) {\n // This is a channel parameter\n if ((syx[5] & 0x10) > 0) {\n // This is an individual part (channel) parameter\n // Determine the channel 0 means channel 10 (default), 1 means 1 etc.\n // SC88 manual page 196\n const channel =\n [\n 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13,\n 14, 15\n ][syx[5] & 0x0f] + channelOffset;\n // For example, 0x1A means A = 11, which corresponds to channel 12 (counting from 1)\n const channelObject = this.midiChannels[channel];\n switch (syx[6]) {\n default:\n // This is some other GS sysex...\n notRecognized();\n break;\n\n case 0x15: {\n // This is the Use for Drum Part sysex (multiple drums)\n const isDrums =\n messageValue > 0 && syx[5] >> 4 > 0; // If set to other than 0, is a drum channel\n channelObject.setGSDrums(isDrums);\n SpessaSynthInfo(\n `%cChannel %c${channel}%c ${\n isDrums\n ? \"is now a drum channel\"\n : \"now isn't a drum channel\"\n }%c via: %c${arrayToHexString(syx)}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.value\n );\n return;\n }\n\n case 0x16: {\n // This is the pitch key shift sysex\n const keyShift = messageValue - 64;\n channelObject.setCustomController(\n customControllers.channelKeyShift,\n keyShift\n );\n niceLogging(\n channel,\n keyShift,\n \"key shift\",\n \"keys\"\n );\n return;\n }\n\n // Pan position\n case 0x1c: {\n // 0 is random\n const panPosition = messageValue;\n if (panPosition === 0) {\n channelObject.randomPan = true;\n SpessaSynthInfo(\n `%cRandom pan is set to %cON%c for %c${channel}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.value\n );\n } else {\n channelObject.randomPan = false;\n channelObject.controllerChange(\n midiControllers.pan,\n panPosition\n );\n }\n break;\n }\n\n // Chorus send\n case 0x21:\n channelObject.controllerChange(\n midiControllers.chorusDepth,\n messageValue\n );\n break;\n\n // Reverb send\n case 0x22:\n channelObject.controllerChange(\n midiControllers.reverbDepth,\n messageValue\n );\n break;\n\n case 0x40:\n case 0x41:\n case 0x42:\n case 0x43:\n case 0x44:\n case 0x45:\n case 0x46:\n case 0x47:\n case 0x48:\n case 0x49:\n case 0x4a:\n case 0x4b: {\n // Scale tuning: up to 12 bytes\n const tuningBytes = syx.length - 9; // Data starts at 7, minus checksum and f7\n // Read em bytes\n const newTuning = new Int8Array(12);\n for (let i = 0; i < tuningBytes; i++) {\n newTuning[i] = syx[i + 7] - 64;\n }\n channelObject.setOctaveTuning(newTuning);\n const cents = messageValue - 64;\n niceLogging(\n channel,\n newTuning.join(\" \"),\n \"octave scale tuning\",\n \"cents\"\n );\n channelObject.setTuning(cents);\n break;\n }\n }\n return;\n } else if ((syx[5] & 0x20) > 0) {\n // This is a channel parameter also\n // This is an individual part (channel) parameter\n // Determine the channel 0 means channel 10 (default), 1 means 1 etc.\n const channel =\n [\n 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13,\n 14, 15\n ][syx[5] & 0x0f] + channelOffset;\n // For example, 0x1A means A = 11, which corresponds to channel 12 (counting from 1)\n const channelObject = this.midiChannels[channel];\n const centeredValue = messageValue - 64;\n const normalizedValue = centeredValue / 64;\n const normalizedNotCentered = messageValue / 128;\n\n // Setup receivers for cc to parameter (sc-88 manual page 198)\n const setupReceivers = (\n source: number,\n sourceName: string,\n bipolar = false\n ) => {\n switch (syx[6] & 0x0f) {\n case 0x00:\n // See https://github.com/spessasus/SpessaSynth/issues/154\n // Pitch control\n // Special case:\n // If the source is a pitch wheel, it's a strange way of setting the bend range\n // Testcase: th07_03.mid\n if (\n source ===\n NON_CC_INDEX_OFFSET +\n modulatorSources.pitchWheel\n ) {\n channelObject.controllerChange(\n midiControllers.registeredParameterMSB,\n 0x0\n );\n channelObject.controllerChange(\n midiControllers.registeredParameterLSB,\n 0x0\n );\n channelObject.controllerChange(\n midiControllers.dataEntryMSB,\n Math.floor(centeredValue)\n );\n } else {\n channelObject.sysExModulators.setModulator(\n source as ModulatorSourceEnum,\n generatorTypes.fineTune,\n centeredValue * 100,\n bipolar\n );\n niceLogging(\n channel,\n centeredValue,\n `${sourceName} pitch control`,\n \"semitones\"\n );\n }\n break;\n\n case 0x01:\n // Cutoff\n channelObject.sysExModulators.setModulator(\n source as ModulatorSourceEnum,\n generatorTypes.initialFilterFc,\n normalizedValue * 9600,\n bipolar\n );\n niceLogging(\n channel,\n normalizedValue * 9600,\n `${sourceName} pitch control`,\n \"cents\"\n );\n break;\n\n case 0x02:\n // Amplitude\n channelObject.sysExModulators.setModulator(\n source as ModulatorSourceEnum,\n generatorTypes.initialAttenuation,\n normalizedValue * 960, // Spec says \"100%\" so 960cB in sf2\n bipolar\n );\n niceLogging(\n channel,\n normalizedValue * 960,\n `${sourceName} amplitude`,\n \"cB\"\n );\n break;\n\n // Rate control is ignored as it is in hertz\n\n case 0x04:\n // LFO1 pitch depth\n channelObject.sysExModulators.setModulator(\n source as ModulatorSourceEnum,\n generatorTypes.vibLfoToPitch,\n normalizedNotCentered * 600,\n bipolar\n );\n niceLogging(\n channel,\n normalizedNotCentered * 600,\n `${sourceName} LFO1 pitch depth`,\n \"cents\"\n );\n break;\n\n case 0x05:\n // LFO1 filter depth\n channelObject.sysExModulators.setModulator(\n source as ModulatorSourceEnum,\n generatorTypes.vibLfoToFilterFc,\n normalizedNotCentered * 2400,\n bipolar\n );\n niceLogging(\n channel,\n normalizedNotCentered * 2400,\n `${sourceName} LFO1 filter depth`,\n \"cents\"\n );\n break;\n\n case 0x06:\n // LFO1 amplitude depth\n channelObject.sysExModulators.setModulator(\n source as ModulatorSourceEnum,\n generatorTypes.vibLfoToVolume,\n normalizedValue * 960,\n bipolar\n );\n niceLogging(\n channel,\n normalizedValue * 960,\n `${sourceName} LFO1 amplitude depth`,\n \"cB\"\n );\n break;\n\n // Rate control is ignored as it is in hertz\n\n case 0x08:\n // LFO2 pitch depth\n channelObject.sysExModulators.setModulator(\n source as ModulatorSourceEnum,\n generatorTypes.modLfoToPitch,\n normalizedNotCentered * 600,\n bipolar\n );\n niceLogging(\n channel,\n normalizedNotCentered * 600,\n `${sourceName} LFO2 pitch depth`,\n \"cents\"\n );\n break;\n\n case 0x09:\n // LFO2 filter depth\n channelObject.sysExModulators.setModulator(\n source as ModulatorSourceEnum,\n generatorTypes.modLfoToFilterFc,\n normalizedNotCentered * 2400,\n bipolar\n );\n niceLogging(\n channel,\n normalizedNotCentered * 2400,\n `${sourceName} LFO2 filter depth`,\n \"cents\"\n );\n break;\n\n case 0x0a:\n // LFO2 amplitude depth\n channelObject.sysExModulators.setModulator(\n source as ModulatorSourceEnum,\n generatorTypes.modLfoToVolume,\n normalizedValue * 960,\n bipolar\n );\n niceLogging(\n channel,\n normalizedValue * 960,\n `${sourceName} LFO2 amplitude depth`,\n \"cB\"\n );\n break;\n }\n };\n\n // SC88 manual page 198\n switch (syx[6] & 0xf0) {\n default:\n // This is some other GS sysex...\n notRecognized();\n break;\n\n case 0x00:\n // Modulation wheel\n setupReceivers(\n midiControllers.modulationWheel,\n \"mod wheel\"\n );\n break;\n\n case 0x10:\n // Pitch bend\n setupReceivers(\n NON_CC_INDEX_OFFSET +\n modulatorSources.pitchWheel,\n \"pitch wheel\",\n true\n );\n break;\n\n case 0x20:\n // Channel pressure\n setupReceivers(\n NON_CC_INDEX_OFFSET +\n modulatorSources.channelPressure,\n \"channel pressure\"\n );\n break;\n\n case 0x30:\n // Poly pressure\n setupReceivers(\n NON_CC_INDEX_OFFSET +\n modulatorSources.polyPressure,\n \"poly pressure\"\n );\n break;\n }\n return;\n } else if (syx[5] === 0x00) {\n // This is a global system parameter\n switch (syx[6]) {\n default:\n notRecognized();\n break;\n\n case 0x7f:\n // Roland mode set\n // GS mode set\n if (messageValue === 0x00) {\n // This is a GS reset\n SpessaSynthInfo(\n \"%cGS Reset received!\",\n consoleColors.info\n );\n this.resetAllControllers(false);\n this.setMasterParameter(\"midiSystem\", \"gs\");\n } else if (messageValue === 0x7f) {\n // GS mode off\n SpessaSynthInfo(\n \"%cGS system off, switching to GM2\",\n consoleColors.info\n );\n this.resetAllControllers(false);\n this.setMasterParameter(\n \"midiSystem\",\n \"gm2\"\n );\n }\n break;\n\n case 0x06:\n // Roland master pan\n SpessaSynthInfo(\n `%cRoland GS Master Pan set to: %c${messageValue}%c with: %c${arrayToHexString(\n syx\n )}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n this.setMasterParameter(\n \"masterPan\",\n (messageValue - 64) / 64\n );\n break;\n\n case 0x04:\n // Roland GS master volume\n SpessaSynthInfo(\n `%cRoland GS Master Volume set to: %c${messageValue}%c with: %c${arrayToHexString(\n syx\n )}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n this.setMIDIVolume(messageValue / 127);\n break;\n\n case 0x05: {\n // Roland master key shift (transpose)\n const transpose = messageValue - 64;\n SpessaSynthInfo(\n `%cRoland GS Master Key-Shift set to: %c${transpose}%c with: %c${arrayToHexString(\n syx\n )}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n this.setMasterTuning(transpose * 100);\n break;\n }\n }\n return;\n } else if (syx[5] === 0x01) {\n // This is a global system parameter also\n switch (syx[6]) {\n default:\n notRecognized();\n break;\n\n case 0x00: {\n // Patch name. cool!\n // Not sure what to do with it, but let's log it!\n const patchName = readBinaryString(syx, 16, 7);\n SpessaSynthInfo(\n `%cGS Patch name: %c${patchName}`,\n consoleColors.info,\n consoleColors.value\n );\n break;\n }\n\n case 0x33:\n // Reverb level\n SpessaSynthInfo(\n `%cGS Reverb level: %c${messageValue}`,\n consoleColors.info,\n consoleColors.value\n );\n // 64 is the default\n this.privateProps.reverbSend =\n messageValue / 64;\n break;\n\n // Unsupported reverb params\n case 0x30:\n case 0x31:\n case 0x32:\n case 0x34:\n case 0x35:\n case 0x37:\n SpessaSynthInfo(\n `%cUnsupported GS Reverb Parameter: %c${syx[6].toString(16)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n break;\n\n case 0x3a:\n // Chorus level\n SpessaSynthInfo(\n `%cGS Chorus level: %c${messageValue}`,\n consoleColors.info,\n consoleColors.value\n );\n // 64 is the default\n this.privateProps.chorusSend =\n messageValue / 64;\n break;\n\n // Unsupported chorus params\n case 0x38:\n case 0x39:\n case 0x3b:\n case 0x3c:\n case 0x3d:\n case 0x3e:\n case 0x3f:\n case 0x40:\n SpessaSynthInfo(\n `%cUnsupported GS Chorus Parameter: %c${syx[6].toString(16)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n break;\n }\n }\n } else {\n // This is some other GS sysex...\n notRecognized();\n }\n return;\n } else if (syx[2] === 0x45 && syx[3] === 0x12) {\n // 0x45: GS Display Data, 0x12: DT1 (Device Transmit)\n // Check for embedded copyright\n // (roland SC display sysex) http://www.bandtrax.com.au/sysex.htm\n\n if (\n syx[4] === 0x10 && // Sound Canvas Display\n syx[6] === 0x00 // Data follows\n ) {\n if (syx[5] === 0x00) {\n // Display letters\n // Get the text\n // And header ends with (checksum) F7\n const text = new Uint8Array(\n syx.slice(7, syx.length - 2)\n );\n this.privateProps.callEvent(\"synthDisplay\", {\n displayData: text,\n displayType: synthDisplayTypes.soundCanvasText\n });\n } else if (syx[5] === 0x01) {\n // Matrix display\n // Get the data\n // And header ends with (checksum) F7\n const dotMatrixData = new Uint8Array(\n syx.slice(7, syx.length - 3)\n );\n this.privateProps.callEvent(\"synthDisplay\", {\n displayData: dotMatrixData,\n displayType: synthDisplayTypes.soundCanvasDotMatrix\n });\n SpessaSynthInfo(\n `%cRoland SC Display Dot Matrix via: %c${arrayToHexString(\n syx\n )}`,\n consoleColors.info,\n consoleColors.value\n );\n } else {\n // This is some other GS sysex...\n notRecognized();\n }\n }\n } else if (syx[2] === 0x16 && syx[3] === 0x12 && syx[4] === 0x10) {\n // This is a roland master volume message\n this.setMIDIVolume(syx[7] / 100);\n SpessaSynthInfo(\n `%cRoland Master Volume control set to: %c${syx[7]}%c via: %c${arrayToHexString(\n syx\n )}`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info,\n consoleColors.value\n );\n return;\n } else {\n // This is something else...\n SpessaSynthInfo(\n `%cUnrecognized Roland SysEx: %c${arrayToHexString(syx)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n return;\n }\n break;\n\n // Yamaha\n // http://www.studio4all.de/htmle/main91.html\n case 0x43:\n // XG sysex\n if (syx[2] === 0x4c) {\n // XG system parameter\n if (syx[3] === 0x00 && syx[4] === 0x00) {\n switch (syx[5]) {\n // Master volume\n case 0x04: {\n const vol = syx[6];\n this.setMIDIVolume(vol / 127);\n SpessaSynthInfo(\n `%cXG master volume. Volume: %c${vol}`,\n consoleColors.info,\n consoleColors.recognized\n );\n break;\n }\n\n // Master transpose\n case 0x06: {\n const transpose = syx[6] - 64;\n this.setMasterParameter(\"transposition\", transpose);\n SpessaSynthInfo(\n `%cXG master transpose. Volume: %c${transpose}`,\n consoleColors.info,\n consoleColors.recognized\n );\n break;\n }\n\n // XG on\n case 0x7e:\n SpessaSynthInfo(\n \"%cXG system on\",\n consoleColors.info\n );\n this.resetAllControllers(false);\n this.setMasterParameter(\"midiSystem\", \"xg\");\n break;\n }\n } else if (syx[3] === 0x08) {\n // XG part parameter\n if (\n !BankSelectHacks.isSystemXG(\n this.privateProps.masterParameters.midiSystem\n )\n ) {\n return;\n }\n const channel = syx[4] + channelOffset;\n if (channel >= this.midiChannels.length) {\n // Invalid channel\n return;\n }\n const channelObject = this.midiChannels[channel];\n const value = syx[6];\n switch (syx[5]) {\n // Bank-select MSB\n case 0x01:\n channelObject.controllerChange(\n midiControllers.bankSelect,\n value\n );\n break;\n\n // Bank-select LSB\n case 0x02:\n channelObject.controllerChange(\n midiControllers.bankSelectLSB,\n value\n );\n break;\n\n // Program change\n case 0x03:\n channelObject.programChange(value);\n break;\n\n // Note shift\n case 0x08: {\n if (channelObject.drumChannel) {\n return;\n }\n channelObject.channelTransposeKeyShift = value - 64;\n break;\n }\n\n // Volume\n case 0x0b:\n channelObject.controllerChange(\n midiControllers.mainVolume,\n value\n );\n break;\n\n // Pan position\n case 0x0e: {\n const pan = value;\n if (pan === 0) {\n // 0 means random\n channelObject.randomPan = true;\n SpessaSynthInfo(\n `%cRandom pan is set to %cON%c for %c${channel}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.value\n );\n } else {\n channelObject.controllerChange(\n midiControllers.pan,\n pan\n );\n }\n break;\n }\n\n // Reverb\n case 0x13:\n channelObject.controllerChange(\n midiControllers.reverbDepth,\n value\n );\n break;\n\n // Chorus\n case 0x12:\n channelObject.controllerChange(\n midiControllers.chorusDepth,\n value\n );\n break;\n\n default:\n SpessaSynthInfo(\n `%cUnrecognized Yamaha XG Part Setup: %c${syx[5]\n .toString(16)\n .toUpperCase()}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n }\n } else if (\n syx[3] === 0x06 && // XG System parameter\n syx[4] === 0x00 // System Byte\n ) {\n // Displayed letters (remove F7 at the end)\n // Include byte 5 as it seems to be line information (useful)\n const textData = new Uint8Array(\n syx.slice(5, syx.length - 1)\n );\n this.privateProps.callEvent(\"synthDisplay\", {\n displayData: textData,\n displayType: synthDisplayTypes.yamahaXGText\n });\n } else if (\n BankSelectHacks.isSystemXG(\n this.privateProps.masterParameters.midiSystem\n )\n ) {\n SpessaSynthInfo(\n `%cUnrecognized Yamaha XG SysEx: %c${arrayToHexString(syx)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n }\n } else {\n if (\n BankSelectHacks.isSystemXG(\n this.privateProps.masterParameters.midiSystem\n )\n ) {\n SpessaSynthInfo(\n `%cUnrecognized Yamaha SysEx: %c${arrayToHexString(syx)}`,\n consoleColors.warn,\n consoleColors.unrecognized\n );\n }\n }\n break;\n }\n}\n","import type { SynthSystem } from \"../../types\";\nimport { type SpessaSynthProcessor } from \"../../processor\";\nimport type { MIDIPatchNamed } from \"../../../soundbank/basic_soundbank/midi_patch\";\n\n/**\n * Represents a snapshot of a single channel's state in the synthesizer.\n */\nexport class ChannelSnapshot {\n /**\n * The MIDI patch that the channel is using.\n */\n public patch: MIDIPatchNamed;\n\n /**\n * Indicates whether the channel's program change is disabled.\n */\n public lockPreset: boolean;\n\n /**\n * Indicates the MIDI system when the preset was locked\n */\n public lockedSystem: SynthSystem;\n\n /**\n * The array of all MIDI controllers (in 14-bit values) with the modulator sources at the end.\n */\n public midiControllers: Int16Array;\n\n /**\n * An array of booleans, indicating if the controller with a current index is locked.\n */\n public lockedControllers: boolean[];\n\n /**\n * Array of custom (not SF2) control values such as RPN pitch tuning, transpose, modulation depth, etc.\n */\n public customControllers: Float32Array;\n\n /**\n * Indicates whether the channel vibrato is locked.\n */\n public lockVibrato: boolean;\n\n /**\n * The channel's vibrato settings.\n * @property depth Vibrato depth, in gain.\n * @property delay Vibrato delay from note on in seconds.\n * @property rate Vibrato rate in Hz.\n */\n public channelVibrato: { depth: number; delay: number; rate: number };\n\n /**\n * Key shift for the channel.\n */\n public channelTransposeKeyShift: number;\n\n /**\n * The channel's octave tuning in cents.\n */\n public channelOctaveTuning: Int8Array;\n\n /**\n * Indicates whether the channel is muted.\n */\n public isMuted: boolean;\n\n /**\n * Indicates whether the channel is a drum channel.\n */\n public drumChannel: boolean;\n\n /**\n * The channel number this snapshot represents.\n */\n public channelNumber: number;\n\n // Creates a new channel snapshot.\n public constructor(\n patch: MIDIPatchNamed,\n lockPreset: boolean,\n lockedSystem: SynthSystem,\n midiControllers: Int16Array,\n lockedControllers: boolean[],\n customControllers: Float32Array,\n lockVibrato: boolean,\n channelVibrato: {\n delay: number;\n depth: number;\n rate: number;\n },\n channelTransposeKeyShift: number,\n channelOctaveTuning: Int8Array,\n isMuted: boolean,\n drumChannel: boolean,\n channelNumber: number\n ) {\n this.patch = patch;\n this.lockPreset = lockPreset;\n this.lockedSystem = lockedSystem;\n this.midiControllers = midiControllers;\n this.lockedControllers = lockedControllers;\n this.customControllers = customControllers;\n this.lockVibrato = lockVibrato;\n this.channelVibrato = channelVibrato;\n this.channelTransposeKeyShift = channelTransposeKeyShift;\n this.channelOctaveTuning = channelOctaveTuning;\n this.isMuted = isMuted;\n this.drumChannel = drumChannel;\n this.channelNumber = channelNumber;\n }\n\n /**\n * Creates a copy of existing snapshot.\n * @param snapshot The snapshot to create a copy from.\n */\n public static copyFrom(snapshot: ChannelSnapshot) {\n return new ChannelSnapshot(\n { ...snapshot.patch },\n snapshot.lockPreset,\n snapshot.lockedSystem,\n snapshot.midiControllers.slice(),\n [...snapshot.lockedControllers],\n snapshot.customControllers.slice(),\n snapshot.lockVibrato,\n { ...snapshot.channelVibrato },\n snapshot.channelTransposeKeyShift,\n snapshot.channelOctaveTuning,\n snapshot.isMuted,\n snapshot.drumChannel,\n snapshot.channelNumber\n );\n }\n\n /**\n * Creates a snapshot of the channel's state.\n * @param spessaSynthProcessor The synthesizer processor containing the channel.\n * @param channelNumber The channel number to snapshot.\n */\n public static create(\n spessaSynthProcessor: SpessaSynthProcessor,\n channelNumber: number\n ) {\n const channelObject = spessaSynthProcessor.midiChannels[channelNumber];\n\n return new ChannelSnapshot(\n {\n ...channelObject.patch,\n name: channelObject?.preset?.name ?? \"undefined\"\n },\n channelObject.lockPreset,\n channelObject.lockedSystem,\n channelObject.midiControllers.slice(),\n [...channelObject.lockedControllers],\n channelObject.customControllers.slice(),\n channelObject.lockGSNRPNParams,\n { ...channelObject.channelVibrato },\n channelObject.channelTransposeKeyShift,\n channelObject.channelOctaveTuning.slice(),\n channelObject.isMuted,\n channelObject.drumChannel,\n channelNumber\n );\n }\n\n /**\n * Applies the snapshot to the specified channel.\n * @param spessaSynthProcessor The processor containing the channel.\n */\n public apply(spessaSynthProcessor: SpessaSynthProcessor) {\n const channelObject =\n spessaSynthProcessor.midiChannels[this.channelNumber];\n channelObject.muteChannel(this.isMuted);\n channelObject.setDrums(this.drumChannel);\n\n // Restore controllers\n channelObject.midiControllers.set(this.midiControllers);\n channelObject.lockedControllers = this.lockedControllers;\n channelObject.customControllers.set(this.customControllers);\n channelObject.updateChannelTuning();\n\n // Restore vibrato and transpose\n channelObject.channelVibrato = this.channelVibrato;\n channelObject.lockGSNRPNParams = this.lockVibrato;\n channelObject.channelTransposeKeyShift = this.channelTransposeKeyShift;\n channelObject.channelOctaveTuning = this.channelOctaveTuning;\n\n // Restore preset and lock\n channelObject.setPresetLock(false);\n channelObject.setPatch(this.patch);\n channelObject.setPresetLock(this.lockPreset);\n channelObject.lockedSystem = this.lockedSystem;\n }\n}\n","/**\n * A manager for custom key overrides for channels\n */\nimport type { MIDIPatch } from \"../../../soundbank/basic_soundbank/midi_patch\";\n\nexport class KeyModifier {\n /**\n * The new override velocity. -1 means unchanged.\n */\n public velocity = -1;\n /**\n * The MIDI patch this key uses. -1 on any property means unchanged.\n */\n public patch: MIDIPatch = {\n bankLSB: -1,\n bankMSB: -1,\n isGMGSDrum: false,\n program: -1\n };\n\n /**\n * Linear gain override for the voice.\n */\n public gain = 1;\n}\n\nexport class KeyModifierManager {\n /**\n * The velocity override mappings for MIDI keys\n * stored as [channelNumber][midiNote].\n */\n private keyMappings: (KeyModifier | undefined)[][] = [];\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Add a mapping for a MIDI key to a KeyModifier.\n * @param channel The MIDI channel number.\n * @param midiNote The MIDI note number (0-127).\n * @param mapping The KeyModifier to apply for this key.\n */\n public addMapping(channel: number, midiNote: number, mapping: KeyModifier) {\n this.keyMappings[channel] ??= [];\n this.keyMappings[channel][midiNote] = mapping;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Delete a mapping for a MIDI key.\n * @param channel The MIDI channel number.\n * @param midiNote The MIDI note number (0-127).\n */\n public deleteMapping(channel: number, midiNote: number) {\n if (this.keyMappings[channel]?.[midiNote] === undefined) {\n return;\n }\n this.keyMappings[channel][midiNote] = undefined;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Clear all key mappings.\n */\n public clearMappings() {\n this.keyMappings = [];\n }\n\n /**\n * Sets the key mappings to a new array.\n * @param mappings A 2D array where the first dimension is the channel number and the second dimension is the MIDI note number.\n */\n public setMappings(mappings: (KeyModifier | undefined)[][]) {\n this.keyMappings = mappings;\n }\n\n /**\n * Returns the current key mappings.\n */\n public getMappings(): (KeyModifier | undefined)[][] {\n return this.keyMappings;\n }\n\n /**\n * Gets the velocity override for a MIDI key.\n * @param channel The MIDI channel number.\n * @param midiNote The MIDI note number (0-127).\n * @returns The velocity override, or -1 if no override is set.\n */\n public getVelocity(channel: number, midiNote: number): number {\n return this.keyMappings[channel]?.[midiNote]?.velocity ?? -1;\n }\n\n /**\n * Gets the gain override for a MIDI key.\n * @param channel The MIDI channel number.\n * @param midiNote The MIDI note number (0-127).\n * @returns The gain override, or 1 if no override is set.\n */\n public getGain(channel: number, midiNote: number): number {\n return this.keyMappings[channel]?.[midiNote]?.gain ?? 1;\n }\n\n /**\n * Checks if a MIDI key has an override for the patch.\n * @param channel The MIDI channel number.\n * @param midiNote The MIDI note number (0-127).\n * @returns True if the key has an override patch, false otherwise.\n */\n public hasOverridePatch(channel: number, midiNote: number): boolean {\n const bank = this.keyMappings[channel]?.[midiNote]?.patch?.bankMSB;\n return bank !== undefined && bank >= 0;\n }\n\n /**\n * Gets the patch override for a MIDI key.\n * @param channel The MIDI channel number.\n * @param midiNote The MIDI note number (0-127).\n * @returns An object containing the bank and program numbers.\n * @throws Error if no modifier is set for the key.\n */\n public getPatch(channel: number, midiNote: number): MIDIPatch {\n const modifier = this.keyMappings[channel]?.[midiNote];\n if (modifier) {\n return modifier.patch;\n }\n throw new Error(\"No modifier.\");\n }\n}\n","import { ChannelSnapshot } from \"./channel_snapshot\";\nimport { type KeyModifier } from \"../engine_components/key_modifier_manager\";\nimport { type SpessaSynthProcessor } from \"../../processor\";\nimport type { MasterParameterType } from \"../../types\";\n\n/**\n * Represents a snapshot of the synthesizer's state.\n */\nexport class SynthesizerSnapshot {\n /**\n * The individual channel snapshots.\n */\n public channelSnapshots: ChannelSnapshot[];\n\n /**\n * Key modifiers.\n */\n public keyMappings: (KeyModifier | undefined)[][];\n\n public masterParameters: MasterParameterType;\n\n public constructor(\n channelSnapshots: ChannelSnapshot[],\n masterParameters: MasterParameterType,\n keyMappings: (KeyModifier | undefined)[][]\n ) {\n this.channelSnapshots = channelSnapshots;\n this.masterParameters = masterParameters;\n this.keyMappings = keyMappings;\n }\n\n /**\n * Creates a new synthesizer snapshot from the given SpessaSynthProcessor.\n * @param processor the processor to take a snapshot of.\n * @returns The snapshot.\n */\n public static create(processor: SpessaSynthProcessor): SynthesizerSnapshot {\n // Channel snapshots\n const channelSnapshots = processor.midiChannels.map((_, i) =>\n ChannelSnapshot.create(processor, i)\n );\n\n return new SynthesizerSnapshot(\n channelSnapshots,\n processor.getAllMasterParameters(),\n processor.keyModifierManager.getMappings()\n );\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Creates a copy of existing snapshot.\n * @param snapshot The snapshot to create a copy from.\n */\n public static copyFrom(snapshot: SynthesizerSnapshot): SynthesizerSnapshot {\n return new SynthesizerSnapshot(\n snapshot.channelSnapshots.map((s) => ChannelSnapshot.copyFrom(s)),\n { ...snapshot.masterParameters },\n [...snapshot.keyMappings]\n );\n }\n\n /**\n * Applies the snapshot to the synthesizer.\n * @param processor the processor to apply the snapshot to.\n */\n public apply(processor: SpessaSynthProcessor) {\n type MasterParameterPair<K extends keyof MasterParameterType> = [\n K,\n MasterParameterType[K]\n ];\n const entries = Object.entries(\n this.masterParameters\n ) as MasterParameterPair<keyof MasterParameterType>[];\n entries.forEach(([parameter, value]) => {\n processor.setMasterParameter(parameter, value);\n });\n\n // Restore key modifiers\n processor.keyModifierManager.setMappings(this.keyMappings);\n\n // Add channels if more needed\n while (processor.midiChannels.length < this.channelSnapshots.length) {\n processor.createMIDIChannel();\n }\n\n // Restore channels\n this.channelSnapshots.forEach((channelSnapshot) => {\n channelSnapshot.apply(processor);\n });\n }\n}\n","import {\n ALL_CHANNELS_OR_DIFFERENT_ACTION,\n DEFAULT_SYNTH_MODE,\n SYNTHESIZER_GAIN,\n VOICE_CAP\n} from \"./synth_constants\";\nimport { interpolationTypes } from \"../../enums\";\nimport type { MasterParameterType } from \"../../types\";\n\nexport const DEFAULT_MASTER_PARAMETERS: MasterParameterType = {\n masterGain: SYNTHESIZER_GAIN,\n masterPan: 0.0,\n voiceCap: VOICE_CAP,\n interpolationType: interpolationTypes.hermite,\n midiSystem: DEFAULT_SYNTH_MODE,\n monophonicRetriggerMode: false,\n reverbGain: 1,\n chorusGain: 1,\n blackMIDIMode: false,\n transposition: 0,\n deviceID: ALL_CHANNELS_OR_DIFFERENT_ACTION\n};\n","import type {\n MTSProgramTuning,\n SynthProcessorEventData,\n VoiceList\n} from \"../../types\";\nimport type { BasicPreset } from \"../../../soundbank/basic_soundbank/basic_preset\";\nimport { DEFAULT_MASTER_PARAMETERS } from \"./master_parameters\";\n\n// This class holds all the internal values of the synthesizer.\n// They are used by both SpessaSynthProcessor and its MIDIChannel instances.\n// It is used to isolate them from the API.\n// Essentially think like all these belong to SpessaSynthProcessor and are \"protected\".\nexport class ProtectedSynthValues {\n /**\n * This.tunings[program][key] = tuning\n */\n public readonly tunings: MTSProgramTuning[] = [];\n\n // The master parameters of the synthesizer.\n public masterParameters = DEFAULT_MASTER_PARAMETERS;\n /**\n * The volume gain, set by MIDI sysEx\n */\n public midiVolume = 1;\n /**\n * Set via system exclusive.\n */\n public reverbSend = 1;\n /**\n * Set via system exclusive.\n */\n public chorusSend = 1;\n /**\n * The pan of the left channel\n */\n public panLeft = 0.5;\n /**\n * The pan of the right channel\n */\n public panRight = 0.5;\n /**\n * Synth's default (reset) preset\n */\n public defaultPreset: BasicPreset | undefined;\n /**\n * Synth's default (reset) drum preset\n */\n public drumPreset: BasicPreset | undefined;\n\n // Volume envelope smoothing factor, adjusted to the sample rate.\n public readonly volumeEnvelopeSmoothingFactor: number;\n\n // Pan smoothing factor, adjusted to the sample rate.\n public readonly panSmoothingFactor: number;\n\n // Filter smoothing factor, adjusted to the sample rate.\n public readonly filterSmoothingFactor: number;\n /**\n * Calls when an event occurs.\n * @param eventType The event type.\n * @param eventData The event data.\n */\n public eventCallbackHandler: <K extends keyof SynthProcessorEventData>(\n eventType: K,\n eventData: SynthProcessorEventData[K]\n ) => unknown;\n public getVoices: (\n channel: number,\n midiNote: number,\n velocity: number,\n realKey: number\n ) => VoiceList;\n public voiceKilling: (amount: number) => unknown;\n /**\n * Cached voices for all presets for this synthesizer.\n * Nesting goes like this:\n * this.cachedVoices[bankMSB][bankLSB][programNumber][midiNote][velocity] = a list of voices for that.\n */\n public cachedVoices: VoiceList[][][][][] = [];\n\n public constructor(\n eventCallbackHandler: <K extends keyof SynthProcessorEventData>(\n eventType: K,\n eventData: SynthProcessorEventData[K]\n ) => unknown,\n getVoices: (\n channel: number,\n midiNote: number,\n velocity: number,\n realKey: number\n ) => VoiceList,\n voiceKillingFunction: (amount: number) => unknown,\n volumeEnvelopeSmoothingFactor: number,\n panSmoothingFactor: number,\n filterSmoothingFactor: number\n ) {\n this.eventCallbackHandler = eventCallbackHandler;\n this.getVoices = getVoices;\n this.voiceKilling = voiceKillingFunction;\n this.volumeEnvelopeSmoothingFactor = volumeEnvelopeSmoothingFactor;\n this.panSmoothingFactor = panSmoothingFactor;\n this.filterSmoothingFactor = filterSmoothingFactor;\n\n for (let i = 0; i < 128; i++) {\n this.tunings.push([]);\n }\n }\n\n /**\n * Copied callback so MIDI channels can call it.\n */\n public callEvent<K extends keyof SynthProcessorEventData>(\n eventName: K,\n eventData: SynthProcessorEventData[K]\n ) {\n this.eventCallbackHandler(eventName, eventData);\n }\n}\n","/**\n * Lfo.ts\n * purpose: low frequency triangle oscillator\n */\n\n/**\n * Gets the current value of the LFO at a given time.\n * @param startTime The time when the LFO started (in seconds).\n * @param frequency The frequency of the LFO (in Hz).\n * @param currentTime The current time (in seconds).\n * @returns The LFO value, which oscillates between -1 and 1.\n */\nexport function getLFOValue(\n startTime: number,\n frequency: number,\n currentTime: number\n): number {\n if (currentTime < startTime) {\n return 0;\n }\n\n const xVal = (currentTime - startTime) / (1 / frequency) + 0.25;\n // Offset by -0.25, otherwise we start at -1 and can have unexpected jump in pitch or low-pass\n // (happened with Synth Strings 2)\n\n // Triangle, not sine\n return Math.abs(xVal - ~~(xVal + 0.5)) * 4 - 1;\n}\n","import { type InterpolationType, interpolationTypes } from \"../../../enums\";\nimport type { Voice } from \"../voice\";\n\n/**\n * Wavetable_oscillator.ts\n * purpose: plays back raw audio data at an arbitrary playback rate\n */\n\nexport class WavetableOscillator {\n /**\n * Fills the output buffer with raw sample data using a given interpolation.\n * @param voice The voice we're working on.\n * @param outputBuffer The output buffer to write to.\n * @param interpolation The interpolation type.\n */\n public static getSample(\n voice: Voice,\n outputBuffer: Float32Array,\n interpolation: InterpolationType\n ) {\n const step = voice.currentTuningCalculated * voice.sample.playbackStep;\n // Why not?\n if (step === 1) {\n WavetableOscillator.getSampleNearest(voice, outputBuffer, step);\n return;\n }\n switch (interpolation) {\n case interpolationTypes.hermite:\n this.getSampleHermite(voice, outputBuffer, step);\n return;\n\n case interpolationTypes.linear:\n default:\n this.getSampleLinear(voice, outputBuffer, step);\n return;\n\n case interpolationTypes.nearestNeighbor:\n WavetableOscillator.getSampleNearest(voice, outputBuffer, step);\n return;\n }\n }\n\n /**\n * Fills the output buffer with raw sample data using linear interpolation.\n * @param voice The voice we're working on.\n * @param outputBuffer The output buffer to write to.\n * @param step The step to advance every sample (playback rate).\n */\n public static getSampleLinear(\n voice: Voice,\n outputBuffer: Float32Array,\n step: number\n ) {\n const sample = voice.sample;\n let cur = sample.cursor;\n const sampleData = sample.sampleData;\n\n if (sample.isLooping) {\n const loopLength = sample.loopEnd - sample.loopStart;\n for (let i = 0; i < outputBuffer.length; i++) {\n // Check for loop\n while (cur >= sample.loopEnd) {\n cur -= loopLength;\n }\n\n // Grab the 2 nearest points\n const floor = ~~cur;\n let ceil = floor + 1;\n\n while (ceil >= sample.loopEnd) {\n ceil -= loopLength;\n }\n\n const fraction = cur - floor;\n\n // Grab the samples and interpolate\n const upper = sampleData[ceil];\n const lower = sampleData[floor];\n outputBuffer[i] = lower + (upper - lower) * fraction;\n\n cur += step;\n }\n } else {\n for (let i = 0; i < outputBuffer.length; i++) {\n // Linear interpolation\n const floor = ~~cur;\n const ceil = floor + 1;\n\n // Flag the voice as finished if needed\n if (ceil >= sample.end) {\n voice.finished = true;\n return;\n }\n\n const fraction = cur - floor;\n\n // Grab the samples and interpolate\n const upper = sampleData[ceil];\n const lower = sampleData[floor];\n outputBuffer[i] = lower + (upper - lower) * fraction;\n\n cur += step;\n }\n }\n voice.sample.cursor = cur;\n }\n\n /**\n * Fills the output buffer with raw sample data using no interpolation (nearest neighbor).\n * @param voice The voice we're working on.\n * @param outputBuffer The output buffer to write to.\n * @param step The step to advance every sample (playback rate).\n */\n public static getSampleNearest(\n voice: Voice,\n outputBuffer: Float32Array,\n step: number\n ) {\n const sample = voice.sample;\n let cur = sample.cursor;\n const sampleData = sample.sampleData;\n\n if (sample.isLooping) {\n const loopLength = sample.loopEnd - sample.loopStart;\n for (let i = 0; i < outputBuffer.length; i++) {\n // Check for loop\n while (cur >= sample.loopEnd) {\n cur -= loopLength;\n }\n\n // Grab the nearest neighbor\n let ceil = ~~cur + 1;\n\n while (ceil >= sample.loopEnd) {\n ceil -= loopLength;\n }\n\n outputBuffer[i] = sampleData[ceil];\n cur += step;\n }\n } else {\n for (let i = 0; i < outputBuffer.length; i++) {\n // Nearest neighbor\n const ceil = ~~cur + 1;\n\n // Flag the voice as finished if needed\n if (ceil >= sample.end) {\n voice.finished = true;\n return;\n }\n\n outputBuffer[i] = sampleData[ceil];\n cur += step;\n }\n }\n sample.cursor = cur;\n }\n\n /**\n * Fills the output buffer with raw sample data using Hermite interpolation.\n * @param voice The voice we're working on.\n * @param outputBuffer The output buffer to write to.\n * @param step The step to advance every sample (playback rate).\n */\n public static getSampleHermite(\n voice: Voice,\n outputBuffer: Float32Array,\n step: number\n ) {\n const sample = voice.sample;\n let cur = sample.cursor;\n const sampleData = sample.sampleData;\n\n if (sample.isLooping) {\n const loopLength = sample.loopEnd - sample.loopStart;\n for (let i = 0; i < outputBuffer.length; i++) {\n // Check for loop (it can exceed the end point multiple times)\n while (cur >= sample.loopEnd) {\n cur -= loopLength;\n }\n\n // Grab the 4 points\n const y0 = ~~cur; // Point before the cursor. twice bitwise-not is just a faster Math.floor\n let y1 = y0 + 1; // Point after the cursor\n let y2 = y0 + 2; // Point 1 after the cursor\n let y3 = y0 + 3; // Point 2 after the cursor\n const t = cur - y0; // The distance from y0 to cursor [0;1]\n // Y0 is not handled here\n // As it's math.floor of cur which is handled above\n if (y1 >= sample.loopEnd) {\n y1 -= loopLength;\n }\n if (y2 >= sample.loopEnd) {\n y2 -= loopLength;\n }\n if (y3 >= sample.loopEnd) {\n y3 -= loopLength;\n }\n\n // Grab the samples\n const xm1 = sampleData[y0];\n const x0 = sampleData[y1];\n const x1 = sampleData[y2];\n const x2 = sampleData[y3];\n\n // Interpolate\n // https://www.musicdsp.org/en/latest/Other/93-hermite-interpollation.html\n const c = (x1 - xm1) * 0.5;\n const v = x0 - x1;\n const w = c + v;\n const a = w + v + (x2 - x0) * 0.5;\n const b = w + a;\n outputBuffer[i] = ((a * t - b) * t + c) * t + x0;\n\n cur += step;\n }\n } else {\n for (let i = 0; i < outputBuffer.length; i++) {\n // Grab the 4 points\n const y0 = ~~cur; // Point before the cursor. twice bitwise-not is just a faster Math.floor\n const y1 = y0 + 1; // Point after the cursor\n const y2 = y0 + 2; // Point 1 after the cursor\n const y3 = y0 + 3; // Point 2 after the cursor\n const t = cur - y0; // The distance from y0 to cursor [0;1]\n\n // Flag as finished if needed\n if (y1 >= sample.end || y2 >= sample.end || y3 >= sample.end) {\n voice.finished = true;\n return;\n }\n\n // Grab the samples\n const xm1 = sampleData[y0];\n const x0 = sampleData[y1];\n const x1 = sampleData[y2];\n const x2 = sampleData[y3];\n\n // Interpolate\n // https://www.musicdsp.org/en/latest/Other/93-hermite-interpollation.html\n const c = (x1 - xm1) * 0.5;\n const v = x0 - x1;\n const w = c + v;\n const a = w + v + (x2 - x0) * 0.5;\n const b = w + a;\n outputBuffer[i] = ((a * t - b) * t + c) * t + x0;\n\n cur += step;\n }\n }\n voice.sample.cursor = cur;\n }\n}\n","import { VolumeEnvelope } from \"./volume_envelope\";\nimport { ModulationEnvelope } from \"./modulation_envelope\";\nimport { absCentsToHz, timecentsToSeconds } from \"../unit_converter\";\nimport { getLFOValue } from \"./lfo\";\nimport { WavetableOscillator } from \"./wavetable_oscillator\";\nimport { LowpassFilter } from \"./lowpass_filter\";\nimport type { Voice } from \"../voice\";\nimport type { MIDIChannel } from \"../midi_channel\";\nimport { generatorTypes } from \"../../../../soundbank/basic_soundbank/generator_types\";\nimport { customControllers } from \"../../../enums\";\n\n/**\n * Renders a voice to the stereo output buffer\n * @param voice the voice to render\n * @param timeNow current time in seconds\n * @param outputLeft the left output buffer\n * @param outputRight the right output buffer\n * @param reverbOutputLeft left output for reverb\n * @param reverbOutputRight right output for reverb\n * @param chorusOutputLeft left output for chorus\n * @param chorusOutputRight right output for chorus\n * @param startIndex\n * @param sampleCount\n * @returns true if the voice is finished\n */\nexport function renderVoice(\n this: MIDIChannel,\n voice: Voice,\n timeNow: number,\n outputLeft: Float32Array,\n outputRight: Float32Array,\n reverbOutputLeft: Float32Array,\n reverbOutputRight: Float32Array,\n chorusOutputLeft: Float32Array,\n chorusOutputRight: Float32Array,\n startIndex: number,\n sampleCount: number\n): boolean {\n // Check if release\n if (!voice.isInRelease) {\n // If not in release, check if the release time is\n if (timeNow >= voice.releaseStartTime) {\n // Release the voice here\n voice.isInRelease = true;\n VolumeEnvelope.startRelease(voice);\n ModulationEnvelope.startRelease(voice);\n if (voice.sample.loopingMode === 3) {\n voice.sample.isLooping = false;\n }\n }\n }\n\n // If the initial attenuation is more than 100dB, skip the voice (it's silent anyway)\n if (voice.modulatedGenerators[generatorTypes.initialAttenuation] > 2500) {\n if (voice.isInRelease) {\n voice.finished = true;\n }\n return voice.finished;\n }\n\n // TUNING\n let targetKey = voice.targetKey;\n\n // Calculate tuning\n let cents =\n voice.modulatedGenerators[generatorTypes.fineTune] + // Soundfont fine tune\n this.channelOctaveTuning[voice.midiNote] + // MTS octave tuning\n this.channelTuningCents; // Channel tuning\n let semitones = voice.modulatedGenerators[generatorTypes.coarseTune]; // Soundfont coarse tuning\n\n // Midi tuning standard\n const tuning =\n this.synthProps.tunings[this.preset?.program ?? 0]?.[voice.realKey];\n if (tuning?.centTuning) {\n // Override key\n targetKey = tuning.midiNote;\n // Add micro-tonal tuning\n cents += tuning.centTuning;\n }\n\n // Portamento\n if (voice.portamentoFromKey > -1) {\n // 0 to 1\n const elapsed = Math.min(\n (timeNow - voice.startTime) / voice.portamentoDuration,\n 1\n );\n const diff = targetKey - voice.portamentoFromKey;\n // Zero progress means the pitch being in fromKey, full progress means the normal pitch\n semitones -= diff * (1 - elapsed);\n }\n\n // Calculate tuning by key using soundfont's scale tuning\n cents +=\n (targetKey - voice.sample.rootKey) *\n voice.modulatedGenerators[generatorTypes.scaleTuning];\n\n // Low pass excursion with LFO and mod envelope\n let lowpassExcursion = 0;\n let volumeExcursionCentibels = 0;\n\n // Vibrato LFO\n const vibPitchDepth =\n voice.modulatedGenerators[generatorTypes.vibLfoToPitch];\n const vibVolDepth =\n voice.modulatedGenerators[generatorTypes.vibLfoToVolume];\n const vibFilterDepth =\n voice.modulatedGenerators[generatorTypes.vibLfoToFilterFc];\n if (vibPitchDepth !== 0 || vibVolDepth !== 0 || vibFilterDepth !== 0) {\n // Calculate start time and lfo value\n const vibStart =\n voice.startTime +\n timecentsToSeconds(\n voice.modulatedGenerators[generatorTypes.delayVibLFO]\n );\n const vibFreqHz = absCentsToHz(\n voice.modulatedGenerators[generatorTypes.freqVibLFO]\n );\n const vibLfoValue = getLFOValue(vibStart, vibFreqHz, timeNow);\n // Use modulation multiplier (RPN modulation depth)\n cents +=\n vibLfoValue *\n (vibPitchDepth *\n this.customControllers[customControllers.modulationMultiplier]);\n // Vol env volume offset\n // Negate the lfo value because audigy starts with increase rather than decrease\n volumeExcursionCentibels += -vibLfoValue * vibVolDepth;\n // Low pass frequency\n lowpassExcursion += vibLfoValue * vibFilterDepth;\n }\n\n // Mod LFO\n const modPitchDepth =\n voice.modulatedGenerators[generatorTypes.modLfoToPitch];\n const modVolDepth =\n voice.modulatedGenerators[generatorTypes.modLfoToVolume];\n const modFilterDepth =\n voice.modulatedGenerators[generatorTypes.modLfoToFilterFc];\n // Don't compute mod lfo unless necessary\n if (modPitchDepth !== 0 || modFilterDepth !== 0 || modVolDepth !== 0) {\n // Calculate start time and lfo value\n const modStart =\n voice.startTime +\n timecentsToSeconds(\n voice.modulatedGenerators[generatorTypes.delayModLFO]\n );\n const modFreqHz = absCentsToHz(\n voice.modulatedGenerators[generatorTypes.freqModLFO]\n );\n const modLfoValue = getLFOValue(modStart, modFreqHz, timeNow);\n // Use modulation multiplier (RPN modulation depth)\n cents +=\n modLfoValue *\n (modPitchDepth *\n this.customControllers[customControllers.modulationMultiplier]);\n // Vol env volume offset\n // Negate the lfo value because audigy starts with increase rather than decrease\n volumeExcursionCentibels += -modLfoValue * modVolDepth;\n // Low pass frequency\n lowpassExcursion += modLfoValue * modFilterDepth;\n }\n\n // Channel vibrato (GS NRPN)\n if (this.channelVibrato.depth > 0) {\n // Same as others\n const channelVibrato = getLFOValue(\n voice.startTime + this.channelVibrato.delay,\n this.channelVibrato.rate,\n timeNow\n );\n if (channelVibrato) {\n cents += channelVibrato * this.channelVibrato.depth;\n }\n }\n\n // Mod env\n const modEnvPitchDepth =\n voice.modulatedGenerators[generatorTypes.modEnvToPitch];\n const modEnvFilterDepth =\n voice.modulatedGenerators[generatorTypes.modEnvToFilterFc];\n // Don't compute mod env unless necessary\n if (modEnvFilterDepth !== 0 || modEnvPitchDepth !== 0) {\n const modEnv = ModulationEnvelope.getValue(voice, timeNow);\n // Apply values\n lowpassExcursion += modEnv * modEnvFilterDepth;\n cents += modEnv * modEnvPitchDepth;\n }\n\n // Default resonant modulator: it does not affect the filter gain (neither XG nor GS did that)\n volumeExcursionCentibels -= voice.resonanceOffset;\n\n // Finally, calculate the playback rate\n const centsTotal = ~~(cents + semitones * 100);\n if (centsTotal !== voice.currentTuningCents) {\n voice.currentTuningCents = centsTotal;\n voice.currentTuningCalculated = Math.pow(2, centsTotal / 1200);\n }\n\n // SYNTHESIS\n const bufferOut = new Float32Array(sampleCount);\n\n // Looping mode 2: start on release. process only volEnv\n if (voice.sample.loopingMode === 2 && !voice.isInRelease) {\n VolumeEnvelope.apply(\n voice,\n bufferOut,\n volumeExcursionCentibels,\n this.synthProps.volumeEnvelopeSmoothingFactor\n );\n return voice.finished;\n }\n\n // Wave table oscillator\n WavetableOscillator.getSample(\n voice,\n bufferOut,\n this.synthProps.masterParameters.interpolationType\n );\n\n // Low pass filter\n LowpassFilter.apply(\n voice,\n bufferOut,\n lowpassExcursion,\n this.synthProps.filterSmoothingFactor\n );\n\n // Vol env\n VolumeEnvelope.apply(\n voice,\n bufferOut,\n volumeExcursionCentibels,\n this.synthProps.volumeEnvelopeSmoothingFactor\n );\n\n this.panAndMixVoice(\n voice,\n bufferOut,\n outputLeft,\n outputRight,\n reverbOutputLeft,\n reverbOutputRight,\n chorusOutputLeft,\n chorusOutputRight,\n startIndex\n );\n return voice.finished;\n}\n","import { SpessaSynthInfo } from \"../../../../../utils/loggin\";\nimport { consoleColors } from \"../../../../../utils/other\";\nimport type { MIDIChannel } from \"../../../engine_components/midi_channel\";\nimport type { GeneratorType } from \"../../../../../soundbank/basic_soundbank/generator_types\";\nimport { NON_CC_INDEX_OFFSET } from \"../../../engine_components/controller_tables\";\nimport { modulatorSources } from \"../../../../../soundbank/enums\";\nimport { customControllers, dataEntryStates } from \"../../../../enums\";\nimport { midiControllers } from \"../../../../../midi/enums\";\n\nexport const registeredParameterTypes = {\n pitchWheelRange: 0x0000,\n fineTuning: 0x0001,\n coarseTuning: 0x0002,\n modulationDepth: 0x0005,\n resetParameters: 0x3fff\n};\n\nexport const nonRegisteredMSB = {\n partParameter: 0x01,\n awe32: 0x7f,\n SF2: 120\n};\n\n/**\n * https://cdn.roland.com/assets/media/pdf/SC-88PRO_OM.pdf\n * http://hummer.stanford.edu/sig/doc/classes/MidiOutput/rpn.html\n * @enum {number}\n */\nconst nonRegisteredGSLSB = {\n vibratoRate: 0x08,\n vibratoDepth: 0x09,\n vibratoDelay: 0x0a,\n\n TVFFilterCutoff: 0x20,\n TVFFilterResonance: 0x21,\n\n EGAttackTime: 0x63,\n EGReleaseTime: 0x66\n};\n\n/**\n * Executes a data entry coarse (MSB) change for the current channel.\n * @param dataValue The value to set for the data entry coarse controller (0-127).\n */\nexport function dataEntryCoarse(this: MIDIChannel, dataValue: number) {\n // Store in cc table\n this.midiControllers[midiControllers.dataEntryMSB] = dataValue << 7;\n /*\n A note on this vibrato.\n This is a completely custom vibrato, with its own oscillator and parameters.\n It is disabled by default,\n only being enabled when one of the NPRN messages changing it is received\n and stays on until the next system-reset.\n It was implemented very early in SpessaSynth's development,\n because I wanted support for Touhou MIDIs :-)\n */\n const addDefaultVibrato = () => {\n if (\n this.channelVibrato.delay === 0 &&\n this.channelVibrato.rate === 0 &&\n this.channelVibrato.depth === 0\n ) {\n this.channelVibrato.depth = 50;\n this.channelVibrato.rate = 8;\n this.channelVibrato.delay = 0.6;\n }\n };\n\n // A helper function to log info in a nice way\n const coolInfo = (what: string, value: string | number, type: string) => {\n if (type.length > 0) {\n type = \" \" + type;\n }\n SpessaSynthInfo(\n `%c${what} for %c${this.channelNumber}%c is now set to %c${value}%c${type}.`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info\n );\n };\n switch (this.dataEntryState) {\n default:\n case dataEntryStates.Idle:\n break;\n\n // Process GS NRPNs\n case dataEntryStates.NRPFine: {\n if (this.lockGSNRPNParams) {\n return;\n }\n const NRPNCoarse =\n this.midiControllers[\n midiControllers.nonRegisteredParameterMSB\n ] >> 7;\n const NRPNFine =\n this.midiControllers[\n midiControllers.nonRegisteredParameterLSB\n ] >> 7;\n const dataEntryFine =\n this.midiControllers[midiControllers.dataEntryLSB] >> 7;\n switch (NRPNCoarse) {\n default:\n if (dataValue === 64) {\n // Default value\n return;\n }\n SpessaSynthInfo(\n `%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${NRPNFine.toString(\n 16\n ).toUpperCase()} 0x${NRPNFine.toString(\n 16\n ).toUpperCase()})%c data value: %c${dataValue}`,\n consoleColors.warn,\n consoleColors.recognized,\n consoleColors.warn,\n consoleColors.unrecognized,\n consoleColors.warn,\n consoleColors.value\n );\n break;\n\n // Part parameters: vibrato, cutoff\n case nonRegisteredMSB.partParameter:\n switch (NRPNFine) {\n default:\n if (dataValue === 64) {\n // Default value\n return;\n }\n SpessaSynthInfo(\n `%cUnrecognized NRPN for %c${this.channelNumber}%c: %c(0x${NRPNCoarse.toString(16)} 0x${NRPNFine.toString(\n 16\n )})%c data value: %c${dataValue}`,\n consoleColors.warn,\n consoleColors.recognized,\n consoleColors.warn,\n consoleColors.unrecognized,\n consoleColors.warn,\n consoleColors.value\n );\n break;\n\n // Vibrato rate\n case nonRegisteredGSLSB.vibratoRate:\n if (dataValue === 64) {\n return;\n }\n addDefaultVibrato();\n this.channelVibrato.rate = (dataValue / 64) * 8;\n coolInfo(\n \"Vibrato rate\",\n `${dataValue} = ${this.channelVibrato.rate}`,\n \"Hz\"\n );\n break;\n\n // Vibrato depth\n case nonRegisteredGSLSB.vibratoDepth:\n if (dataValue === 64) {\n return;\n }\n addDefaultVibrato();\n this.channelVibrato.depth = dataValue / 2;\n coolInfo(\n \"Vibrato depth\",\n `${dataValue} = ${this.channelVibrato.depth}`,\n \"cents of detune\"\n );\n break;\n\n // Vibrato delay\n case nonRegisteredGSLSB.vibratoDelay:\n if (dataValue === 64) {\n return;\n }\n addDefaultVibrato();\n this.channelVibrato.delay = dataValue / 64 / 3;\n coolInfo(\n \"Vibrato delay\",\n `${dataValue} = ${this.channelVibrato.delay}`,\n \"seconds\"\n );\n break;\n\n // Filter cutoff\n case nonRegisteredGSLSB.TVFFilterCutoff:\n // Affect the \"brightness\" controller as we have a default modulator that controls it\n this.controllerChange(\n midiControllers.brightness,\n dataValue\n );\n coolInfo(\"Filter cutoff\", dataValue.toString(), \"\");\n break;\n\n // Attack time\n case nonRegisteredGSLSB.EGAttackTime:\n // Affect the \"attack time\" controller as we have a default modulator that controls it\n this.controllerChange(\n midiControllers.attackTime,\n dataValue\n );\n coolInfo(\n \"EG attack time\",\n dataValue.toString(),\n \"\"\n );\n break;\n\n // Release time\n case nonRegisteredGSLSB.EGReleaseTime:\n // Affect the \"release time\" controller as we have a default modulator that controls it\n this.controllerChange(\n midiControllers.releaseTime,\n dataValue\n );\n coolInfo(\n \"EG release time\",\n dataValue.toString(),\n \"\"\n );\n break;\n }\n break;\n\n case nonRegisteredMSB.awe32:\n break;\n\n // SF2 NRPN\n case nonRegisteredMSB.SF2: {\n if (NRPNFine > 100) {\n // Sf spec:\n // Note that NRPN Select LSB greater than 100 are for setup only, and should not be used on their own to select a\n // Generator parameter.\n break;\n }\n const gen = this.customControllers[\n customControllers.sf2NPRNGeneratorLSB\n ] as GeneratorType;\n const offset = ((dataValue << 7) | dataEntryFine) - 8192;\n this.setGeneratorOffset(gen, offset);\n break;\n }\n }\n break;\n }\n\n case dataEntryStates.RPCoarse:\n case dataEntryStates.RPFine: {\n const rpnValue =\n this.midiControllers[midiControllers.registeredParameterMSB] |\n (this.midiControllers[midiControllers.registeredParameterLSB] >>\n 7);\n switch (rpnValue) {\n default:\n SpessaSynthInfo(\n `%cUnrecognized RPN for %c${this.channelNumber}%c: %c(0x${rpnValue.toString(16)})%c data value: %c${dataValue}`,\n consoleColors.warn,\n consoleColors.recognized,\n consoleColors.warn,\n consoleColors.unrecognized,\n consoleColors.warn,\n consoleColors.value\n );\n break;\n\n // Pitch bend range\n case registeredParameterTypes.pitchWheelRange:\n this.midiControllers[\n NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange\n ] = dataValue << 7;\n coolInfo(\n \"Pitch wheel range\",\n dataValue.toString(),\n \"semitones\"\n );\n break;\n\n // Coarse tuning\n case registeredParameterTypes.coarseTuning: {\n // Semitones\n const semitones = dataValue - 64;\n this.setCustomController(\n customControllers.channelTuningSemitones,\n semitones\n );\n coolInfo(\n \"Coarse tuning\",\n semitones.toString(),\n \"semitones\"\n );\n break;\n }\n\n // Fine-tuning\n case registeredParameterTypes.fineTuning:\n // Note: this will not work properly unless the lsb is sent!\n // Here we store the raw value to then adjust in fine\n this.setTuning(dataValue - 64, false);\n break;\n\n // Modulation depth\n case registeredParameterTypes.modulationDepth:\n this.setModulationDepth(dataValue * 100);\n break;\n\n case registeredParameterTypes.resetParameters:\n this.resetParameters();\n break;\n }\n }\n }\n}\n","import { SpessaSynthWarn } from \"../../../../../utils/loggin\";\nimport { consoleColors } from \"../../../../../utils/other\";\nimport {\n type GeneratorType,\n generatorTypes\n} from \"../../../../../soundbank/basic_soundbank/generator_types\";\nimport type { MIDIChannel } from \"../../../engine_components/midi_channel\";\n\n/**\n * SoundBlaster AWE32 NRPN generator mappings.\n * http://archive.gamedev.net/archive/reference/articles/article445.html\n * https://github.com/user-attachments/files/15757220/adip301.pdf\n */\nconst AWE_NRPN_GENERATOR_MAPPINGS: GeneratorType[] = [\n generatorTypes.delayModLFO,\n generatorTypes.freqModLFO,\n\n generatorTypes.delayVibLFO,\n generatorTypes.freqVibLFO,\n\n generatorTypes.delayModEnv,\n generatorTypes.attackModEnv,\n generatorTypes.holdModEnv,\n generatorTypes.decayModEnv,\n generatorTypes.sustainModEnv,\n generatorTypes.releaseModEnv,\n\n generatorTypes.delayVolEnv,\n generatorTypes.attackVolEnv,\n generatorTypes.holdVolEnv,\n generatorTypes.decayVolEnv,\n generatorTypes.sustainVolEnv,\n generatorTypes.releaseVolEnv,\n\n generatorTypes.fineTune,\n\n generatorTypes.modLfoToPitch,\n generatorTypes.vibLfoToPitch,\n generatorTypes.modEnvToPitch,\n generatorTypes.modLfoToVolume,\n\n generatorTypes.initialFilterFc,\n generatorTypes.initialFilterQ,\n\n generatorTypes.modLfoToFilterFc,\n generatorTypes.modEnvToFilterFc,\n\n generatorTypes.chorusEffectsSend,\n generatorTypes.reverbEffectsSend\n] as const;\n\n/**\n * Function that emulates AWE32 similarly to fluidsynth\n * https://github.com/FluidSynth/fluidsynth/wiki/FluidFeatures\n *\n * Note: This makes use of findings by mrbumpy409:\n * https://github.com/fluidSynth/fluidsynth/issues/1473\n *\n * The excellent test files are available here, also collected and converted by mrbumpy409:\n * https://github.com/mrbumpy409/AWE32-midi-conversions\n */\nexport function handleAWE32NRPN(\n this: MIDIChannel,\n aweGen: number,\n dataLSB: number,\n dataMSB: number\n) {\n // Helper functions\n const clip = (v: number, min: number, max: number) =>\n Math.max(min, Math.min(max, v));\n const msecToTimecents = (ms: number) =>\n Math.max(-32768, 1200 * Math.log2(ms / 1000));\n const hzToCents = (hz: number) => 6900 + 1200 * Math.log2(hz / 440);\n\n let dataValue = (dataMSB << 7) | dataLSB;\n // Center the value\n // Though ranges reported as 0 to 127 only use LSB\n dataValue -= 8192;\n const generator = AWE_NRPN_GENERATOR_MAPPINGS[aweGen];\n if (!generator) {\n SpessaSynthWarn(\n `Invalid AWE32 LSB: %c${aweGen}`,\n consoleColors.unrecognized\n );\n }\n let milliseconds, hertz, centibels, cents;\n switch (generator) {\n default:\n // This should not happen\n break;\n\n // Delays\n case generatorTypes.delayModLFO:\n case generatorTypes.delayVibLFO:\n case generatorTypes.delayVolEnv:\n case generatorTypes.delayModEnv:\n milliseconds = 4 * clip(dataValue, 0, 5900);\n // Convert to timecents\n this.setGeneratorOverride(generator, msecToTimecents(milliseconds));\n break;\n\n // Attacks\n case generatorTypes.attackVolEnv:\n case generatorTypes.attackModEnv:\n milliseconds = clip(dataValue, 0, 5940);\n // Convert to timecents\n this.setGeneratorOverride(generator, msecToTimecents(milliseconds));\n break;\n\n // Holds\n case generatorTypes.holdVolEnv:\n case generatorTypes.holdModEnv:\n milliseconds = clip(dataValue, 0, 8191);\n // Convert to timecents\n this.setGeneratorOverride(generator, msecToTimecents(milliseconds));\n break;\n\n // Decays and releases (share clips and units)\n case generatorTypes.decayModEnv:\n case generatorTypes.decayVolEnv:\n case generatorTypes.releaseVolEnv:\n case generatorTypes.releaseModEnv:\n milliseconds = 4 * clip(dataValue, 0, 5940);\n // Convert to timecents\n this.setGeneratorOverride(generator, msecToTimecents(milliseconds));\n break;\n\n // Lfo frequencies\n case generatorTypes.freqVibLFO:\n case generatorTypes.freqModLFO:\n hertz = 0.084 * dataLSB;\n // Convert to abs cents\n this.setGeneratorOverride(generator, hzToCents(hertz), true);\n break;\n\n // Sustains\n case generatorTypes.sustainVolEnv:\n case generatorTypes.sustainModEnv:\n // 0.75 dB is 7.5 cB\n centibels = dataLSB * 7.5;\n this.setGeneratorOverride(generator, centibels);\n break;\n\n // Pitch\n case generatorTypes.fineTune:\n // Data is already centered\n this.setGeneratorOverride(generator, dataValue, true);\n break;\n\n // Lfo to pitch\n case generatorTypes.modLfoToPitch:\n case generatorTypes.vibLfoToPitch:\n cents = clip(dataValue, -127, 127) * 9.375;\n this.setGeneratorOverride(generator, cents, true);\n break;\n\n // Env to pitch\n case generatorTypes.modEnvToPitch:\n cents = clip(dataValue, -127, 127) * 9.375;\n this.setGeneratorOverride(generator, cents);\n break;\n\n // Mod lfo to vol\n case generatorTypes.modLfoToVolume:\n // 0.1875 dB is 1.875 cB\n centibels = 1.875 * dataLSB;\n this.setGeneratorOverride(generator, centibels, true);\n break;\n\n // Filter fc\n case generatorTypes.initialFilterFc: {\n // Minimum: 100 Hz -> 4335 cents\n const fcCents = 4335 + 59 * dataLSB;\n this.setGeneratorOverride(generator, fcCents, true);\n break;\n }\n\n // Filter Q\n case generatorTypes.initialFilterQ:\n // Note: this uses the \"modulator-ish\" approach proposed by mrbumpy409\n // Here https://github.com/FluidSynth/fluidsynth/issues/1473\n centibels = 215 * (dataLSB / 127);\n this.setGeneratorOverride(generator, centibels, true);\n break;\n\n // To filterFc\n case generatorTypes.modLfoToFilterFc:\n cents = clip(dataValue, -64, 63) * 56.25;\n this.setGeneratorOverride(generator, cents, true);\n break;\n\n case generatorTypes.modEnvToFilterFc:\n cents = clip(dataValue, -64, 63) * 56.25;\n this.setGeneratorOverride(generator, cents);\n break;\n\n // Effects\n case generatorTypes.chorusEffectsSend:\n case generatorTypes.reverbEffectsSend:\n this.setGeneratorOverride(\n generator,\n clip(dataValue, 0, 255) * (1000 / 255)\n );\n break;\n }\n}\n","import { consoleColors } from \"../../../../../utils/other\";\nimport { SpessaSynthInfo } from \"../../../../../utils/loggin\";\nimport { NON_CC_INDEX_OFFSET } from \"../../../engine_components/controller_tables\";\nimport { nonRegisteredMSB, registeredParameterTypes } from \"./data_entry_coarse\";\nimport { handleAWE32NRPN } from \"./awe32\";\nimport type { MIDIChannel } from \"../../../engine_components/midi_channel\";\nimport { midiControllers } from \"../../../../../midi/enums\";\nimport { customControllers, dataEntryStates } from \"../../../../enums\";\nimport { modulatorSources } from \"../../../../../soundbank/enums\";\n\n/**\n * Executes a data entry fine (LSB) change for the current channel.\n * @param dataValue The value to set for the data entry fine controller (0-127).\n */\nexport function dataEntryFine(this: MIDIChannel, dataValue: number) {\n // Store in cc table\n this.midiControllers[midiControllers.dataEntryLSB] = dataValue << 7;\n switch (this.dataEntryState) {\n default:\n break;\n\n case dataEntryStates.RPCoarse:\n case dataEntryStates.RPFine: {\n const rpnValue =\n this.midiControllers[midiControllers.registeredParameterMSB] |\n (this.midiControllers[midiControllers.registeredParameterLSB] >>\n 7);\n switch (rpnValue) {\n default:\n break;\n\n // Pitch bend range fine tune\n case registeredParameterTypes.pitchWheelRange: {\n if (dataValue === 0) {\n break;\n }\n // 14-bit value, so upper 7 are coarse and lower 7 are fine!\n this.midiControllers[\n NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange\n ] |= dataValue;\n const actualTune =\n (this.midiControllers[\n NON_CC_INDEX_OFFSET +\n modulatorSources.pitchWheelRange\n ] >>\n 7) +\n dataValue / 128;\n SpessaSynthInfo(\n `%cChannel ${this.channelNumber} pitch wheel range. Semitones: %c${actualTune}`,\n consoleColors.info,\n consoleColors.value\n );\n break;\n }\n\n // Fine-tuning\n case registeredParameterTypes.fineTuning: {\n // Grab the data and shift\n const coarse =\n this.customControllers[customControllers.channelTuning];\n const finalTuning = (coarse << 7) | dataValue;\n this.setTuning(finalTuning * 0.01220703125); // Multiply by 8192 / 100 (cent increments)\n break;\n }\n\n // Modulation depth\n case registeredParameterTypes.modulationDepth: {\n const currentModulationDepthCents =\n this.customControllers[\n customControllers.modulationMultiplier\n ] * 50;\n const cents =\n currentModulationDepthCents + (dataValue / 128) * 100;\n this.setModulationDepth(cents);\n break;\n }\n\n case 0x3fff:\n this.resetParameters();\n break;\n }\n break;\n }\n\n case dataEntryStates.NRPFine: {\n const NRPNCoarse =\n this.midiControllers[\n midiControllers.nonRegisteredParameterMSB\n ] >> 7;\n const NRPNFine =\n this.midiControllers[\n midiControllers.nonRegisteredParameterLSB\n ] >> 7;\n if (NRPNCoarse === nonRegisteredMSB.SF2) {\n return;\n }\n switch (NRPNCoarse) {\n default:\n SpessaSynthInfo(\n `%cUnrecognized NRPN LSB for %c${this.channelNumber}%c: %c(0x${NRPNFine.toString(\n 16\n ).toUpperCase()} 0x${NRPNFine.toString(\n 16\n ).toUpperCase()})%c data value: %c${dataValue}`,\n consoleColors.warn,\n consoleColors.recognized,\n consoleColors.warn,\n consoleColors.unrecognized,\n consoleColors.warn,\n consoleColors.value\n );\n break;\n\n case nonRegisteredMSB.awe32:\n handleAWE32NRPN.call(\n this,\n NRPNFine,\n dataValue,\n this.midiControllers[midiControllers.dataEntryMSB] >> 7\n );\n break;\n }\n }\n }\n}\n","import { nonRegisteredMSB } from \"./data_entry/data_entry_coarse\";\nimport type { MIDIChannel } from \"../../engine_components/midi_channel\";\nimport { type MIDIController, midiControllers } from \"../../../../midi/enums\";\nimport { customControllers, dataEntryStates } from \"../../../enums\";\nimport { DEFAULT_PERCUSSION } from \"../../engine_components/synth_constants\";\nimport { BankSelectHacks } from \"../../../../utils/midi_hacks\";\n\n/**\n * Handles MIDI controller changes for a channel.\n * @param controllerNumber The MIDI controller number (0-127).\n * @param controllerValue The value of the controller (0-127).\n * @param sendEvent If an event should be emitted.\n * @remarks\n * This function processes MIDI controller changes, updating the channel's\n * midiControllers table and handling special cases like bank select,\n * data entry, and sustain pedal. It also computes modulators for all voices\n * in the channel based on the controller change.\n * If the controller number is greater than 127, it is treated as a channel\n * configuration controller, and the `force` parameter must be set to true\n * to allow changes.\n */\nexport function controllerChange(\n this: MIDIChannel,\n controllerNumber: MIDIController,\n controllerValue: number,\n sendEvent = true\n) {\n if (controllerNumber > 127) {\n throw new Error(\"Invalid MIDI Controller.\");\n }\n\n // Lsb controller values: append them as the lower nibble of the 14-bit value\n // Excluding bank select and data entry as it's handled separately\n if (\n controllerNumber >= midiControllers.modulationWheelLSB &&\n controllerNumber <= midiControllers.effectControl2LSB &&\n controllerNumber !== midiControllers.dataEntryLSB\n ) {\n const actualCCNum = controllerNumber - 32;\n if (this.lockedControllers[actualCCNum]) {\n return;\n }\n // Append the lower nibble to the main controller\n this.midiControllers[actualCCNum] =\n (this.midiControllers[actualCCNum] & 0x3f80) |\n (controllerValue & 0x7f);\n this.voices.forEach((v) => this.computeModulators(v, 1, actualCCNum));\n }\n if (this.lockedControllers[controllerNumber]) {\n return;\n }\n\n // Apply the cc to the table\n this.midiControllers[controllerNumber] = controllerValue << 7;\n\n // Interpret special CCs\n {\n switch (controllerNumber) {\n case midiControllers.allNotesOff:\n this.stopAllNotes();\n break;\n\n case midiControllers.allSoundOff:\n this.stopAllNotes(true);\n break;\n\n // Special case: bank select\n case midiControllers.bankSelect:\n this.setBankMSB(controllerValue);\n // Ensure that for XG, drum channels always are 127\n // Testcase\n // Dave-Rodgers-D-j-Vu-Anonymous-20200419154845-nonstop2k.com.mid\n if (\n this.channelNumber % 16 === DEFAULT_PERCUSSION &&\n BankSelectHacks.isSystemXG(this.channelSystem)\n ) {\n this.setBankMSB(127);\n }\n\n break;\n\n case midiControllers.bankSelectLSB:\n this.setBankLSB(controllerValue);\n break;\n\n // Check for RPN and NPRN and data entry\n case midiControllers.registeredParameterLSB:\n this.dataEntryState = dataEntryStates.RPFine;\n break;\n\n case midiControllers.registeredParameterMSB:\n this.dataEntryState = dataEntryStates.RPCoarse;\n break;\n\n case midiControllers.nonRegisteredParameterMSB:\n // Sf spec section 9.6.2\n this.customControllers[customControllers.sf2NPRNGeneratorLSB] =\n 0;\n this.dataEntryState = dataEntryStates.NRPCoarse;\n break;\n\n case midiControllers.nonRegisteredParameterLSB:\n if (\n this.midiControllers[\n midiControllers.nonRegisteredParameterMSB\n ] >>\n 7 ===\n nonRegisteredMSB.SF2\n ) {\n // If a <100 value has already been sent, reset!\n if (\n this.customControllers[\n customControllers.sf2NPRNGeneratorLSB\n ] %\n 100 !==\n 0\n ) {\n this.customControllers[\n customControllers.sf2NPRNGeneratorLSB\n ] = 0;\n }\n\n if (controllerValue === 100) {\n this.customControllers[\n customControllers.sf2NPRNGeneratorLSB\n ] += 100;\n } else if (controllerValue === 101) {\n this.customControllers[\n customControllers.sf2NPRNGeneratorLSB\n ] += 1000;\n } else if (controllerValue === 102) {\n this.customControllers[\n customControllers.sf2NPRNGeneratorLSB\n ] += 10000;\n } else if (controllerValue < 100) {\n this.customControllers[\n customControllers.sf2NPRNGeneratorLSB\n ] += controllerValue;\n }\n }\n this.dataEntryState = dataEntryStates.NRPFine;\n break;\n\n case midiControllers.dataEntryMSB:\n this.dataEntryCoarse(controllerValue);\n break;\n\n case midiControllers.dataEntryLSB:\n this.dataEntryFine(controllerValue);\n break;\n\n case midiControllers.resetAllControllers:\n this.resetControllersRP15Compliant();\n break;\n\n case midiControllers.sustainPedal:\n if (controllerValue < 64) {\n this.sustainedVoices.forEach((v) => {\n v.release(this.synth.currentSynthTime);\n });\n this.sustainedVoices = [];\n }\n break;\n\n // Default: just compute modulators\n default:\n this.voices.forEach((v) =>\n this.computeModulators(v, 1, controllerNumber)\n );\n break;\n }\n }\n if (!sendEvent) {\n return;\n }\n this.synthProps.callEvent(\"controllerChange\", {\n channel: this.channelNumber,\n controllerNumber: controllerNumber,\n controllerValue: controllerValue\n });\n}\n","// Tests were performed by John Novak\n// https://github.com/dosbox-staging/dosbox-staging/pull/2705\n\n/*\nCC 5 value Portamento time\n---------- ---------------\n 0 0.000 s\n 1 0.006 s\n 2 0.023 s\n 4 0.050 s\n 8 0.110 s\n 16 0.250 s\n 32 0.500 s\n 64 2.060 s\n 80 4.200 s\n 96 8.400 s\n 112 19.500 s\n 116 26.700 s\n 120 40.000 s\n 124 80.000 s\n 127 480.000 s\n*/\n\nconst portamentoLookup: Record<number, number> = {\n 0: 0.0,\n 1: 0.006,\n 2: 0.023,\n 4: 0.05,\n 8: 0.11,\n 16: 0.25,\n 32: 0.5,\n 64: 2.06,\n 80: 4.2,\n 96: 8.4,\n 112: 19.5,\n 116: 26.7,\n 120: 40.0,\n 124: 80.0,\n 127: 480.0\n} as const;\n\nfunction getLookup(value: number): number {\n if (portamentoLookup[value] !== undefined) {\n return portamentoLookup[value];\n }\n // Get the nearest lower and upper points from the lookup table\n let lower = null;\n let upper = null;\n\n for (const k of Object.keys(portamentoLookup)) {\n const key = parseInt(k);\n if (key < value && (lower === null || key > lower)) {\n lower = key;\n }\n if (key > value && (upper === null || key < upper)) {\n upper = key;\n }\n }\n\n // If we have found both lower and upper points, perform linear interpolation\n if (lower !== null && upper !== null) {\n const lowerTime = portamentoLookup[lower];\n const upperTime = portamentoLookup[upper];\n\n // Linear interpolation\n return (\n lowerTime +\n ((value - lower) * (upperTime - lowerTime)) / (upper - lower)\n );\n }\n return 0;\n}\n\n/**\n * Converts portamento time to seconds.\n * @param time MIDI portamento time (CC 5 value) (0-127)\n * @param distance Distance in semitones (keys) to slide over.\n * @returns The portamento time in seconds.\n */\nexport function portamentoTimeToSeconds(\n time: number,\n distance: number\n): number {\n // This seems to work fine for the MIDIs I have.\n // Why? No idea, but it does. :-)\n return getLookup(time) * (distance / 30);\n}\n","import { portamentoTimeToSeconds } from \"./portamento_time\";\nimport { Modulator } from \"../../../soundbank/basic_soundbank/modulator\";\nimport { GENERATOR_OVERRIDE_NO_CHANGE_VALUE } from \"../engine_components/synth_constants\";\nimport { SpessaSynthWarn } from \"../../../utils/loggin\";\nimport type { MIDIChannel } from \"../engine_components/midi_channel\";\nimport { generatorTypes } from \"../../../soundbank/basic_soundbank/generator_types\";\nimport { midiControllers } from \"../../../midi/enums\";\nimport { customControllers } from \"../../enums\";\n\n/**\n * Sends a \"MIDI Note on\" message and starts a note.\n * @param midiNote The MIDI note number (0-127).\n * @param velocity The velocity of the note (0-127). If less than 1, it will send a note off instead.\n */\nexport function noteOn(this: MIDIChannel, midiNote: number, velocity: number) {\n if (velocity < 1) {\n this.noteOff(midiNote);\n return;\n }\n velocity = Math.min(127, velocity);\n\n if (\n (this.synthProps.masterParameters.blackMIDIMode &&\n this.synth.totalVoicesAmount > 200 &&\n velocity < 40) ||\n (this.synthProps.masterParameters.blackMIDIMode && velocity < 10) ||\n this._isMuted\n ) {\n return;\n }\n\n if (!this.preset) {\n SpessaSynthWarn(`No preset for channel ${this.channelNumber}!`);\n return;\n }\n\n const realKey =\n midiNote +\n this.channelTransposeKeyShift +\n this.customControllers[customControllers.channelKeyShift];\n let internalMidiNote = realKey;\n\n if (realKey > 127 || realKey < 0) {\n return;\n }\n const program = this.preset?.program;\n const tune = this.synthProps.tunings[program]?.[realKey]?.midiNote;\n if (tune >= 0) {\n internalMidiNote = tune;\n }\n\n // Monophonic retrigger\n if (this.synthProps.masterParameters.monophonicRetriggerMode) {\n this.killNote(midiNote, -7200);\n }\n\n // Key velocity override\n const keyVel = this.synth.keyModifierManager.getVelocity(\n this.channelNumber,\n realKey\n );\n if (keyVel > -1) {\n velocity = keyVel;\n }\n\n // Gain\n const voiceGain = this.synth.keyModifierManager.getGain(\n this.channelNumber,\n realKey\n );\n\n // Portamento\n let portamentoFromKey = -1;\n let portamentoDuration = 0;\n // Note: the 14-bit value needs to go down to 7-bit\n const portamentoTime =\n this.midiControllers[midiControllers.portamentoTime] >> 7;\n const control = this.midiControllers[midiControllers.portamentoControl];\n const currentFromKey = control >> 7;\n if (\n !this.drumChannel && // No portamento on drum channel\n currentFromKey !== internalMidiNote && // If the same note, there's no portamento\n this.midiControllers[midiControllers.portamentoOnOff] >= 8192 && // (64 << 7)\n portamentoTime > 0 // 0 duration is no portamento\n ) {\n // A value of one means the initial portamento\n if (control !== 1) {\n const diff = Math.abs(internalMidiNote - currentFromKey);\n portamentoDuration = portamentoTimeToSeconds(portamentoTime, diff);\n portamentoFromKey = currentFromKey;\n }\n // Set portamento control to previous value\n this.controllerChange(\n midiControllers.portamentoControl,\n internalMidiNote\n );\n }\n // Get voices\n const voices = this.synthProps.getVoices(\n this.channelNumber,\n internalMidiNote,\n velocity,\n realKey\n );\n\n // Zero means disabled\n let panOverride = 0;\n if (this.randomPan) {\n // The range is -500 to 500\n panOverride = Math.round(Math.random() * 1000 - 500);\n }\n\n // Add voices\n const channelVoices = this.voices;\n voices.forEach((voice) => {\n // Apply portamento\n voice.portamentoFromKey = portamentoFromKey;\n voice.portamentoDuration = portamentoDuration;\n\n // Apply pan override\n voice.overridePan = panOverride;\n\n // Apply gain override\n voice.gain = voiceGain;\n\n // Dynamic modulators (if none, this won't iterate over anything)\n this.sysExModulators.modulatorList.forEach((m) => {\n const mod = m.mod;\n const existingModIndex = voice.modulators.findIndex((voiceMod) =>\n Modulator.isIdentical(voiceMod, mod)\n );\n\n // Replace or add\n if (existingModIndex !== -1) {\n voice.modulators[existingModIndex] = Modulator.copyFrom(mod);\n } else {\n voice.modulators.push(Modulator.copyFrom(mod));\n }\n });\n\n // Apply generator override\n if (this.generatorOverridesEnabled) {\n this.generatorOverrides.forEach((overrideValue, generatorType) => {\n if (overrideValue === GENERATOR_OVERRIDE_NO_CHANGE_VALUE) {\n return;\n }\n voice.generators[generatorType] = overrideValue;\n });\n }\n\n // Apply exclusive class\n const exclusive = voice.exclusiveClass;\n if (exclusive !== 0) {\n // Kill all voices with the same exclusive class\n channelVoices.forEach((v) => {\n if (v.exclusiveClass === exclusive) {\n v.exclusiveRelease(this.synth.currentSynthTime);\n }\n });\n }\n // Compute all modulators\n this.computeModulators(voice);\n // Modulate sample offsets (these are not real time)\n const cursorStartOffset =\n voice.modulatedGenerators[generatorTypes.startAddrsOffset] +\n voice.modulatedGenerators[generatorTypes.startAddrsCoarseOffset] *\n 32768;\n const endOffset =\n voice.modulatedGenerators[generatorTypes.endAddrOffset] +\n voice.modulatedGenerators[generatorTypes.endAddrsCoarseOffset] *\n 32768;\n const loopStartOffset =\n voice.modulatedGenerators[generatorTypes.startloopAddrsOffset] +\n voice.modulatedGenerators[\n generatorTypes.startloopAddrsCoarseOffset\n ] *\n 32768;\n const loopEndOffset =\n voice.modulatedGenerators[generatorTypes.endloopAddrsOffset] +\n voice.modulatedGenerators[generatorTypes.endloopAddrsCoarseOffset] *\n 32768;\n const sm = voice.sample;\n // Apply them\n const clamp = (num: number) =>\n Math.max(0, Math.min(sm.sampleData.length - 1, num));\n sm.cursor = clamp(sm.cursor + cursorStartOffset);\n sm.end = clamp(sm.end + endOffset);\n sm.loopStart = clamp(sm.loopStart + loopStartOffset);\n sm.loopEnd = clamp(sm.loopEnd + loopEndOffset);\n // Swap loops if needed\n if (sm.loopEnd < sm.loopStart) {\n const temp = sm.loopStart;\n sm.loopStart = sm.loopEnd;\n sm.loopEnd = temp;\n }\n if (sm.loopEnd - sm.loopStart < 1) {\n // Disable loop if enabled\n // Don't disable on release mode. Testcase:\n // https://github.com/spessasus/SpessaSynth/issues/174\n if (sm.loopingMode === 1 || sm.loopingMode === 3) {\n sm.loopingMode = 0;\n sm.isLooping = false;\n }\n }\n // Set the current attenuation to target,\n // As it's interpolated (we don't want 0 attenuation for even a split second)\n voice.volumeEnvelope.attenuation =\n voice.volumeEnvelope.attenuationTargetGain;\n // Set initial pan to avoid split second changing from middle to the correct value\n voice.currentPan = Math.max(\n -500,\n Math.min(500, voice.modulatedGenerators[generatorTypes.pan])\n ); // -500 to 500\n });\n\n this.synth.totalVoicesAmount += voices.length;\n // Cap the voices\n if (\n this.synth.totalVoicesAmount > this.synthProps.masterParameters.voiceCap\n ) {\n this.synthProps.voiceKilling(voices.length);\n }\n channelVoices.push(...voices);\n this.sendChannelProperty();\n this.synthProps.callEvent(\"noteOn\", {\n midiNote: midiNote,\n channel: this.channelNumber,\n velocity: velocity\n });\n}\n","import { SpessaSynthWarn } from \"../../../../utils/loggin\";\nimport type { MIDIChannel } from \"../../engine_components/midi_channel\";\nimport { customControllers } from \"../../../enums\";\n\n/**\n * Releases a note by its MIDI note number.\n * If the note is in high performance mode and the channel is not a drum channel,\n * it kills the note instead of releasing it.\n * @param midiNote The MIDI note number to release (0-127).\n */\nexport function noteOff(this: MIDIChannel, midiNote: number) {\n if (midiNote > 127 || midiNote < 0) {\n SpessaSynthWarn(`Received a noteOn for note`, midiNote, \"Ignoring.\");\n return;\n }\n\n // Adjust the midi note with the channel transpose key shift\n const realKey =\n midiNote +\n this.channelTransposeKeyShift +\n this.customControllers[customControllers.channelKeyShift];\n\n // If high performance mode, kill notes instead of stopping them\n if (this.synthProps.masterParameters.blackMIDIMode) {\n // If the channel is percussion channel, do not kill the notes\n if (!this.drumChannel) {\n this.killNote(realKey, -6950);\n this.synthProps.callEvent(\"noteOff\", {\n midiNote: midiNote,\n channel: this.channelNumber\n });\n return;\n }\n }\n\n const channelVoices = this.voices;\n channelVoices.forEach((v) => {\n if (v.realKey !== realKey || v.isInRelease) {\n return;\n }\n // If hold pedal, move to sustain\n if (this.holdPedal) {\n this.sustainedVoices.push(v);\n } else {\n v.release(this.synth.currentSynthTime);\n }\n });\n this.synthProps.callEvent(\"noteOff\", {\n midiNote: midiNote,\n channel: this.channelNumber\n });\n}\n","import { SpessaSynthWarn } from \"../../../utils/loggin\";\nimport { BasicPreset } from \"../../../soundbank/basic_soundbank/basic_preset\";\nimport type { MIDIChannel } from \"../engine_components/midi_channel\";\n\n/**\n * Changes the program (preset) of the channel.\n * @param program The program number (0-127) to change to.\n */\nexport function programChange(this: MIDIChannel, program: number) {\n if (this.lockPreset) {\n return;\n }\n\n this.patch.program = program;\n let preset = this.synth.soundBankManager.getPreset(\n this.patch,\n this.channelSystem\n );\n if (!preset) {\n SpessaSynthWarn(\"No presets! Using empty fallback.\");\n preset = new BasicPreset(\n this.synth.soundBankManager.soundBankList[0].soundBank\n );\n // Fallback preset, make it scream so it's easy to notice :-)\n preset.name = \"SPESSA EMPTY FALLBACK PRESET\";\n }\n this.preset = preset;\n\n // Drums first\n if (preset.isAnyDrums !== this.drumChannel) {\n this.setDrumFlag(preset.isAnyDrums);\n }\n // Do not spread the preset as we don't want to copy it entirely.\n this.synthProps.callEvent(\"programChange\", {\n channel: this.channelNumber,\n bankLSB: this.preset.bankLSB,\n bankMSB: this.preset.bankMSB,\n program: this.preset.program,\n isGMGSDrum: this.preset.isGMGSDrum\n });\n this.sendChannelProperty();\n}\n","import { Modulator } from \"../../../soundbank/basic_soundbank/modulator\";\nimport { modulatorCurveTypes, type ModulatorSourceEnum } from \"../../../soundbank/enums\";\nimport { NON_CC_INDEX_OFFSET } from \"./controller_tables\";\nimport type { GeneratorType } from \"../../../soundbank/basic_soundbank/generator_types\";\nimport { ModulatorSource } from \"../../../soundbank/basic_soundbank/modulator_source\";\n\n/**\n * A class for dynamic modulators\n * that are assigned for more complex system exclusive messages\n */\nexport class DynamicModulatorSystem {\n /**\n * The current dynamic modulator list.\n */\n public modulatorList: { mod: Modulator; id: string }[] = [];\n\n public resetModulators() {\n this.modulatorList = [];\n }\n\n /**\n * @param source Like in midiControllers: values below NON_CC_INDEX_OFFSET are CCs,\n * above are regular modulator sources.\n * @param destination The generator type to modulate.\n * @param amount The amount of modulation to apply.\n * @param isBipolar If true, the modulation is bipolar (ranges from -1 to 1 instead of from 0 to 1).\n * @param isNegative If true, the modulation is negative (goes from 1 to 0 instead of from 0 to 1).\n */\n public setModulator(\n source: ModulatorSourceEnum,\n destination: GeneratorType,\n amount: number,\n isBipolar = false,\n isNegative = false\n ) {\n const id = this.getModulatorID(\n source,\n destination,\n isBipolar,\n isNegative\n );\n if (amount === 0) {\n this.deleteModulator(id);\n }\n const mod = this.modulatorList.find((m) => m.id === id);\n if (mod) {\n mod.mod.transformAmount = amount;\n } else {\n let srcNum: ModulatorSourceEnum, isCC: boolean;\n if (source >= NON_CC_INDEX_OFFSET) {\n srcNum = (source - NON_CC_INDEX_OFFSET) as ModulatorSourceEnum;\n isCC = false;\n } else {\n srcNum = source;\n isCC = true;\n }\n const modulator = new Modulator(\n new ModulatorSource(\n srcNum,\n modulatorCurveTypes.linear,\n isCC,\n isBipolar\n ),\n new ModulatorSource(),\n destination,\n amount,\n 0\n );\n this.modulatorList.push({\n mod: modulator,\n id: id\n });\n }\n }\n\n private getModulatorID(\n source: number,\n destination: GeneratorType,\n isBipolar: boolean,\n isNegative: boolean\n ) {\n return `${source}-${destination}-${isBipolar}-${isNegative}`;\n }\n\n private deleteModulator(id: string) {\n this.modulatorList = this.modulatorList.filter((m) => m.id !== id);\n }\n}\n","import { VolumeEnvelope } from \"./dsp_chain/volume_envelope\";\nimport { ModulationEnvelope } from \"./dsp_chain/modulation_envelope\";\nimport { Modulator } from \"../../../soundbank/basic_soundbank/modulator\";\nimport { generatorTypes } from \"../../../soundbank/enums\";\nimport { generatorLimits, type GeneratorType } from \"../../../soundbank/basic_soundbank/generator_types\";\nimport type { MIDIChannel } from \"./midi_channel\";\nimport type { Voice } from \"./voice\";\n\n/**\n * Compute_modulator.ts\n * purpose: precomputes all curve types and computes modulators\n */\n\nconst EFFECT_MODULATOR_TRANSFORM_MULTIPLIER = 1000 / 200;\n\n/**\n * Computes a given modulator\n * @param controllerTable all midi controllers as 14bit values + the non-controller indexes, starting at 128\n * @param modulator the modulator to compute\n * @param voice the voice belonging to the modulator\n * @returns the computed value\n */\nexport function computeModulator(\n controllerTable: Int16Array,\n modulator: Modulator,\n voice: Voice\n): number {\n if (modulator.transformAmount === 0) {\n modulator.currentValue = 0;\n return 0;\n }\n const sourceValue = modulator.primarySource.getValue(\n controllerTable,\n voice\n );\n const secondSrcValue = modulator.secondarySource.getValue(\n controllerTable,\n voice\n );\n\n // See the comment for isEffectModulator (modulator.ts in basic_soundbank) for explanation\n let transformAmount = modulator.transformAmount;\n if (modulator.isEffectModulator && transformAmount <= 1000) {\n transformAmount *= EFFECT_MODULATOR_TRANSFORM_MULTIPLIER;\n transformAmount = Math.min(transformAmount, 1000);\n }\n\n // Compute the modulator\n let computedValue = sourceValue * secondSrcValue * transformAmount;\n\n if (modulator.transformType === 2) {\n // Abs value\n computedValue = Math.abs(computedValue);\n }\n\n // Resonant modulator: take its value and ensure that it won't change the final gain\n if (modulator.isDefaultResonantModulator) {\n // Half the gain, negates the filter\n voice.resonanceOffset = Math.max(0, computedValue / 2);\n }\n\n modulator.currentValue = computedValue;\n return computedValue;\n}\n\n/**\n * Computes modulators of a given voice. Source and index indicate what modulators shall be computed.\n * @param voice the voice to compute modulators for.\n * @param sourceUsesCC what modulators should be computed, -1 means all, 0 means modulator source enum 1 means midi controller.\n * @param sourceIndex enum for the source.\n */\nexport function computeModulators(\n this: MIDIChannel,\n voice: Voice,\n sourceUsesCC: -1 | 0 | 1 = -1,\n sourceIndex = 0\n) {\n const modulators = voice.modulators;\n let generators = voice.generators;\n // Apply offsets if enabled\n if (this.generatorOffsetsEnabled) {\n generators = new Int16Array(generators);\n for (let i = 0; i < generators.length; i++) {\n generators[i] += this.generatorOffsets[i];\n }\n }\n const modulatedGenerators = voice.modulatedGenerators;\n\n if (sourceUsesCC === -1) {\n // All modulators mode: compute all modulators\n modulatedGenerators.set(generators);\n modulators.forEach((mod) => {\n modulatedGenerators[mod.destination] += computeModulator(\n this.midiControllers,\n mod,\n voice\n );\n });\n // Apply limits\n for (let gen = 0; gen < modulatedGenerators.length; gen++) {\n const limit = generatorLimits[gen];\n if (!limit) {\n // Skip unused\n continue;\n }\n modulatedGenerators[gen] = Math.min(\n limit.max,\n Math.max(limit.min, modulatedGenerators[gen])\n );\n }\n VolumeEnvelope.recalculate(voice);\n ModulationEnvelope.recalculate(voice);\n return;\n }\n\n // Optimized mode: calculate only modulators that use the given source\n const volumeEnvelopeNeedsRecalculation = new Set<GeneratorType>([\n generatorTypes.initialAttenuation,\n generatorTypes.delayVolEnv,\n generatorTypes.attackVolEnv,\n generatorTypes.holdVolEnv,\n generatorTypes.decayVolEnv,\n generatorTypes.sustainVolEnv,\n generatorTypes.releaseVolEnv,\n generatorTypes.keyNumToVolEnvHold,\n generatorTypes.keyNumToVolEnvDecay\n ]);\n\n const computedDestinations = new Set<GeneratorType>();\n\n const sourceCC = !!sourceUsesCC;\n\n modulators.forEach((mod) => {\n if (\n (mod.primarySource.isCC === sourceCC &&\n mod.primarySource.index === sourceIndex) ||\n (mod.secondarySource.isCC === sourceCC &&\n mod.secondarySource.index === sourceIndex)\n ) {\n const destination = mod.destination;\n if (!computedDestinations.has(destination)) {\n // Reset this destination\n modulatedGenerators[destination] = generators[destination];\n // Compute our modulator\n computeModulator(this.midiControllers, mod, voice);\n // Sum the values of all modulators for this destination\n modulators.forEach((m) => {\n if (m.destination === destination) {\n modulatedGenerators[destination] += m.currentValue;\n }\n });\n // Apply limits\n const limits = generatorLimits[destination];\n modulatedGenerators[destination] = Math.max(\n limits.min,\n Math.min(modulatedGenerators[destination], limits.max)\n );\n computedDestinations.add(destination);\n }\n }\n });\n\n // Recalculate volume envelope if necessary\n if (\n [...computedDestinations].some((dest) =>\n volumeEnvelopeNeedsRecalculation.has(dest)\n )\n ) {\n VolumeEnvelope.recalculate(voice);\n }\n\n ModulationEnvelope.recalculate(voice);\n}\n","import { CONTROLLER_TABLE_SIZE, CUSTOM_CONTROLLER_TABLE_SIZE, NON_CC_INDEX_OFFSET } from \"./controller_tables\";\nimport {\n resetControllers,\n resetControllersRP15Compliant,\n resetParameters,\n resetPreset\n} from \"../engine_methods/controller_control/reset_controllers\";\nimport { renderVoice } from \"./dsp_chain/render_voice\";\nimport { panAndMixVoice } from \"./dsp_chain/stereo_panner\";\nimport { dataEntryFine } from \"../engine_methods/controller_control/data_entry/data_entry_fine\";\nimport { controllerChange } from \"../engine_methods/controller_control/controller_change\";\nimport { dataEntryCoarse } from \"../engine_methods/controller_control/data_entry/data_entry_coarse\";\nimport { noteOn } from \"../engine_methods/note_on\";\nimport { noteOff } from \"../engine_methods/stopping_notes/note_off\";\nimport { programChange } from \"../engine_methods/program_change\";\nimport { DEFAULT_PERCUSSION, GENERATOR_OVERRIDE_NO_CHANGE_VALUE } from \"./synth_constants\";\nimport { DynamicModulatorSystem } from \"./dynamic_modulator_system\";\nimport { computeModulators } from \"./compute_modulator\";\nimport {\n generatorLimits,\n GENERATORS_AMOUNT,\n type GeneratorType,\n generatorTypes\n} from \"../../../soundbank/basic_soundbank/generator_types\";\nimport type { BasicPreset } from \"../../../soundbank/basic_soundbank/basic_preset\";\nimport type { ChannelProperty, SynthSystem, VoiceList } from \"../../types\";\nimport type { SpessaSynthProcessor } from \"../../processor\";\nimport { type CustomController, customControllers, type DataEntryState, dataEntryStates } from \"../../enums\";\nimport { SpessaSynthInfo } from \"../../../utils/loggin\";\nimport { consoleColors } from \"../../../utils/other\";\nimport type { ProtectedSynthValues } from \"./internal_synth_values\";\nimport { midiControllers } from \"../../../midi/enums\";\nimport { modulatorSources } from \"../../../soundbank/enums\";\nimport type { MIDIPatch } from \"../../../soundbank/basic_soundbank/midi_patch\";\nimport { BankSelectHacks } from \"../../../utils/midi_hacks\";\n\n/**\n * This class represents a single MIDI Channel within the synthesizer.\n */\nexport class MIDIChannel {\n /*\n * An array of MIDI controllers for the channel.\n * This array is used to store the state of various MIDI controllers\n * such as volume, pan, modulation, etc.\n * @remarks\n * A bit of an explanation:\n * The controller table is stored as an int16 array, it stores 14-bit values.\n * This controller table is then extended with the modulatorSources section,\n * for example, pitch range and pitch range depth.\n * This allows us for precise control range and supports full pitch-wheel resolution.\n */\n public readonly midiControllers: Int16Array = new Int16Array(\n CONTROLLER_TABLE_SIZE\n );\n\n /**\n * An array indicating if a controller, at the equivalent index in the midiControllers array, is locked\n * (i.e., not allowed changing).\n * A locked controller cannot be modified.\n */\n public lockedControllers: boolean[] = Array(CONTROLLER_TABLE_SIZE).fill(\n false\n ) as boolean[];\n\n /**\n * An array of custom (non-SF2) control values such as RPN pitch tuning, transpose, modulation depth, etc.\n * Refer to controller_tables.ts for the index definitions.\n */\n public readonly customControllers: Float32Array = new Float32Array(\n CUSTOM_CONTROLLER_TABLE_SIZE\n );\n\n /**\n * The key shift of the channel (in semitones).\n */\n public channelTransposeKeyShift = 0;\n\n /**\n * An array of octave tuning values for each note on the channel.\n * Each index corresponds to a note (0 = C, 1 = C#, ..., 11 = B).\n * Note: Repeated every 12 notes.\n */\n public channelOctaveTuning: Int8Array = new Int8Array(128);\n /**\n * A system for dynamic modulator assignment for advanced system exclusives.\n */\n public sysExModulators: DynamicModulatorSystem =\n new DynamicModulatorSystem();\n /**\n * Indicates whether this channel is a drum channel.\n */\n public drumChannel = false;\n /**\n * Enables random panning for every note played on this channel.\n */\n public randomPan = false;\n /**\n * The current state of the data entry for the channel.\n */\n public dataEntryState: DataEntryState = dataEntryStates.Idle;\n\n /**\n * The currently selected MIDI patch of the channel.\n * Note that the exact matching preset may not be available, but this represents exactly what MIDI asks for.\n */\n public readonly patch: MIDIPatch = {\n bankMSB: 0,\n bankLSB: 0,\n program: 0,\n isGMGSDrum: false\n };\n /**\n * The preset currently assigned to the channel.\n */\n public preset?: BasicPreset;\n /**\n * Indicates whether the program on this channel is locked.\n */\n public lockPreset = false;\n /**\n * Indicates the MIDI system when the preset was locked.\n */\n public lockedSystem: SynthSystem = \"gs\";\n /**\n * Indicates whether the GS NRPN parameters are enabled for this channel.\n */\n public lockGSNRPNParams = false;\n /**\n * The vibrato settings for the channel.\n * @property depth - Depth of the vibrato effect in cents.\n * @property delay - Delay before the vibrato effect starts (in seconds).\n * @property rate - Rate of the vibrato oscillation (in Hz).\n */\n public channelVibrato: { delay: number; depth: number; rate: number } = {\n delay: 0,\n depth: 0,\n rate: 0\n };\n /**\n * An array of voices currently active on the channel.\n */\n public voices: VoiceList = [];\n /**\n * An array of voices that are sustained on the channel.\n */\n public sustainedVoices: VoiceList = [];\n /**\n * The channel's number (0-based index)\n */\n public readonly channelNumber: number;\n /**\n * Parent processor instance.\n */\n public synth: SpessaSynthProcessor;\n /**\n * Grants access to protected synth values.\n */\n public synthProps: ProtectedSynthValues;\n // MIDI messages\n /**\n * Sends a \"MIDI Note on\" message and starts a note.\n * @param midiNote The MIDI note number (0-127).\n * @param velocity The velocity of the note (0-127). If less than 1, it will send a note off instead.\n */\n public noteOn = noteOn.bind(this) as typeof noteOn;\n // (A hacky way to split the class into multiple files)\n /**\n * Releases a note by its MIDI note number.\n * If the note is in high performance mode and the channel is not a drum channel,\n * it kills the note instead of releasing it.\n * @param midiNote The MIDI note number to release (0-127).\n */\n public noteOff = noteOff.bind(this) as typeof noteOff;\n // Bind all methods to the instance\n /**\n * Changes the program (preset) of the channel.\n * @param programNumber The program number (0-127) to change to.\n */\n public programChange = programChange.bind(this) as typeof programChange;\n // CC (Continuous Controller)\n public controllerChange = controllerChange.bind(\n this\n ) as typeof controllerChange;\n /**\n * Reset all controllers for channel.\n * This will reset all controllers to their default values,\n * except for the locked controllers.\n */\n public readonly resetControllers = resetControllers.bind(\n this\n ) as typeof resetControllers;\n public readonly resetPreset = resetPreset.bind(this) as typeof resetPreset;\n /**\n * https://amei.or.jp/midistandardcommittee/Recommended_Practice/e/rp15.pdf\n * Reset controllers according to RP-15 Recommended Practice.\n */\n public readonly resetControllersRP15Compliant =\n resetControllersRP15Compliant.bind(\n this\n ) as typeof resetControllersRP15Compliant;\n /**\n * Reset all parameters to their default values.\n * This includes NRPN and RPN controllers, data entry state,\n * and generator overrides and offsets.\n */\n public resetParameters = resetParameters.bind(\n this\n ) as typeof resetParameters;\n /**\n * Executes a data entry fine (LSB) change for the current channel.\n * @param dataValue The value to set for the data entry fine controller (0-127).\n */\n public dataEntryFine = dataEntryFine.bind(this) as typeof dataEntryFine;\n /**\n * Executes a data entry coarse (MSB) change for the current channel.\n * @param dataValue The value to set for the data entry coarse controller (0-127).\n */\n public dataEntryCoarse = dataEntryCoarse.bind(\n this\n ) as typeof dataEntryCoarse;\n /**\n * Will be updated every time something tuning-related gets changed.\n * This is used to avoid a big addition for every voice rendering call.\n */\n protected channelTuningCents = 0;\n /**\n * An array of offsets generators for SF2 nrpn support.\n * A value of 0 means no change; -10 means 10 lower, etc.\n */\n protected generatorOffsets: Int16Array = new Int16Array(GENERATORS_AMOUNT);\n // Tuning\n /**\n * A small optimization that disables applying offsets until at least one is set.\n */\n protected generatorOffsetsEnabled = false;\n /**\n * An array of override generators for AWE32 support.\n * A value of 32,767 means unchanged, as it is not allowed anywhere.\n */\n protected generatorOverrides: Int16Array = new Int16Array(\n GENERATORS_AMOUNT\n );\n /**\n * A small optimization that disables applying overrides until at least one is set.\n */\n protected generatorOverridesEnabled = false;\n // Voice rendering methods\n protected renderVoice = renderVoice.bind(this);\n protected panAndMixVoice = panAndMixVoice.bind(this);\n protected computeModulators = computeModulators.bind(this);\n\n /**\n * Constructs a new MIDI channel.\n */\n public constructor(\n synth: SpessaSynthProcessor,\n synthProps: ProtectedSynthValues,\n preset: BasicPreset | undefined,\n channelNumber: number\n ) {\n this.synth = synth;\n this.synthProps = synthProps;\n this.preset = preset;\n this.channelNumber = channelNumber;\n this.resetGeneratorOverrides();\n this.resetGeneratorOffsets();\n }\n\n /**\n * Indicates whether the channel is muted.\n */\n protected _isMuted = false;\n\n /**\n * Indicates whether the channel is muted.\n */\n public get isMuted() {\n return this._isMuted;\n }\n\n /**\n * Indicates whether the sustain (hold) pedal is active.\n */\n public get holdPedal() {\n // 64 << 7 = 8192\n return this.midiControllers[midiControllers.sustainPedal] >= 8192;\n }\n\n protected get channelSystem(): SynthSystem {\n return this.lockPreset\n ? this.lockedSystem\n : this.synthProps.masterParameters.midiSystem;\n }\n\n /**\n * Transposes the channel by given amount of semitones.\n * @param semitones The number of semitones to transpose the channel by. Can be decimal.\n * @param force Defaults to false, if true, it will force the transpose even if the channel is a drum channel.\n */\n public transposeChannel(semitones: number, force = false) {\n if (!this.drumChannel) {\n semitones += this.synthProps.masterParameters.transposition;\n }\n const keyShift = Math.trunc(semitones);\n const currentTranspose =\n this.channelTransposeKeyShift +\n this.customControllers[customControllers.channelTransposeFine] /\n 100;\n if ((this.drumChannel && !force) || semitones === currentTranspose) {\n return;\n }\n if (keyShift !== this.channelTransposeKeyShift) {\n // Stop all\n this.stopAllNotes();\n }\n // Apply transpose\n this.channelTransposeKeyShift = keyShift;\n this.setCustomController(\n customControllers.channelTransposeFine,\n (semitones - keyShift) * 100\n );\n this.sendChannelProperty();\n }\n\n /**\n * Sets the octave tuning for a given channel.\n * @param tuning The tuning array of 12 values, each representing the tuning for a note in the octave.\n * @remarks\n * Cent tunings are relative.\n */\n public setOctaveTuning(tuning: Int8Array) {\n if (tuning.length !== 12) {\n throw new Error(\"Tuning is not the length of 12.\");\n }\n this.channelOctaveTuning = new Int8Array(128);\n for (let i = 0; i < 128; i++) {\n this.channelOctaveTuning[i] = tuning[i % 12];\n }\n }\n\n /**\n * Sets the modulation depth for the channel.\n * @param cents The modulation depth in cents to set.\n * @remarks\n * This method sets the modulation depth for the channel by converting the given cents value into a\n * multiplier. The MIDI specification assumes the default modulation depth is 50 cents,\n * but it may vary for different sound banks.\n * For example, if you want a modulation depth of 100 cents,\n * the multiplier will be 2,\n * which, for a preset with a depth of 50,\n * will create a total modulation depth of 100 cents.\n *\n */\n public setModulationDepth(cents: number) {\n cents = Math.round(cents);\n SpessaSynthInfo(\n `%cChannel ${this.channelNumber} modulation depth. Cents: %c${cents}`,\n consoleColors.info,\n consoleColors.value\n );\n this.setCustomController(\n customControllers.modulationMultiplier,\n cents / 50\n );\n }\n\n /**\n * Sets the channel's tuning.\n * @param cents The tuning in cents to set.\n * @param log If true, logs the change to the console.\n */\n public setTuning(cents: number, log = true) {\n cents = Math.round(cents);\n this.setCustomController(customControllers.channelTuning, cents);\n if (!log) {\n return;\n }\n SpessaSynthInfo(\n `%cFine tuning for %c${this.channelNumber}%c is now set to %c${cents}%c cents.`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info\n );\n }\n\n /**\n * Sets the pitch of the given channel.\n * @param pitch The pitch (0 - 16384)\n */\n public pitchWheel(pitch: number) {\n if (\n this.lockedControllers[\n NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel\n ]\n ) {\n return;\n }\n this.synthProps.callEvent(\"pitchWheel\", {\n channel: this.channelNumber,\n pitch\n });\n this.midiControllers[\n NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel\n ] = pitch;\n this.voices.forEach((v) =>\n // Compute pitch modulators\n this.computeModulators(v, 0, modulatorSources.pitchWheel)\n );\n this.sendChannelProperty();\n }\n\n /**\n * Sets the channel pressure (MIDI Aftertouch).\n * @param pressure the pressure of the channel.\n */\n public channelPressure(pressure: number) {\n this.midiControllers[\n NON_CC_INDEX_OFFSET + modulatorSources.channelPressure\n ] = pressure << 7;\n this.updateChannelTuning();\n this.voices.forEach((v) =>\n this.computeModulators(v, 0, modulatorSources.channelPressure)\n );\n this.synthProps.callEvent(\"channelPressure\", {\n channel: this.channelNumber,\n pressure: pressure\n });\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Sets the pressure of the given note on a specific channel.\n * This is used for polyphonic pressure (aftertouch).\n * @param midiNote 0 - 127, the MIDI note number to set the pressure for.\n * @param pressure 0 - 127, the pressure value to set for the note.\n */\n public polyPressure(midiNote: number, pressure: number) {\n this.voices.forEach((v) => {\n if (v.midiNote !== midiNote) {\n return;\n }\n v.pressure = pressure;\n this.computeModulators(v, 0, modulatorSources.polyPressure);\n });\n this.synthProps.callEvent(\"polyPressure\", {\n channel: this.channelNumber,\n midiNote: midiNote,\n pressure: pressure\n });\n }\n\n public setCustomController(type: CustomController, value: number) {\n this.customControllers[type] = value;\n this.updateChannelTuning();\n }\n\n public updateChannelTuning() {\n this.channelTuningCents =\n this.customControllers[customControllers.channelTuning] + // RPN channel fine tuning\n this.customControllers[customControllers.channelTransposeFine] + // User tuning (transpose)\n this.customControllers[customControllers.masterTuning] + // Master tuning, set by sysEx\n this.customControllers[customControllers.channelTuningSemitones] *\n 100; // RPN channel coarse tuning\n }\n\n /**\n * Renders Float32 audio for this channel.\n * @param outputLeft the left output buffer.\n * @param outputRight the right output buffer.\n * @param reverbOutputLeft left output for reverb.\n * @param reverbOutputRight right output for reverb.\n * @param chorusOutputLeft left output for chorus.\n * @param chorusOutputRight right output for chorus.\n * @param startIndex start index offset.\n * @param sampleCount sample count to render.\n */\n public renderAudio(\n outputLeft: Float32Array,\n outputRight: Float32Array,\n reverbOutputLeft: Float32Array,\n reverbOutputRight: Float32Array,\n chorusOutputLeft: Float32Array,\n chorusOutputRight: Float32Array,\n startIndex: number,\n sampleCount: number\n ) {\n this.voices = this.voices.filter(\n (v) =>\n !this.renderVoice(\n v,\n this.synth.currentSynthTime,\n outputLeft,\n outputRight,\n reverbOutputLeft,\n reverbOutputRight,\n chorusOutputLeft,\n chorusOutputRight,\n startIndex,\n sampleCount\n )\n );\n }\n\n /**\n * Locks or unlocks the preset from MIDI program changes.\n * @param locked If the preset should be locked.\n */\n public setPresetLock(locked: boolean) {\n if (this.lockPreset === locked) {\n return;\n }\n this.lockPreset = locked;\n if (locked) {\n this.lockedSystem = this.synthProps.masterParameters.midiSystem;\n }\n }\n\n /**\n * Changes the preset to, or from drums.\n * Note that this executes a program change.\n * @param isDrum If the channel should be a drum preset or not.\n */\n public setDrums(isDrum: boolean) {\n if (BankSelectHacks.isSystemXG(this.channelSystem)) {\n if (isDrum) {\n this.setBankMSB(\n BankSelectHacks.getDrumBank(this.channelSystem)\n );\n this.setBankLSB(0);\n } else {\n if (this.channelNumber % 16 === DEFAULT_PERCUSSION) {\n throw new Error(\n `Cannot disable drums on channel ${this.channelNumber} for XG.`\n );\n }\n this.setBankMSB(0);\n this.setBankLSB(0);\n }\n } else {\n this.setGSDrums(isDrum);\n }\n this.setDrumFlag(isDrum);\n this.programChange(this.patch.program);\n }\n\n /**\n * Sets the channel to a given MIDI patch.\n * Note that this executes a program change.\n * @param patch The MIDI patch to set the channel to.\n */\n public setPatch(patch: MIDIPatch) {\n this.setBankMSB(patch.bankMSB);\n this.setBankLSB(patch.bankLSB);\n this.setGSDrums(patch.isGMGSDrum);\n this.programChange(patch.program);\n }\n\n /**\n * Sets the GM/GS drum flag.\n * @param drums\n */\n public setGSDrums(drums: boolean) {\n if (drums === this.patch.isGMGSDrum) {\n return;\n }\n this.setBankLSB(0);\n this.setBankMSB(0);\n this.patch.isGMGSDrum = drums;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Sets a custom vibrato.\n * @param depth In cents.\n * @param rate In Hertz.\n * @param delay seconds.\n */\n public setVibrato(depth: number, rate: number, delay: number) {\n if (this.lockGSNRPNParams) {\n return;\n }\n this.channelVibrato.rate = rate;\n this.channelVibrato.delay = delay;\n this.channelVibrato.depth = depth;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Disables and locks all GS NPRN parameters, including the custom vibrato.\n */\n public disableAndLockGSNRPN() {\n this.lockGSNRPNParams = true;\n this.channelVibrato.rate = 0;\n this.channelVibrato.delay = 0;\n this.channelVibrato.depth = 0;\n }\n\n public resetGeneratorOverrides() {\n this.generatorOverrides.fill(GENERATOR_OVERRIDE_NO_CHANGE_VALUE);\n this.generatorOverridesEnabled = false;\n }\n\n public setGeneratorOverride(\n gen: GeneratorType,\n value: number,\n realtime = false\n ) {\n this.generatorOverrides[gen] = value;\n this.generatorOverridesEnabled = true;\n if (realtime) {\n this.voices.forEach((v) => {\n v.generators[gen] = value;\n this.computeModulators(v);\n });\n }\n }\n\n public resetGeneratorOffsets() {\n this.generatorOffsets.fill(0);\n this.generatorOffsetsEnabled = false;\n }\n\n public setGeneratorOffset(gen: GeneratorType, value: number) {\n this.generatorOffsets[gen] = value * generatorLimits[gen].nrpn;\n this.generatorOffsetsEnabled = true;\n this.voices.forEach((v) => {\n this.computeModulators(v);\n });\n }\n\n /**\n * Stops a note nearly instantly.\n * @param midiNote The note to stop.\n * @param releaseTime in timecents, defaults to -12000 (very short release).\n */\n public killNote(midiNote: number, releaseTime = -12000) {\n // Adjust midiNote by channel key shift\n midiNote += this.customControllers[customControllers.channelKeyShift];\n\n this.voices.forEach((v) => {\n if (v.realKey !== midiNote) {\n return;\n }\n v.modulatedGenerators[generatorTypes.releaseVolEnv] = releaseTime; // Set release to be very short\n v.release(this.synth.currentSynthTime);\n });\n }\n\n /**\n * Stops all notes on the channel.\n * @param force If true, stops all notes immediately, otherwise applies release time.\n */\n public stopAllNotes(force = false) {\n if (force) {\n // Force stop all\n this.voices.length = 0;\n this.sustainedVoices.length = 0;\n this.sendChannelProperty();\n } else {\n this.voices.forEach((v) => {\n if (v.isInRelease) {\n return;\n }\n v.release(this.synth.currentSynthTime);\n });\n this.sustainedVoices.forEach((v) => {\n v.release(this.synth.currentSynthTime);\n });\n }\n this.synthProps.callEvent(\"stopAll\", {\n channel: this.channelNumber,\n force\n });\n }\n\n /**\n * Mutes or unmutes a channel.\n * @param isMuted If the channel should be muted.\n */\n public muteChannel(isMuted: boolean) {\n if (isMuted) {\n this.stopAllNotes(true);\n }\n this._isMuted = isMuted;\n this.sendChannelProperty();\n this.synthProps.callEvent(\"muteChannel\", {\n channel: this.channelNumber,\n isMuted: isMuted\n });\n }\n\n /**\n * Sends this channel's property\n */\n public sendChannelProperty() {\n if (!this.synth.enableEventSystem) {\n return;\n }\n const data: ChannelProperty = {\n voicesAmount: this.voices.length,\n pitchWheel:\n this.midiControllers[\n NON_CC_INDEX_OFFSET + modulatorSources.pitchWheel\n ],\n pitchWheelRange:\n this.midiControllers[\n NON_CC_INDEX_OFFSET + modulatorSources.pitchWheelRange\n ] / 128,\n isMuted: this.isMuted,\n transposition:\n this.channelTransposeKeyShift +\n this.customControllers[customControllers.channelTransposeFine] /\n 100,\n isDrum: this.drumChannel\n };\n this.synthProps.callEvent(\"channelPropertyChange\", {\n channel: this.channelNumber,\n property: data\n });\n }\n\n protected setBankMSB(bankMSB: number) {\n if (this.lockPreset) {\n return;\n }\n this.patch.bankMSB = bankMSB;\n }\n\n protected setBankLSB(bankLSB: number) {\n if (this.lockPreset) {\n return;\n }\n this.patch.bankLSB = bankLSB;\n }\n\n /**\n * Sets drums on channel.\n */\n protected setDrumFlag(isDrum: boolean) {\n if (this.lockPreset || !this.preset) {\n return;\n }\n if (this.drumChannel === isDrum) {\n return;\n }\n if (isDrum) {\n // Clear transpose\n this.channelTransposeKeyShift = 0;\n this.drumChannel = true;\n } else {\n this.drumChannel = false;\n }\n this.synthProps.callEvent(\"drumChange\", {\n channel: this.channelNumber,\n isDrumChannel: this.drumChannel\n });\n }\n}\n","import { IndexedByteArray } from \"../../../utils/indexed_array\";\nimport { writeBinaryStringIndexed } from \"../../../utils/byte_functions/string\";\nimport { writeLittleEndianIndexed } from \"../../../utils/byte_functions/little_endian\";\nimport { SpessaSynthInfo } from \"../../../utils/loggin\";\nimport { consoleColors } from \"../../../utils/other\";\nimport type { BasicSoundBank } from \"../../basic_soundbank/basic_soundbank\";\nimport type { ProgressFunction, SampleEncodingFunction } from \"../../types\";\n\n/*\nSdta structure:\n\nLIST chunk\n- \"sdta\" ASCII string\n- smpl chunk\n- - raw data\n */\n\n// In bytes, from the start of sdta-LIST to the first actual sample\nconst SDTA_TO_DATA_OFFSET =\n 4 + // \"LIST\"\n 4 + // Sdta size\n 4 + // \"sdta\"\n 4 + // \"smpl\"\n 4; // Smpl size\n\nexport async function getSDTA(\n bank: BasicSoundBank,\n smplStartOffsets: number[],\n smplEndOffsets: number[],\n compress: boolean,\n decompress: boolean,\n vorbisFunc?: SampleEncodingFunction,\n progressFunc?: ProgressFunction\n): Promise<Uint8Array> {\n // Write smpl: write int16 data of each sample linearly\n // Get size (calling getAudioData twice doesn't matter since it gets cached)\n let writtenCount = 0;\n let smplChunkSize = 0;\n const sampleDatas: Uint8Array[] = [];\n\n // Linear async is faster here as the writing function usually uses a single wasm instance\n for (const s of bank.samples) {\n if (compress && vorbisFunc) {\n await s.compressSample(vorbisFunc);\n }\n if (decompress) {\n s.setAudioData(s.getAudioData(), s.sampleRate);\n }\n\n // Raw data: either copy s16le or encoded vorbis or encode manually if overridden\n // Use set timeout so the thread doesn't die\n const r = s.getRawData(true);\n writtenCount++;\n await progressFunc?.(s.name, writtenCount, bank.samples.length);\n\n SpessaSynthInfo(\n `%cEncoded sample %c${writtenCount}. ${s.name}%c of %c${bank.samples.length}%c. Compressed: %c${s.isCompressed}%c.`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n s.isCompressed\n ? consoleColors.recognized\n : consoleColors.unrecognized,\n consoleColors.info\n );\n\n /* 6.1 Sample Data Format in the smpl Sub-chunk\n Each sample is followed by a minimum of forty-six zero\n valued sample data points. These zero valued data points are necessary to guarantee that any reasonable upward pitch shift\n using any reasonable interpolator can loop on zero data at the end of the sound.\n This doesn't apply to sf3 tho\n */\n smplChunkSize += r.length + (s.isCompressed ? 0 : 92);\n sampleDatas.push(r);\n }\n\n if (smplChunkSize % 2 !== 0) {\n smplChunkSize++;\n }\n\n const sdta = new IndexedByteArray(smplChunkSize + SDTA_TO_DATA_OFFSET);\n\n // Avoid using writeRIFFChunk for performance\n // Sdta chunk\n writeBinaryStringIndexed(sdta, \"LIST\");\n // \"sdta\" + full smpl length\n writeLittleEndianIndexed(sdta, smplChunkSize + SDTA_TO_DATA_OFFSET - 8, 4);\n writeBinaryStringIndexed(sdta, \"sdta\");\n writeBinaryStringIndexed(sdta, \"smpl\");\n writeLittleEndianIndexed(sdta, smplChunkSize, 4);\n\n let offset = 0;\n // Write out\n bank.samples.forEach((sample, i) => {\n const data = sampleDatas[i];\n sdta.set(data, offset + SDTA_TO_DATA_OFFSET);\n let startOffset;\n let endOffset;\n if (sample.isCompressed) {\n // Sf3 offset is in bytes\n startOffset = offset;\n endOffset = startOffset + data.length;\n } else {\n // Sf2 in sample data points\n startOffset = offset / 2; // Inclusive\n endOffset = startOffset + data.length / 2; // Exclusive\n offset += 92; // 46 sample data points\n }\n offset += data.length;\n smplStartOffsets.push(startOffset);\n\n smplEndOffsets.push(endOffset);\n });\n\n return sdta;\n}\n","import { SpessaSynthWarn } from \"../../utils/loggin\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport { stbvorbis } from \"../../externals/stbvorbis_sync/stbvorbis_wrapper\";\nimport { type SampleType, sampleTypes } from \"../enums\";\nimport type { BasicInstrument } from \"./basic_instrument\";\nimport type { SampleEncodingFunction } from \"../types\";\n\n// Should be reasonable for most cases\nconst RESAMPLE_RATE = 48000;\n\nexport class BasicSample {\n /**\n * The sample's name.\n */\n public name: string;\n\n /**\n * Sample rate in Hz.\n */\n public sampleRate: number;\n\n /**\n * Original pitch of the sample as a MIDI note number.\n */\n public originalKey: number;\n\n /**\n * Pitch correction, in cents. Can be negative.\n */\n public pitchCorrection: number;\n\n /**\n * Linked sample, unused if mono.\n */\n public linkedSample?: BasicSample;\n\n /**\n * The type of the sample.\n */\n public sampleType: SampleType;\n\n /**\n * Relative to the start of the sample in sample points.\n */\n public loopStart: number;\n\n /**\n * Relative to the start of the sample in sample points.\n */\n public loopEnd: number;\n /**\n * Sample's linked instruments (the instruments that use it)\n * note that duplicates are allowed since one instrument can use the same sample multiple times.\n */\n public linkedTo: BasicInstrument[] = [];\n /**\n * Indicates if the data was overridden, so it cannot be copied back unchanged.\n */\n protected dataOverridden = true;\n /**\n * The compressed sample data if the sample has been compressed.\n */\n protected compressedData?: Uint8Array;\n /**\n * The sample's audio data.\n */\n protected audioData?: Float32Array;\n\n /**\n * The basic representation of a sample\n * @param sampleName The sample's name\n * @param sampleRate The sample's rate in Hz\n * @param originalKey The sample's pitch as a MIDI note number\n * @param pitchCorrection The sample's pitch correction in cents\n * @param sampleType The sample's type, an enum that can indicate SF3\n * @param loopStart The sample's loop start relative to the sample start in sample points\n * @param loopEnd The sample's loop end relative to the sample start in sample points\n */\n public constructor(\n sampleName: string,\n sampleRate: number,\n originalKey: number,\n pitchCorrection: number,\n sampleType: SampleType,\n loopStart: number,\n loopEnd: number\n ) {\n this.name = sampleName;\n this.sampleRate = sampleRate;\n this.originalKey = originalKey;\n this.pitchCorrection = pitchCorrection;\n this.loopStart = loopStart;\n this.loopEnd = loopEnd;\n this.sampleType = sampleType;\n }\n\n /**\n * Indicates if the sample is compressed using vorbis SF3.\n */\n public get isCompressed(): boolean {\n return this.compressedData !== undefined;\n }\n\n /**\n * If the sample is linked to another sample.\n */\n public get isLinked(): boolean {\n return (\n this.sampleType === sampleTypes.rightSample ||\n this.sampleType === sampleTypes.leftSample ||\n this.sampleType === sampleTypes.linkedSample\n );\n }\n\n /**\n * The sample's use count\n */\n public get useCount() {\n return this.linkedTo.length;\n }\n\n /**\n * Get raw data for writing the file, either a compressed bit stream or signed 16-bit little endian PCM data.\n * @param allowVorbis if vorbis file data is allowed.\n * @return either s16le or vorbis data.\n */\n public getRawData(allowVorbis: boolean): Uint8Array {\n if (this.compressedData && allowVorbis && !this.dataOverridden) {\n return this.compressedData;\n }\n return this.encodeS16LE();\n }\n\n /**\n * Resamples the audio data to a given sample rate.\n */\n public resampleData(newSampleRate: number) {\n let audioData = this.getAudioData();\n const ratio = newSampleRate / this.sampleRate;\n const resampled = new Float32Array(\n Math.floor(audioData.length * ratio)\n );\n for (let i = 0; i < resampled.length; i++) {\n resampled[i] = audioData[Math.floor(i * (1 / ratio))];\n }\n audioData = resampled;\n this.sampleRate = newSampleRate;\n // Adjust loop points\n this.loopStart = Math.floor(this.loopStart * ratio);\n this.loopEnd = Math.floor(this.loopEnd * ratio);\n this.audioData = audioData;\n }\n\n /**\n * Compresses the audio data\n * @param encodeVorbis the compression function to use when compressing\n */\n public async compressSample(encodeVorbis: SampleEncodingFunction) {\n // No need to compress\n if (this.isCompressed) {\n return;\n }\n // Compress, always mono!\n try {\n // If the sample rate is too low or too high, resample\n let audioData = this.getAudioData();\n if (this.sampleRate < 8000 || this.sampleRate > 96000) {\n this.resampleData(RESAMPLE_RATE);\n audioData = this.getAudioData();\n }\n const compressed = await encodeVorbis(audioData, this.sampleRate);\n this.setCompressedData(compressed);\n } catch (e) {\n SpessaSynthWarn(\n `Failed to compress ${this.name}. Leaving as uncompressed!`,\n e\n );\n this.compressedData = undefined;\n }\n }\n\n /**\n * Sets the sample type and unlinks if needed.\n * @param type The type to set it to.\n */\n public setSampleType(type: SampleType) {\n this.sampleType = type;\n if (!this.isLinked) {\n // Unlink the other sample\n if (this.linkedSample) {\n this.linkedSample.linkedSample = undefined;\n this.linkedSample.sampleType = type;\n }\n\n this.linkedSample = undefined;\n }\n if ((type & 0x8000) > 0) {\n throw new Error(\"ROM samples are not supported.\");\n }\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Unlinks the sample from its stereo link if it has any.\n */\n public unlinkSample() {\n this.setSampleType(sampleTypes.monoSample);\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Links a stereo sample.\n * @param sample the sample to link to.\n * @param type either left, right or linked.\n */\n public setLinkedSample(sample: BasicSample, type: SampleType) {\n // Sanity check\n if (sample.linkedSample) {\n throw new Error(\n `${sample.name} is linked tp ${sample.linkedSample.name}. Unlink it first.`\n );\n }\n this.linkedSample = sample;\n sample.linkedSample = this;\n if (type === sampleTypes.leftSample) {\n this.setSampleType(sampleTypes.leftSample);\n sample.setSampleType(sampleTypes.rightSample);\n } else if (type === sampleTypes.rightSample) {\n this.setSampleType(sampleTypes.rightSample);\n sample.setSampleType(sampleTypes.leftSample);\n } else if (type === sampleTypes.linkedSample) {\n this.setSampleType(sampleTypes.linkedSample);\n sample.setSampleType(sampleTypes.linkedSample);\n } else {\n throw new Error(\"Invalid sample type: \" + type);\n }\n }\n\n /**\n * Links the sample to a given instrument\n * @param instrument the instrument to link to\n */\n public linkTo(instrument: BasicInstrument) {\n this.linkedTo.push(instrument);\n }\n\n /**\n * Unlinks the sample from a given instrument\n * @param instrument the instrument to unlink from\n */\n public unlinkFrom(instrument: BasicInstrument) {\n const index = this.linkedTo.indexOf(instrument);\n if (index < 0) {\n SpessaSynthWarn(\n `Cannot unlink ${instrument.name} from ${this.name}: not linked.`\n );\n return;\n }\n this.linkedTo.splice(index, 1);\n }\n\n /**\n * Get the float32 audio data.\n * Note that this either decodes the compressed data or passes the ready sampleData.\n * If neither are set then it will throw an error!\n * @returns the audio data\n */\n public getAudioData(): Float32Array {\n if (this.audioData) {\n return this.audioData;\n }\n if (this.isCompressed) {\n // SF3\n // If compressed, decode\n this.audioData = this.decodeVorbis();\n return this.audioData;\n }\n throw new Error(\"Sample data is undefined for a BasicSample instance.\");\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Replaces the audio data *in-place*.\n * @param audioData The new audio data as Float32.\n * @param sampleRate The new sample rate, in Hertz.\n */\n public setAudioData(audioData: Float32Array, sampleRate: number) {\n this.audioData = audioData;\n this.sampleRate = sampleRate;\n this.dataOverridden = true;\n this.compressedData = undefined;\n }\n\n /**\n * Replaces the audio with a compressed data sample and flags the sample as compressed\n * @param data the new compressed data\n */\n public setCompressedData(data: Uint8Array) {\n this.audioData = undefined;\n this.compressedData = data;\n this.dataOverridden = false;\n }\n\n /**\n * Encodes s16le sample\n * @return the encoded data\n */\n protected encodeS16LE(): IndexedByteArray {\n const data = this.getAudioData();\n const data16 = new Int16Array(data.length);\n const len = data.length;\n for (let i = 0; i < len; i++) {\n let sample = data[i] * 32768;\n // Clamp for safety (do not use Math.max/Math.min here)\n if (sample > 32767) {\n sample = 32767;\n } else if (sample < -32768) {\n sample = -32768;\n }\n data16[i] = sample;\n }\n return new IndexedByteArray(data16.buffer);\n }\n\n /**\n * Decode binary vorbis into a float32 pcm\n */\n protected decodeVorbis(): Float32Array {\n if (this.audioData) {\n return this.audioData;\n }\n if (!this.compressedData) {\n throw new Error(\"Compressed data is missing.\");\n }\n try {\n const vorbis = stbvorbis.decode(this.compressedData);\n const decoded = vorbis.data[0];\n if (decoded === undefined) {\n SpessaSynthWarn(\n `Error decoding sample ${this.name}: Vorbis decode returned undefined.`\n );\n return new Float32Array(0);\n }\n // Clip\n // Because vorbis can go above 1 sometimes\n for (let i = 0; i < decoded.length; i++) {\n // Magic number is 32,767 / 32,768\n decoded[i] = Math.max(\n -1,\n Math.min(decoded[i], 0.999969482421875)\n );\n }\n return decoded;\n } catch (e) {\n // Do not error out, fill with silence\n SpessaSynthWarn(\n `Error decoding sample ${this.name}: ${e as Error}`\n );\n return new Float32Array(this.loopEnd + 1);\n }\n }\n}\n\nexport class EmptySample extends BasicSample {\n /**\n * A simplified class for creating samples.\n */\n public constructor() {\n super(\"\", 44100, 60, 0, sampleTypes.monoSample, 0, 0);\n }\n}\n","import { IndexedByteArray } from \"../../../utils/indexed_array\";\nimport {\n readLittleEndianIndexed,\n signedInt8\n} from \"../../../utils/byte_functions/little_endian\";\nimport { SpessaSynthInfo, SpessaSynthWarn } from \"../../../utils/loggin\";\nimport { readBinaryStringIndexed } from \"../../../utils/byte_functions/string\";\nimport { BasicSample } from \"../../basic_soundbank/basic_sample\";\nimport { consoleColors } from \"../../../utils/other\";\nimport type { SampleType } from \"../../enums\";\nimport type { RIFFChunk } from \"../../../utils/riff_chunk\";\n\n/**\n * Samples.ts\n * purpose: parses soundfont samples\n */\n\nexport const SF3_BIT_FLIT = 0x10;\n\nexport class SoundFontSample extends BasicSample {\n /**\n * Linked sample index for retrieving linked samples in sf2\n */\n public linkedSampleIndex: number;\n\n /**\n * The sliced sample from the smpl chunk.\n */\n protected s16leData?: Uint8Array;\n\n protected startByteOffset: number;\n\n protected endByteOffset: number;\n\n protected sampleID: number;\n\n /**\n * Creates a sample\n * @param sampleName\n * @param sampleStartIndex\n * @param sampleEndIndex\n * @param sampleLoopStartIndex\n * @param sampleLoopEndIndex\n * @param sampleRate\n * @param samplePitch\n * @param samplePitchCorrection\n * @param linkedSampleIndex\n * @param sampleType\n * @param sampleDataArray\n * @param sampleIndex initial sample index when loading the sfont\n * Used for SF2Pack support\n */\n public constructor(\n sampleName: string,\n sampleStartIndex: number,\n sampleEndIndex: number,\n sampleLoopStartIndex: number,\n sampleLoopEndIndex: number,\n sampleRate: number,\n samplePitch: number,\n samplePitchCorrection: number,\n linkedSampleIndex: number,\n sampleType: SampleType,\n sampleDataArray: IndexedByteArray | Float32Array,\n sampleIndex: number\n ) {\n // Read sf3\n // https://github.com/FluidSynth/fluidsynth/wiki/SoundFont3Format\n const compressed = (sampleType & SF3_BIT_FLIT) > 0;\n // Remove the compression flag\n sampleType &= ~SF3_BIT_FLIT;\n super(\n sampleName,\n sampleRate,\n samplePitch,\n samplePitchCorrection,\n sampleType as SampleType,\n sampleLoopStartIndex - sampleStartIndex / 2,\n sampleLoopEndIndex - sampleStartIndex / 2\n );\n this.dataOverridden = false;\n this.name = sampleName;\n // In bytes\n this.startByteOffset = sampleStartIndex;\n this.endByteOffset = sampleEndIndex;\n this.sampleID = sampleIndex;\n const smplStart =\n sampleDataArray instanceof IndexedByteArray\n ? sampleDataArray.currentIndex\n : 0;\n\n // Three data types in:\n // SF2 (s16le)\n // SF3 (vorbis)\n // SF2Pack (entire smpl vorbis)\n if (sampleDataArray instanceof IndexedByteArray) {\n if (compressed) {\n // Correct loop points\n this.loopStart += this.startByteOffset / 2;\n this.loopEnd += this.startByteOffset / 2;\n\n // Copy the compressed data, it can be preserved during writing\n this.setCompressedData(\n sampleDataArray.slice(\n this.startByteOffset / 2 + smplStart,\n this.endByteOffset / 2 + smplStart\n )\n );\n } else {\n // Regular sf2 s16le\n this.s16leData = sampleDataArray.slice(\n smplStart + this.startByteOffset,\n smplStart + this.endByteOffset\n );\n }\n } else {\n // Float32 array from SF2pack, copy directly\n this.setAudioData(\n sampleDataArray.slice(\n this.startByteOffset / 2,\n this.endByteOffset / 2\n ),\n sampleRate\n );\n }\n this.linkedSampleIndex = linkedSampleIndex;\n }\n\n public getLinkedSample(samplesArray: BasicSample[]) {\n if (this.linkedSample || !this.isLinked) {\n return;\n }\n const linked = samplesArray[this.linkedSampleIndex];\n if (!linked) {\n // Log as info because it's common and not really dangerous\n SpessaSynthInfo(\n `%cInvalid linked sample for ${this.name}. Setting to mono.`,\n consoleColors.warn\n );\n this.unlinkSample();\n } else {\n // Check for corrupted files (like FluidR3_GM.sf2 that link EVERYTHING to a single sample)\n if (linked.linkedSample) {\n SpessaSynthInfo(\n `%cInvalid linked sample for ${this.name}: Already linked to ${linked.linkedSample.name}`,\n consoleColors.warn\n );\n this.unlinkSample();\n } else {\n this.setLinkedSample(linked, this.sampleType);\n }\n }\n }\n\n /**\n * Loads the audio data and stores it for reuse\n * @returns The audio data\n */\n public getAudioData(): Float32Array {\n if (this.audioData) {\n return this.audioData;\n }\n // SF2Pack is decoded during load time\n // SF3 is decoded in BasicSample\n if (this.isCompressed) {\n return super.getAudioData();\n }\n if (!this.s16leData) {\n console.error(this);\n throw new Error(\"Unexpected lack of audio data.\");\n }\n\n // Start loading data if it is not loaded\n const byteLength = this.endByteOffset - this.startByteOffset;\n if (byteLength < 1) {\n SpessaSynthWarn(\n `Invalid sample ${this.name}! Invalid length: ${byteLength}`\n );\n return new Float32Array(1);\n }\n\n // SF2\n // Read the sample data\n const audioData = new Float32Array(byteLength / 2);\n const convertedSigned16 = new Int16Array(this.s16leData.buffer);\n\n // Convert to float\n for (let i = 0; i < convertedSigned16.length; i++) {\n audioData[i] = convertedSigned16[i] / 32768;\n }\n\n this.audioData = audioData;\n return audioData;\n }\n\n public getRawData(allowVorbis: boolean): Uint8Array {\n if (this.dataOverridden || this.compressedData) {\n // Return vorbis or encode manually\n return super.getRawData(allowVorbis);\n }\n // Copy the smpl directly\n return this.s16leData ?? new Uint8Array(0);\n }\n}\n\n/**\n * Reads the samples from the shdr chunk\n */\nexport function readSamples(\n sampleHeadersChunk: RIFFChunk,\n smplChunkData: IndexedByteArray | Float32Array,\n linkSamples = true\n): SoundFontSample[] {\n const samples: SoundFontSample[] = [];\n let index = 0;\n while (\n sampleHeadersChunk.data.length > sampleHeadersChunk.data.currentIndex\n ) {\n const sample = readSample(\n index,\n sampleHeadersChunk.data,\n smplChunkData\n );\n samples.push(sample);\n index++;\n }\n // Remove EOS\n samples.pop();\n\n // Link samples\n if (linkSamples) {\n samples.forEach((s) => s.getLinkedSample(samples));\n }\n\n return samples;\n}\n\n/**\n * Reads it into a sample\n */\nfunction readSample(\n index: number,\n sampleHeaderData: IndexedByteArray,\n smplArrayData: IndexedByteArray | Float32Array\n): SoundFontSample {\n // Read the sample name\n const sampleName = readBinaryStringIndexed(sampleHeaderData, 20);\n\n // Read the sample start index\n const sampleStartIndex = readLittleEndianIndexed(sampleHeaderData, 4) * 2;\n\n // Read the sample end index\n const sampleEndIndex = readLittleEndianIndexed(sampleHeaderData, 4) * 2;\n\n // Read the sample looping start index\n const sampleLoopStartIndex = readLittleEndianIndexed(sampleHeaderData, 4);\n\n // Read the sample looping end index\n const sampleLoopEndIndex = readLittleEndianIndexed(sampleHeaderData, 4);\n\n // Read the sample rate\n const sampleRate = readLittleEndianIndexed(sampleHeaderData, 4);\n\n // Read the original sample pitch\n let samplePitch = sampleHeaderData[sampleHeaderData.currentIndex++];\n if (samplePitch > 127) {\n // If it's out of range, then default to 60\n samplePitch = 60;\n }\n\n // Read the sample pitch correction\n const samplePitchCorrection = signedInt8(\n sampleHeaderData[sampleHeaderData.currentIndex++]\n );\n\n // Read the link to the other channel\n const sampleLink = readLittleEndianIndexed(sampleHeaderData, 2);\n const sampleType = readLittleEndianIndexed(\n sampleHeaderData,\n 2\n ) as SampleType;\n\n return new SoundFontSample(\n sampleName,\n sampleStartIndex,\n sampleEndIndex,\n sampleLoopStartIndex,\n sampleLoopEndIndex,\n sampleRate,\n samplePitch,\n samplePitchCorrection,\n sampleLink,\n sampleType,\n smplArrayData,\n index\n );\n}\n","import { IndexedByteArray } from \"../../../utils/indexed_array\";\nimport { writeBinaryStringIndexed } from \"../../../utils/byte_functions/string\";\nimport {\n writeDword,\n writeWord\n} from \"../../../utils/byte_functions/little_endian\";\nimport { writeRIFFChunkRaw } from \"../../../utils/riff_chunk\";\nimport { SF3_BIT_FLIT } from \"../read/samples\";\nimport type { BasicSoundBank } from \"../../basic_soundbank/basic_soundbank\";\n\nimport type { ExtendedSF2Chunks } from \"./types\";\n\nexport function getSHDR(\n bank: BasicSoundBank,\n smplStartOffsets: number[],\n smplEndOffsets: number[]\n): ExtendedSF2Chunks {\n const sampleLength = 46;\n const shdrSize = sampleLength * (bank.samples.length + 1); // +1 because EOP\n const shdrData = new IndexedByteArray(shdrSize);\n // https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md\n const xshdrData = new IndexedByteArray(shdrSize);\n let maxSampleLink = 0;\n bank.samples.forEach((sample, index) => {\n // Sample name\n writeBinaryStringIndexed(shdrData, sample.name.substring(0, 20), 20);\n writeBinaryStringIndexed(xshdrData, sample.name.substring(20), 20);\n // Start offset\n const dwStart = smplStartOffsets[index];\n writeDword(shdrData, dwStart);\n xshdrData.currentIndex += 4;\n // End offset\n const dwEnd = smplEndOffsets[index];\n writeDword(shdrData, dwEnd);\n xshdrData.currentIndex += 4;\n // Loop is stored as relative in sample points, change it to absolute sample points here\n let loopStart = sample.loopStart + dwStart;\n let loopEnd = sample.loopEnd + dwStart;\n if (sample.isCompressed) {\n // https://github.com/FluidSynth/fluidsynth/wiki/SoundFont3Format\n loopStart -= dwStart;\n loopEnd -= dwStart;\n }\n writeDword(shdrData, loopStart);\n writeDword(shdrData, loopEnd);\n // Sample rate\n writeDword(shdrData, sample.sampleRate);\n // Pitch and correction\n shdrData[shdrData.currentIndex++] = sample.originalKey;\n shdrData[shdrData.currentIndex++] = sample.pitchCorrection;\n // Skip all those for xshdr\n xshdrData.currentIndex += 14;\n // Sample link\n const sampleLinkIndex = sample.linkedSample\n ? bank.samples.indexOf(sample.linkedSample)\n : 0;\n writeWord(shdrData, Math.max(0, sampleLinkIndex) & 0xffff);\n writeWord(xshdrData, Math.max(0, sampleLinkIndex) >> 16);\n maxSampleLink = Math.max(maxSampleLink, sampleLinkIndex);\n // Sample type: add byte if compressed\n let type = sample.sampleType;\n if (sample.isCompressed) {\n type |= SF3_BIT_FLIT;\n }\n writeWord(shdrData, type);\n xshdrData.currentIndex += 2;\n });\n\n // Write EOS and zero everything else\n writeBinaryStringIndexed(shdrData, \"EOS\", sampleLength);\n writeBinaryStringIndexed(xshdrData, \"EOS\", sampleLength);\n const shdr = writeRIFFChunkRaw(\"shdr\", shdrData);\n const xshdr = writeRIFFChunkRaw(\"shdr\", xshdrData);\n return {\n pdta: shdr,\n xdta: xshdr\n };\n}\n","import type { BasicSoundBank } from \"../../basic_soundbank/basic_soundbank\";\nimport { IndexedByteArray } from \"../../../utils/indexed_array\";\nimport { GEN_BYTE_SIZE } from \"../../basic_soundbank/generator\";\nimport { MOD_BYTE_SIZE } from \"../../basic_soundbank/modulator\";\nimport { BAG_BYTE_SIZE } from \"../../basic_soundbank/basic_zone\";\nimport type { ExtendedSF2Chunks, SoundFontWriteIndexes } from \"./types\";\nimport { INST_BYTE_SIZE } from \"../../basic_soundbank/basic_instrument\";\nimport {\n BasicPreset,\n PHDR_BYTE_SIZE\n} from \"../../basic_soundbank/basic_preset\";\nimport { writeRIFFChunkRaw } from \"../../../utils/riff_chunk\";\nimport { writeBinaryStringIndexed } from \"../../../utils/byte_functions/string\";\nimport { writeWord } from \"../../../utils/byte_functions/little_endian\";\n\nexport function writeSF2Elements(\n bank: BasicSoundBank,\n isPreset = false\n): {\n gen: ExtendedSF2Chunks;\n mod: ExtendedSF2Chunks;\n bag: ExtendedSF2Chunks;\n hdr: ExtendedSF2Chunks;\n writeXdta: boolean;\n} {\n // Note:\n // https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md\n const elements = isPreset ? bank.presets : bank.instruments;\n const genHeader = isPreset ? \"pgen\" : \"igen\";\n const modHeader = isPreset ? \"pmod\" : \"imod\";\n const bagHeader = isPreset ? \"pbag\" : \"ibag\";\n const hdrHeader = isPreset ? \"phdr\" : \"inst\";\n const hdrByteSize = isPreset ? PHDR_BYTE_SIZE : INST_BYTE_SIZE;\n\n const sizes = elements.map((i) =>\n i instanceof BasicPreset ? i.getSize() : i.getSize()\n );\n\n // Get sizes (make sure to get the terminal records\n const genSize = sizes.reduce((l, s) => l + s.gen, 0) + GEN_BYTE_SIZE;\n const genData = new IndexedByteArray(genSize);\n const modSize = sizes.reduce((l, s) => l + s.mod, 0) + MOD_BYTE_SIZE;\n const modData = new IndexedByteArray(modSize);\n\n const bagSize = sizes.reduce((l, s) => l + s.bag, 0) + BAG_BYTE_SIZE;\n const bagData: ExtendedSF2Chunks = {\n pdta: new IndexedByteArray(bagSize),\n xdta: new IndexedByteArray(bagSize)\n };\n\n const hdrSize = sizes.reduce((l, s) => s.hdr + l, 0) + hdrByteSize;\n const hdrData: ExtendedSF2Chunks = {\n pdta: new IndexedByteArray(hdrSize),\n xdta: new IndexedByteArray(hdrSize)\n };\n\n const indexes: SoundFontWriteIndexes = {\n gen: 0,\n bag: 0,\n mod: 0,\n hdr: 0\n };\n\n // Write!\n elements.forEach((element) => {\n // This check suppresses the \"unused method getSize()\" on basic preset...\n if (element instanceof BasicPreset) {\n element.write(genData, modData, bagData, hdrData, indexes, bank);\n } else {\n element.write(genData, modData, bagData, hdrData, indexes, bank);\n }\n });\n\n // Write terminal records\n if (isPreset) {\n writeBinaryStringIndexed(hdrData.pdta, \"EOP\", 20);\n hdrData.pdta.currentIndex += 4; // Program, bank\n writeWord(hdrData.pdta, indexes.hdr & 0xffff);\n hdrData.pdta.currentIndex += 12; // Library, genre, morphology\n\n writeBinaryStringIndexed(hdrData.xdta, \"\", 20);\n hdrData.xdta.currentIndex += 4; // Program, bank\n writeWord(hdrData.xdta, indexes.hdr >> 16);\n hdrData.xdta.currentIndex += 12; // Library, genre, morphology\n } else {\n // Write EOI\n writeBinaryStringIndexed(hdrData.pdta, \"EOI\", 20);\n writeBinaryStringIndexed(hdrData.xdta, \"\", 20);\n writeWord(hdrData.pdta, indexes.hdr & 0xffff);\n writeWord(hdrData.xdta, indexes.hdr >> 16);\n }\n\n // Write bag terminal record\n writeWord(bagData.pdta, indexes.gen & 0xffff);\n writeWord(bagData.xdta, indexes.gen >> 16);\n writeWord(bagData.pdta, indexes.mod & 0xffff);\n writeWord(bagData.xdta, indexes.mod >> 16);\n\n return {\n writeXdta:\n Math.max(\n genSize / GEN_BYTE_SIZE,\n modSize / MOD_BYTE_SIZE,\n bagSize / BAG_BYTE_SIZE,\n hdrSize / hdrByteSize\n ) > 0xffff,\n gen: {\n pdta: writeRIFFChunkRaw(genHeader, genData),\n // Same as pmod, this chunk includes only the terminal generator record to allow reuse of the pdta parser.\n xdta: writeRIFFChunkRaw(\n modHeader,\n new IndexedByteArray(GEN_BYTE_SIZE)\n )\n },\n mod: {\n pdta: writeRIFFChunkRaw(modHeader, modData),\n // This chunk exists solely to preserve parser compatibility and contains only the terminal modulator record.\n xdta: writeRIFFChunkRaw(\n modHeader,\n new IndexedByteArray(MOD_BYTE_SIZE)\n )\n },\n bag: {\n pdta: writeRIFFChunkRaw(bagHeader, bagData.pdta),\n xdta: writeRIFFChunkRaw(bagHeader, bagData.xdta)\n },\n hdr: {\n pdta: writeRIFFChunkRaw(hdrHeader, hdrData.pdta),\n xdta: writeRIFFChunkRaw(hdrHeader, hdrData.xdta)\n }\n };\n}\n","import { IndexedByteArray } from \"../../../utils/indexed_array\";\nimport {\n writeRIFFChunkParts,\n writeRIFFChunkRaw\n} from \"../../../utils/riff_chunk\";\nimport { getStringBytes } from \"../../../utils/byte_functions/string\";\nimport { consoleColors } from \"../../../utils/other\";\nimport { getSDTA } from \"./sdta\";\nimport { getSHDR } from \"./shdr\";\nimport {\n writeLittleEndianIndexed,\n writeWord\n} from \"../../../utils/byte_functions/little_endian\";\nimport {\n SpessaSynthGroup,\n SpessaSynthGroupCollapsed,\n SpessaSynthGroupEnd,\n SpessaSynthInfo\n} from \"../../../utils/loggin\";\nimport {\n MOD_BYTE_SIZE,\n Modulator,\n SPESSASYNTH_DEFAULT_MODULATORS\n} from \"../../basic_soundbank/modulator\";\nimport { fillWithDefaults } from \"../../../utils/fill_with_defaults\";\nimport type {\n SF2InfoFourCC,\n SoundBankInfoData,\n SoundBankInfoFourCC,\n SoundFont2WriteOptions\n} from \"../../types\";\nimport type { BasicSoundBank } from \"../../basic_soundbank/basic_soundbank\";\nimport type { ExtendedSF2Chunks } from \"./types\";\nimport { writeSF2Elements } from \"./write_sf2_elements\";\n\nexport const DEFAULT_SF2_WRITE_OPTIONS: SoundFont2WriteOptions = {\n compress: false,\n compressionFunction: undefined,\n progressFunction: undefined,\n writeDefaultModulators: true,\n writeExtendedLimits: true,\n decompress: false\n};\n\n/**\n * Writes the sound bank as an SF2 file.\n * @param bank\n * @param writeOptions the options for writing.\n * @returns the binary file data.\n */\nexport async function writeSF2Internal(\n bank: BasicSoundBank,\n writeOptions: Partial<SoundFont2WriteOptions> = DEFAULT_SF2_WRITE_OPTIONS\n): Promise<ArrayBuffer> {\n const options: SoundFont2WriteOptions = fillWithDefaults(\n writeOptions,\n DEFAULT_SF2_WRITE_OPTIONS\n );\n if (options?.compress) {\n if (typeof options?.compressionFunction !== \"function\") {\n throw new Error(\n \"No compression function supplied but compression enabled.\"\n );\n }\n if (options?.decompress) {\n throw new Error(\"Decompressed and compressed at the same time.\");\n }\n }\n SpessaSynthGroupCollapsed(\"%cSaving soundbank...\", consoleColors.info);\n SpessaSynthInfo(\n `%cCompression: %c${options?.compress || \"false\"}%c`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n SpessaSynthGroup(\"%cWriting INFO...\", consoleColors.info);\n /**\n * Write INFO\n */\n const infoArrays: IndexedByteArray[] = [];\n bank.soundBankInfo.software = \"SpessaSynth\"; // ( ͡° ͜ʖ ͡°)\n if (options?.compress || bank.samples.some((s) => s.isCompressed)) {\n // Set version to 3\n bank.soundBankInfo.version.major = 3;\n bank.soundBankInfo.version.minor = 0;\n }\n if (options?.decompress) {\n // Set version to 2.4\n bank.soundBankInfo.version.major = 2;\n bank.soundBankInfo.version.minor = 4;\n }\n\n const writeSF2Info = (type: SF2InfoFourCC, data: string) => {\n infoArrays.push(\n writeRIFFChunkRaw(\n type,\n getStringBytes(data, true, true) // Pad with zero and ensure even length\n )\n );\n };\n\n // Write versions\n const ifilData = new IndexedByteArray(4);\n writeWord(ifilData, bank.soundBankInfo.version.major);\n writeWord(ifilData, bank.soundBankInfo.version.minor);\n infoArrays.push(writeRIFFChunkRaw(\"ifil\", ifilData));\n\n if (bank.soundBankInfo.romVersion) {\n const ifilData = new IndexedByteArray(4);\n writeWord(ifilData, bank.soundBankInfo.romVersion.major);\n writeWord(ifilData, bank.soundBankInfo.romVersion.minor);\n infoArrays.push(writeRIFFChunkRaw(\"iver\", ifilData));\n }\n\n // Special comment case: merge subject and comment\n const commentText =\n (bank.soundBankInfo?.comment ?? \"\") +\n (bank.soundBankInfo.subject\n ? `\n${bank.soundBankInfo.subject}`\n : \"\");\n\n for (const [t, d] of Object.entries(bank.soundBankInfo)) {\n const type = t as SoundBankInfoFourCC;\n const data = d as SoundBankInfoData[SoundBankInfoFourCC];\n if (!data) {\n continue;\n }\n\n switch (type) {\n case \"name\":\n writeSF2Info(\"INAM\", data as string);\n break;\n\n case \"comment\":\n writeSF2Info(\"ICMT\", commentText);\n break;\n\n case \"copyright\":\n writeSF2Info(\"ICOP\", data as string);\n break;\n\n case \"creationDate\":\n writeSF2Info(\"ICRD\", (data as Date).toISOString());\n break;\n\n case \"engineer\":\n writeSF2Info(\"IENG\", data as string);\n break;\n\n case \"product\":\n writeSF2Info(\"IPRD\", data as string);\n break;\n\n case \"romInfo\":\n writeSF2Info(\"irom\", data as string);\n break;\n\n case \"software\":\n writeSF2Info(\"ISFT\", data as string);\n break;\n\n case \"soundEngine\":\n writeSF2Info(\"isng\", data as string);\n break;\n\n case \"subject\":\n // Merged with the comment\n break;\n }\n }\n\n // Do not write unchanged default modulators\n const unchangedDefaultModulators = bank.defaultModulators.some(\n (mod) =>\n SPESSASYNTH_DEFAULT_MODULATORS.findIndex((m) =>\n Modulator.isIdentical(m, mod, true)\n ) === -1\n );\n\n if (unchangedDefaultModulators && options?.writeDefaultModulators) {\n const mods = bank.defaultModulators;\n SpessaSynthInfo(\n `%cWriting %c${mods.length}%c default modulators...`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n const dmodSize = MOD_BYTE_SIZE + mods.length * MOD_BYTE_SIZE;\n const dmodData = new IndexedByteArray(dmodSize);\n for (const mod of mods) {\n mod.write(dmodData);\n }\n\n // Terminal modulator, is zero\n writeLittleEndianIndexed(dmodData, 0, MOD_BYTE_SIZE);\n\n infoArrays.push(writeRIFFChunkRaw(\"DMOD\", dmodData));\n }\n\n SpessaSynthGroupEnd();\n SpessaSynthInfo(\"%cWriting SDTA...\", consoleColors.info);\n // Write sdta\n const smplStartOffsets: number[] = [];\n const smplEndOffsets: number[] = [];\n const sdtaChunk = await getSDTA(\n bank,\n smplStartOffsets,\n smplEndOffsets,\n options.compress,\n options.decompress,\n options?.compressionFunction,\n options?.progressFunction\n );\n\n SpessaSynthInfo(\"%cWriting PDTA...\", consoleColors.info);\n // Write pdta\n // Go in reverse so the indexes are correct\n // Instruments\n SpessaSynthInfo(\"%cWriting SHDR...\", consoleColors.info);\n const shdrChunk = getSHDR(bank, smplStartOffsets, smplEndOffsets);\n\n // Note:\n // https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md\n\n SpessaSynthGroup(\"%cWriting instruments...\", consoleColors.info);\n const instData = writeSF2Elements(bank, false);\n SpessaSynthGroupEnd();\n\n SpessaSynthGroup(\"%cWriting presets...\", consoleColors.info);\n const presData = writeSF2Elements(bank, true);\n SpessaSynthGroupEnd();\n\n const chunks: ExtendedSF2Chunks[] = [\n presData.hdr,\n presData.bag,\n presData.mod,\n presData.gen,\n instData.hdr,\n instData.bag,\n instData.mod,\n instData.gen,\n shdrChunk\n ];\n // Combine in the sfspec order\n const pdtaChunk = writeRIFFChunkParts(\n \"pdta\",\n chunks.map((c) => c.pdta),\n true\n );\n\n const writeXdta =\n options.writeExtendedLimits &&\n (instData.writeXdta ||\n presData.writeXdta ||\n bank.presets.some((p) => p.name.length > 20) ||\n bank.instruments.some((i) => i.name.length > 20) ||\n bank.samples.some((s) => s.name.length > 20));\n\n if (writeXdta) {\n SpessaSynthInfo(\n `%cWriting the xdta chunk as writeExendedLimits is enabled and at least one condition was met.`,\n consoleColors.info,\n consoleColors.value\n );\n // https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md\n const xpdtaChunk = writeRIFFChunkParts(\n \"xdta\",\n chunks.map((c) => c.xdta),\n true\n );\n infoArrays.push(xpdtaChunk);\n }\n\n const infoChunk = writeRIFFChunkParts(\"INFO\", infoArrays, true);\n SpessaSynthInfo(\"%cWriting the output file...\", consoleColors.info);\n // Finally, combine everything\n const main = writeRIFFChunkParts(\"RIFF\", [\n getStringBytes(\"sfbk\"),\n infoChunk,\n sdtaChunk,\n pdtaChunk\n ]);\n SpessaSynthInfo(\n `%cSaved succesfully! Final file size: %c${main.length}`,\n consoleColors.info,\n consoleColors.recognized\n );\n SpessaSynthGroupEnd();\n return main.buffer;\n}\n","import {\n type FourCC,\n readRIFFChunk,\n type RIFFChunk\n} from \"../../utils/riff_chunk\";\nimport type { DLSChunkFourCC } from \"../types\";\nimport { SpessaSynthGroupEnd } from \"../../utils/loggin\";\nimport { readBinaryStringIndexed } from \"../../utils/byte_functions/string\";\n\nexport abstract class DLSVerifier {\n /**\n * @param chunk\n * @param expected\n * @throws error if the check doesn't pass\n */\n protected static verifyHeader(chunk: RIFFChunk, ...expected: FourCC[]) {\n for (const expect of expected) {\n if (chunk.header.toLowerCase() === expect.toLowerCase()) {\n return;\n }\n }\n this.parsingError(\n `Invalid DLS chunk header! Expected \"${expected.join(\", or \")}\" got \"${chunk.header.toLowerCase()}\"`\n );\n }\n\n /**\n * @param text {string}\n * @param expected {string}\n * @throws error if the check doesn't pass\n */\n protected static verifyText(text: string, ...expected: DLSChunkFourCC[]) {\n for (const expect of expected) {\n if (text.toLowerCase() === expect.toLowerCase()) {\n return;\n }\n }\n this.parsingError(\n `FourCC error: Expected \"${expected.join(\", or \")}\" got \"${text.toLowerCase()}\"`\n );\n }\n\n /**\n * @throws error if the check doesn't pass\n */\n protected static parsingError(error: string) {\n SpessaSynthGroupEnd();\n throw new Error(`DLS parse error: ${error} The file may be corrupted.`);\n }\n\n protected static verifyAndReadList(\n chunk: RIFFChunk,\n ...type: DLSChunkFourCC[]\n ) {\n this.verifyHeader(chunk, \"LIST\");\n chunk.data.currentIndex = 0;\n this.verifyText(readBinaryStringIndexed(chunk.data, 4), ...type);\n const chunks: RIFFChunk[] = [];\n while (chunk.data.length > chunk.data.currentIndex) {\n chunks.push(readRIFFChunk(chunk.data));\n }\n return chunks;\n }\n}\n","import type { DLSLoop } from \"../types\";\nimport { type RIFFChunk, writeRIFFChunkRaw } from \"../../utils/riff_chunk\";\nimport { readLittleEndianIndexed, signedInt16, writeDword, writeWord } from \"../../utils/byte_functions/little_endian\";\nimport { type DLSLoopType, DLSLoopTypes, generatorTypes } from \"../enums\";\nimport { DLSVerifier } from \"./dls_verifier\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport type { BasicZone } from \"../basic_soundbank/basic_zone\";\nimport { type BasicSample } from \"../basic_soundbank/basic_sample\";\nimport type { SampleLoopingMode } from \"../../synthesizer/types\";\nimport { SpessaSynthWarn } from \"../../utils/loggin\";\nimport type { BasicInstrumentZone } from \"../basic_soundbank/basic_instrument_zone\";\n\nconst WSMP_SIZE = 20;\nconst WSMP_LOOP_SIZE = 16;\n\nexport class WaveSample extends DLSVerifier {\n /**\n * Specifies the gain to be applied to this sample in 32 bit relative gain units.\n * Each unit of gain represents 1/655360 dB.\n */\n public gain = 0;\n /**\n * Specifies the MIDI note which will replay the sample at original pitch. This value ranges\n * from 0 to 127 (a value of 60 represents Middle C, as defined by the MIDI specification).\n */\n public unityNote = 60;\n /**\n * Specifies the tuning offset from the usUnityNote in 16 bit relative pitch. (cents)\n */\n public fineTune = 0;\n /**\n * Specifies the number (count) of <wavesample-loop> records that are contained in the\n * <wsmp-ck> chunk. The <wavesample-loop> records are stored immediately following the\n * cSampleLoops data field. One shot sounds will have the cSampleLoops field set to 0.\n * Looped sounds will have the cSampleLoops field set to 1. Values greater than 1 are not yet\n * defined at this time.\n */\n public loops = new Array<DLSLoop>();\n\n /**\n * Specifies flag options for the digital audio sample.\n * Default to F_WSMP_NO_COMPRESSION,\n * according to all DLS files I have.\n */\n public fulOptions = 2;\n\n public static copyFrom(inputWaveSample: WaveSample) {\n const outputWaveSample = new WaveSample();\n outputWaveSample.unityNote = inputWaveSample.unityNote;\n outputWaveSample.gain = inputWaveSample.gain;\n outputWaveSample.fineTune = inputWaveSample.fineTune;\n outputWaveSample.loops = inputWaveSample.loops.map((l) => {\n return { ...l };\n });\n outputWaveSample.fulOptions = inputWaveSample.fulOptions;\n return outputWaveSample;\n }\n\n public static read(chunk: RIFFChunk) {\n this.verifyHeader(chunk, \"wsmp\");\n const waveSample = new WaveSample();\n // CbSize\n const cbSize = readLittleEndianIndexed(chunk.data, 4);\n if (cbSize !== WSMP_SIZE) {\n SpessaSynthWarn(\n `Wsmp cbSize mismatch: got ${cbSize}, expected ${WSMP_SIZE}.`\n );\n }\n waveSample.unityNote = readLittleEndianIndexed(chunk.data, 2);\n // SFineTune\n waveSample.fineTune = signedInt16(\n chunk.data[chunk.data.currentIndex++],\n chunk.data[chunk.data.currentIndex++]\n );\n\n // LGain: Each unit of gain represents 1/655360 dB\n waveSample.gain = readLittleEndianIndexed(chunk.data, 4) | 0;\n waveSample.fulOptions = readLittleEndianIndexed(chunk.data, 4);\n\n // Read loop count (always one or zero)\n const loopsAmount = readLittleEndianIndexed(chunk.data, 4);\n if (loopsAmount === 0) {\n // No loop\n } else {\n const cbSize = readLittleEndianIndexed(chunk.data, 4);\n if (cbSize !== WSMP_LOOP_SIZE) {\n SpessaSynthWarn(\n `CbSize for loop in wsmp mismatch. Expected ${WSMP_SIZE}, got ${cbSize}.`\n );\n }\n // Loop type: loop normally or loop until release (like soundfont)\n const loopType = readLittleEndianIndexed(\n chunk.data,\n 4\n ) as DLSLoopType; // Why is it long?\n const loopStart = readLittleEndianIndexed(chunk.data, 4);\n const loopLength = readLittleEndianIndexed(chunk.data, 4);\n waveSample.loops.push({\n loopStart,\n loopLength,\n loopType\n });\n }\n return waveSample;\n }\n\n public static fromSFSample(sample: BasicSample) {\n const waveSample = new WaveSample();\n waveSample.unityNote = sample.originalKey;\n waveSample.fineTune = sample.pitchCorrection;\n if (sample.loopEnd !== 0 || sample.loopStart !== 0) {\n waveSample.loops.push({\n loopStart: sample.loopStart,\n loopLength: sample.loopEnd - sample.loopStart,\n loopType: DLSLoopTypes.forward\n });\n }\n return waveSample;\n }\n\n public static fromSFZone(zone: BasicInstrumentZone) {\n const waveSample = new WaveSample();\n waveSample.unityNote = zone.getGenerator(\n generatorTypes.overridingRootKey,\n zone.sample.originalKey\n );\n\n // A lot of sound banks like to set scale tuning to 0 in drums and keep the key at 60\n // Since we implement scale tuning via a dls articulator and fluid doesn't support these,\n // Change the root key here\n if (\n zone.getGenerator(generatorTypes.scaleTuning, 100) === 0 &&\n zone.keyRange.max - zone.keyRange.min === 0\n ) {\n waveSample.unityNote = zone.keyRange.min;\n }\n\n /*\n Note: this may slightly change the generators themselves when doing SF -> DLS -> SF, but the tuning remains the same\n Testcase: Helicopter from GeneralUser-GS v2.0.1\n It sets coarse -13 fine 2 which is a total of -1298 cents\n This then gets converted into -12 coarse and -98 tune which is still correct!\n */\n waveSample.fineTune = zone.fineTuning + zone.sample.pitchCorrection;\n // E-mu attenuation correction\n const attenuationCb =\n zone.getGenerator(generatorTypes.initialAttenuation, 0) * 0.4;\n // Gain is stored as a 32-bit value, shift here\n waveSample.gain = -attenuationCb << 16;\n const loopingMode = zone.getGenerator(\n generatorTypes.sampleModes,\n 0\n ) as SampleLoopingMode;\n // Don't add loops unless needed\n if (loopingMode !== 0) {\n // Make sure to get offsets\n const loopStart =\n zone.sample.loopStart +\n zone.getGenerator(generatorTypes.startloopAddrsOffset, 0) +\n zone.getGenerator(\n generatorTypes.startloopAddrsCoarseOffset,\n 0\n ) *\n 32768;\n const loopEnd =\n zone.sample.loopEnd +\n zone.getGenerator(generatorTypes.endloopAddrsOffset, 0) +\n zone.getGenerator(generatorTypes.endloopAddrsCoarseOffset, 0) *\n 32768;\n let dlsLoopType: DLSLoopType;\n switch (loopingMode) {\n case 1:\n default:\n dlsLoopType = 0;\n break;\n\n case 3:\n dlsLoopType = 1;\n }\n waveSample.loops.push({\n loopType: dlsLoopType,\n loopStart,\n loopLength: loopEnd - loopStart\n });\n }\n return waveSample;\n }\n\n /**\n * Converts the wsmp data into an SF zone.\n */\n public toSFZone(zone: BasicZone, sample: BasicSample) {\n let loopingMode: SampleLoopingMode = 0;\n const loop = this.loops[0];\n if (loop) {\n loopingMode = loop.loopType === DLSLoopTypes.loopAndRelease ? 3 : 1;\n }\n if (loopingMode !== 0) {\n zone.setGenerator(generatorTypes.sampleModes, loopingMode);\n }\n\n // Convert to signed and turn into attenuation (invert)\n const wsmpGain16 = this.gain >> 16;\n const wsmpAttenuation = -wsmpGain16;\n // Apply the E-MU attenuation correction here\n const wsmpAttenuationCorrected = wsmpAttenuation / 0.4;\n\n if (wsmpAttenuationCorrected !== 0) {\n zone.setGenerator(\n generatorTypes.initialAttenuation,\n wsmpAttenuationCorrected\n );\n }\n\n // Correct tuning\n zone.fineTuning = this.fineTune - sample.pitchCorrection;\n\n // Correct the key if needed\n if (this.unityNote !== sample.originalKey) {\n zone.setGenerator(generatorTypes.overridingRootKey, this.unityNote);\n }\n // Correct loop if needed\n if (loop) {\n const diffStart = loop.loopStart - sample.loopStart;\n const loopEnd = loop.loopStart + loop.loopLength;\n const diffEnd = loopEnd - sample.loopEnd;\n if (diffStart !== 0) {\n const fine = diffStart % 32768;\n zone.setGenerator(generatorTypes.startloopAddrsOffset, fine);\n // Coarse generator uses 32768 samples per step\n const coarse = Math.trunc(diffStart / 32768);\n if (coarse !== 0) {\n zone.setGenerator(\n generatorTypes.startloopAddrsCoarseOffset,\n coarse\n );\n }\n }\n if (diffEnd !== 0) {\n const fine = diffEnd % 32768;\n zone.setGenerator(generatorTypes.endloopAddrsOffset, fine);\n // Coarse generator uses 32768 samples per step\n const coarse = Math.trunc(diffEnd / 32768);\n if (coarse !== 0) {\n zone.setGenerator(\n generatorTypes.endloopAddrsCoarseOffset,\n coarse\n );\n }\n }\n }\n }\n\n public write() {\n const wsmpData = new IndexedByteArray(\n WSMP_SIZE + this.loops.length * WSMP_LOOP_SIZE\n );\n // CbSize\n writeDword(wsmpData, WSMP_SIZE);\n writeWord(wsmpData, this.unityNote);\n writeWord(wsmpData, this.fineTune);\n writeDword(wsmpData, this.gain);\n writeDword(wsmpData, this.fulOptions);\n // CSampleLoops\n writeDword(wsmpData, this.loops.length);\n this.loops.forEach((loop) => {\n writeDword(wsmpData, WSMP_LOOP_SIZE);\n writeDword(wsmpData, loop.loopType);\n writeDword(wsmpData, loop.loopStart);\n writeDword(wsmpData, loop.loopLength);\n });\n return writeRIFFChunkRaw(\"wsmp\", wsmpData);\n }\n}\n","import { BasicSample } from \"../basic_soundbank/basic_sample\";\nimport { SpessaSynthWarn } from \"../../utils/loggin\";\nimport { readLittleEndianIndexed } from \"../../utils/byte_functions/little_endian\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport type { RIFFChunk } from \"../../utils/riff_chunk\";\nimport { sampleTypes } from \"../enums\";\n\nconst W_FORMAT_TAG = {\n PCM: 0x01,\n ALAW: 0x6\n} as const;\n\nfunction readPCM(data: IndexedByteArray, bytesPerSample: number): Float32Array {\n const maxSampleValue = Math.pow(2, bytesPerSample * 8 - 1); // Max value for the sample\n const maxUnsigned = Math.pow(2, bytesPerSample * 8);\n\n let normalizationFactor;\n let isUnsigned = false;\n\n if (bytesPerSample === 1) {\n normalizationFactor = 255; // For 8-bit normalize from 0-255\n isUnsigned = true;\n } else {\n normalizationFactor = maxSampleValue; // For 16-bit normalize from -32,768 to 32,767\n }\n const sampleLength = data.length / bytesPerSample;\n const sampleData = new Float32Array(sampleLength);\n if (bytesPerSample === 2) {\n // Special optimized case for s16 (most common)\n const s16 = new Int16Array(data.buffer);\n for (let i = 0; i < s16.length; i++) {\n sampleData[i] = s16[i] / 32768;\n }\n } else {\n for (let i = 0; i < sampleData.length; i++) {\n // Read\n let sample = readLittleEndianIndexed(data, bytesPerSample);\n // Turn into signed\n if (isUnsigned) {\n // Normalize unsigned 8-bit sample\n sampleData[i] = sample / normalizationFactor - 0.5;\n } else {\n // Normalize signed sample\n if (sample >= maxSampleValue) {\n sample -= maxUnsigned;\n }\n sampleData[i] = sample / normalizationFactor;\n }\n }\n }\n return sampleData;\n}\n\nfunction readALAW(\n data: IndexedByteArray,\n bytesPerSample: number\n): Float32Array {\n const sampleLength = data.length / bytesPerSample;\n const sampleData = new Float32Array(sampleLength);\n for (let i = 0; i < sampleData.length; i++) {\n // Read\n const input = readLittleEndianIndexed(data, bytesPerSample);\n\n // https://en.wikipedia.org/wiki/G.711#A-law\n // Re-toggle toggled bits\n let sample = input ^ 0x55;\n\n // Remove sign bit\n sample &= 0x7f;\n\n // Extract exponent\n const exponent = sample >> 4;\n // Extract mantissa\n let mantissa = sample & 0xf;\n if (exponent > 0) {\n mantissa += 16; // Add leading '1', if exponent > 0\n }\n\n mantissa = (mantissa << 4) + 0x8;\n if (exponent > 1) {\n mantissa = mantissa << (exponent - 1);\n }\n\n const s16sample = input > 127 ? mantissa : -mantissa;\n\n // Convert to float\n sampleData[i] = s16sample / 32678;\n }\n return sampleData;\n}\n\nexport class DLSSample extends BasicSample {\n protected wFormatTag: number;\n protected bytesPerSample: number;\n\n /**\n * Sample's raw data before decoding it, for faster writing\n */\n protected rawData: IndexedByteArray;\n\n /**\n * @param name\n * @param rate\n * @param pitch\n * @param pitchCorrection\n * @param loopStart sample data points\n * @param loopEnd sample data points\n * @param dataChunk\n * @param wFormatTag\n * @param bytesPerSample\n */\n public constructor(\n name: string,\n rate: number,\n pitch: number,\n pitchCorrection: number,\n loopStart: number,\n loopEnd: number,\n dataChunk: RIFFChunk,\n wFormatTag: number,\n bytesPerSample: number\n ) {\n super(\n name,\n rate,\n pitch,\n pitchCorrection,\n sampleTypes.monoSample,\n loopStart,\n loopEnd\n );\n this.dataOverridden = false;\n this.rawData = dataChunk.data;\n this.wFormatTag = wFormatTag;\n this.bytesPerSample = bytesPerSample;\n }\n\n public getAudioData(): Float32Array {\n if (!this.rawData) {\n return new Float32Array(0);\n }\n if (!this.audioData) {\n let sampleData;\n switch (this.wFormatTag) {\n default:\n SpessaSynthWarn(\n `Failed to decode sample. Unknown wFormatTag: ${this.wFormatTag}`\n );\n sampleData = new Float32Array(\n this.rawData.length / this.bytesPerSample\n );\n break;\n\n case W_FORMAT_TAG.PCM:\n sampleData = readPCM(this.rawData, this.bytesPerSample);\n break;\n\n case W_FORMAT_TAG.ALAW:\n sampleData = readALAW(this.rawData, this.bytesPerSample);\n break;\n }\n this.setAudioData(sampleData, this.sampleRate);\n }\n return this.audioData ?? new Float32Array(0);\n }\n\n public getRawData(allowVorbis: boolean) {\n if (this.dataOverridden || this.isCompressed) {\n return super.getRawData(allowVorbis);\n }\n if (this.wFormatTag === W_FORMAT_TAG.PCM && this.bytesPerSample === 2) {\n // Copy straight away\n return this.rawData;\n }\n return this.encodeS16LE();\n }\n}\n","import { DLSVerifier } from \"./dls_verifier\";\nimport { WaveSample } from \"./wave_sample\";\nimport {\n findRIFFListType,\n readRIFFChunk,\n RIFFChunk,\n writeRIFFChunkParts,\n writeRIFFChunkRaw\n} from \"../../utils/riff_chunk\";\nimport {\n readLittleEndianIndexed,\n writeDword,\n writeWord\n} from \"../../utils/byte_functions/little_endian\";\nimport {\n getStringBytes,\n readBinaryStringIndexed\n} from \"../../utils/byte_functions/string\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport { SpessaSynthInfo } from \"../../utils/loggin\";\nimport { consoleColors } from \"../../utils/other\";\nimport { DLSSample } from \"./dls_sample\";\nimport type { BasicSoundBank } from \"../basic_soundbank/basic_soundbank\";\nimport type { BasicSample } from \"../basic_soundbank/basic_sample\";\n\nexport class DownloadableSoundsSample extends DLSVerifier {\n public waveSample = new WaveSample();\n public readonly wFormatTag: number;\n public readonly bytesPerSample: number;\n public readonly sampleRate: number;\n public readonly dataChunk: RIFFChunk;\n public name = \"Unnamed sample\";\n\n public constructor(\n wFormatTag: number,\n bytesPerSample: number,\n sampleRate: number,\n dataChunk: RIFFChunk\n ) {\n super();\n this.wFormatTag = wFormatTag;\n this.bytesPerSample = bytesPerSample;\n this.sampleRate = sampleRate;\n this.dataChunk = dataChunk;\n }\n\n public static read(waveChunk: RIFFChunk) {\n const chunks = this.verifyAndReadList(waveChunk, \"wave\");\n\n const fmtChunk = chunks.find((c) => c.header === \"fmt \");\n if (!fmtChunk) {\n throw new Error(\"No fmt chunk in the wave file!\");\n }\n\n // https://github.com/tpn/winsdk-10/blob/9b69fd26ac0c7d0b83d378dba01080e93349c2ed/Include/10.0.14393.0/shared/mmreg.h#L2108\n const wFormatTag = readLittleEndianIndexed(fmtChunk.data, 2);\n const channelsAmount = readLittleEndianIndexed(fmtChunk.data, 2);\n if (channelsAmount !== 1) {\n throw new Error(\n `Only mono samples are supported. Fmt reports ${channelsAmount} channels.`\n );\n }\n const sampleRate = readLittleEndianIndexed(fmtChunk.data, 4);\n // Skip avg bytes\n readLittleEndianIndexed(fmtChunk.data, 4);\n // BlockAlign\n readLittleEndianIndexed(fmtChunk.data, 2);\n // It's bits per sample because one channel\n const wBitsPerSample = readLittleEndianIndexed(fmtChunk.data, 2);\n const bytesPerSample = wBitsPerSample / 8;\n const dataChunk = chunks.find((c) => c.header === \"data\");\n if (!dataChunk) {\n throw new Error(\"No data chunk in the WAVE chunk!\");\n }\n const sample = new DownloadableSoundsSample(\n wFormatTag,\n bytesPerSample,\n sampleRate,\n dataChunk\n );\n\n // Read sample name\n const waveInfo = findRIFFListType(chunks, \"INFO\");\n if (waveInfo) {\n let infoChunk = readRIFFChunk(waveInfo.data);\n while (\n infoChunk.header !== \"INAM\" &&\n waveInfo.data.currentIndex < waveInfo.data.length\n ) {\n infoChunk = readRIFFChunk(waveInfo.data);\n }\n if (infoChunk.header === \"INAM\") {\n sample.name = readBinaryStringIndexed(\n infoChunk.data,\n infoChunk.size\n ).trim();\n }\n }\n\n // Read wave sample\n const wsmpChunk = chunks.find((c) => c.header === \"wsmp\");\n if (wsmpChunk) {\n sample.waveSample = WaveSample.read(wsmpChunk);\n }\n return sample;\n }\n\n public static fromSFSample(sample: BasicSample) {\n const raw = sample.getRawData(false);\n const dlsSample = new DownloadableSoundsSample(\n 0x01, // PCM\n 2, // 2 bytes per sample\n sample.sampleRate,\n // Get the s16le data\n new RIFFChunk(\n \"data\",\n raw.length,\n new IndexedByteArray(raw.buffer as ArrayBuffer)\n )\n );\n dlsSample.name = sample.name;\n dlsSample.waveSample = WaveSample.fromSFSample(sample);\n return dlsSample;\n }\n\n public toSFSample(soundBank: BasicSoundBank) {\n // DLS allows tuning to be a SHORT (32767 max), while SF uses BYTE (with 99 max -99 min)\n // Clamp it down and change root key if needed\n let originalKey = this.waveSample.unityNote;\n let pitchCorrection = this.waveSample.fineTune;\n const samplePitchSemitones = Math.trunc(pitchCorrection / 100);\n\n originalKey += samplePitchSemitones;\n pitchCorrection -= samplePitchSemitones * 100;\n\n let loopStart = 0;\n let loopEnd = 0;\n const loop = this.waveSample.loops?.[0];\n if (loop) {\n loopStart = loop.loopStart;\n loopEnd = loop.loopStart + loop.loopLength;\n }\n\n const sample = new DLSSample(\n this.name,\n this.sampleRate,\n originalKey,\n pitchCorrection,\n loopStart,\n loopEnd,\n this.dataChunk,\n this.wFormatTag,\n this.bytesPerSample\n );\n soundBank.addSamples(sample);\n }\n\n public write() {\n const fmt = this.writeFmt();\n const wsmp = this.waveSample.write();\n const data = writeRIFFChunkRaw(\"data\", this.dataChunk.data);\n\n const inam = writeRIFFChunkRaw(\"INAM\", getStringBytes(this.name, true));\n const info = writeRIFFChunkRaw(\"INFO\", inam, false, true);\n SpessaSynthInfo(\n `%cSaved %c${this.name}%c successfully!`,\n consoleColors.recognized,\n consoleColors.value,\n consoleColors.recognized\n );\n return writeRIFFChunkParts(\"wave\", [fmt, wsmp, data, info], true);\n }\n\n private writeFmt() {\n const fmtData = new IndexedByteArray(18);\n writeWord(fmtData, this.wFormatTag); // WFormatTag\n writeWord(fmtData, 1); // WChannels\n writeDword(fmtData, this.sampleRate);\n writeDword(fmtData, this.sampleRate * 2); // 16-bit samples\n writeWord(fmtData, 2); // WBlockAlign\n writeWord(fmtData, this.bytesPerSample * 8); // WBitsPerSample\n return writeRIFFChunkRaw(\"fmt \", fmtData);\n }\n}\n","import { DecodedModulator } from \"../basic_soundbank/modulator\";\nimport { generatorTypes } from \"../basic_soundbank/generator_types\";\n\nexport const DEFAULT_DLS_REVERB = new DecodedModulator(\n 0x00db,\n 0x0,\n generatorTypes.reverbEffectsSend,\n 1000,\n 0\n);\n\nexport const DEFAULT_DLS_CHORUS = new DecodedModulator(\n 0x00dd,\n 0x0,\n generatorTypes.chorusEffectsSend,\n 1000,\n 0\n);\n\nexport const DLS_1_NO_VIBRATO_MOD = new DecodedModulator(\n 0x0081,\n 0x0,\n generatorTypes.vibLfoToPitch,\n 0,\n 0\n);\n\nexport const DLS_1_NO_VIBRATO_PRESSURE = new DecodedModulator(\n 0x000d,\n 0x0,\n generatorTypes.vibLfoToPitch,\n 0,\n 0\n);\n","import {\n type DLSSource,\n dlsSources,\n type DLSTransform,\n modulatorCurveTypes,\n type ModulatorSourceEnum,\n modulatorSources\n} from \"../enums\";\nimport { ModulatorSource } from \"../basic_soundbank/modulator_source\";\nimport { type MIDIController, midiControllers } from \"../../midi/enums\";\nimport type { ModulatorSourceIndex } from \"../types\";\n\nexport class ConnectionSource {\n public source: DLSSource;\n public transform: DLSTransform;\n public bipolar: boolean;\n public invert: boolean;\n\n public constructor(\n source: DLSSource = dlsSources.none,\n transform: DLSTransform = modulatorCurveTypes.linear,\n bipolar = false,\n invert = false\n ) {\n this.source = source;\n this.transform = transform;\n this.bipolar = bipolar;\n this.invert = invert;\n }\n\n private get sourceName() {\n return (\n Object.keys(dlsSources).find(\n (k) => dlsSources[k as keyof typeof dlsSources] === this.source\n ) ?? this.source.toString()\n );\n }\n\n private get transformName() {\n return (\n Object.keys(modulatorCurveTypes).find(\n (k) =>\n modulatorCurveTypes[\n k as keyof typeof modulatorCurveTypes\n ] === this.transform\n ) ?? this.transform.toString()\n );\n }\n\n public static copyFrom(inputSource: ConnectionSource) {\n return new ConnectionSource(\n inputSource.source,\n inputSource.transform,\n inputSource.bipolar,\n inputSource.invert\n );\n }\n\n public static fromSFSource(\n source: ModulatorSource\n ): ConnectionSource | undefined {\n let sourceEnum: DLSSource | undefined = undefined;\n if (source.isCC) {\n // DLS only supports a specific set of controllers\n switch (source.index as MIDIController) {\n case midiControllers.modulationWheel:\n sourceEnum = dlsSources.modulationWheel;\n break;\n\n case midiControllers.mainVolume:\n sourceEnum = dlsSources.volume;\n break;\n\n case midiControllers.pan:\n sourceEnum = dlsSources.pan;\n break;\n\n case midiControllers.expressionController:\n sourceEnum = dlsSources.expression;\n break;\n\n case midiControllers.chorusDepth:\n sourceEnum = dlsSources.chorus;\n break;\n\n case midiControllers.reverbDepth:\n sourceEnum = dlsSources.reverb;\n break;\n }\n } else {\n switch (source.index as ModulatorSourceEnum) {\n case modulatorSources.noController:\n sourceEnum = dlsSources.none;\n break;\n\n case modulatorSources.noteOnKeyNum:\n sourceEnum = dlsSources.keyNum;\n break;\n\n case modulatorSources.noteOnVelocity:\n sourceEnum = dlsSources.velocity;\n break;\n\n case modulatorSources.pitchWheel:\n sourceEnum = dlsSources.pitchWheel;\n break;\n\n case modulatorSources.pitchWheelRange:\n sourceEnum = dlsSources.pitchWheelRange;\n break;\n\n case modulatorSources.polyPressure:\n sourceEnum = dlsSources.polyPressure;\n break;\n\n case modulatorSources.channelPressure:\n sourceEnum = dlsSources.channelPressure;\n }\n }\n // Unable to convert into DLS\n if (sourceEnum === undefined) {\n return undefined;\n }\n\n return new ConnectionSource(\n sourceEnum,\n source.curveType,\n source.isBipolar,\n source.isNegative\n );\n }\n\n public toString() {\n return `${this.sourceName} ${this.transformName} ${this.bipolar ? \"bipolar\" : \"unipolar\"} ${this.invert ? \"inverted\" : \"positive\"}`;\n }\n\n public toTransformFlag() {\n return (\n this.transform |\n ((this.bipolar ? 1 : 0) << 4) |\n ((this.invert ? 1 : 0) << 5)\n );\n }\n\n public toSFSource(): ModulatorSource | undefined {\n let sourceEnum: ModulatorSourceIndex | undefined = undefined;\n let isCC = false;\n switch (this.source) {\n default:\n case dlsSources.modLfo:\n case dlsSources.vibratoLfo:\n case dlsSources.coarseTune:\n case dlsSources.fineTune:\n case dlsSources.modEnv:\n return undefined; // Cannot be this in sf2\n\n case dlsSources.keyNum:\n sourceEnum = modulatorSources.noteOnKeyNum;\n break;\n case dlsSources.none:\n sourceEnum = modulatorSources.noController;\n break;\n case dlsSources.modulationWheel:\n sourceEnum = midiControllers.modulationWheel;\n isCC = true;\n break;\n case dlsSources.pan:\n sourceEnum = midiControllers.pan;\n isCC = true;\n break;\n case dlsSources.reverb:\n sourceEnum = midiControllers.reverbDepth;\n isCC = true;\n break;\n case dlsSources.chorus:\n sourceEnum = midiControllers.chorusDepth;\n isCC = true;\n break;\n case dlsSources.expression:\n sourceEnum = midiControllers.expressionController;\n isCC = true;\n break;\n case dlsSources.volume:\n sourceEnum = midiControllers.mainVolume;\n isCC = true;\n break;\n case dlsSources.velocity:\n sourceEnum = modulatorSources.noteOnVelocity;\n break;\n case dlsSources.polyPressure:\n sourceEnum = modulatorSources.polyPressure;\n break;\n case dlsSources.channelPressure:\n sourceEnum = modulatorSources.channelPressure;\n break;\n case dlsSources.pitchWheel:\n sourceEnum = modulatorSources.pitchWheel;\n break;\n case dlsSources.pitchWheelRange:\n sourceEnum = modulatorSources.pitchWheelRange;\n break;\n }\n if (sourceEnum === undefined) {\n return undefined;\n }\n\n return new ModulatorSource(\n sourceEnum,\n this.transform,\n isCC,\n this.bipolar,\n this.invert\n );\n }\n}\n","import { ConnectionSource } from \"./connection_source\";\nimport {\n type DLSDestination,\n dlsDestinations,\n type DLSSource,\n dlsSources,\n type DLSTransform,\n modulatorCurveTypes\n} from \"../enums\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport {\n readLittleEndianIndexed,\n writeDword,\n writeWord\n} from \"../../utils/byte_functions/little_endian\";\nimport { bitMaskToBool } from \"../../utils/byte_functions/bit_mask\";\nimport { Generator } from \"../basic_soundbank/generator\";\nimport {\n type GeneratorType,\n generatorTypes\n} from \"../basic_soundbank/generator_types\";\nimport { SpessaSynthInfo, SpessaSynthWarn } from \"../../utils/loggin\";\nimport { BasicZone } from \"../basic_soundbank/basic_zone\";\nimport { consoleColors } from \"../../utils/other\";\nimport { ModulatorSource } from \"../basic_soundbank/modulator_source\";\nimport { Modulator } from \"../basic_soundbank/modulator\";\nimport type { DownloadableSoundsArticulation } from \"./articulation\";\nimport {\n DEFAULT_DLS_CHORUS,\n DEFAULT_DLS_REVERB\n} from \"./default_dls_modulators\";\n\nconst invalidGeneratorTypes = new Set<GeneratorType>([\n generatorTypes.sampleModes, // Set in wave sample\n generatorTypes.initialAttenuation, // Set in wave sample\n generatorTypes.keyRange, // Set in region header\n generatorTypes.velRange, // Set in region header\n generatorTypes.sampleID, // Set in wave link\n generatorTypes.fineTune, // Set in wave sample\n generatorTypes.coarseTune, // Set in wave sample\n generatorTypes.startAddrsOffset, // Does not exist in DLS\n generatorTypes.startAddrsCoarseOffset, // Does not exist in DLS\n generatorTypes.endAddrOffset, // Does not exist in DLS\n generatorTypes.endAddrsCoarseOffset, // Set in wave sample\n generatorTypes.startloopAddrsOffset, // Set in wave sample\n generatorTypes.startloopAddrsCoarseOffset, // Set in wave sample\n generatorTypes.endloopAddrsOffset, // Set in wave sample\n generatorTypes.endloopAddrsCoarseOffset, // Set in wave sample\n generatorTypes.overridingRootKey, // Set in wave sample\n generatorTypes.exclusiveClass // Set in region header\n] as const);\n\n/**\n * Represents a single DLS articulator (connection block)\n */\nexport class ConnectionBlock {\n /**\n * Like SF2 modulator source.\n */\n public readonly source: ConnectionSource;\n /**\n * Like SF2 modulator secondary source.\n */\n public readonly control: ConnectionSource;\n /**\n * Like SF2 destination.\n */\n public readonly destination: DLSDestination;\n /**\n * Like SF2 amount, but long (32-bit) instead of short.\n */\n public readonly scale: number;\n /**\n * Like SF2 source transforms.\n */\n public readonly transform: DLSTransform;\n\n public constructor(\n source = new ConnectionSource(),\n control = new ConnectionSource(),\n destination: DLSDestination,\n transform: DLSTransform,\n scale: number\n ) {\n this.source = source;\n this.control = control;\n this.destination = destination;\n this.transform = transform;\n this.scale = scale;\n }\n\n public get isStaticParameter() {\n return (\n this.source.source === dlsSources.none &&\n this.control.source === dlsSources.none\n );\n }\n\n public get shortScale() {\n return this.scale >> 16;\n }\n\n private get transformName() {\n return (\n Object.keys(modulatorCurveTypes).find(\n (k) =>\n modulatorCurveTypes[\n k as keyof typeof modulatorCurveTypes\n ] === this.transform\n ) ?? this.transform.toString()\n );\n }\n\n private get destinationName() {\n return (\n Object.keys(dlsDestinations).find(\n (k) =>\n dlsDestinations[k as keyof typeof dlsDestinations] ===\n this.destination\n ) ?? this.destination.toString()\n );\n }\n\n public static read(artData: IndexedByteArray) {\n const usSource = readLittleEndianIndexed(artData, 2);\n const usControl = readLittleEndianIndexed(artData, 2);\n const usDestination = readLittleEndianIndexed(\n artData,\n 2\n ) as DLSDestination;\n const usTransform = readLittleEndianIndexed(artData, 2);\n const lScale = readLittleEndianIndexed(artData, 4) | 0;\n /*\n 2.10 <art2-ck>, Level 2 Articulator Chunk\n usTransform\n Bits 0-3 specify one of 16 possible output transforms. Bits 4-7 specify one of 16 possible transforms to apply to\n the usControl input. Bits 8 and 9 specify whether the usControl input should be inverted and/or bipolar. Bits 10-13\n specify one of 16 possible transforms to apply to the usSource input. Bit 14 and 15 specify whether the usSource\n input should be inverted and/or bipolar.\n */\n // Decode usTransform\n const transform = (usTransform & 0x0f) as DLSTransform;\n\n // Decode usControl\n const controlTransform = ((usTransform >> 4) & 0x0f) as DLSTransform;\n const controlBipolar = bitMaskToBool(usTransform, 8);\n const controlInvert = bitMaskToBool(usTransform, 9);\n const control = new ConnectionSource(\n usControl as DLSSource,\n controlTransform,\n controlBipolar,\n controlInvert\n );\n\n // Decode usSource\n const sourceTransform = ((usTransform >> 10) & 0x0f) as DLSTransform;\n const sourceBipolar = bitMaskToBool(usTransform, 14);\n const sourceInvert = bitMaskToBool(usTransform, 15);\n\n const source = new ConnectionSource(\n usSource as DLSSource,\n sourceTransform,\n sourceBipolar,\n sourceInvert\n );\n\n return new ConnectionBlock(\n source,\n control,\n usDestination,\n transform,\n lScale\n );\n }\n\n public static fromSFModulator(\n m: Modulator,\n articulation: DownloadableSoundsArticulation\n ) {\n const failed = (msg: string) => {\n SpessaSynthWarn(\n `Failed converting SF modulator into DLS:\\n ${m.toString()} \\n(${msg})`\n );\n };\n\n if (m.transformType !== 0) {\n failed(\"Absolute transform type is not supported\");\n return;\n }\n // Do not write the default DLS effect modulators\n if (\n Modulator.isIdentical(m, DEFAULT_DLS_CHORUS, true) ||\n Modulator.isIdentical(m, DEFAULT_DLS_REVERB, true)\n ) {\n return;\n }\n let source = ConnectionSource.fromSFSource(m.primarySource);\n if (!source) {\n failed(\"Invalid primary source\");\n return;\n }\n let control = ConnectionSource.fromSFSource(m.secondarySource);\n if (!control) {\n failed(\"Invalid secondary source\");\n return;\n }\n const dlsDestination = ConnectionBlock.fromSFDestination(\n m.destination,\n m.transformAmount\n );\n if (dlsDestination === undefined) {\n failed(\"Invalid destination\");\n return;\n }\n let amount = m.transformAmount;\n let destination: DLSDestination;\n if (typeof dlsDestination === \"number\") {\n destination = dlsDestination;\n } else {\n destination = dlsDestination.destination;\n amount = dlsDestination.amount;\n /*\n Check for a special case, for example mod wheel to vibLfoToPitch\n comprises vibLFO source, mod wheel control and pitch destination.\n */\n if (dlsDestination.source !== dlsSources.none) {\n if (\n control.source !== dlsSources.none &&\n source.source !== dlsSources.none\n ) {\n failed(\n \"Articulation generators with secondary source are not supported\"\n );\n return;\n }\n // Move the source to control if needed\n if (source.source !== dlsSources.none) {\n control = source;\n }\n source = new ConnectionSource(\n dlsDestination.source,\n modulatorCurveTypes.linear,\n dlsDestination.isBipolar\n );\n }\n }\n const bloc = new ConnectionBlock(\n source,\n control,\n destination,\n 0,\n amount << 16\n );\n articulation.connectionBlocks.push(bloc);\n }\n\n public static copyFrom(inputBlock: ConnectionBlock) {\n return new ConnectionBlock(\n ConnectionSource.copyFrom(inputBlock.source),\n ConnectionSource.copyFrom(inputBlock.control),\n inputBlock.destination,\n inputBlock.transform,\n inputBlock.scale\n );\n }\n\n public static fromSFGenerator(\n generator: Generator,\n articulation: DownloadableSoundsArticulation\n ) {\n if (invalidGeneratorTypes.has(generator.generatorType)) {\n return;\n }\n\n const failed = (msg: string) => {\n SpessaSynthWarn(\n `Failed converting SF2 generator into DLS:\\n ${generator.toString()} \\n(${msg})`\n );\n };\n\n const dlsDestination = ConnectionBlock.fromSFDestination(\n generator.generatorType,\n generator.generatorValue\n );\n if (dlsDestination === undefined) {\n failed(\"Invalid type\");\n return;\n }\n const source = new ConnectionSource();\n let destination: DLSDestination;\n let amount = generator.generatorValue;\n\n // Envelope generators are limited to 40 seconds,\n // However the keyToEnv correction makes us use the full SF range.\n\n if (typeof dlsDestination === \"number\") {\n destination = dlsDestination;\n } else {\n destination = dlsDestination.destination;\n amount = dlsDestination.amount;\n\n source.source = dlsDestination.source;\n source.bipolar = dlsDestination.isBipolar;\n }\n\n articulation.connectionBlocks.push(\n new ConnectionBlock(\n source,\n new ConnectionSource(),\n destination,\n 0,\n amount << 16\n )\n );\n }\n\n private static fromSFDestination(\n dest: GeneratorType,\n amount: number\n ):\n | DLSDestination\n | {\n source: DLSSource;\n destination: DLSDestination;\n isBipolar: boolean;\n amount: number;\n }\n | undefined {\n switch (dest) {\n default:\n return undefined;\n\n case generatorTypes.initialAttenuation:\n // The amount does not get EMU corrected here, as this only applies to modulator attenuation\n // The generator (affected) attenuation is handled in wsmp.\n return {\n destination: dlsDestinations.gain,\n amount: -amount,\n isBipolar: false,\n source: dlsSources.none\n };\n case generatorTypes.fineTune:\n return dlsDestinations.pitch;\n case generatorTypes.pan:\n return dlsDestinations.pan;\n case generatorTypes.keyNum:\n return dlsDestinations.keyNum;\n\n case generatorTypes.reverbEffectsSend:\n return dlsDestinations.reverbSend;\n case generatorTypes.chorusEffectsSend:\n return dlsDestinations.chorusSend;\n\n case generatorTypes.freqModLFO:\n return dlsDestinations.modLfoFreq;\n case generatorTypes.delayModLFO:\n return dlsDestinations.modLfoDelay;\n\n case generatorTypes.delayVibLFO:\n return dlsDestinations.vibLfoDelay;\n case generatorTypes.freqVibLFO:\n return dlsDestinations.vibLfoFreq;\n\n case generatorTypes.delayVolEnv:\n return dlsDestinations.volEnvDelay;\n case generatorTypes.attackVolEnv:\n return dlsDestinations.volEnvAttack;\n case generatorTypes.holdVolEnv:\n return dlsDestinations.volEnvHold;\n case generatorTypes.decayVolEnv:\n return dlsDestinations.volEnvDecay;\n case generatorTypes.sustainVolEnv:\n return {\n destination: dlsDestinations.volEnvSustain,\n amount: 1000 - amount,\n isBipolar: false,\n source: dlsSources.none\n };\n case generatorTypes.releaseVolEnv:\n return dlsDestinations.volEnvRelease;\n\n case generatorTypes.delayModEnv:\n return dlsDestinations.modEnvDelay;\n case generatorTypes.attackModEnv:\n return dlsDestinations.modEnvAttack;\n case generatorTypes.holdModEnv:\n return dlsDestinations.modEnvHold;\n case generatorTypes.decayModEnv:\n return dlsDestinations.modEnvDecay;\n case generatorTypes.sustainModEnv:\n return {\n destination: dlsDestinations.modEnvSustain,\n amount: 1000 - amount,\n isBipolar: false,\n source: dlsSources.none\n };\n case generatorTypes.releaseModEnv:\n return dlsDestinations.modEnvRelease;\n\n case generatorTypes.initialFilterFc:\n return dlsDestinations.filterCutoff;\n case generatorTypes.initialFilterQ:\n return dlsDestinations.filterQ;\n\n // Mod env\n case generatorTypes.modEnvToFilterFc:\n return {\n source: dlsSources.modEnv,\n destination: dlsDestinations.filterCutoff,\n amount,\n isBipolar: false\n };\n case generatorTypes.modEnvToPitch:\n return {\n source: dlsSources.modEnv,\n destination: dlsDestinations.pitch,\n amount,\n isBipolar: false\n };\n\n // Mod lfo\n case generatorTypes.modLfoToFilterFc:\n return {\n source: dlsSources.modLfo,\n destination: dlsDestinations.filterCutoff,\n amount,\n isBipolar: true\n };\n case generatorTypes.modLfoToVolume:\n return {\n source: dlsSources.modLfo,\n destination: dlsDestinations.gain,\n amount,\n isBipolar: true\n };\n case generatorTypes.modLfoToPitch:\n return {\n source: dlsSources.modLfo,\n destination: dlsDestinations.pitch,\n amount,\n isBipolar: true\n };\n\n // Vib lfo\n case generatorTypes.vibLfoToPitch:\n return {\n source: dlsSources.vibratoLfo,\n destination: dlsDestinations.pitch,\n amount,\n isBipolar: true\n };\n\n // Key to something\n case generatorTypes.keyNumToVolEnvHold:\n return {\n source: dlsSources.keyNum,\n destination: dlsDestinations.volEnvHold,\n amount,\n isBipolar: true\n };\n case generatorTypes.keyNumToVolEnvDecay:\n return {\n source: dlsSources.keyNum,\n destination: dlsDestinations.volEnvDecay,\n amount,\n isBipolar: true\n };\n case generatorTypes.keyNumToModEnvHold:\n return {\n source: dlsSources.keyNum,\n destination: dlsDestinations.modEnvHold,\n amount,\n isBipolar: true\n };\n case generatorTypes.keyNumToModEnvDecay:\n return {\n source: dlsSources.keyNum,\n destination: dlsDestinations.modEnvDecay,\n amount,\n isBipolar: true\n };\n\n case generatorTypes.scaleTuning:\n // Scale tuning is implemented in DLS via an articulator:\n // KeyNum to relative pitch at 12,800 cents.\n // Change that to scale tuning * 128.\n // Therefore, a regular scale is still 12,800, half is 6400, etc.\n return {\n source: dlsSources.keyNum,\n destination: dlsDestinations.pitch,\n amount: amount * 128,\n isBipolar: false // According to table 4, this should be false.\n };\n }\n }\n\n public toString() {\n return (\n `Source: ${this.source.toString()},\\n` +\n `Control: ${this.control.toString()},\\n` +\n `Scale: ${this.scale} >> 16 = ${this.shortScale},\\n` +\n `Output transform: ${this.transformName}\\n` +\n `Destination: ${this.destinationName}`\n );\n }\n\n public write() {\n const out = new IndexedByteArray(12);\n writeWord(out, this.source.source);\n writeWord(out, this.control.source);\n writeWord(out, this.destination);\n const transformEnum =\n this.transform |\n (this.control.toTransformFlag() << 4) |\n (this.source.toTransformFlag() << 10);\n writeWord(out, transformEnum);\n writeDword(out, this.scale);\n return out;\n }\n\n public toSFGenerator(zone: BasicZone) {\n const destination = this.destination;\n // SF2 uses 16-bit amounts, DLS uses 32-bit scale.\n const value = this.shortScale;\n\n switch (destination) {\n default:\n SpessaSynthInfo(\n `%cFailed converting DLS articulator into SF generator: %c${this.toString()}%c\\n(invalid destination)`,\n consoleColors.warn,\n consoleColors.value,\n consoleColors.unrecognized\n );\n return;\n\n case dlsDestinations.pan:\n zone.setGenerator(generatorTypes.pan, value);\n break;\n case dlsDestinations.gain:\n // Turn to centibels and apply emu correction\n zone.addToGenerator(\n generatorTypes.initialAttenuation,\n -value / 0.4\n );\n break;\n case dlsDestinations.filterCutoff:\n zone.setGenerator(generatorTypes.initialFilterFc, value);\n break;\n case dlsDestinations.filterQ:\n zone.setGenerator(generatorTypes.initialFilterQ, value);\n break;\n\n // Mod LFO raw values it seems\n case dlsDestinations.modLfoFreq:\n zone.setGenerator(generatorTypes.freqModLFO, value);\n break;\n case dlsDestinations.modLfoDelay:\n zone.setGenerator(generatorTypes.delayModLFO, value);\n break;\n case dlsDestinations.vibLfoFreq:\n zone.setGenerator(generatorTypes.freqVibLFO, value);\n break;\n case dlsDestinations.vibLfoDelay:\n zone.setGenerator(generatorTypes.delayVibLFO, value);\n break;\n\n // Vol. env: all times are timecents like sf2\n case dlsDestinations.volEnvDelay:\n zone.setGenerator(generatorTypes.delayVolEnv, value);\n break;\n case dlsDestinations.volEnvAttack:\n zone.setGenerator(generatorTypes.attackVolEnv, value);\n break;\n case dlsDestinations.volEnvHold:\n zone.setGenerator(generatorTypes.holdVolEnv, value);\n break;\n case dlsDestinations.volEnvDecay:\n zone.setGenerator(generatorTypes.decayVolEnv, value);\n break;\n case dlsDestinations.volEnvRelease:\n zone.setGenerator(generatorTypes.releaseVolEnv, value);\n break;\n case dlsDestinations.volEnvSustain:\n // Gain seems to be (1000 - value) = sustain cB\n zone.setGenerator(generatorTypes.sustainVolEnv, 1000 - value);\n break;\n\n // Mod env\n case dlsDestinations.modEnvDelay:\n zone.setGenerator(generatorTypes.delayModEnv, value);\n break;\n case dlsDestinations.modEnvAttack:\n zone.setGenerator(generatorTypes.attackModEnv, value);\n break;\n case dlsDestinations.modEnvHold:\n zone.setGenerator(generatorTypes.holdModEnv, value);\n break;\n case dlsDestinations.modEnvDecay:\n zone.setGenerator(generatorTypes.decayModEnv, value);\n break;\n case dlsDestinations.modEnvRelease:\n zone.setGenerator(generatorTypes.releaseModEnv, value);\n break;\n case dlsDestinations.modEnvSustain:\n // DLS uses 0.1%, SF uses 0.1%\n zone.setGenerator(generatorTypes.sustainModEnv, 1000 - value);\n break;\n\n case dlsDestinations.reverbSend:\n zone.setGenerator(generatorTypes.reverbEffectsSend, value);\n break;\n case dlsDestinations.chorusSend:\n zone.setGenerator(generatorTypes.chorusEffectsSend, value);\n break;\n case dlsDestinations.pitch:\n zone.fineTuning += value;\n break;\n }\n }\n\n public toSFModulator(zone: BasicZone) {\n // Output modulator variables\n let amount = this.shortScale;\n let modulatorDestination: GeneratorType;\n let primarySource: ModulatorSource | undefined;\n let secondarySource = new ModulatorSource();\n\n const failed = (msg: string) => {\n SpessaSynthInfo(\n `%cFailed converting DLS articulator into SF2:\\n %c${this.toString()}%c\\n(${msg})`,\n consoleColors.warn,\n consoleColors.value,\n consoleColors.unrecognized\n );\n };\n\n const specialDestination = this.toCombinedSFDestination();\n if (specialDestination) {\n /*\n Special destination detected.\n This means modLfoToPitch for example, as an SF modulator like\n\n CC#1 -> | x50 | -> modLfoToPitch\n\n In DLS is:\n\n Mod LFO -> | x50 | -> pitch\n CC#1 -> | |\n */\n modulatorDestination = specialDestination;\n const controlSF = this.control.toSFSource();\n if (!controlSF) {\n failed(\"Invalid control\");\n return;\n }\n primarySource = controlSF;\n } else {\n // Convert destination\n const convertedDestination = this.toSFDestination();\n if (!convertedDestination) {\n // Cannot be a valid modulator\n failed(\"Invalid destination\");\n return;\n }\n // The conversion may specify an adjusted value\n if (typeof convertedDestination === \"object\") {\n amount = convertedDestination.newAmount;\n modulatorDestination = convertedDestination.gen;\n } else {\n modulatorDestination = convertedDestination;\n }\n const convertedPrimary = this.source.toSFSource();\n if (!convertedPrimary) {\n failed(\"Invalid source\");\n return;\n }\n primarySource = convertedPrimary;\n\n const convertedSecondary = this.control.toSFSource();\n if (!convertedSecondary) {\n failed(\"Invalid control\");\n return;\n }\n secondarySource = convertedSecondary;\n }\n // Output transform is ignored as it's not a thing in soundfont format\n // Unless the curve type of source is linear, then output is copied.\n // Testcase: Fury.dls (sets concave output transform for the key to attenuation)\n if (\n this.transform !== modulatorCurveTypes.linear &&\n primarySource.curveType === modulatorCurveTypes.linear\n ) {\n primarySource.curveType = this.transform;\n }\n\n if (modulatorDestination === generatorTypes.initialAttenuation) {\n if (\n this.source.source === dlsSources.velocity ||\n this.source.source === dlsSources.volume ||\n this.source.source === dlsSources.expression\n ) {\n /*\n Some DLS banks (example: Fury.dls or 1 - House.rmi) only specify the output transform,\n while completely omitting the invert flag for this articulator.\n This results in the modulator rendering the voice inaudible, as the attenuation increases with velocity,\n which also conflicts with the default velToAtt modulator\n Yet most software seems to load them fine, so we invert it here.\n */\n primarySource.isNegative = true;\n }\n\n // A corrupted rendition of gm.dls was found under\n // https://sembiance.com/fileFormatSamples/audio/downloadableSoundBank/\n // Name: (GM.dls)\n // Which specifies a whopping 32,768 centibels of attenuation\n amount = Math.min(960, Math.max(0, amount));\n }\n\n // Get the modulator!\n const mod = new Modulator(\n primarySource,\n secondarySource,\n modulatorDestination,\n amount,\n 0\n );\n zone.addModulators(mod);\n }\n\n /**\n * Checks for an SF generator that consists of DLS source and destination (such as mod LFO and pitch)\n * @returns either a matching SF generator or nothing.\n */\n public toCombinedSFDestination(): GeneratorType | undefined {\n const source = this.source.source;\n const destination = this.destination;\n if (\n source === dlsSources.vibratoLfo &&\n destination === dlsDestinations.pitch\n ) {\n // Vibrato lfo to pitch\n return generatorTypes.vibLfoToPitch;\n } else if (\n source === dlsSources.modLfo &&\n destination === dlsDestinations.pitch\n ) {\n // Mod lfo to pitch\n return generatorTypes.modLfoToPitch;\n } else if (\n source === dlsSources.modLfo &&\n destination === dlsDestinations.filterCutoff\n ) {\n // Mod lfo to filter\n return generatorTypes.modLfoToFilterFc;\n } else if (\n source === dlsSources.modLfo &&\n destination === dlsDestinations.gain\n ) {\n // Mod lfo to volume\n return generatorTypes.modLfoToVolume;\n } else if (\n source === dlsSources.modEnv &&\n destination === dlsDestinations.filterCutoff\n ) {\n // Mod envelope to filter\n return generatorTypes.modEnvToFilterFc;\n } else if (\n source === dlsSources.modEnv &&\n destination === dlsDestinations.pitch\n ) {\n // Mod envelope to pitch\n return generatorTypes.modEnvToPitch;\n } else {\n return undefined;\n }\n }\n\n /**\n * Converts DLS destination of this block to an SF2 one, also with the correct amount.\n * @private\n */\n private toSFDestination():\n | GeneratorType\n | undefined\n | { gen: GeneratorType; newAmount: number } {\n const amount = this.shortScale;\n switch (this.destination) {\n default:\n case dlsDestinations.none:\n return undefined;\n case dlsDestinations.pan:\n return generatorTypes.pan;\n case dlsDestinations.gain:\n return {\n // DLS uses gain, SF uses attenuation\n gen: generatorTypes.initialAttenuation,\n newAmount: -amount\n };\n case dlsDestinations.pitch:\n return generatorTypes.fineTune;\n case dlsDestinations.keyNum:\n return generatorTypes.overridingRootKey;\n\n // Vol env\n case dlsDestinations.volEnvDelay:\n return generatorTypes.delayVolEnv;\n case dlsDestinations.volEnvAttack:\n return generatorTypes.attackVolEnv;\n case dlsDestinations.volEnvHold:\n return generatorTypes.holdVolEnv;\n case dlsDestinations.volEnvDecay:\n return generatorTypes.decayVolEnv;\n case dlsDestinations.volEnvSustain:\n return {\n gen: generatorTypes.sustainVolEnv,\n newAmount: 1000 - amount\n };\n case dlsDestinations.volEnvRelease:\n return generatorTypes.releaseVolEnv;\n\n // Mod env\n case dlsDestinations.modEnvDelay:\n return generatorTypes.delayModEnv;\n case dlsDestinations.modEnvAttack:\n return generatorTypes.attackModEnv;\n case dlsDestinations.modEnvHold:\n return generatorTypes.holdModEnv;\n case dlsDestinations.modEnvDecay:\n return generatorTypes.decayModEnv;\n case dlsDestinations.modEnvSustain:\n return {\n gen: generatorTypes.sustainModEnv,\n newAmount: 1000 - amount\n };\n case dlsDestinations.modEnvRelease:\n return generatorTypes.releaseModEnv;\n\n case dlsDestinations.filterCutoff:\n return generatorTypes.initialFilterFc;\n case dlsDestinations.filterQ:\n return generatorTypes.initialFilterQ;\n case dlsDestinations.chorusSend:\n return generatorTypes.chorusEffectsSend;\n case dlsDestinations.reverbSend:\n return generatorTypes.reverbEffectsSend;\n\n // Lfo\n case dlsDestinations.modLfoFreq:\n return generatorTypes.freqModLFO;\n case dlsDestinations.modLfoDelay:\n return generatorTypes.delayModLFO;\n case dlsDestinations.vibLfoFreq:\n return generatorTypes.freqVibLFO;\n case dlsDestinations.vibLfoDelay:\n return generatorTypes.delayVibLFO;\n }\n }\n}\n","import {\n type DLSDestination,\n dlsDestinations,\n dlsSources,\n type GeneratorType,\n generatorTypes\n} from \"../enums\";\nimport {\n findRIFFListType,\n readRIFFChunk,\n type RIFFChunk,\n writeRIFFChunkParts,\n writeRIFFChunkRaw\n} from \"../../utils/riff_chunk\";\nimport {\n readLittleEndianIndexed,\n writeDword\n} from \"../../utils/byte_functions/little_endian\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport { DLSVerifier } from \"./dls_verifier\";\nimport { BasicZone } from \"../basic_soundbank/basic_zone\";\nimport { BasicInstrumentZone, Modulator } from \"../exports\";\nimport { SpessaSynthWarn } from \"../../utils/loggin\";\nimport {\n DLS_1_NO_VIBRATO_MOD,\n DLS_1_NO_VIBRATO_PRESSURE\n} from \"./default_dls_modulators\";\nimport { ConnectionBlock } from \"./connection_block\";\n\ntype KeyToEnv =\n | typeof generatorTypes.keyNumToModEnvDecay\n | typeof generatorTypes.keyNumToModEnvHold\n | typeof generatorTypes.keyNumToVolEnvDecay\n | typeof generatorTypes.keyNumToVolEnvHold;\n\nexport class DownloadableSoundsArticulation extends DLSVerifier {\n public readonly connectionBlocks = new Array<ConnectionBlock>();\n public mode: \"dls1\" | \"dls2\" = \"dls2\";\n public get length() {\n return this.connectionBlocks.length;\n }\n\n public copyFrom(inputArticulation: DownloadableSoundsArticulation) {\n this.mode = inputArticulation.mode;\n inputArticulation.connectionBlocks.forEach((block) => {\n this.connectionBlocks.push(ConnectionBlock.copyFrom(block));\n });\n }\n\n public fromSFZone(z: BasicInstrumentZone) {\n this.mode = \"dls2\";\n\n // Copy to avoid changing the input zone\n const zone = new BasicZone();\n zone.copyFrom(z);\n\n // Read_articulation.ts:\n // According to viena and another strange (with modulators) rendition of gm.dls in sf2,\n // It shall be divided by -128,\n // And a strange correction needs to be applied to the real value:\n // Real + (60 / 128) * scale\n // We do this here.\n for (const relativeGenerator of zone.generators) {\n let absoluteCounterpart: GeneratorType | undefined = undefined;\n switch (relativeGenerator.generatorType) {\n default:\n continue;\n\n case generatorTypes.keyNumToVolEnvDecay:\n absoluteCounterpart = generatorTypes.decayVolEnv;\n break;\n case generatorTypes.keyNumToVolEnvHold:\n absoluteCounterpart = generatorTypes.holdVolEnv;\n break;\n case generatorTypes.keyNumToModEnvDecay:\n absoluteCounterpart = generatorTypes.decayModEnv;\n break;\n case generatorTypes.keyNumToModEnvHold:\n absoluteCounterpart = generatorTypes.holdModEnv;\n }\n const absoluteValue = zone.getGenerator(\n absoluteCounterpart,\n undefined\n );\n const dlsRelative = relativeGenerator.generatorValue * -128;\n\n if (absoluteValue === undefined) {\n // There's no absolute generator here.\n continue;\n }\n const subtraction = (60 / 128) * dlsRelative;\n const newAbsolute = absoluteValue - subtraction;\n zone.setGenerator(\n relativeGenerator.generatorType,\n dlsRelative,\n false\n );\n zone.setGenerator(absoluteCounterpart, newAbsolute, false);\n }\n for (const generator of zone.generators) {\n ConnectionBlock.fromSFGenerator(generator, this);\n }\n for (const modulator of zone.modulators) {\n ConnectionBlock.fromSFModulator(modulator, this);\n }\n }\n\n /**\n * Chunk list for the region/instrument (containing lar2 or lart)\n * @param chunks\n */\n public read(chunks: RIFFChunk[]) {\n const lart = findRIFFListType(chunks, \"lart\");\n const lar2 = findRIFFListType(chunks, \"lar2\");\n\n if (lart) {\n this.mode = \"dls1\";\n while (lart.data.currentIndex < lart.data.length) {\n const art1 = readRIFFChunk(lart.data);\n DownloadableSoundsArticulation.verifyHeader(art1, \"art1\");\n const artData = art1.data;\n const cbSize = readLittleEndianIndexed(artData, 4);\n if (cbSize !== 8) {\n SpessaSynthWarn(\n `CbSize in articulation mismatch. Expected 8, got ${cbSize}`\n );\n }\n const connectionsAmount = readLittleEndianIndexed(artData, 4);\n for (let i = 0; i < connectionsAmount; i++) {\n this.connectionBlocks.push(ConnectionBlock.read(artData));\n }\n }\n } else if (lar2) {\n this.mode = \"dls2\";\n while (lar2.data.currentIndex < lar2.data.length) {\n const art2 = readRIFFChunk(lar2.data);\n DownloadableSoundsArticulation.verifyHeader(art2, \"art2\");\n const artData = art2.data;\n const cbSize = readLittleEndianIndexed(artData, 4);\n if (cbSize !== 8) {\n SpessaSynthWarn(\n `CbSize in articulation mismatch. Expected 8, got ${cbSize}`\n );\n }\n const connectionsAmount = readLittleEndianIndexed(artData, 4);\n for (let i = 0; i < connectionsAmount; i++) {\n this.connectionBlocks.push(ConnectionBlock.read(artData));\n }\n }\n }\n }\n\n /**\n * Note: this writes \"lar2\", not just \"art2\"\n */\n public write() {\n const art2Data = new IndexedByteArray(8);\n writeDword(art2Data, 8); // CbSize\n writeDword(art2Data, this.connectionBlocks.length); // CConnectionBlocks\n\n const out = this.connectionBlocks.map((a) => a.write());\n const art2 = writeRIFFChunkParts(\n this.mode === \"dls2\" ? \"art2\" : \"art1\",\n [art2Data, ...out]\n );\n return writeRIFFChunkRaw(\n this.mode === \"dls2\" ? \"lar2\" : \"lart\",\n art2,\n false,\n true\n );\n }\n\n /**\n * Converts DLS articulation into an SF zone.\n * @param zone The zone to write to.\n */\n public toSFZone(zone: BasicZone) {\n const applyKeyToCorrection = (\n value: number,\n keyToGen: KeyToEnv,\n realGen: GeneratorType,\n dlsDestination: DLSDestination\n ) => {\n // According to viena and another strange (with modulators) rendition of gm.dls in sf2,\n // It shall be divided by -128\n // And a strange correction needs to be applied to the real (generator) value:\n // Real + (60 / 128) * scale\n // Where real means the actual generator (e.g. decayVolEnv\n // And scale means the keyNumToVolEnvDecay\n const keyToGenValue = value / -128;\n zone.setGenerator(keyToGen, keyToGenValue);\n // Airfont 340 fix\n if (keyToGenValue <= 120) {\n // Apply correction\n const correction = Math.round((60 / 128) * value);\n\n const realValueConnection = this.connectionBlocks.find(\n (block) =>\n block.isStaticParameter &&\n block.destination === dlsDestination\n );\n if (realValueConnection) {\n // Overwrite existing\n zone.setGenerator(\n realGen,\n correction + realValueConnection.shortScale\n );\n }\n }\n };\n\n for (const connection of this.connectionBlocks) {\n // SF2 uses 16-bit amounts, DLS uses 32-bit scale.\n const amount = connection.shortScale;\n\n const source = connection.source.source;\n const control = connection.control.source;\n const destination = connection.destination;\n\n // If source and control are both zero, it's a generator\n if (connection.isStaticParameter) {\n connection.toSFGenerator(zone);\n continue;\n }\n // A few special cases which are generators\n if (control === dlsSources.none) {\n // The keyNum source\n // It usually requires a special treatment\n if (source === dlsSources.keyNum) {\n // Scale tuning\n if (destination === dlsDestinations.pitch) {\n zone.setGenerator(\n generatorTypes.scaleTuning,\n amount / 128\n );\n continue;\n }\n if (\n destination === dlsDestinations.modEnvHold ||\n destination === dlsDestinations.modEnvDecay ||\n destination === dlsDestinations.volEnvHold ||\n destination == dlsDestinations.volEnvDecay\n ) {\n // Skip, will be applied later\n continue;\n }\n } else {\n const specialGen = connection.toCombinedSFDestination();\n if (specialGen) {\n zone.setGenerator(specialGen, amount);\n continue;\n }\n }\n }\n // Modulator, transform!\n connection.toSFModulator(zone);\n }\n\n // It seems that dls 1 does not have vibrato lfo, so we shall disable it\n if (this.mode === \"dls1\") {\n zone.addModulators(\n // Modulation to vibrato\n Modulator.copyFrom(DLS_1_NO_VIBRATO_MOD),\n Modulator.copyFrom(DLS_1_NO_VIBRATO_PRESSURE)\n // Pressure to vibrato\n );\n }\n\n // Perform correction for the key to something generators\n for (const connection of this.connectionBlocks) {\n if (connection.source.source !== dlsSources.keyNum) {\n continue;\n }\n const generatorAmount = connection.shortScale;\n switch (connection.destination) {\n default:\n continue;\n\n case dlsDestinations.volEnvHold:\n // Key to vol env hold\n applyKeyToCorrection(\n generatorAmount,\n generatorTypes.keyNumToVolEnvHold,\n generatorTypes.holdVolEnv,\n dlsDestinations.volEnvHold\n );\n break;\n\n case dlsDestinations.volEnvDecay:\n applyKeyToCorrection(\n generatorAmount,\n generatorTypes.keyNumToVolEnvDecay,\n generatorTypes.decayVolEnv,\n dlsDestinations.volEnvDecay\n );\n break;\n\n case dlsDestinations.modEnvHold:\n applyKeyToCorrection(\n generatorAmount,\n generatorTypes.keyNumToModEnvHold,\n generatorTypes.holdModEnv,\n dlsDestinations.modEnvHold\n );\n break;\n\n case dlsDestinations.modEnvDecay:\n applyKeyToCorrection(\n generatorAmount,\n generatorTypes.keyNumToModEnvDecay,\n generatorTypes.decayModEnv,\n dlsDestinations.modEnvDecay\n );\n break;\n }\n }\n }\n}\n","import { type RIFFChunk, writeRIFFChunkRaw } from \"../../utils/riff_chunk\";\nimport {\n readLittleEndianIndexed,\n writeDword,\n writeWord\n} from \"../../utils/byte_functions/little_endian\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport type { BasicSample } from \"../basic_soundbank/basic_sample\";\nimport type { BasicInstrumentZone } from \"../basic_soundbank/basic_instrument_zone\";\nimport { sampleTypes } from \"../enums\";\n\nexport class WaveLink {\n /**\n * Specifies the channel placement of the sample. This is used to place mono sounds within a\n * stereo pair or for multi-track placement. Each bit position within the ulChannel field specifies\n * a channel placement with bit 0 specifying a mono sample or the left channel of a stereo file.\n */\n public channel = 1;\n\n /**\n * Specifies the 0 based index of the cue entry in the wave pool table.\n */\n public tableIndex: number;\n\n /**\n * Specifies flag options for this wave link. All bits not defined must be set to 0.\n */\n public fusOptions = 0;\n\n /**\n * Specifies a group number for samples which are phase locked. All waves in a set of wave\n * links with the same group are phase locked and follow the wave in the group with the\n * F_WAVELINK_PHASE_MASTER flag set. If a wave is not a member of a phase locked\n * group, this value should be set to 0.\n */\n public phaseGroup = 0;\n\n public constructor(tableIndex: number) {\n this.tableIndex = tableIndex;\n }\n\n public static copyFrom(waveLink: WaveLink) {\n const wlnk = new WaveLink(waveLink.tableIndex);\n wlnk.channel = waveLink.channel;\n wlnk.phaseGroup = waveLink.phaseGroup;\n wlnk.fusOptions = waveLink.fusOptions;\n return wlnk;\n }\n\n public static read(chunk: RIFFChunk) {\n // Flags\n const fusOptions = readLittleEndianIndexed(chunk.data, 2);\n // Phase group\n const phaseGroup = readLittleEndianIndexed(chunk.data, 2);\n // Channel\n const ulChannel = readLittleEndianIndexed(chunk.data, 4);\n // Table index\n const ulTableIndex = readLittleEndianIndexed(chunk.data, 4);\n const wlnk = new WaveLink(ulTableIndex);\n wlnk.channel = ulChannel;\n wlnk.fusOptions = fusOptions;\n wlnk.phaseGroup = phaseGroup;\n return wlnk;\n }\n\n public static fromSFZone(\n samples: BasicSample[],\n zone: BasicInstrumentZone\n ) {\n const index = samples.indexOf(zone.sample);\n if (index < 0) {\n throw new Error(\n `Wave link error: Sample ${zone.sample.name} does not exist in the sample list.`\n );\n }\n const waveLink = new WaveLink(index);\n switch (zone.sample.sampleType) {\n default:\n case sampleTypes.leftSample:\n case sampleTypes.monoSample:\n // Left (or mono)\n waveLink.channel = 1 << 0;\n break;\n\n case sampleTypes.rightSample:\n // Right channel\n waveLink.channel = 1 << 1;\n }\n return waveLink;\n }\n\n public write() {\n const wlnkData = new IndexedByteArray(12);\n writeWord(wlnkData, this.fusOptions); // FusOptions\n writeWord(wlnkData, this.phaseGroup); // UsPhaseGroup\n writeDword(wlnkData, this.channel); // UlChannel\n writeDword(wlnkData, this.tableIndex); // UlTableIndex\n return writeRIFFChunkRaw(\"wlnk\", wlnkData);\n }\n}\n","import { DownloadableSoundsArticulation } from \"./articulation\";\nimport type { GenericRange } from \"../types\";\nimport { WaveSample } from \"./wave_sample\";\nimport { WaveLink } from \"./wave_link\";\nimport {\n type RIFFChunk,\n writeRIFFChunkParts,\n writeRIFFChunkRaw\n} from \"../../utils/riff_chunk\";\nimport { SpessaSynthWarn } from \"../../utils/loggin\";\nimport {\n readLittleEndianIndexed,\n writeWord\n} from \"../../utils/byte_functions/little_endian\";\nimport { DLSVerifier } from \"./dls_verifier\";\nimport type { DownloadableSoundsSample } from \"./sample\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport type { BasicInstrumentZone } from \"../basic_soundbank/basic_instrument_zone\";\nimport type { BasicSample } from \"../basic_soundbank/basic_sample\";\nimport type { BasicInstrument } from \"../basic_soundbank/basic_instrument\";\nimport {\n generatorLimits,\n generatorTypes\n} from \"../basic_soundbank/generator_types\";\n\nexport class DownloadableSoundsRegion extends DLSVerifier {\n public readonly articulation = new DownloadableSoundsArticulation();\n /**\n * Specifies the key range for this region.\n */\n public keyRange: GenericRange = {\n min: 0,\n max: 127\n };\n /**\n * Specifies the velocity range for this region.\n */\n public velRange: GenericRange = {\n min: 0,\n max: 127\n };\n\n /**\n * Specifies the key group for a drum instrument. Key group values allow multiple regions\n * within a drum instrument to belong to the same \"key group.\" If a synthesis engine is\n * instructed to play a note with a key group setting and any other notes are currently playing\n * with this same key group, then the synthesis engine should turn off all notes with the same\n * key group value as soon as possible.\n */\n public keyGroup = 0;\n\n /**\n * Specifies flag options for the synthesis of this region.\n */\n public fusOptions = 0;\n\n /**\n * Indicates the layer of this region for editing purposes. This field facilitates the\n * organization of overlapping regions into layers for display to the user of a DLS sound editor.\n * For example, if a piano sound and a string section are overlapped to create a piano/string pad,\n * all the regions of the piano might be labeled as layer 1, and all the regions of the string\n * section might be labeled as layer 2\n */\n public usLayer = 0;\n\n public readonly waveSample: WaveSample;\n public readonly waveLink: WaveLink;\n\n public constructor(waveLink: WaveLink, waveSample: WaveSample) {\n super();\n this.waveSample = waveSample;\n this.waveLink = waveLink;\n }\n\n public static copyFrom(inputRegion: DownloadableSoundsRegion) {\n const outputRegion = new DownloadableSoundsRegion(\n WaveLink.copyFrom(inputRegion.waveLink),\n WaveSample.copyFrom(inputRegion.waveSample)\n );\n outputRegion.keyGroup = inputRegion.keyGroup;\n outputRegion.keyRange = { ...inputRegion.keyRange };\n outputRegion.velRange = { ...inputRegion.velRange };\n outputRegion.usLayer = inputRegion.usLayer;\n outputRegion.fusOptions = inputRegion.fusOptions;\n outputRegion.articulation.copyFrom(inputRegion.articulation);\n return outputRegion;\n }\n\n public static read(samples: DownloadableSoundsSample[], chunk: RIFFChunk) {\n const regionChunks = this.verifyAndReadList(chunk, \"rgn \", \"rgn2\");\n // Wsmp: wave sample chunk\n const waveSampleChunk = regionChunks.find((c) => c.header === \"wsmp\");\n let waveSample = waveSampleChunk\n ? WaveSample.read(waveSampleChunk)\n : undefined;\n\n // Wlnk: wave link chunk\n const waveLinkChunk = regionChunks.find((c) => c.header === \"wlnk\");\n if (!waveLinkChunk) {\n // No wave link means no sample. What? Why is it even here then?\n SpessaSynthWarn(\n \"Invalid DLS region: missing 'wlnk' chunk! Discarding...\"\n );\n return;\n }\n const waveLink = WaveLink.read(waveLinkChunk);\n\n // Region header\n const regionHeader = regionChunks.find((c) => c.header === \"rgnh\");\n if (!regionHeader) {\n SpessaSynthWarn(\n \"Invalid DLS region: missing 'rgnh' chunk! Discarding...\"\n );\n return;\n }\n\n const sample = samples[waveLink.tableIndex];\n if (!sample) {\n DownloadableSoundsRegion.parsingError(\n `Invalid sample index: ${waveLink.tableIndex}. Samples available: ${samples.length}`\n );\n }\n waveSample ??= sample.waveSample;\n\n const region = new DownloadableSoundsRegion(waveLink, waveSample);\n\n // Key range\n const keyMin = readLittleEndianIndexed(regionHeader.data, 2);\n const keyMax = readLittleEndianIndexed(regionHeader.data, 2);\n // Vel range\n let velMin = readLittleEndianIndexed(regionHeader.data, 2);\n let velMax = readLittleEndianIndexed(regionHeader.data, 2);\n\n // A fix for not cool files\n // Cannot do the same to key zones sadly\n if (velMin === 0 && velMax === 0) {\n velMax = 127;\n velMin = 0;\n }\n region.keyRange.max = keyMax;\n region.keyRange.min = keyMin;\n\n region.velRange.max = velMax;\n region.velRange.min = velMin;\n\n // FusOptions\n region.fusOptions = readLittleEndianIndexed(regionHeader.data, 2);\n // KeyGroup: essentially exclusive class\n region.keyGroup = readLittleEndianIndexed(regionHeader.data, 2);\n\n // UsLayer\n if (regionHeader.data.length - regionHeader.data.currentIndex >= 2) {\n region.usLayer = readLittleEndianIndexed(regionHeader.data, 2);\n }\n\n region.articulation.read(regionChunks);\n return region;\n }\n\n public static fromSFZone(\n zone: BasicInstrumentZone,\n samples: BasicSample[]\n ) {\n const waveSample = WaveSample.fromSFZone(zone);\n\n const waveLink = WaveLink.fromSFZone(samples, zone);\n\n const region = new DownloadableSoundsRegion(waveLink, waveSample);\n\n // Assign ranges\n region.keyRange.min = Math.max(zone.keyRange.min, 0);\n region.keyRange.max = zone.keyRange.max;\n region.velRange.min = Math.max(zone.velRange.min, 0);\n region.velRange.max = zone.velRange.max;\n\n // KeyGroup (exclusive class)\n region.keyGroup = zone.getGenerator(generatorTypes.exclusiveClass, 0);\n region.articulation.fromSFZone(zone);\n return region;\n }\n\n public write() {\n // In that order!\n const chunks = [\n this.writeHeader(),\n this.waveSample.write(),\n this.waveLink.write(),\n this.articulation.write()\n ];\n return writeRIFFChunkParts(\"rgn2\", chunks, true);\n }\n\n public toSFZone(\n instrument: BasicInstrument,\n samples: BasicSample[]\n ): BasicInstrumentZone {\n const sample = samples[this.waveLink.tableIndex];\n if (!sample) {\n DownloadableSoundsRegion.parsingError(\n `Invalid sample index: ${this.waveLink.tableIndex}`\n );\n }\n const zone = instrument.createZone(sample);\n zone.keyRange = this.keyRange;\n zone.velRange = this.velRange;\n // If the zones are default (0-127), set to -1 as \"not set\"\n if (this.keyRange.max === 127 && this.keyRange.min === 0) {\n zone.keyRange.min = -1;\n }\n if (this.velRange.max === 127 && this.velRange.min === 0) {\n zone.velRange.min = -1;\n }\n\n // KeyGroup: essentially exclusive class\n if (this.keyGroup !== 0) {\n zone.setGenerator(generatorTypes.exclusiveClass, this.keyGroup);\n }\n\n this.waveSample.toSFZone(zone, sample);\n this.articulation.toSFZone(zone);\n // Remove generators with default values\n zone.generators = zone.generators.filter(\n (g) => g.generatorValue !== generatorLimits[g.generatorType].def\n );\n return zone;\n }\n\n private writeHeader() {\n // Region header\n const rgnhData = new IndexedByteArray(12);\n // KeyRange\n writeWord(rgnhData, Math.max(this.keyRange.min, 0));\n writeWord(rgnhData, this.keyRange.max);\n // VelRange\n writeWord(rgnhData, Math.max(this.velRange.min, 0));\n writeWord(rgnhData, this.velRange.max);\n writeWord(rgnhData, this.fusOptions);\n // KeyGroup (exclusive class)\n writeWord(rgnhData, this.keyGroup);\n // UsLayer\n writeWord(rgnhData, this.usLayer);\n return writeRIFFChunkRaw(\"rgnh\", rgnhData);\n }\n}\n","import { DownloadableSoundsArticulation } from \"./articulation\";\nimport { DownloadableSoundsRegion } from \"./region\";\nimport { type MIDIPatchNamed } from \"../basic_soundbank/midi_patch\";\nimport {\n findRIFFListType,\n readRIFFChunk,\n type RIFFChunk,\n writeRIFFChunkParts,\n writeRIFFChunkRaw\n} from \"../../utils/riff_chunk\";\nimport { getStringBytes, readBinaryStringIndexed } from \"../../utils/byte_functions/string\";\nimport { SpessaSynthGroup, SpessaSynthGroupCollapsed, SpessaSynthGroupEnd } from \"../../utils/loggin\";\nimport { readLittleEndianIndexed, writeDword } from \"../../utils/byte_functions/little_endian\";\nimport { consoleColors } from \"../../utils/other\";\nimport { DLSVerifier } from \"./dls_verifier\";\nimport type { DLSChunkFourCC } from \"../types\";\nimport type { DownloadableSoundsSample } from \"./sample\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport { BasicPreset } from \"../basic_soundbank/basic_preset\";\nimport { BasicInstrument } from \"../basic_soundbank/basic_instrument\";\nimport { BasicSample, BasicSoundBank, generatorLimits, generatorTypes, Modulator } from \"../exports\";\nimport { DEFAULT_DLS_CHORUS, DEFAULT_DLS_REVERB } from \"./default_dls_modulators\";\n\n/**\n * Represents a proper DLS instrument, with regions and articulation.\n * DLS\n */\nexport class DownloadableSoundsInstrument\n extends DLSVerifier\n implements MIDIPatchNamed\n{\n public readonly articulation = new DownloadableSoundsArticulation();\n public readonly regions = new Array<DownloadableSoundsRegion>();\n public name = \"Unnamed\";\n public bankLSB = 0;\n public bankMSB = 0;\n public isGMGSDrum = false;\n public program = 0;\n\n public static copyFrom(inputInstrument: DownloadableSoundsInstrument) {\n const outputInstrument = new DownloadableSoundsInstrument();\n outputInstrument.name = inputInstrument.name;\n outputInstrument.isGMGSDrum = inputInstrument.isGMGSDrum;\n outputInstrument.bankMSB = inputInstrument.bankMSB;\n outputInstrument.bankLSB = inputInstrument.bankLSB;\n outputInstrument.program = inputInstrument.program;\n outputInstrument.articulation.copyFrom(inputInstrument.articulation);\n inputInstrument.regions.forEach((region) => {\n outputInstrument.regions.push(\n DownloadableSoundsRegion.copyFrom(region)\n );\n });\n return outputInstrument;\n }\n\n public static read(samples: DownloadableSoundsSample[], chunk: RIFFChunk) {\n const chunks = this.verifyAndReadList(chunk, \"ins \");\n\n const instrumentHeader = chunks.find((c) => c.header === \"insh\");\n if (!instrumentHeader) {\n SpessaSynthGroupEnd();\n throw new Error(\"No instrument header!\");\n }\n\n // Read the instrument name in INFO\n let instrumentName = ``;\n const infoChunk = findRIFFListType(chunks, \"INFO\");\n if (infoChunk) {\n let info = readRIFFChunk(infoChunk.data);\n while (info.header !== \"INAM\") {\n info = readRIFFChunk(infoChunk.data);\n }\n instrumentName = readBinaryStringIndexed(\n info.data,\n info.data.length\n ).trim();\n }\n if (instrumentName.length < 1) {\n instrumentName = `Unnamed Instrument`;\n }\n const instrument = new DownloadableSoundsInstrument();\n instrument.name = instrumentName;\n // Read instrument header\n const regions = readLittleEndianIndexed(instrumentHeader.data, 4);\n /**\n *\n * Specifies the MIDI bank location. Bits 0-6 are defined as MIDI CC32 and bits 8-14 are\n * defined as MIDI CC0. Bits 7 and 15-30 are reserved and should be written to zero. If the\n * F_INSTRUMENT_DRUMS flag (Bit 31) is equal to 1 then the instrument is a drum\n * instrument; if equal to 0 then the instrument is a melodic instrument.\n */\n const ulBank = readLittleEndianIndexed(instrumentHeader.data, 4);\n /**\n * Specifies the MIDI Program Change (PC) value. Bits 0-6 are defined as PC value and bits 7-\n * 31 are reserved and should be written to zero.\n */\n const ulInstrument = readLittleEndianIndexed(instrumentHeader.data, 4);\n\n instrument.program = ulInstrument & 127;\n instrument.bankMSB = (ulBank >>> 8) & 127;\n instrument.bankLSB = ulBank & 127;\n instrument.isGMGSDrum = ulBank >>> 31 > 0;\n\n SpessaSynthGroupCollapsed(\n `%cParsing %c\"${instrumentName}\"%c...`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n\n // List of regions\n const regionListChunk = findRIFFListType(chunks, \"lrgn\");\n if (!regionListChunk) {\n SpessaSynthGroupEnd();\n throw new Error(\"No region list!\");\n }\n\n instrument.articulation.read(chunks);\n\n // Read regions\n for (let i = 0; i < regions; i++) {\n const chunk = readRIFFChunk(regionListChunk.data);\n this.verifyHeader(chunk, \"LIST\");\n const type = readBinaryStringIndexed(\n chunk.data,\n 4\n ) as DLSChunkFourCC;\n if (type !== \"rgn \" && type !== \"rgn2\") {\n SpessaSynthGroupEnd();\n this.parsingError(\n `Invalid DLS region! Expected \"rgn \" or \"rgn2\" got \"${type}\"`\n );\n }\n\n const region = DownloadableSoundsRegion.read(samples, chunk);\n if (region) {\n instrument.regions.push(region);\n }\n }\n SpessaSynthGroupEnd();\n return instrument;\n }\n\n public static fromSFPreset(preset: BasicPreset, samples: BasicSample[]) {\n const instrument = new DownloadableSoundsInstrument();\n instrument.name = preset.name;\n instrument.bankLSB = preset.bankLSB;\n instrument.bankMSB = preset.bankMSB;\n instrument.program = preset.program;\n instrument.isGMGSDrum = preset.isGMGSDrum;\n SpessaSynthGroup(\n `%cConverting %c${preset.toString()}%c to DLS...`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info\n );\n\n // Combine preset and instrument zones into a single instrument zone (region) list\n const inst = preset.toFlattenedInstrument();\n\n inst.zones.forEach((z) => {\n instrument.regions.push(\n DownloadableSoundsRegion.fromSFZone(z, samples)\n );\n });\n SpessaSynthGroupEnd();\n return instrument;\n }\n\n public write() {\n SpessaSynthGroupCollapsed(\n `%cWriting %c${this.name}%c...`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n const chunks = [this.writeHeader()];\n\n const regionChunks = this.regions.map((r) => r.write());\n chunks.push(writeRIFFChunkParts(\"lrgn\", regionChunks, true));\n\n // This will mostly be false as SF2 -> DLS can't have both global and local regions,\n // So it only has global, hence this check.\n if (this.articulation.length > 0) {\n chunks.push(this.articulation.write());\n }\n\n // Write the name\n const inam = writeRIFFChunkRaw(\"INAM\", getStringBytes(this.name, true));\n chunks.push(writeRIFFChunkRaw(\"INFO\", inam, false, true));\n SpessaSynthGroupEnd();\n return writeRIFFChunkParts(\"ins \", chunks, true);\n }\n\n /**\n * Performs the full DLS to SF2 instrument conversion.\n */\n public toSFPreset(soundBank: BasicSoundBank) {\n const preset = new BasicPreset(soundBank);\n preset.name = this.name;\n preset.bankMSB = this.bankMSB;\n preset.bankLSB = this.bankLSB;\n preset.isGMGSDrum = this.isGMGSDrum;\n preset.program = this.program;\n\n const instrument = new BasicInstrument();\n instrument.name = this.name;\n preset.createZone(instrument);\n\n // Global articulation\n this.articulation.toSFZone(instrument.globalZone);\n\n this.regions.forEach((region) =>\n region.toSFZone(instrument, soundBank.samples)\n );\n\n // Globalize!\n instrument.globalize();\n\n // Override reverb and chorus with 1000 instead of 200\n // Reverb\n if (\n instrument.globalZone.modulators.find(\n (m) => m.destination === generatorTypes.reverbEffectsSend\n ) === undefined\n ) {\n instrument.globalZone.addModulators(\n Modulator.copyFrom(DEFAULT_DLS_REVERB)\n );\n }\n // Chorus\n if (\n instrument.globalZone.modulators.find(\n (m) => m.destination === generatorTypes.chorusEffectsSend\n ) === undefined\n ) {\n instrument.globalZone.addModulators(\n Modulator.copyFrom(DEFAULT_DLS_CHORUS)\n );\n }\n\n // Remove generators with default values\n instrument.globalZone.generators =\n instrument.globalZone.generators.filter(\n (g) => g.generatorValue !== generatorLimits[g.generatorType].def\n );\n\n soundBank.addPresets(preset);\n soundBank.addInstruments(instrument);\n }\n\n private writeHeader() {\n // Insh: instrument header\n const inshData = new IndexedByteArray(12);\n writeDword(inshData, this.regions.length); // CRegions\n // Bank MSB is in bits 8-14\n let ulBank = ((this.bankMSB & 127) << 8) | (this.bankLSB & 127);\n // Bit 32 means drums\n if (this.isGMGSDrum) {\n ulBank |= 1 << 31;\n }\n writeDword(inshData, ulBank); // UlBank\n writeDword(inshData, this.program & 127); // UlInstrument\n\n return writeRIFFChunkRaw(\"insh\", inshData);\n }\n}\n","import { DLSVerifier } from \"./dls_verifier\";\nimport { DownloadableSoundsSample } from \"./sample\";\nimport { DownloadableSoundsInstrument } from \"./instrument\";\nimport type {\n DLSInfoFourCC,\n DLSWriteOptions,\n SF2VersionTag,\n SoundBankInfoData,\n SoundBankInfoFourCC\n} from \"../types\";\nimport { IndexedByteArray } from \"../../utils/indexed_array\";\nimport { consoleColors } from \"../../utils/other\";\nimport {\n findRIFFListType,\n readRIFFChunk,\n RIFFChunk,\n writeRIFFChunkParts,\n writeRIFFChunkRaw\n} from \"../../utils/riff_chunk\";\nimport {\n getStringBytes,\n readBinaryStringIndexed\n} from \"../../utils/byte_functions/string\";\nimport { parseDateString } from \"../../utils/load_date\";\nimport {\n readLittleEndianIndexed,\n writeDword\n} from \"../../utils/byte_functions/little_endian\";\nimport {\n SpessaSynthGroup,\n SpessaSynthGroupCollapsed,\n SpessaSynthGroupEnd,\n SpessaSynthInfo,\n SpessaSynthWarn\n} from \"../../utils/loggin\";\nimport { BasicSoundBank } from \"../basic_soundbank/basic_soundbank\";\nimport { BankSelectHacks } from \"../../utils/midi_hacks\";\nimport { DownloadableSoundsRegion } from \"./region\";\n\nexport const DEFAULT_DLS_OPTIONS: DLSWriteOptions = {\n progressFunction: undefined\n};\n\nexport class DownloadableSounds extends DLSVerifier {\n public readonly samples = new Array<DownloadableSoundsSample>();\n public readonly instruments = new Array<DownloadableSoundsInstrument>();\n public soundBankInfo: SoundBankInfoData = {\n name: \"Unnamed\",\n creationDate: new Date(),\n software: \"SpessaSynth\",\n soundEngine: \"DLS Level 2.2\",\n version: {\n major: 2,\n minor: 4\n }\n };\n\n public static read(buffer: ArrayBuffer): DownloadableSounds {\n if (!buffer) {\n throw new Error(\"No data provided!\");\n }\n const dataArray = new IndexedByteArray(buffer);\n SpessaSynthGroup(\"%cParsing DLS file...\", consoleColors.info);\n\n // Read the main chunk\n const firstChunk = readRIFFChunk(dataArray, false);\n this.verifyHeader(firstChunk, \"RIFF\");\n this.verifyText(\n readBinaryStringIndexed(dataArray, 4).toLowerCase(),\n \"dls \"\n );\n\n /**\n * Read the list\n */\n const chunks: RIFFChunk[] = [];\n while (dataArray.currentIndex < dataArray.length) {\n chunks.push(readRIFFChunk(dataArray));\n }\n\n const dls = new DownloadableSounds();\n\n // Set some defaults\n dls.soundBankInfo.name = \"Unnamed DLS\";\n dls.soundBankInfo.product = \"SpessaSynth DLS\";\n dls.soundBankInfo.comment = \"(no description)\";\n\n // Read info\n const infoChunk = findRIFFListType(chunks, \"INFO\");\n if (infoChunk) {\n while (infoChunk.data.currentIndex < infoChunk.data.length) {\n const infoPart = readRIFFChunk(infoChunk.data);\n const headerTyped = infoPart.header as DLSInfoFourCC;\n const text = readBinaryStringIndexed(\n infoPart.data,\n infoPart.size\n );\n switch (headerTyped) {\n case \"INAM\":\n dls.soundBankInfo.name = text;\n break;\n\n case \"ICRD\":\n dls.soundBankInfo.creationDate = parseDateString(text);\n break;\n\n case \"ICMT\":\n dls.soundBankInfo.comment = text;\n break;\n\n case \"ISBJ\":\n dls.soundBankInfo.subject = text;\n break;\n\n case \"ICOP\":\n dls.soundBankInfo.copyright = text;\n break;\n\n case \"IENG\":\n dls.soundBankInfo.engineer = text;\n break;\n\n case \"IPRD\":\n dls.soundBankInfo.product = text;\n break;\n\n case \"ISFT\":\n dls.soundBankInfo.software = text;\n }\n }\n }\n\n this.printInfo(dls);\n\n // Read \"colh\"\n const colhChunk = chunks.find((c) => c.header === \"colh\");\n if (!colhChunk) {\n this.parsingError(\"No colh chunk!\");\n return 5 as never;\n }\n const instrumentAmount = readLittleEndianIndexed(colhChunk.data, 4);\n SpessaSynthInfo(\n `%cInstruments amount: %c${instrumentAmount}`,\n consoleColors.info,\n consoleColors.recognized\n );\n\n // Read the wave list\n const waveListChunk = findRIFFListType(chunks, \"wvpl\");\n if (!waveListChunk) {\n this.parsingError(\"No wvpl chunk!\");\n return 5 as never;\n }\n const waveList = this.verifyAndReadList(waveListChunk, \"wvpl\");\n waveList.forEach((wave) => {\n dls.samples.push(DownloadableSoundsSample.read(wave));\n });\n\n // Read the instrument list\n const instrumentListChunk = findRIFFListType(chunks, \"lins\");\n if (!instrumentListChunk) {\n this.parsingError(\"No lins chunk!\");\n return 5 as never;\n }\n const instruments = this.verifyAndReadList(instrumentListChunk, \"lins\");\n SpessaSynthGroupCollapsed(\n \"%cLoading instruments...\",\n consoleColors.info\n );\n if (instruments.length !== instrumentAmount) {\n SpessaSynthWarn(\n `Colh reported invalid amount of instruments. Detected ${instruments.length}, expected ${instrumentAmount}`\n );\n }\n instruments.forEach((ins) => {\n dls.instruments.push(\n DownloadableSoundsInstrument.read(dls.samples, ins)\n );\n });\n SpessaSynthGroupEnd();\n\n /*\n MobileBAE Instrument aliasing\n https://github.com/spessasus/spessasynth_core/issues/14\n https://lpcwiki.miraheze.org/wiki/MobileBAE#Proprietary_instrument_aliasing_chunk\n http://onj3.andrelouis.com/phonetones/Software%20and%20Soundbanks/Soundbanks/Beatnik%20mobileBAE/\n */\n const aliasingChunk = chunks.find((c) => c.header === \"pgal\");\n if (aliasingChunk) {\n SpessaSynthInfo(\n \"%cFound the instrument aliasing chunk!\",\n consoleColors.recognized\n );\n const pgalData = aliasingChunk.data;\n // Check for the unused 4 bytes at the start\n // If the bank starts with 02 00 00 00, skip them\n if (\n pgalData[0] === 2 &&\n pgalData[1] + pgalData[2] + pgalData[3] === 0\n ) {\n pgalData.currentIndex += 4;\n }\n // Read the drum alias\n const drumInstrument = dls.instruments.find(\n (i) => BankSelectHacks.isXGDrums(i.bankMSB) || i.isGMGSDrum\n );\n if (!drumInstrument) {\n SpessaSynthWarn(\n \"MobileBAE aliasing chunk without a drum preset. Aborting!\"\n );\n return dls;\n }\n const drumAliases = pgalData.slice(\n pgalData.currentIndex,\n pgalData.currentIndex + 128\n );\n pgalData.currentIndex += 128;\n for (let keyNum = 0; keyNum < 128; keyNum++) {\n const alias = drumAliases[keyNum];\n if (alias === keyNum) {\n // Skip the same aliases\n continue;\n }\n const region = drumInstrument.regions.find(\n (r) => r.keyRange.max === alias && r.keyRange.min === alias\n );\n if (!region) {\n SpessaSynthWarn(\n `Invalid drum alias ${keyNum} to ${alias}: region does not exist.`\n );\n continue;\n }\n const copied = DownloadableSoundsRegion.copyFrom(region);\n copied.keyRange.max = keyNum;\n copied.keyRange.min = keyNum;\n drumInstrument.regions.push(copied);\n }\n // 4 bytes: Unknown purpose, 'footer'.\n pgalData.currentIndex += 4;\n while (pgalData.currentIndex < pgalData.length) {\n const aliasBankNum = readLittleEndianIndexed(pgalData, 2);\n // Little-endian 16-bit value (only 14 bits used): Upper 7 bits: Bank MSB, lower 7 bits: Bank LSB\n const aliasBankLSB = aliasBankNum & 0x7f;\n const aliasBankMSB = (aliasBankNum >> 7) & 0x7f;\n const aliasProgram = pgalData[pgalData.currentIndex++];\n let nullByte = pgalData[pgalData.currentIndex++];\n if (nullByte !== 0) {\n SpessaSynthWarn(\n `Invalid alias byte. Expected 0, got ${nullByte}`\n );\n }\n const inputBankNum = readLittleEndianIndexed(pgalData, 2);\n const inputBankLSB = inputBankNum & 0x7f;\n const inputBankMSB = (inputBankNum >> 7) & 0x7f;\n const inputProgram = pgalData[pgalData.currentIndex++];\n nullByte = pgalData[pgalData.currentIndex++];\n if (nullByte !== 0) {\n SpessaSynthWarn(\n `Invalid alias header. Expected 0, got ${nullByte}`\n );\n }\n\n const inputInstrument = dls.instruments.find(\n (inst) =>\n inst.bankLSB === inputBankLSB &&\n inst.bankMSB === inputBankMSB &&\n inst.program === inputProgram &&\n !inst.isGMGSDrum\n );\n if (!inputInstrument) {\n SpessaSynthWarn(\n `Invalid alias. Missing instrument: ${inputBankLSB}:${inputBankMSB}:${inputProgram}`\n );\n continue;\n }\n\n const alias =\n DownloadableSoundsInstrument.copyFrom(inputInstrument);\n alias.bankMSB = aliasBankMSB;\n alias.bankLSB = aliasBankLSB;\n alias.program = aliasProgram;\n dls.instruments.push(alias);\n }\n }\n\n SpessaSynthInfo(\n `%cParsing finished! %c\"${dls.soundBankInfo.name || \"UNNAMED\"}\"%c has %c${dls.instruments.length}%c instruments and %c${dls.samples.length}%c samples.`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n SpessaSynthGroupEnd();\n return dls;\n }\n\n /**\n * Performs a full conversion from BasicSoundBank to DownloadableSounds.\n */\n public static fromSF(bank: BasicSoundBank) {\n SpessaSynthGroupCollapsed(\n \"%cSaving SF2 to DLS level 2...\",\n consoleColors.info\n );\n const dls = new DownloadableSounds();\n dls.soundBankInfo = { ...bank.soundBankInfo };\n dls.soundBankInfo.comment =\n (dls.soundBankInfo.comment ?? \"(No description)\") +\n \"\\nConverted from SF2 to DLS with SpessaSynth\";\n\n bank.samples.forEach((s) => {\n dls.samples.push(DownloadableSoundsSample.fromSFSample(s));\n });\n bank.presets.forEach((p) => {\n dls.instruments.push(\n DownloadableSoundsInstrument.fromSFPreset(p, bank.samples)\n );\n });\n\n SpessaSynthInfo(\"%cConversion complete!\", consoleColors.recognized);\n SpessaSynthGroupEnd();\n return dls;\n }\n\n private static printInfo(dls: DownloadableSounds) {\n for (const [info, value] of Object.entries(dls.soundBankInfo)) {\n if (typeof value === \"object\" && \"major\" in value) {\n const v = value as SF2VersionTag;\n SpessaSynthInfo(\n `%c${info}: %c\"${v.major}.${v.minor}\"`,\n consoleColors.info,\n consoleColors.recognized\n );\n }\n SpessaSynthInfo(\n `%c${info}: %c${(value as string | Date).toLocaleString()}`,\n consoleColors.info,\n consoleColors.recognized\n );\n }\n }\n\n /**\n * Writes an SF2 file\n * @param options\n */\n public async write(options: DLSWriteOptions = DEFAULT_DLS_OPTIONS) {\n SpessaSynthGroupCollapsed(\"%cSaving DLS...\", consoleColors.info);\n // Write colh\n const colhNum = new IndexedByteArray(4);\n writeDword(colhNum, this.instruments.length);\n const colh = writeRIFFChunkRaw(\"colh\", colhNum);\n SpessaSynthGroupCollapsed(\n \"%cWriting instruments...\",\n consoleColors.info\n );\n\n const lins = writeRIFFChunkParts(\n \"lins\",\n this.instruments.map((i) => i.write()),\n true\n );\n SpessaSynthInfo(\"%cSuccess!\", consoleColors.recognized);\n SpessaSynthGroupEnd();\n\n SpessaSynthGroupCollapsed(\n \"%cWriting WAVE samples...\",\n consoleColors.info\n );\n\n let currentIndex = 0;\n const ptblOffsets = [];\n const samples: IndexedByteArray[] = [];\n let written = 0;\n for (const s of this.samples) {\n const out = s.write();\n await options?.progressFunction?.(\n s.name,\n written,\n this.samples.length\n );\n ptblOffsets.push(currentIndex);\n currentIndex += out.length;\n samples.push(out);\n written++;\n }\n const wvpl = writeRIFFChunkParts(\"wvpl\", samples, true);\n SpessaSynthInfo(\"%cSucceeded!\", consoleColors.recognized);\n\n // Write ptbl\n const ptblData = new IndexedByteArray(8 + 4 * ptblOffsets.length);\n writeDword(ptblData, 8);\n writeDword(ptblData, ptblOffsets.length);\n for (const offset of ptblOffsets) {\n writeDword(ptblData, offset);\n }\n const ptbl = writeRIFFChunkRaw(\"ptbl\", ptblData);\n this.soundBankInfo.software = \"SpessaSynth\"; // ( ͡° ͜ʖ ͡°)\n\n // Write INFO\n const infos: Uint8Array[] = [];\n\n const writeDLSInfo = (type: DLSInfoFourCC, data: string) => {\n infos.push(writeRIFFChunkRaw(type, getStringBytes(data, true)));\n };\n\n for (const [t, d] of Object.entries(this.soundBankInfo)) {\n const type = t as SoundBankInfoFourCC;\n const data = d as SoundBankInfoData[SoundBankInfoFourCC];\n if (!data) {\n continue;\n }\n switch (type) {\n case \"name\":\n writeDLSInfo(\"INAM\", data as string);\n break;\n\n case \"comment\":\n writeDLSInfo(\"ICMT\", data as string);\n break;\n\n case \"copyright\":\n writeDLSInfo(\"ICOP\", data as string);\n break;\n\n case \"creationDate\":\n writeDLSInfo(\"ICRD\", (data as Date).toISOString());\n break;\n\n case \"engineer\":\n writeDLSInfo(\"IENG\", data as string);\n break;\n\n case \"product\":\n writeDLSInfo(\"IPRD\", data as string);\n break;\n\n case \"romVersion\":\n case \"version\":\n case \"soundEngine\":\n case \"romInfo\":\n // Not writable\n break;\n\n case \"software\":\n writeDLSInfo(\"ISFT\", data as string);\n break;\n\n case \"subject\":\n writeDLSInfo(\"ISBJ\", data as string);\n }\n }\n const info = writeRIFFChunkParts(\"INFO\", infos, true);\n\n SpessaSynthInfo(\"%cCombining everything...\");\n const out = writeRIFFChunkParts(\"RIFF\", [\n getStringBytes(\"DLS \"),\n colh,\n lins,\n ptbl,\n wvpl,\n info\n ]);\n\n SpessaSynthInfo(\"%cSaved successfully!\", consoleColors.recognized);\n SpessaSynthGroupEnd();\n return out.buffer;\n }\n\n /**\n * Performs a full conversion from DownloadableSounds to BasicSoundBank.\n */\n public toSF(): BasicSoundBank {\n SpessaSynthGroup(\"%cConverting DLS to SF2...\", consoleColors.info);\n const soundBank = new BasicSoundBank();\n\n soundBank.soundBankInfo.version.minor = 4;\n soundBank.soundBankInfo.version.major = 2;\n soundBank.soundBankInfo = { ...this.soundBankInfo };\n soundBank.soundBankInfo.comment =\n (soundBank.soundBankInfo.comment ?? \"(No description)\") +\n \"\\nConverted from DLS to SF2 with SpessaSynth\";\n\n this.samples.forEach((sample) => {\n sample.toSFSample(soundBank);\n });\n\n this.instruments.forEach((instrument) => {\n instrument.toSFPreset(soundBank);\n });\n soundBank.flush();\n\n SpessaSynthInfo(\"%cConversion complete!\", consoleColors.recognized);\n SpessaSynthGroupEnd();\n return soundBank;\n }\n}\n","import { SpessaSynthGroup, SpessaSynthGroupCollapsed, SpessaSynthGroupEnd, SpessaSynthInfo } from \"../../utils/loggin\";\nimport { consoleColors } from \"../../utils/other\";\nimport { DEFAULT_SF2_WRITE_OPTIONS, writeSF2Internal } from \"../soundfont/write/write\";\nimport { Modulator, SPESSASYNTH_DEFAULT_MODULATORS } from \"./modulator\";\nimport { BasicSample, EmptySample } from \"./basic_sample\";\nimport { Generator } from \"./generator\";\nimport { BasicInstrument } from \"./basic_instrument\";\nimport { BasicPreset } from \"./basic_preset\";\nimport { BankSelectHacks } from \"../../utils/midi_hacks\";\nimport { stbvorbis } from \"../../externals/stbvorbis_sync/stbvorbis_wrapper\";\nimport type { BasicMIDI } from \"../../midi/basic_midi\";\n\nimport type { DLSWriteOptions, SF2VersionTag, SoundBankInfoData, SoundFont2WriteOptions } from \"../types\";\nimport { generatorTypes } from \"./generator_types\";\nimport type { SynthSystem } from \"../../synthesizer/types\";\nimport { selectPreset } from \"./preset_selector\";\nimport { type MIDIPatch, MIDIPatchTools } from \"./midi_patch\";\nimport { DEFAULT_DLS_OPTIONS, DownloadableSounds } from \"../downloadable_sounds/downloadable_sounds\";\n\n/**\n * Represents a single sound bank, be it DLS or SF2.\n */\nexport class BasicSoundBank {\n /**\n * Indicates if the SF3/SF2Pack decoder is ready.\n */\n public static isSF3DecoderReady: Promise<boolean> = stbvorbis.isInitialized;\n\n /**\n * Sound bank's info.\n */\n public soundBankInfo: SoundBankInfoData = {\n name: \"Unnamed\",\n creationDate: new Date(),\n software: \"SpessaSynth\",\n soundEngine: \"E-mu 10K2\",\n version: {\n major: 2,\n minor: 4\n }\n };\n\n /**\n * The sound bank's presets.\n */\n public presets: BasicPreset[] = [];\n\n /**\n * The sound bank's samples.\n */\n public samples: BasicSample[] = [];\n\n /**\n * The sound bank's instruments.\n */\n public instruments: BasicInstrument[] = [];\n\n /**\n * Sound bank's default modulators.\n */\n public defaultModulators: Modulator[] = SPESSASYNTH_DEFAULT_MODULATORS.map(\n Modulator.copyFrom.bind(Modulator)\n );\n\n /**\n * If the sound bank has custom default modulators (DMOD).\n */\n public customDefaultModulators = false;\n\n private _isXGBank = false;\n\n /**\n * Checks for XG drum sets and considers if this sound bank is XG.\n */\n public get isXGBank() {\n return this._isXGBank;\n }\n\n /**\n * Merges sound banks with the given order. Keep in mind that the info read is copied from the first one\n * @param soundBanks the sound banks to merge, the first overwrites the last\n */\n public static mergeSoundBanks(\n ...soundBanks: BasicSoundBank[]\n ): BasicSoundBank {\n const mainSf = soundBanks.shift();\n if (!mainSf) {\n throw new Error(\"No sound banks provided!\");\n }\n const presets = mainSf.presets;\n while (soundBanks.length) {\n const newPresets = soundBanks?.shift()?.presets;\n if (newPresets) {\n newPresets.forEach((newPreset) => {\n if (\n presets.find((existingPreset) =>\n newPreset.matches(existingPreset)\n ) === undefined\n ) {\n presets.push(newPreset);\n }\n });\n }\n }\n\n const b = new BasicSoundBank();\n b.addCompletePresets(presets);\n b.soundBankInfo = { ...mainSf.soundBankInfo };\n return b;\n }\n\n /**\n * Creates a simple sound bank with one saw wave preset.\n */\n public static async getSampleSoundBankFile(): Promise<ArrayBuffer> {\n const font = new BasicSoundBank();\n const sampleData = new Float32Array(128);\n for (let i = 0; i < 128; i++) {\n sampleData[i] = (i / 128) * 2 - 1;\n }\n const sample = new EmptySample();\n sample.name = \"Saw\";\n sample.originalKey = 65;\n sample.pitchCorrection = 20;\n sample.loopEnd = 127;\n sample.setAudioData(sampleData, 44100);\n font.addSamples(sample);\n\n const inst = new BasicInstrument();\n inst.name = \"Saw Wave\";\n inst.globalZone.addGenerators(\n new Generator(generatorTypes.initialAttenuation, 375),\n new Generator(generatorTypes.releaseVolEnv, -1000),\n new Generator(generatorTypes.sampleModes, 1)\n );\n\n inst.createZone(sample);\n const zone2 = inst.createZone(sample);\n zone2.addGenerators(new Generator(generatorTypes.fineTune, -9));\n\n font.addInstruments(inst);\n\n const preset = new BasicPreset(font);\n preset.name = \"Saw Wave\";\n preset.createZone(inst);\n\n font.addPresets(preset);\n\n font.soundBankInfo.name = \"Dummy\";\n font.flush();\n return await font.writeSF2();\n }\n\n /**\n * Copies a given sound bank.\n * @param bank The sound bank to copy.\n */\n public static copyFrom(bank: BasicSoundBank) {\n const copied = new BasicSoundBank();\n bank.presets.forEach((p) => copied.clonePreset(p));\n copied.soundBankInfo = { ...bank.soundBankInfo };\n return copied;\n }\n\n /**\n * Adds complete presets along with their instruments and samples.\n * @param presets The presets to add.\n */\n public addCompletePresets(presets: BasicPreset[]) {\n this.addPresets(...presets);\n const instrumentList: BasicInstrument[] = [];\n for (const preset of presets) {\n for (const zone of preset.zones) {\n if (\n zone.instrument &&\n !instrumentList.includes(zone.instrument)\n ) {\n instrumentList.push(zone.instrument);\n }\n }\n }\n this.addInstruments(...instrumentList);\n\n const sampleList: BasicSample[] = [];\n\n for (const instrument of instrumentList) {\n for (const zone of instrument.zones) {\n if (zone.sample && !sampleList.includes(zone.sample)) {\n sampleList.push(zone.sample);\n }\n }\n }\n this.addSamples(...sampleList);\n }\n\n /**\n * Write the sound bank as a .dls file. This may not be 100% accurate.\n * @param options - options for writing the file.\n * @returns the binary file.\n */\n public async writeDLS(\n options: Partial<DLSWriteOptions> = DEFAULT_DLS_OPTIONS\n ): Promise<ArrayBuffer> {\n const dls = DownloadableSounds.fromSF(this);\n return dls.write(options);\n }\n\n /**\n * Writes the sound bank as an SF2 file.\n * @param writeOptions the options for writing.\n * @returns the binary file data.\n */\n public async writeSF2(\n writeOptions: Partial<SoundFont2WriteOptions> = DEFAULT_SF2_WRITE_OPTIONS\n ): Promise<ArrayBuffer> {\n return writeSF2Internal(this, writeOptions);\n }\n\n public addPresets(...presets: BasicPreset[]) {\n this.presets.push(...presets);\n }\n\n public addInstruments(...instruments: BasicInstrument[]) {\n this.instruments.push(...instruments);\n }\n\n public addSamples(...samples: BasicSample[]) {\n this.samples.push(...samples);\n }\n\n /**\n * Clones a sample into this bank.\n * @param sample The sample to copy.\n * @returns the copied sample, if a sample exists with that name, it is returned instead\n */\n public cloneSample(sample: BasicSample): BasicSample {\n const duplicate = this.samples.find((s) => s.name === sample.name);\n if (duplicate) {\n return duplicate;\n }\n const newSample = new BasicSample(\n sample.name,\n sample.sampleRate,\n sample.originalKey,\n sample.pitchCorrection,\n sample.sampleType,\n sample.loopStart,\n sample.loopEnd\n );\n if (sample.isCompressed) {\n newSample.setCompressedData(sample.getRawData(true));\n } else {\n newSample.setAudioData(sample.getAudioData(), sample.sampleRate);\n }\n this.addSamples(newSample);\n if (sample.linkedSample) {\n const clonedLinked = this.cloneSample(sample.linkedSample);\n // Sanity check\n if (!clonedLinked.linkedSample) {\n newSample.setLinkedSample(clonedLinked, newSample.sampleType);\n }\n }\n return newSample;\n }\n\n /**\n * Recursively clones an instrument into this sound bank, as well as its samples.\n * @returns the copied instrument, if an instrument exists with that name, it is returned instead.\n */\n public cloneInstrument(instrument: BasicInstrument): BasicInstrument {\n const duplicate = this.instruments.find(\n (i) => i.name === instrument.name\n );\n if (duplicate) {\n return duplicate;\n }\n const newInstrument = new BasicInstrument();\n newInstrument.name = instrument.name;\n newInstrument.globalZone.copyFrom(instrument.globalZone);\n for (const zone of instrument.zones) {\n const copiedZone = newInstrument.createZone(\n this.cloneSample(zone.sample)\n );\n copiedZone.copyFrom(zone);\n }\n this.addInstruments(newInstrument);\n return newInstrument;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Recursively clones a preset into this sound bank, as well as its instruments and samples.\n * @returns the copied preset, if a preset exists with that name, it is returned instead.\n */\n public clonePreset(preset: BasicPreset): BasicPreset {\n const duplicate = this.presets.find((p) => p.name === preset.name);\n if (duplicate) {\n return duplicate;\n }\n const newPreset = new BasicPreset(this);\n newPreset.name = preset.name;\n newPreset.bankMSB = preset.bankMSB;\n newPreset.bankLSB = preset.bankLSB;\n newPreset.isGMGSDrum = preset.isGMGSDrum;\n newPreset.program = preset.program;\n newPreset.library = preset.library;\n newPreset.genre = preset.genre;\n newPreset.morphology = preset.morphology;\n newPreset.globalZone.copyFrom(preset.globalZone);\n for (const zone of preset.zones) {\n const copiedZone = newPreset.createZone(\n this.cloneInstrument(zone.instrument)\n );\n copiedZone.copyFrom(zone);\n }\n\n this.addPresets(newPreset);\n return newPreset;\n }\n\n /**\n * Updates internal values.\n */\n public flush() {\n this.presets.sort(MIDIPatchTools.sorter.bind(MIDIPatchTools));\n this.parseInternal();\n }\n\n /**\n * Trims a sound bank to only contain samples in a given MIDI file.\n * @param mid - the MIDI file\n */\n public trimSoundBank(mid: BasicMIDI) {\n const trimInstrumentZones = (\n instrument: BasicInstrument,\n combos: { key: number; velocity: number }[]\n ): number => {\n let trimmedIZones = 0;\n for (\n let iZoneIndex = 0;\n iZoneIndex < instrument.zones.length;\n iZoneIndex++\n ) {\n const iZone = instrument.zones[iZoneIndex];\n const iKeyRange = iZone.keyRange;\n const iVelRange = iZone.velRange;\n let isIZoneUsed = false;\n for (const iCombo of combos) {\n if (\n iCombo.key >= iKeyRange.min &&\n iCombo.key <= iKeyRange.max &&\n iCombo.velocity >= iVelRange.min &&\n iCombo.velocity <= iVelRange.max\n ) {\n isIZoneUsed = true;\n break;\n }\n }\n if (!isIZoneUsed && iZone.sample) {\n SpessaSynthInfo(\n `%c${iZone.sample.name}%c removed from %c${instrument.name}%c.`,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n if (instrument.deleteZone(iZoneIndex)) {\n trimmedIZones++;\n iZoneIndex--;\n SpessaSynthInfo(\n `%c${iZone.sample.name}%c deleted`,\n consoleColors.recognized,\n consoleColors.info\n );\n }\n if (iZone.sample.useCount < 1) {\n this.deleteSample(iZone.sample);\n }\n }\n }\n return trimmedIZones;\n };\n\n SpessaSynthGroup(\"%cTrimming sound bank...\", consoleColors.info);\n const usedProgramsAndKeys = mid.getUsedProgramsAndKeys(this);\n\n SpessaSynthGroupCollapsed(\n \"%cModifying sound bank...\",\n consoleColors.info\n );\n SpessaSynthInfo(\"Detected keys for midi:\", usedProgramsAndKeys);\n // Modify the sound bank to only include programs and samples that are used\n for (\n let presetIndex = 0;\n presetIndex < this.presets.length;\n presetIndex++\n ) {\n const p = this.presets[presetIndex];\n const used = usedProgramsAndKeys.get(p);\n if (used === undefined) {\n SpessaSynthInfo(\n `%cDeleting preset %c${p.name}%c and its zones`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n this.deletePreset(p);\n presetIndex--;\n } else {\n const combos = [...used].map((s) => {\n const split = s.split(\"-\");\n return {\n key: parseInt(split[0]),\n velocity: parseInt(split[1])\n };\n });\n SpessaSynthGroupCollapsed(\n `%cTrimming %c${p.name}`,\n consoleColors.info,\n consoleColors.recognized\n );\n SpessaSynthInfo(`Keys for ${p.name}:`, combos);\n let trimmedZones = 0;\n // Clean the preset to only use zones that are used\n for (\n let zoneIndex = 0;\n zoneIndex < p.zones.length;\n zoneIndex++\n ) {\n const zone = p.zones[zoneIndex];\n const keyRange = zone.keyRange;\n const velRange = zone.velRange;\n // Check if any of the combos matches the zone\n let isZoneUsed = false;\n for (const combo of combos) {\n if (\n combo.key >= keyRange.min &&\n combo.key <= keyRange.max &&\n combo.velocity >= velRange.min &&\n combo.velocity <= velRange.max &&\n zone.instrument\n ) {\n // Zone is used, trim the instrument zones\n isZoneUsed = true;\n const trimmedIZones = trimInstrumentZones(\n zone.instrument,\n combos\n );\n SpessaSynthInfo(\n `%cTrimmed off %c${trimmedIZones}%c zones from %c${zone.instrument.name}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n break;\n }\n }\n if (!isZoneUsed && zone.instrument) {\n trimmedZones++;\n p.deleteZone(zoneIndex);\n if (zone.instrument.useCount < 1) {\n this.deleteInstrument(zone.instrument);\n }\n zoneIndex--;\n }\n }\n SpessaSynthInfo(\n `%cTrimmed off %c${trimmedZones}%c zones from %c${p.name}`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized\n );\n SpessaSynthGroupEnd();\n }\n }\n this.removeUnusedElements();\n\n SpessaSynthInfo(\"%cSound bank modified!\", consoleColors.recognized);\n SpessaSynthGroupEnd();\n SpessaSynthGroupEnd();\n }\n\n public removeUnusedElements() {\n this.instruments = this.instruments.filter((i) => {\n i.deleteUnusedZones();\n const deletable = i.useCount < 1;\n if (deletable) {\n i.delete();\n }\n return !deletable;\n });\n this.samples = this.samples.filter((s) => {\n const deletable = s.useCount < 1;\n if (deletable) {\n s.unlinkSample();\n }\n return !deletable;\n });\n }\n\n public deleteInstrument(instrument: BasicInstrument) {\n instrument.delete();\n this.instruments.splice(this.instruments.indexOf(instrument), 1);\n }\n\n public deletePreset(preset: BasicPreset) {\n preset.delete();\n this.presets.splice(this.presets.indexOf(preset), 1);\n }\n\n public deleteSample(sample: BasicSample) {\n sample.unlinkSample();\n this.samples.splice(this.samples.indexOf(sample), 1);\n }\n\n /**\n * Get the appropriate preset.\n */\n public getPreset(patch: MIDIPatch, system: SynthSystem): BasicPreset {\n return selectPreset(this.presets, patch, system);\n }\n\n public destroySoundBank() {\n this.presets.length = 0;\n this.instruments.length = 0;\n this.samples.length = 0;\n }\n\n protected parsingError(error: string) {\n throw new Error(\n `SF parsing error: ${error} The file may be corrupted.`\n );\n }\n\n /**\n * Parses the bank after loading is done\n * @protected\n */\n protected parseInternal() {\n this._isXGBank = false;\n // Definitions for XG:\n // At least one preset with bank 127, 126 or 120\n // MUST be a valid XG bank.\n // Allowed banks: (see XG specification)\n // Note: XG spec numbers the programs from 1...\n const allowedPrograms = new Set([\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 24, 25, 26, 27, 28, 29, 30,\n 31, 32, 33, 40, 41, 48, 56, 57, 58, 64, 65, 66, 126, 127\n ]);\n for (const preset of this.presets) {\n if (BankSelectHacks.isXGDrums(preset.bankMSB)) {\n this._isXGBank = true;\n if (!allowedPrograms.has(preset.program)) {\n // Not valid!\n this._isXGBank = false;\n SpessaSynthInfo(\n `%cThis bank is not valid XG. Preset %c${preset.toString()}%c is not a valid XG drum. XG mode will use presets on bank 128.`,\n consoleColors.info,\n consoleColors.value,\n consoleColors.info\n );\n break;\n }\n }\n }\n }\n\n protected printInfo() {\n for (const [info, value] of Object.entries(this.soundBankInfo)) {\n if (typeof value === \"object\" && \"major\" in value) {\n const v = value as SF2VersionTag;\n SpessaSynthInfo(\n `%c${info}: %c\"${v.major}.${v.minor}\"`,\n consoleColors.info,\n consoleColors.recognized\n );\n }\n SpessaSynthInfo(\n `%c${info}: %c${(value as string | Date).toLocaleString()}`,\n consoleColors.info,\n consoleColors.recognized\n );\n }\n }\n}\n","import { IndexedByteArray } from \"../../../utils/indexed_array\";\nimport { RIFFChunk } from \"../../../utils/riff_chunk\";\nimport { signedInt16 } from \"../../../utils/byte_functions/little_endian\";\nimport { Generator } from \"../../basic_soundbank/generator\";\nimport type { GeneratorType } from \"../../basic_soundbank/generator_types\";\n\nexport class ReadGenerator extends Generator {\n /**\n * Creates a generator\n */\n public constructor(dataArray: IndexedByteArray) {\n // Note: We skip validation here as some sf2 files use invalid values that end up being correct after applying limits at the modulator level.\n // Test case: LiveHQ Natural soundfont GM, \"Brass\" preset (negative attenuation with quiet samples)\n // 4 bytes:\n // Type, type, type, value\n const i = dataArray.currentIndex;\n const generatorType = ((dataArray[i + 1] << 8) |\n dataArray[i]) as GeneratorType;\n const generatorValue = signedInt16(dataArray[i + 2], dataArray[i + 3]);\n dataArray.currentIndex += 4;\n super(generatorType, generatorValue, false);\n }\n}\n\n/**\n * Reads the generators\n */\nexport function readGenerators(generatorChunk: RIFFChunk): Generator[] {\n const gens = [];\n while (generatorChunk.data.length > generatorChunk.data.currentIndex) {\n gens.push(new ReadGenerator(generatorChunk.data));\n }\n // Remove terminal\n gens.pop();\n return gens;\n}\n","import { BasicPresetZone } from \"../../basic_soundbank/basic_preset_zone\";\nimport { Generator } from \"../../basic_soundbank/generator\";\nimport { Modulator } from \"../../basic_soundbank/modulator\";\nimport type { BasicPreset } from \"../../basic_soundbank/basic_preset\";\nimport type { BasicInstrument } from \"../../basic_soundbank/basic_instrument\";\nimport type { SoundFontPreset } from \"./presets\";\nimport { generatorTypes } from \"../../basic_soundbank/generator_types\";\n\n/**\n * Preset_zones.ts\n * purpose: reads preset zones from soundfont and gets their respective samples and generators and modulators\n */\n\nexport class SoundFontPresetZone extends BasicPresetZone {\n /**\n * Creates a zone (preset)\n */\n public constructor(\n preset: BasicPreset,\n modulators: Modulator[],\n generators: Generator[],\n instruments: BasicInstrument[]\n ) {\n const instrumentID = generators.find(\n (g) => g.generatorType === generatorTypes.instrument\n );\n let instrument = undefined;\n if (instrumentID) {\n instrument = instruments[instrumentID.generatorValue];\n } else {\n throw new Error(\"No instrument ID found in preset zone.\");\n }\n super(preset, instrument);\n this.addGenerators(...generators);\n this.addModulators(...modulators);\n }\n}\n\n/**\n * Reads the given preset zone\n */\nexport function applyPresetZones(\n indexes: { mod: number[]; gen: number[] },\n presetGens: Generator[],\n presetMods: Modulator[],\n instruments: BasicInstrument[],\n presets: SoundFontPreset[]\n) {\n const genStartIndexes = indexes.gen;\n const modStartIndexes = indexes.mod;\n\n let modIndex = 0;\n let genIndex = 0;\n for (const preset of presets) {\n for (let i = 0; i < preset.zonesCount; i++) {\n const gensStart = genStartIndexes[genIndex++];\n const gensEnd = genStartIndexes[genIndex];\n const gens = presetGens.slice(gensStart, gensEnd);\n const modsStart = modStartIndexes[modIndex++];\n const modsEnd = modStartIndexes[modIndex];\n const mods = presetMods.slice(modsStart, modsEnd);\n // Check for global zone\n if (\n gens.find(\n (g) => g.generatorType === generatorTypes.instrument\n ) !== undefined\n ) {\n // Regular zone\n preset.createSoundFontZone(mods, gens, instruments);\n } else {\n // global zone\n preset.globalZone.addGenerators(...gens);\n preset.globalZone.addModulators(...mods);\n }\n }\n }\n}\n","import { RIFFChunk } from \"../../../utils/riff_chunk\";\nimport { readLittleEndianIndexed } from \"../../../utils/byte_functions/little_endian\";\nimport { readBinaryStringIndexed } from \"../../../utils/byte_functions/string\";\nimport { BasicPreset } from \"../../basic_soundbank/basic_preset\";\nimport { SoundFontPresetZone } from \"./preset_zones\";\nimport type { BasicSoundBank } from \"../../basic_soundbank/basic_soundbank\";\nimport type { BasicInstrument } from \"../../basic_soundbank/basic_instrument\";\nimport type { Modulator } from \"../../basic_soundbank/modulator\";\nimport type { Generator } from \"../../basic_soundbank/generator\";\n\n/**\n * Parses soundfont presets, also includes function for getting the generators and samples from midi note and velocity\n */\n\nexport class SoundFontPreset extends BasicPreset {\n public zoneStartIndex: number;\n public zonesCount = 0;\n\n /**\n * Creates a preset\n */\n public constructor(presetChunk: RIFFChunk, sf2: BasicSoundBank) {\n super(sf2);\n this.name = readBinaryStringIndexed(presetChunk.data, 20).replace(\n /\\d{3}:\\d{3}/,\n \"\"\n ); // Remove those pesky \"000:001\"\n\n this.program = readLittleEndianIndexed(presetChunk.data, 2);\n const wBank = readLittleEndianIndexed(presetChunk.data, 2);\n this.bankMSB = wBank & 0x7f;\n this.isGMGSDrum = (wBank & 0x80) > 0;\n this.bankLSB = wBank >> 8;\n\n this.zoneStartIndex = readLittleEndianIndexed(presetChunk.data, 2);\n\n // Read the dword\n this.library = readLittleEndianIndexed(presetChunk.data, 4);\n this.genre = readLittleEndianIndexed(presetChunk.data, 4);\n this.morphology = readLittleEndianIndexed(presetChunk.data, 4);\n }\n\n public createSoundFontZone(\n modulators: Modulator[],\n generators: Generator[],\n instruments: BasicInstrument[]\n ): SoundFontPresetZone {\n const z = new SoundFontPresetZone(\n this,\n modulators,\n generators,\n instruments\n );\n this.zones.push(z);\n return z;\n }\n}\n\n/**\n * Reads the presets\n */\nexport function readPresets(\n presetChunk: RIFFChunk,\n parent: BasicSoundBank\n): SoundFontPreset[] {\n const presets: SoundFontPreset[] = [];\n while (presetChunk.data.length > presetChunk.data.currentIndex) {\n const preset = new SoundFontPreset(presetChunk, parent);\n if (presets.length > 0) {\n const previous = presets[presets.length - 1];\n previous.zonesCount =\n preset.zoneStartIndex - previous.zoneStartIndex;\n }\n presets.push(preset);\n }\n // Remove EOP\n presets.pop();\n return presets;\n}\n","/**\n * Instrument_zones.ts\n * purpose: reads instrument zones from soundfont and gets their respective samples and generators and modulators\n */\nimport { BasicInstrumentZone } from \"../../basic_soundbank/basic_instrument_zone\";\nimport type { SoundFontInstrument } from \"./instruments\";\nimport type { BasicSample } from \"../../basic_soundbank/basic_sample\";\nimport type { Modulator } from \"../../basic_soundbank/modulator\";\nimport type { Generator } from \"../../basic_soundbank/generator\";\nimport type { BasicInstrument } from \"../../basic_soundbank/basic_instrument\";\nimport { generatorTypes } from \"../../basic_soundbank/generator_types\";\n\nexport class SoundFontInstrumentZone extends BasicInstrumentZone {\n /**\n * Creates a zone (instrument)\n */\n public constructor(\n inst: BasicInstrument,\n modulators: Modulator[],\n generators: Generator[],\n samples: BasicSample[]\n ) {\n const sampleID = generators.find(\n (g) => g.generatorType === generatorTypes.sampleID\n );\n let sample = undefined;\n if (sampleID) {\n sample = samples[sampleID.generatorValue];\n } else {\n throw new Error(\"No sample ID found in instrument zone.\");\n }\n super(inst, sample);\n this.addGenerators(...generators);\n this.addModulators(...modulators);\n }\n}\n\n/**\n * Reads the given instrument zone\n */\nexport function applyInstrumentZones(\n indexes: { mod: number[]; gen: number[] },\n instrumentGenerators: Generator[],\n instrumentModulators: Modulator[],\n samples: BasicSample[],\n instruments: SoundFontInstrument[]\n) {\n const genStartIndexes = indexes.gen;\n const modStartIndexes = indexes.mod;\n\n let modIndex = 0;\n let genIndex = 0;\n for (const instrument of instruments) {\n for (let i = 0; i < instrument.zonesCount; i++) {\n const gensStart = genStartIndexes[genIndex++];\n const gensEnd = genStartIndexes[genIndex];\n const gens = instrumentGenerators.slice(gensStart, gensEnd);\n const modsStart = modStartIndexes[modIndex++];\n const modsEnd = modStartIndexes[modIndex];\n const mods = instrumentModulators.slice(modsStart, modsEnd);\n // Check for global zone\n if (gens.find((g) => g.generatorType === generatorTypes.sampleID)) {\n // Regular zone\n instrument.createSoundFontZone(mods, gens, samples);\n } else {\n // global zone\n instrument.globalZone.addGenerators(...gens);\n instrument.globalZone.addModulators(...mods);\n }\n }\n }\n}\n","import { RIFFChunk } from \"../../../utils/riff_chunk\";\nimport { readLittleEndianIndexed } from \"../../../utils/byte_functions/little_endian\";\nimport { readBinaryStringIndexed } from \"../../../utils/byte_functions/string\";\nimport { BasicInstrument } from \"../../basic_soundbank/basic_instrument\";\n\nimport { SoundFontInstrumentZone } from \"./instrument_zones\";\nimport type { BasicSample } from \"../../basic_soundbank/basic_sample\";\nimport type { Modulator } from \"../../basic_soundbank/modulator\";\nimport type { Generator } from \"../../basic_soundbank/generator\";\n\n/**\n * Instrument.ts\n * purpose: parses soundfont instrument and stores them as a class\n */\n\nexport class SoundFontInstrument extends BasicInstrument {\n public zoneStartIndex: number;\n\n public zonesCount = 0;\n\n /**\n * Creates an instrument\n */\n public constructor(instrumentChunk: RIFFChunk) {\n super();\n this.name = readBinaryStringIndexed(instrumentChunk.data, 20);\n this.zoneStartIndex = readLittleEndianIndexed(instrumentChunk.data, 2);\n }\n\n public createSoundFontZone(\n modulators: Modulator[],\n generators: Generator[],\n samples: BasicSample[]\n ): SoundFontInstrumentZone {\n const z = new SoundFontInstrumentZone(\n this,\n modulators,\n generators,\n samples\n );\n this.zones.push(z);\n return z;\n }\n}\n\n/**\n * Reads the instruments\n */\nexport function readInstruments(\n instrumentChunk: RIFFChunk\n): SoundFontInstrument[] {\n const instruments: SoundFontInstrument[] = [];\n while (instrumentChunk.data.length > instrumentChunk.data.currentIndex) {\n const instrument = new SoundFontInstrument(instrumentChunk);\n\n if (instruments.length > 0) {\n const previous = instruments[instruments.length - 1];\n previous.zonesCount =\n instrument.zoneStartIndex - previous.zoneStartIndex;\n }\n instruments.push(instrument);\n }\n // Remove EOI\n instruments.pop();\n return instruments;\n}\n","import {\n readLittleEndianIndexed,\n signedInt16\n} from \"../../../utils/byte_functions/little_endian\";\nimport { DecodedModulator, Modulator } from \"../../basic_soundbank/modulator\";\nimport type { RIFFChunk } from \"../../../utils/riff_chunk\";\nimport type { GeneratorType } from \"../../basic_soundbank/generator_types\";\n\n/**\n * Reads the modulator read\n */\nexport function readModulators(modulatorChunk: RIFFChunk): Modulator[] {\n const mods = [];\n while (modulatorChunk.data.length > modulatorChunk.data.currentIndex) {\n const dataArray = modulatorChunk.data;\n const sourceEnum = readLittleEndianIndexed(dataArray, 2);\n const destination = readLittleEndianIndexed(dataArray, 2);\n const amount = signedInt16(\n dataArray[dataArray.currentIndex++],\n dataArray[dataArray.currentIndex++]\n );\n const secondarySourceEnum = readLittleEndianIndexed(dataArray, 2);\n const transformType = readLittleEndianIndexed(dataArray, 2);\n mods.push(\n new DecodedModulator(\n sourceEnum,\n secondarySourceEnum,\n destination as GeneratorType,\n amount,\n transformType\n )\n );\n }\n // Remove terminal\n mods.pop();\n return mods;\n}\n","import { readLittleEndianIndexed } from \"../../../utils/byte_functions/little_endian\";\nimport type { RIFFChunk } from \"../../../utils/riff_chunk\";\n\n/**\n * @param zonesChunk both pbag and ibag work\n */\nexport function readZoneIndexes(zonesChunk: RIFFChunk): {\n mod: number[];\n gen: number[];\n} {\n const modStartIndexes: number[] = [];\n const genStartIndexes: number[] = [];\n\n while (zonesChunk.data.length > zonesChunk.data.currentIndex) {\n genStartIndexes.push(readLittleEndianIndexed(zonesChunk.data, 2));\n modStartIndexes.push(readLittleEndianIndexed(zonesChunk.data, 2));\n }\n return {\n mod: modStartIndexes,\n gen: genStartIndexes\n };\n}\n","import { IndexedByteArray } from \"../../../utils/indexed_array\";\nimport { readSamples } from \"./samples\";\nimport { readLittleEndianIndexed } from \"../../../utils/byte_functions/little_endian\";\nimport { readGenerators } from \"./generators\";\nimport { applyPresetZones } from \"./preset_zones\";\nimport { readPresets } from \"./presets\";\nimport { readInstruments } from \"./instruments\";\nimport { readModulators } from \"./modulators\";\nimport { readRIFFChunk, RIFFChunk } from \"../../../utils/riff_chunk\";\nimport { consoleColors } from \"../../../utils/other\";\nimport { SpessaSynthGroup, SpessaSynthGroupEnd, SpessaSynthInfo } from \"../../../utils/loggin\";\nimport { readBinaryString, readBinaryStringIndexed } from \"../../../utils/byte_functions/string\";\nimport { stbvorbis } from \"../../../externals/stbvorbis_sync/stbvorbis_wrapper\";\nimport { BasicSoundBank } from \"../../basic_soundbank/basic_soundbank\";\nimport { applyInstrumentZones } from \"./instrument_zones\";\nimport { readZoneIndexes } from \"./zones\";\nimport type { SF2InfoFourCC } from \"../../types\";\nimport type { Generator } from \"../../basic_soundbank/generator\";\nimport type { Modulator } from \"../../basic_soundbank/modulator\";\nimport { parseDateString } from \"../../../utils/load_date\";\nimport { BankSelectHacks } from \"../../../utils/midi_hacks\";\n\n/**\n * Soundfont.ts\n * purpose: parses a soundfont2 file\n */\n\nexport class SoundFont2 extends BasicSoundBank {\n protected sampleDataStartIndex = 0;\n\n /**\n * Initializes a new SoundFont2 Parser and parses the given data array\n */\n public constructor(arrayBuffer: ArrayBuffer, warnDeprecated = true) {\n super();\n if (warnDeprecated) {\n throw new Error(\n \"Using the constructor directly is deprecated. Use SoundBankLoader.fromArrayBuffer() instead.\"\n );\n }\n const mainFileArray = new IndexedByteArray(arrayBuffer);\n SpessaSynthGroup(\"%cParsing a SoundFont2 file...\", consoleColors.info);\n if (!mainFileArray) {\n SpessaSynthGroupEnd();\n this.parsingError(\"No data provided!\");\n }\n\n // Read the main chunk\n const firstChunk = readRIFFChunk(mainFileArray, false);\n this.verifyHeader(firstChunk, \"riff\");\n\n const type = readBinaryStringIndexed(mainFileArray, 4).toLowerCase();\n if (type !== \"sfbk\" && type !== \"sfpk\") {\n SpessaSynthGroupEnd();\n throw new SyntaxError(\n `Invalid soundFont! Expected \"sfbk\" or \"sfpk\" got \"${type}\"`\n );\n }\n /*\n Some SF2Pack description:\n this is essentially sf2, but the entire smpl chunk is compressed (we only support Ogg Vorbis here)\n and the only other difference is that the main chunk isn't \"sfbk\" but rather \"sfpk\"\n */\n const isSF2Pack = type === \"sfpk\";\n\n // INFO\n const infoChunk = readRIFFChunk(mainFileArray);\n this.verifyHeader(infoChunk, \"list\");\n const infoString = readBinaryStringIndexed(infoChunk.data, 4);\n if (infoString !== \"INFO\") {\n SpessaSynthGroupEnd();\n throw new SyntaxError(\n `Invalid soundFont! Expected \"INFO\" or \"${infoString}\"`\n );\n }\n\n let xdtaChunk: RIFFChunk | undefined = undefined;\n\n while (infoChunk.data.length > infoChunk.data.currentIndex) {\n const chunk = readRIFFChunk(infoChunk.data);\n const text = readBinaryString(chunk.data, chunk.data.length);\n // Special cases\n const headerTyped = chunk.header as SF2InfoFourCC;\n switch (headerTyped) {\n case \"ifil\":\n case \"iver\":\n const major = readLittleEndianIndexed(chunk.data, 2);\n const minor = readLittleEndianIndexed(chunk.data, 2);\n if (headerTyped === \"ifil\") {\n this.soundBankInfo.version = {\n major,\n minor\n };\n } else {\n this.soundBankInfo.romVersion = {\n major,\n minor\n };\n }\n break;\n\n // Dmod: default modulators\n case \"DMOD\": {\n // Override default modulators\n this.defaultModulators = readModulators(chunk);\n this.customDefaultModulators = true;\n break;\n }\n\n case \"LIST\": {\n // Possible xdta\n const listType = readBinaryStringIndexed(chunk.data, 4);\n if (listType === \"xdta\") {\n SpessaSynthInfo(\n \"%cExtended SF2 found!\",\n consoleColors.recognized\n );\n xdtaChunk = chunk;\n }\n break;\n }\n\n case \"ICRD\":\n this.soundBankInfo.creationDate = parseDateString(\n readBinaryStringIndexed(chunk.data, chunk.data.length)\n );\n break;\n\n case \"ISFT\":\n this.soundBankInfo.software = text;\n break;\n\n case \"IPRD\":\n this.soundBankInfo.product = text;\n break;\n\n case \"IENG\":\n this.soundBankInfo.engineer = text;\n break;\n\n case \"ICOP\":\n this.soundBankInfo.copyright = text;\n break;\n\n case \"INAM\":\n this.soundBankInfo.name = text;\n break;\n\n case \"ICMT\":\n this.soundBankInfo.comment = text;\n break;\n\n case \"irom\":\n this.soundBankInfo.romInfo = text;\n break;\n\n case \"isng\":\n this.soundBankInfo.soundEngine = text;\n }\n }\n this.printInfo();\n // https://github.com/spessasus/soundfont-proposals/blob/main/extended_limits.md\n const xChunks: Partial<{\n phdr: RIFFChunk;\n pbag: RIFFChunk;\n pmod: RIFFChunk;\n pgen: RIFFChunk;\n inst: RIFFChunk;\n ibag: RIFFChunk;\n imod: RIFFChunk;\n igen: RIFFChunk;\n shdr: RIFFChunk;\n }> = {};\n if (xdtaChunk !== undefined) {\n // Read the hydra chunks\n xChunks.phdr = readRIFFChunk(xdtaChunk.data);\n xChunks.pbag = readRIFFChunk(xdtaChunk.data);\n xChunks.pmod = readRIFFChunk(xdtaChunk.data);\n xChunks.pgen = readRIFFChunk(xdtaChunk.data);\n xChunks.inst = readRIFFChunk(xdtaChunk.data);\n xChunks.ibag = readRIFFChunk(xdtaChunk.data);\n xChunks.imod = readRIFFChunk(xdtaChunk.data);\n xChunks.igen = readRIFFChunk(xdtaChunk.data);\n xChunks.shdr = readRIFFChunk(xdtaChunk.data);\n }\n\n // SDTA\n const sdtaChunk = readRIFFChunk(mainFileArray, false);\n this.verifyHeader(sdtaChunk, \"list\");\n this.verifyText(readBinaryStringIndexed(mainFileArray, 4), \"sdta\");\n\n // Smpl\n SpessaSynthInfo(\"%cVerifying smpl chunk...\", consoleColors.warn);\n const sampleDataChunk = readRIFFChunk(mainFileArray, false);\n this.verifyHeader(sampleDataChunk, \"smpl\");\n let sampleData: IndexedByteArray | Float32Array;\n // SF2Pack: the entire data is compressed\n if (isSF2Pack) {\n SpessaSynthInfo(\n \"%cSF2Pack detected, attempting to decode the smpl chunk...\",\n consoleColors.info\n );\n try {\n sampleData = stbvorbis.decode(\n mainFileArray.buffer.slice(\n mainFileArray.currentIndex,\n mainFileArray.currentIndex + sdtaChunk.size - 12\n )\n ).data[0];\n } catch (e) {\n SpessaSynthGroupEnd();\n throw new Error(\n `SF2Pack Ogg Vorbis decode error: ${e as Error}`\n );\n }\n SpessaSynthInfo(\n `%cDecoded the smpl chunk! Length: %c${sampleData.length}`,\n consoleColors.info,\n consoleColors.value\n );\n } else {\n sampleData = mainFileArray;\n this.sampleDataStartIndex = mainFileArray.currentIndex;\n }\n\n SpessaSynthInfo(\n `%cSkipping sample chunk, length: %c${sdtaChunk.size - 12}`,\n consoleColors.info,\n consoleColors.value\n );\n mainFileArray.currentIndex += sdtaChunk.size - 12;\n\n // PDTA\n SpessaSynthInfo(\"%cLoading preset data chunk...\", consoleColors.warn);\n const presetChunk = readRIFFChunk(mainFileArray);\n this.verifyHeader(presetChunk, \"list\");\n readBinaryStringIndexed(presetChunk.data, 4);\n\n // Read the hydra chunks\n const phdrChunk = readRIFFChunk(presetChunk.data);\n this.verifyHeader(phdrChunk, \"phdr\");\n\n const pbagChunk = readRIFFChunk(presetChunk.data);\n this.verifyHeader(pbagChunk, \"pbag\");\n\n const pmodChunk = readRIFFChunk(presetChunk.data);\n this.verifyHeader(pmodChunk, \"pmod\");\n\n const pgenChunk = readRIFFChunk(presetChunk.data);\n this.verifyHeader(pgenChunk, \"pgen\");\n\n const instChunk = readRIFFChunk(presetChunk.data);\n this.verifyHeader(instChunk, \"inst\");\n\n const ibagChunk = readRIFFChunk(presetChunk.data);\n this.verifyHeader(ibagChunk, \"ibag\");\n\n const imodChunk = readRIFFChunk(presetChunk.data);\n this.verifyHeader(imodChunk, \"imod\");\n\n const igenChunk = readRIFFChunk(presetChunk.data);\n this.verifyHeader(igenChunk, \"igen\");\n\n const shdrChunk = readRIFFChunk(presetChunk.data);\n this.verifyHeader(shdrChunk, \"shdr\");\n\n SpessaSynthInfo(\"%cParsing samples...\", consoleColors.info);\n\n /**\n * Read all the samples\n * (the current index points to start of the smpl read)\n */\n mainFileArray.currentIndex = this.sampleDataStartIndex;\n const samples = readSamples(\n shdrChunk,\n sampleData,\n xdtaChunk === undefined\n );\n\n if (xdtaChunk && xChunks.shdr) {\n // Apply extensions to samples\n const xSamples = readSamples(\n xChunks.shdr,\n new Float32Array(1),\n false\n );\n if (xSamples.length === samples.length) {\n samples.forEach((s, i) => {\n s.name += xSamples[i].name;\n s.linkedSampleIndex |= xSamples[i].linkedSampleIndex << 16;\n });\n }\n }\n // Trim names\n samples.forEach((s) => (s.name = s.name.trim()));\n this.samples.push(...samples);\n\n /**\n * Read all the instrument generators\n */\n const instrumentGenerators: Generator[] = readGenerators(igenChunk);\n\n /**\n * Read all the instrument modulators\n */\n const instrumentModulators: Modulator[] = readModulators(imodChunk);\n\n const instruments = readInstruments(instChunk);\n\n if (xdtaChunk && xChunks.inst) {\n // Apply extensions to instruments\n const xInst = readInstruments(xChunks.inst);\n if (xInst.length === instruments.length) {\n instruments.forEach((inst, i) => {\n inst.name += xInst[i].name;\n inst.zoneStartIndex |= xInst[i].zoneStartIndex;\n });\n // Adjust zone counts\n instruments.forEach((inst, i) => {\n if (i < instruments.length - 1) {\n inst.zonesCount =\n instruments[i + 1].zoneStartIndex -\n inst.zoneStartIndex;\n }\n });\n }\n }\n // Trim names\n instruments.forEach((i) => (i.name = i.name.trim()));\n this.instruments.push(...instruments);\n\n const ibagIndexes = readZoneIndexes(ibagChunk);\n\n if (xdtaChunk && xChunks.ibag) {\n const extraIndexes = readZoneIndexes(xChunks.ibag);\n for (let i = 0; i < ibagIndexes.mod.length; i++) {\n ibagIndexes.mod[i] |= extraIndexes.mod[i] << 16;\n }\n for (let i = 0; i < ibagIndexes.gen.length; i++) {\n ibagIndexes.gen[i] |= extraIndexes.gen[i] << 16;\n }\n }\n\n /**\n * Read all the instrument zones (and apply them)\n */\n applyInstrumentZones(\n ibagIndexes,\n instrumentGenerators,\n instrumentModulators,\n this.samples,\n instruments\n );\n\n /**\n * Read all the preset generators\n */\n const presetGenerators: Generator[] = readGenerators(pgenChunk);\n\n /**\n * Read all the preset modulators\n */\n const presetModulators: Modulator[] = readModulators(pmodChunk);\n\n const presets = readPresets(phdrChunk, this);\n\n if (xdtaChunk && xChunks.phdr) {\n // Apply extensions to presets\n const xPreset = readPresets(xChunks.phdr, this);\n if (xPreset.length === presets.length) {\n presets.forEach((pres, i) => {\n pres.name += xPreset[i].name;\n pres.zoneStartIndex |= xPreset[i].zoneStartIndex;\n });\n // Adjust zone counts\n presets.forEach((preset, i) => {\n if (i < presets.length - 1) {\n preset.zonesCount =\n presets[i + 1].zoneStartIndex -\n preset.zoneStartIndex;\n }\n });\n }\n }\n\n // Trim names\n presets.forEach((p) => p.name === p.name.trim());\n this.addPresets(...presets);\n\n const pbagIndexes = readZoneIndexes(pbagChunk);\n\n if (xdtaChunk && xChunks.pbag) {\n const extraIndexes = readZoneIndexes(xChunks.pbag);\n for (let i = 0; i < pbagIndexes.mod.length; i++) {\n pbagIndexes.mod[i] |= extraIndexes.mod[i] << 16;\n }\n for (let i = 0; i < pbagIndexes.gen.length; i++) {\n pbagIndexes.gen[i] |= extraIndexes.gen[i] << 16;\n }\n }\n\n applyPresetZones(\n pbagIndexes,\n presetGenerators,\n presetModulators,\n this.instruments,\n presets\n );\n\n // Shadow presets with LSB (for XG)\n const hasLSB = this.presets.some((p) => p.bankLSB > 0);\n if (!hasLSB) {\n SpessaSynthInfo(\"%cCopying MSB to LSBs...\", consoleColors.info);\n for (const preset of this.presets) {\n if (!BankSelectHacks.isValidXGMSB(preset.bankMSB)) {\n preset.bankLSB = preset.bankMSB;\n }\n }\n }\n this.flush();\n SpessaSynthInfo(\n `%cParsing finished! %c\"${this.soundBankInfo.name}\"%c has %c${this.presets.length}%c presets,\n %c${this.instruments.length}%c instruments and %c${this.samples.length}%c samples.`,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info,\n consoleColors.recognized,\n consoleColors.info\n );\n SpessaSynthGroupEnd();\n }\n\n protected verifyHeader(chunk: RIFFChunk, expected: string) {\n if (chunk.header.toLowerCase() !== expected.toLowerCase()) {\n SpessaSynthGroupEnd();\n this.parsingError(\n `Invalid chunk header! Expected \"${expected.toLowerCase()}\" got \"${chunk.header.toLowerCase()}\"`\n );\n }\n }\n\n protected verifyText(text: string, expected: string) {\n if (text.toLowerCase() !== expected.toLowerCase()) {\n SpessaSynthGroupEnd();\n this.parsingError(\n `Invalid FourCC: Expected \"${expected.toLowerCase()}\" got \"${text.toLowerCase()}\"\\``\n );\n }\n }\n}\n","import { BasicSoundBank } from \"./basic_soundbank/basic_soundbank\";\nimport { IndexedByteArray } from \"../utils/indexed_array\";\nimport { readBinaryStringIndexed } from \"../utils/byte_functions/string\";\nimport { SoundFont2 } from \"./soundfont/read/soundfont\";\nimport { DownloadableSounds } from \"./downloadable_sounds/downloadable_sounds\";\n\nexport class SoundBankLoader {\n /**\n * Loads a sound bank from a file buffer.\n * @param buffer The binary file buffer to load.\n * @returns The loaded sound bank, a BasicSoundBank instance.\n */\n public static fromArrayBuffer(buffer: ArrayBuffer): BasicSoundBank {\n const check = buffer.slice(8, 12);\n const a = new IndexedByteArray(check);\n const id = readBinaryStringIndexed(a, 4).toLowerCase();\n if (id === \"dls \") {\n return this.loadDLS(buffer);\n }\n return new SoundFont2(buffer, false);\n }\n\n private static loadDLS(buffer: ArrayBuffer) {\n const dls = DownloadableSounds.read(buffer);\n return dls.toSF();\n }\n}\n","import { SpessaSynthInfo } from \"../utils/loggin\";\nimport { consoleColors } from \"../utils/other\";\nimport {\n DEFAULT_SYNTH_METHOD_OPTIONS,\n EMBEDDED_SOUND_BANK_ID,\n MIDI_CHANNEL_COUNT\n} from \"./audio_engine/engine_components/synth_constants\";\nimport { stbvorbis } from \"../externals/stbvorbis_sync/stbvorbis_wrapper\";\nimport { VOLUME_ENVELOPE_SMOOTHING_FACTOR } from \"./audio_engine/engine_components/dsp_chain/volume_envelope\";\nimport {\n getAllMasterParametersInternal,\n getMasterParameterInternal,\n setMasterParameterInternal\n} from \"./audio_engine/engine_methods/controller_control/master_parameters\";\nimport { SoundBankManager } from \"./audio_engine/engine_components/sound_bank_manager\";\nimport { PAN_SMOOTHING_FACTOR } from \"./audio_engine/engine_components/dsp_chain/stereo_panner\";\nimport { FILTER_SMOOTHING_FACTOR } from \"./audio_engine/engine_components/dsp_chain/lowpass_filter\";\nimport { getEvent } from \"../midi/midi_message\";\nimport { IndexedByteArray } from \"../utils/indexed_array\";\nimport { DEFAULT_SYNTH_OPTIONS } from \"./audio_engine/engine_components/synth_processor_options\";\nimport { fillWithDefaults } from \"../utils/fill_with_defaults\";\nimport { killVoicesIntenral } from \"./audio_engine/engine_methods/stopping_notes/voice_killing\";\nimport { getVoicesForPresetInternal, getVoicesInternal } from \"./audio_engine/engine_components/voice\";\nimport { systemExclusiveInternal } from \"./audio_engine/engine_methods/system_exclusive\";\nimport { resetAllControllersInternal } from \"./audio_engine/engine_methods/controller_control/reset_controllers\";\nimport { SynthesizerSnapshot } from \"./audio_engine/snapshot/synthesizer_snapshot\";\nimport type {\n SynthMethodOptions,\n SynthProcessorEvent,\n SynthProcessorEventData,\n SynthProcessorOptions,\n VoiceList\n} from \"./types\";\nimport { type MIDIController, type MIDIMessageType, midiMessageTypes } from \"../midi/enums\";\nimport { ProtectedSynthValues } from \"./audio_engine/engine_components/internal_synth_values\";\nimport { KeyModifierManager } from \"./audio_engine/engine_components/key_modifier_manager\";\nimport { MIDIChannel } from \"./audio_engine/engine_components/midi_channel\";\nimport { SoundBankLoader } from \"../soundbank/sound_bank_loader\";\nimport { customControllers } from \"./enums\";\nimport type { MIDIPatch } from \"../soundbank/basic_soundbank/midi_patch\";\n\n/**\n * Processor.ts\n * purpose: the core synthesis engine\n */\n\n// The core synthesis engine of spessasynth.\nexport class SpessaSynthProcessor {\n // The sound bank manager, which manages all sound banks and presets.\n public soundBankManager: SoundBankManager = new SoundBankManager(\n this.updatePresetList.bind(this)\n );\n\n /**\n * All MIDI channels of the synthesizer.\n */\n public midiChannels: MIDIChannel[] = [];\n\n /**\n * Handles the custom key overrides: velocity and preset\n */\n public keyModifierManager: KeyModifierManager = new KeyModifierManager();\n\n /**\n * Current total amount of voices that are currently playing.\n */\n public totalVoicesAmount = 0;\n /**\n * Controls if the processor is fully initialized.\n */\n public readonly processorInitialized: Promise<boolean> =\n stbvorbis.isInitialized;\n /**\n * The current time of the synthesizer, in seconds. You probably should not modify this directly.\n */\n public currentSynthTime = 0;\n /**\n * Sample rate in Hertz.\n */\n public readonly sampleRate: number;\n /**\n * Are the chorus and reverb effects enabled?\n */\n public enableEffects = true;\n\n /**\n * Is the event system enabled?\n */\n public enableEventSystem: boolean;\n\n /**\n * Calls when an event occurs.\n * @param event The event that occurred.\n */\n public onEventCall?: (event: SynthProcessorEvent) => unknown;\n\n /**\n * Executes a system exclusive message for the synthesizer.\n * @param syx The system exclusive message as an array of bytes.\n * @param channelOffset The channel offset to apply (default is 0).\n */\n public readonly systemExclusive: typeof systemExclusiveInternal =\n systemExclusiveInternal.bind(this) as typeof systemExclusiveInternal;\n /**\n * Executes a full system reset of all controllers.\n * This will reset all controllers to their default values,\n * except for the locked controllers.\n */\n public readonly resetAllControllers: typeof resetAllControllersInternal =\n resetAllControllersInternal.bind(\n this\n ) as typeof resetAllControllersInternal;\n /**\n * Sets a master parameter of the synthesizer.\n * @param type The type of the master parameter to set.\n * @param value The value to set for the master parameter.\n */\n public readonly setMasterParameter: typeof setMasterParameterInternal =\n setMasterParameterInternal.bind(\n this\n ) as typeof setMasterParameterInternal;\n // noinspection JSUnusedGlobalSymbols\n /**\n * Gets a master parameter of the synthesizer.\n * @param type The type of the master parameter to get.\n * @returns The value of the master parameter.\n */\n public readonly getMasterParameter: typeof getMasterParameterInternal =\n getMasterParameterInternal.bind(\n this\n ) as typeof getMasterParameterInternal;\n /**\n * Gets all master parameters of the synthesizer.\n * @returns All the master parameters.\n */\n public readonly getAllMasterParameters: typeof getAllMasterParametersInternal =\n getAllMasterParametersInternal.bind(\n this\n ) as typeof getAllMasterParametersInternal;\n /**\n * Gets voices for a preset.\n * @param preset The preset to get voices for.\n * @param bankMSB The bank to cache the voices in.\n * @param program Program to cache the voices in.\n * @param midiNote The MIDI note to use.\n * @param velocity The velocity to use.\n * @param realKey The real MIDI note if the \"midiNote\" was changed by MIDI Tuning Standard.\n * @returns Output is an array of voices.\n * @remarks\n * This is a public method, but it is only intended to be used by the sequencer.\n */\n public readonly getVoicesForPreset: typeof getVoicesForPresetInternal =\n getVoicesForPresetInternal.bind(\n this\n ) as typeof getVoicesForPresetInternal;\n /**\n * Kills the specified number of voices based on their priority.\n * @param amount The number of voices to remove.\n */\n public readonly killVoices: typeof killVoicesIntenral =\n killVoicesIntenral.bind(this) as typeof killVoicesIntenral;\n // Protected methods\n protected readonly getVoices = getVoicesInternal.bind(this);\n // This contains the properties that have to be accessed from the MIDI channels.\n protected privateProps: ProtectedSynthValues;\n /**\n * Tor applying the snapshot after an override sound bank too.\n */\n protected savedSnapshot?: SynthesizerSnapshot;\n /**\n * Synth's event queue from the main thread\n */\n protected eventQueue: { callback: () => unknown; time: number }[] = [];\n\n // The time of a single sample, in seconds.\n private readonly sampleTime: number;\n\n /**\n * Creates a new synthesizer engine.\n * @param sampleRate sample rate, in Hertz.\n * @param opts the processor's options.\n */\n public constructor(\n sampleRate: number,\n opts: Partial<SynthProcessorOptions> = DEFAULT_SYNTH_OPTIONS\n ) {\n const options: SynthProcessorOptions = fillWithDefaults(\n opts,\n DEFAULT_SYNTH_OPTIONS\n );\n this.enableEffects = options.enableEffects;\n this.enableEventSystem = options.enableEventSystem;\n this.currentSynthTime = options.initialTime;\n this.sampleRate = sampleRate;\n this.sampleTime = 1 / sampleRate;\n if (isNaN(options.initialTime) || isNaN(sampleRate)) {\n throw new Error(\"Initial time or sample rate is NaN!\");\n }\n\n // Initialize the protected synth values\n this.privateProps = new ProtectedSynthValues(\n this.callEvent.bind(this),\n this.getVoices.bind(this),\n this.killVoices.bind(this),\n // These smoothing factors were tested on 44,100 Hz, adjust them to target sample rate here\n // Volume envelope smoothing factor\n VOLUME_ENVELOPE_SMOOTHING_FACTOR * (44100 / sampleRate),\n // Pan smoothing factor\n PAN_SMOOTHING_FACTOR * (44100 / sampleRate),\n // Filter smoothing factor\n FILTER_SMOOTHING_FACTOR * (44100 / sampleRate)\n );\n\n for (let i = 0; i < MIDI_CHANNEL_COUNT; i++) {\n // Don't send events as we're creating the initial channels\n this.createMIDIChannelInternal(false);\n }\n void this.processorInitialized.then(() => {\n SpessaSynthInfo(\n \"%cSpessaSynth is ready!\",\n consoleColors.recognized\n );\n });\n }\n\n /**\n * Applies the snapshot to the synth\n */\n public applySynthesizerSnapshot(snapshot: SynthesizerSnapshot) {\n this.savedSnapshot = snapshot;\n snapshot.apply(this);\n SpessaSynthInfo(\"%cFinished applying snapshot!\", consoleColors.info);\n this.resetAllControllers();\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Gets a synthesizer snapshot from this processor instance.\n */\n public getSnapshot(): SynthesizerSnapshot {\n return SynthesizerSnapshot.create(this);\n }\n\n /**\n * Sets the embedded sound bank.\n * @param bank The sound bank file to set.\n * @param offset The bank offset of the embedded sound bank.\n */\n public setEmbeddedSoundBank(bank: ArrayBuffer, offset: number) {\n // The embedded bank is set as the first bank in the manager,\n // With a special ID that is randomized.\n const loadedFont = SoundBankLoader.fromArrayBuffer(bank);\n this.soundBankManager.addSoundBank(\n loadedFont,\n EMBEDDED_SOUND_BANK_ID,\n offset\n );\n // Rearrange so the embedded is first (most important as it overrides all others)\n const order = this.soundBankManager.priorityOrder;\n order.pop();\n order.unshift(EMBEDDED_SOUND_BANK_ID);\n this.soundBankManager.priorityOrder = order;\n\n // Apply snapshot again if applicable\n if (this.savedSnapshot !== undefined) {\n this.applySynthesizerSnapshot(this.savedSnapshot);\n }\n SpessaSynthInfo(\n `%cEmbedded sound bank set at offset %c${offset}`,\n consoleColors.recognized,\n consoleColors.value\n );\n }\n\n // Removes the embedded sound bank from the synthesizer.\n public clearEmbeddedBank() {\n if (\n this.soundBankManager.soundBankList.some(\n (s) => s.id === EMBEDDED_SOUND_BANK_ID\n )\n ) {\n this.soundBankManager.deleteSoundBank(EMBEDDED_SOUND_BANK_ID);\n }\n }\n\n // Creates a new MIDI channel for the synthesizer.\n public createMIDIChannel() {\n this.createMIDIChannelInternal(true);\n }\n\n /**\n * Stops all notes on all channels.\n * @param force if true, all notes are stopped immediately, otherwise they are stopped gracefully.\n */\n public stopAllChannels(force = false) {\n SpessaSynthInfo(\"%cStop all received!\", consoleColors.info);\n for (const channel of this.midiChannels) {\n channel.stopAllNotes(force);\n }\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Renders float32 audio data to stereo outputs; buffer size of 128 is recommended.\n * All float arrays must have the same length.\n * @param outputs output stereo channels (L, R).\n * @param reverb reverb stereo channels (L, R).\n * @param chorus chorus stereo channels (L, R).\n * @param startIndex start offset of the passed arrays, rendering starts at this index, defaults to 0.\n * @param sampleCount the length of the rendered buffer, defaults to float32array length - startOffset.\n */\n public renderAudio(\n outputs: Float32Array[],\n reverb: Float32Array[],\n chorus: Float32Array[],\n startIndex = 0,\n sampleCount = 0\n ) {\n this.renderAudioSplit(\n reverb,\n chorus,\n Array(16).fill(outputs) as Float32Array[][],\n startIndex,\n sampleCount\n );\n }\n\n /**\n * Renders the float32 audio data of each channel; buffer size of 128 is recommended.\n * All float arrays must have the same length.\n * @param reverbChannels reverb stereo channels (L, R).\n * @param chorusChannels chorus stereo channels (L, R).\n * @param separateChannels a total of 16 stereo pairs (L, R) for each MIDI channel.\n * @param startIndex start offset of the passed arrays, rendering starts at this index, defaults to 0.\n * @param sampleCount the length of the rendered buffer, defaults to float32array length - startOffset.\n */\n public renderAudioSplit(\n reverbChannels: Float32Array[],\n chorusChannels: Float32Array[],\n separateChannels: Float32Array[][],\n startIndex = 0,\n sampleCount = 0\n ) {\n // Process event queue\n const time = this.currentSynthTime;\n while (this.eventQueue[0]?.time <= time) {\n this.eventQueue.shift()?.callback();\n }\n const revL = reverbChannels[0];\n const revR = reverbChannels[1];\n const chrL = chorusChannels[0];\n const chrR = chorusChannels[1];\n\n // Validate\n startIndex = Math.max(startIndex, 0);\n const quantumSize =\n sampleCount || separateChannels[0][0].length - startIndex;\n\n // For every channel\n this.totalVoicesAmount = 0;\n this.midiChannels.forEach((channel, index) => {\n if (channel.voices.length < 1 || channel.isMuted) {\n // There's nothing to do!\n return;\n }\n const voiceCount = channel.voices.length;\n const ch = index % 16;\n\n // Render to the appropriate output\n channel.renderAudio(\n separateChannels[ch][0],\n separateChannels[ch][1],\n revL,\n revR,\n chrL,\n chrR,\n startIndex,\n quantumSize\n );\n\n this.totalVoicesAmount += channel.voices.length;\n // If voice count changed, update voice amount\n if (channel.voices.length !== voiceCount) {\n channel.sendChannelProperty();\n }\n });\n\n // Advance the time appropriately\n this.currentSynthTime += quantumSize * this.sampleTime;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Destroy the synthesizer processor, clearing all channels and voices.\n * This is irreversible, so use with caution.\n */\n public destroySynthProcessor() {\n this.midiChannels.forEach((c) => {\n c.voices.length = 0;\n c.sustainedVoices.length = 0;\n c.lockedControllers = [];\n c.preset = undefined;\n });\n this.clearCache();\n this.midiChannels.length = 0;\n this.soundBankManager.destroy();\n }\n\n /**\n * Executes a MIDI controller change message on the specified channel.\n * @param channel The MIDI channel to change the controller on.\n * @param controllerNumber The MIDI controller number to change.\n * @param controllerValue The value to set the controller to.\n */\n public controllerChange(\n channel: number,\n controllerNumber: MIDIController,\n controllerValue: number\n ) {\n this.midiChannels[channel].controllerChange(\n controllerNumber,\n controllerValue\n );\n }\n\n /**\n * Executes a MIDI Note-on message on the specified channel.\n * @param channel The MIDI channel to send the note on.\n * @param midiNote The MIDI note number to play.\n * @param velocity The velocity of the note, from 0 to 127.\n * @remarks\n * If the velocity is 0, it will be treated as a Note-off message.\n */\n public noteOn(channel: number, midiNote: number, velocity: number) {\n this.midiChannels[channel].noteOn(midiNote, velocity);\n }\n\n /**\n * Executes a MIDI Note-off message on the specified channel.\n * @param channel The MIDI channel to send the note off.\n * @param midiNote The MIDI note number to stop playing.\n */\n public noteOff(channel: number, midiNote: number) {\n this.midiChannels[channel].noteOff(midiNote);\n }\n\n /**\n * Executes a MIDI Poly Pressure (Aftertouch) message on the specified channel.\n * @param channel The MIDI channel to send the poly pressure on.\n * @param midiNote The MIDI note number to apply the pressure to.\n * @param pressure The pressure value, from 0 to 127.\n */\n public polyPressure(channel: number, midiNote: number, pressure: number) {\n this.midiChannels[channel].polyPressure(midiNote, pressure);\n }\n\n /**\n * Executes a MIDI Channel Pressure (Aftertouch) message on the specified channel.\n * @param channel The MIDI channel to send the channel pressure on.\n * @param pressure The pressure value, from 0 to 127.\n */\n public channelPressure(channel: number, pressure: number) {\n this.midiChannels[channel].channelPressure(pressure);\n }\n\n /**\n * Executes a MIDI Pitch Wheel message on the specified channel.\n * @param channel The MIDI channel to send the pitch wheel on.\n * @param pitch The new pitch value: 0-16384\n */\n public pitchWheel(channel: number, pitch: number) {\n this.midiChannels[channel].pitchWheel(pitch);\n }\n\n /**\n * Executes a MIDI Program Change message on the specified channel.\n * @param channel The MIDI channel to send the program change on.\n * @param programNumber The program number to change to, from 0 to 127.\n */\n public programChange(channel: number, programNumber: number) {\n this.midiChannels[channel].programChange(programNumber);\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Processes a raw MIDI message.\n * @param message The message to process.\n * @param channelOffset The channel offset for the message.\n * @param force If true, forces the message to be processed.\n * @param options Additional options for scheduling the message.\n */\n public processMessage(\n message: Uint8Array | number[],\n channelOffset = 0,\n force = false,\n options: SynthMethodOptions = DEFAULT_SYNTH_METHOD_OPTIONS\n ) {\n const call = () => {\n const statusByteData = getEvent(message[0] as MIDIMessageType);\n\n const channel = statusByteData.channel + channelOffset;\n // Process the event\n switch (statusByteData.status as MIDIMessageType) {\n case midiMessageTypes.noteOn: {\n const velocity = message[2];\n if (velocity > 0) {\n this.noteOn(channel, message[1], velocity);\n } else {\n this.noteOff(channel, message[1]);\n }\n break;\n }\n\n case midiMessageTypes.noteOff:\n if (force) {\n this.midiChannels[channel].killNote(message[1]);\n } else {\n this.noteOff(channel, message[1]);\n }\n break;\n\n case midiMessageTypes.pitchWheel:\n // LSB | (MSB << 7)\n this.pitchWheel(channel, (message[2] << 7) | message[1]);\n break;\n\n case midiMessageTypes.controllerChange:\n this.controllerChange(\n channel,\n message[1] as MIDIController,\n message[2]\n );\n break;\n\n case midiMessageTypes.programChange:\n this.programChange(channel, message[1]);\n break;\n\n case midiMessageTypes.polyPressure:\n this.polyPressure(channel, message[0], message[1]);\n break;\n\n case midiMessageTypes.channelPressure:\n this.channelPressure(channel, message[1]);\n break;\n\n case midiMessageTypes.systemExclusive:\n this.systemExclusive(\n new IndexedByteArray(message.slice(1)),\n channelOffset\n );\n break;\n\n case midiMessageTypes.reset:\n this.stopAllChannels(true);\n this.resetAllControllers();\n break;\n\n default:\n break;\n }\n };\n\n const time = options.time;\n if (time > this.currentSynthTime) {\n this.eventQueue.push({\n callback: call.bind(this),\n time: time\n });\n this.eventQueue.sort((e1, e2) => e1.time - e2.time);\n } else {\n call();\n }\n }\n\n // Clears the synthesizer's voice cache.\n public clearCache() {\n this.privateProps.cachedVoices = [];\n }\n\n /**\n * @param volume {number} 0 to 1\n */\n protected setMIDIVolume(volume: number) {\n // GM2 specification, section 4.1: volume is squared.\n // Though, according to my own testing, Math.E seems like a better choice\n this.privateProps.midiVolume = Math.pow(volume, Math.E);\n }\n\n /**\n * Sets the synth's primary tuning.\n * @param cents\n */\n protected setMasterTuning(cents: number) {\n cents = Math.round(cents);\n for (const channel of this.midiChannels) {\n channel.setCustomController(customControllers.masterTuning, cents);\n }\n }\n\n /**\n * Calls synth event\n * @param eventName the event name\n * @param eventData the event data\n */\n protected callEvent<K extends keyof SynthProcessorEventData>(\n eventName: K,\n eventData: SynthProcessorEventData[K]\n ) {\n this.onEventCall?.({\n type: eventName,\n data: eventData\n } as SynthProcessorEvent);\n }\n\n protected getCachedVoice(\n patch: MIDIPatch,\n midiNote: number,\n velocity: number\n ): VoiceList | undefined {\n let bankMSB = patch.bankMSB;\n let bankLSB = patch.bankLSB;\n const { isGMGSDrum, program } = patch;\n if (isGMGSDrum) {\n bankMSB = 128;\n bankLSB = 0;\n }\n return this.privateProps.cachedVoices?.[bankMSB]?.[bankLSB]?.[\n program\n ]?.[midiNote]?.[velocity];\n }\n\n protected setCachedVoice(\n patch: MIDIPatch,\n midiNote: number,\n velocity: number,\n voices: VoiceList\n ) {\n let bankMSB = patch.bankMSB;\n let bankLSB = patch.bankLSB;\n const { isGMGSDrum, program } = patch;\n if (isGMGSDrum) {\n bankMSB = 128;\n bankLSB = 0;\n }\n // Make sure that it exists\n if (!this.privateProps.cachedVoices[bankMSB]) {\n this.privateProps.cachedVoices[bankMSB] = [];\n }\n if (!this.privateProps.cachedVoices[bankMSB][bankLSB]) {\n this.privateProps.cachedVoices[bankMSB][bankLSB] = [];\n }\n if (!this.privateProps.cachedVoices[bankMSB][bankLSB][program]) {\n this.privateProps.cachedVoices[bankMSB][bankLSB][program] = [];\n }\n if (\n !this.privateProps.cachedVoices[bankMSB][bankLSB][program][midiNote]\n ) {\n this.privateProps.cachedVoices[bankMSB][bankLSB][program][\n midiNote\n ] = [];\n }\n\n // Cache\n this.privateProps.cachedVoices[bankMSB][bankLSB][program][midiNote][\n velocity\n ] = voices;\n }\n\n private createMIDIChannelInternal(sendEvent: boolean) {\n const channel: MIDIChannel = new MIDIChannel(\n this,\n this.privateProps,\n this.privateProps.defaultPreset,\n this.midiChannels.length\n );\n this.midiChannels.push(channel);\n if (sendEvent) {\n this.callEvent(\"newChannel\", undefined);\n channel.sendChannelProperty();\n this.midiChannels[this.midiChannels.length - 1].setDrums(true);\n }\n }\n\n private updatePresetList() {\n const mainFont = this.soundBankManager.presetList;\n this.clearCache();\n this.privateProps.callEvent(\"presetListChange\", mainFont);\n this.getDefaultPresets();\n // Unlock presets\n this.midiChannels.forEach((c) => {\n c.setPresetLock(false);\n });\n this.resetAllControllers(false);\n }\n\n private getDefaultPresets() {\n // Override this to XG, to set the default preset to NOT be XG drums!\n this.privateProps.defaultPreset = this.soundBankManager.getPreset(\n {\n bankLSB: 0,\n bankMSB: 0,\n program: 0,\n isGMGSDrum: false\n },\n \"xg\"\n );\n this.privateProps.drumPreset = this.soundBankManager.getPreset(\n {\n bankLSB: 0,\n bankMSB: 0,\n program: 0,\n isGMGSDrum: true\n },\n \"gs\"\n );\n }\n}\n"],"mappings":"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","names":["type","noteOff","e","dataEntryCoarse","dataEntryFine","programChange","nodeStartIndex","BasicMIDI","BasicMIDI","A","I","B","E","Q","g","C","i","h","o","G","D","a","S","F","R","s","w","y","sustainDb","fraction","midiControllers","globalKeyRange","globalVelRange","p","voices","midiControllers","customControllers","dataEntryFine","ifilData","cbSize","chunk","out","SpessaSynthProcessor"]}
|